first step at rewriting the button code - nothing works, but it compiles
[swfdec.git] / libswfdec / swfdec_amf.c
blob4baab4101855ceffaec4c5c823c2991ec0767b1a
1 /* Swfdec
2 * Copyright (C) 2007 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
20 #ifndef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include "swfdec_amf.h"
25 #include "swfdec_as_array.h"
26 #include "swfdec_debug.h"
28 typedef gboolean (* SwfdecAmfParseFunc) (SwfdecAsContext *cx, SwfdecBits *bits, SwfdecAsValue *val);
29 extern const SwfdecAmfParseFunc parse_funcs[SWFDEC_AMF_N_TYPES];
31 static gboolean
32 swfdec_amf_parse_boolean (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val)
34 SWFDEC_AS_VALUE_SET_BOOLEAN (val, swfdec_bits_get_u8 (bits) ? TRUE : FALSE);
35 return TRUE;
38 static gboolean
39 swfdec_amf_parse_number (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val)
41 SWFDEC_AS_VALUE_SET_NUMBER (val, swfdec_bits_get_bdouble (bits));
42 return TRUE;
45 static gboolean
46 swfdec_amf_parse_string (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val)
48 guint len = swfdec_bits_get_bu16 (bits);
49 char *s;
51 /* FIXME: the supplied version is likely incorrect */
52 s = swfdec_bits_get_string_length (bits, len, context->version);
53 if (s == NULL)
54 return FALSE;
55 SWFDEC_AS_VALUE_SET_STRING (val, swfdec_as_context_give_string (context, s));
56 return TRUE;
59 static gboolean
60 swfdec_amf_parse_properties (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsObject *object)
62 guint type;
63 SwfdecAmfParseFunc func;
65 while (swfdec_bits_left (bits)) {
66 SwfdecAsValue val;
67 const char *name;
69 if (!swfdec_amf_parse_string (context, bits, &val))
70 return FALSE;
71 name = SWFDEC_AS_VALUE_GET_STRING (&val);
72 type = swfdec_bits_get_u8 (bits);
73 if (type == SWFDEC_AMF_END_OBJECT)
74 break;
75 if (type >= SWFDEC_AMF_N_TYPES ||
76 (func = parse_funcs[type]) == NULL) {
77 SWFDEC_ERROR ("no parse func for AMF type %u", type);
78 goto error;
80 swfdec_as_object_set_variable (object, name, &val); /* GC... */
81 if (!func (context, bits, &val)) {
82 goto error;
84 swfdec_as_object_set_variable (object, name, &val);
86 /* no more bytes seems to end automatically */
87 return TRUE;
89 error:
90 return FALSE;
93 static gboolean
94 swfdec_amf_parse_object (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val)
96 SwfdecAsObject *object;
98 object = swfdec_as_object_new (context);
99 if (object == NULL)
100 return FALSE;
101 if (!swfdec_amf_parse_properties (context, bits, object))
102 return FALSE;
103 SWFDEC_AS_VALUE_SET_OBJECT (val, object);
104 return TRUE;
107 static gboolean
108 swfdec_amf_parse_mixed_array (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val)
110 guint len;
111 SwfdecAsObject *array;
113 len = swfdec_bits_get_bu32 (bits);
114 array = swfdec_as_array_new (context);
115 if (array == NULL)
116 return FALSE;
117 if (!swfdec_amf_parse_properties (context, bits, array))
118 return FALSE;
119 SWFDEC_AS_VALUE_SET_OBJECT (val, array);
120 return TRUE;
123 static gboolean
124 swfdec_amf_parse_array (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val)
126 guint i, len;
127 SwfdecAsObject *array;
128 guint type;
129 SwfdecAmfParseFunc func;
131 len = swfdec_bits_get_bu32 (bits);
132 array = swfdec_as_array_new (context);
133 if (array == NULL)
134 return FALSE;
135 for (i = 0; i < len; i++) {
136 SwfdecAsValue tmp;
137 type = swfdec_bits_get_u8 (bits);
138 if (type >= SWFDEC_AMF_N_TYPES ||
139 (func = parse_funcs[type]) == NULL) {
140 SWFDEC_ERROR ("no parse func for AMF type %u", type);
141 goto fail;
143 if (!func (context, bits, &tmp))
144 goto fail;
145 swfdec_as_array_push (SWFDEC_AS_ARRAY (array), &tmp);
148 SWFDEC_AS_VALUE_SET_OBJECT (val, array);
149 return TRUE;
151 fail:
152 return FALSE;
155 const SwfdecAmfParseFunc parse_funcs[SWFDEC_AMF_N_TYPES] = {
156 [SWFDEC_AMF_NUMBER] = swfdec_amf_parse_number,
157 [SWFDEC_AMF_BOOLEAN] = swfdec_amf_parse_boolean,
158 [SWFDEC_AMF_STRING] = swfdec_amf_parse_string,
159 [SWFDEC_AMF_OBJECT] = swfdec_amf_parse_object,
160 [SWFDEC_AMF_MIXED_ARRAY] = swfdec_amf_parse_mixed_array,
161 [SWFDEC_AMF_ARRAY] = swfdec_amf_parse_array,
162 #if 0
163 SWFDEC_AMF_MOVIECLIP = 4,
164 SWFDEC_AMF_NULL = 5,
165 SWFDEC_AMF_UNDEFINED = 6,
166 SWFDEC_AMF_REFERENCE = 7,
167 SWFDEC_AMF_END_OBJECT = 9,
168 SWFDEC_AMF_ARRAY = 10,
169 SWFDEC_AMF_DATE = 11,
170 SWFDEC_AMF_BIG_STRING = 12,
171 SWFDEC_AMF_RECORDSET = 14,
172 SWFDEC_AMF_XML = 15,
173 SWFDEC_AMF_CLASS = 16,
174 SWFDEC_AMF_FLASH9 = 17,
175 #endif
178 gboolean
179 swfdec_amf_parse_one (SwfdecAsContext *context, SwfdecBits *bits,
180 SwfdecAmfType expected_type, SwfdecAsValue *rval)
182 SwfdecAmfParseFunc func;
183 guint type;
185 g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), 0);
186 g_return_val_if_fail (bits != NULL, FALSE);
187 g_return_val_if_fail (rval != NULL, FALSE);
188 g_return_val_if_fail (expected_type < SWFDEC_AMF_N_TYPES, FALSE);
190 type = swfdec_bits_get_u8 (bits);
191 if (type != expected_type) {
192 SWFDEC_ERROR ("parse object should be type %u, but is %u",
193 expected_type, type);
194 return FALSE;
196 if (type >= SWFDEC_AMF_N_TYPES ||
197 (func = parse_funcs[type]) == NULL) {
198 SWFDEC_ERROR ("no parse func for AMF type %u", type);
199 return FALSE;
201 return func (context, bits, rval);
204 guint
205 swfdec_amf_parse (SwfdecAsContext *context, SwfdecBits *bits, guint n_items, ...)
207 va_list args;
208 guint i;
210 g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), 0);
211 g_return_val_if_fail (bits != NULL, 0);
213 va_start (args, n_items);
214 for (i = 0; i < n_items; i++) {
215 SwfdecAmfType type = va_arg (args, SwfdecAmfType);
216 SwfdecAsValue *val = va_arg (args, SwfdecAsValue *);
217 if (!swfdec_amf_parse_one (context, bits, type, val))
218 break;
220 va_end (args);
221 return i;