bump libtool version
[swfdec.git] / libswfdec / swfdec_xml_node.c
blobda64a5c89ed1ebea0132ae582ef8db1366f03ea5
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 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include <string.h>
26 #include "swfdec_xml_node.h"
27 #include "swfdec_xml.h"
28 #include "swfdec_as_array.h"
29 #include "swfdec_as_native_function.h"
30 #include "swfdec_as_object.h"
31 #include "swfdec_as_strings.h"
32 #include "swfdec_debug.h"
33 #include "swfdec_internal.h"
34 #include "swfdec_as_internal.h"
35 #include "swfdec_load_object.h"
36 #include "swfdec_player_internal.h"
38 G_DEFINE_TYPE (SwfdecXmlNode, swfdec_xml_node, SWFDEC_TYPE_AS_OBJECT)
40 static void
41 swfdec_xml_node_do_mark (SwfdecAsObject *object)
43 SwfdecXmlNode *node = SWFDEC_XML_NODE (object);
45 if (node->name != NULL)
46 swfdec_as_string_mark (node->name);
47 if (node->value != NULL)
48 swfdec_as_string_mark (node->value);
49 if (node->parent != NULL)
50 swfdec_as_object_mark (SWFDEC_AS_OBJECT (node->parent));
51 if (node->children != NULL)
52 swfdec_as_object_mark (SWFDEC_AS_OBJECT (node->children));
53 if (node->attributes != NULL)
54 swfdec_as_object_mark (SWFDEC_AS_OBJECT (node->attributes));
55 if (node->childNodes != NULL)
56 swfdec_as_object_mark (SWFDEC_AS_OBJECT (node->childNodes));
58 SWFDEC_AS_OBJECT_CLASS (swfdec_xml_node_parent_class)->mark (object);
61 static void
62 swfdec_xml_node_class_init (SwfdecXmlNodeClass *klass)
64 SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (klass);
66 asobject_class->mark = swfdec_xml_node_do_mark;
69 static void
70 swfdec_xml_node_init (SwfdecXmlNode *xml_node)
74 /*** AS CODE ***/
76 gint32
77 swfdec_xml_node_num_children (SwfdecXmlNode *node)
79 g_return_val_if_fail (SWFDEC_IS_VALID_XML_NODE (node), 0);
81 return swfdec_as_array_get_length (node->children);
84 static SwfdecXmlNode *
85 swfdec_xml_node_get_child (SwfdecXmlNode *node, gint32 ind)
87 SwfdecAsValue val;
89 g_return_val_if_fail (SWFDEC_IS_VALID_XML_NODE (node), NULL);
90 g_return_val_if_fail (ind >= 0, NULL);
92 if (ind >= swfdec_xml_node_num_children (node))
93 return NULL;
95 swfdec_as_array_get_value (node->children, ind, &val);
97 g_return_val_if_fail (SWFDEC_AS_VALUE_IS_OBJECT (&val), NULL);
98 g_return_val_if_fail (SWFDEC_IS_VALID_XML_NODE (
99 SWFDEC_AS_VALUE_GET_OBJECT (&val)), NULL);
101 return SWFDEC_XML_NODE (SWFDEC_AS_VALUE_GET_OBJECT (&val));
104 static gint32
105 swfdec_xml_node_index_of_child (SwfdecXmlNode *node, SwfdecXmlNode *child)
107 gint32 num, i;
109 g_return_val_if_fail (SWFDEC_IS_VALID_XML_NODE (node), -1);
110 g_return_val_if_fail (SWFDEC_IS_VALID_XML_NODE (child), -1);
112 num = swfdec_xml_node_num_children (node);
113 for (i = 0; i < num; i++) {
114 if (swfdec_xml_node_get_child (node, i) == child)
115 return i;
118 return -1;
121 static void
122 swfdec_xml_node_update_childNodes (SwfdecXmlNode *node)
124 SwfdecAsValue val;
125 SwfdecAsValue *vals;
126 gint32 num, i;
128 g_return_if_fail (SWFDEC_IS_VALID_XML_NODE (node));
130 // remove old
131 SWFDEC_AS_VALUE_SET_INT (&val, 0);
132 swfdec_as_object_set_variable (SWFDEC_AS_OBJECT (node->childNodes),
133 SWFDEC_AS_STR_length, &val);
135 // add everything
136 num = swfdec_xml_node_num_children (node);
137 vals = g_malloc (sizeof (SwfdecAsValue) * num);
138 for (i = 0; i < num; i++) {
139 SWFDEC_AS_VALUE_SET_OBJECT (&vals[i],
140 SWFDEC_AS_OBJECT (swfdec_xml_node_get_child (node, i)));
142 swfdec_as_array_append_with_flags (node->childNodes, num, vals,
143 SWFDEC_AS_VARIABLE_CONSTANT);
144 g_free (vals);
147 static const char *
148 swfdec_xml_node_getNamespaceForPrefix (SwfdecXmlNode *node, const char *prefix)
150 const char *var;
151 SwfdecAsValue val;
153 g_return_val_if_fail (SWFDEC_IS_VALID_XML_NODE (node), NULL);
155 if (prefix == NULL || strlen (prefix) == 0) {
156 var = swfdec_as_context_get_string (SWFDEC_AS_OBJECT (node)->context,
157 "xmlns");
158 } else {
159 var = swfdec_as_context_give_string (SWFDEC_AS_OBJECT (node)->context,
160 g_strconcat ("xmlns:", prefix, NULL));
163 do {
164 swfdec_as_object_get_variable (node->attributes, var, &val);
165 if (!SWFDEC_AS_VALUE_IS_UNDEFINED (&val)) {
166 return swfdec_as_value_to_string (SWFDEC_AS_OBJECT (node)->context, &val);
168 node = node->parent;
169 } while (node != NULL);
171 return NULL;
174 typedef struct {
175 const char *namespace;
176 const char *variable;
177 } ForeachFindNamespaceData;
179 static gboolean
180 swfdec_xml_node_foreach_find_namespace (SwfdecAsObject *object,
181 const char *variable, SwfdecAsValue *value, guint flags, gpointer data)
183 const char *uri;
184 ForeachFindNamespaceData *fdata = data;
186 // check whether it's namespace variable (xmlns or xmlns:*)
187 if (strlen (variable) < strlen("xmlns"))
188 return TRUE;
190 if (g_ascii_strncasecmp (variable, "xmlns", strlen("xmlns")))
191 return TRUE;
193 if (variable[strlen("xmlns")] != '\0' && variable[strlen("xmlns")] != ':')
194 return TRUE;
196 // ok, now check if the uri is the one we are searching for
197 uri = swfdec_as_value_to_string (object->context, value);
198 if (!g_ascii_strcasecmp (uri, fdata->namespace)) {
199 fdata->variable = variable;
200 return FALSE;
201 } else {
202 return TRUE;
206 static const char *
207 swfdec_xml_node_getPrefixForNamespace (SwfdecXmlNode *node,
208 const char *namespace)
210 ForeachFindNamespaceData fdata;
212 g_return_val_if_fail (SWFDEC_IS_VALID_XML_NODE (node), NULL);
213 g_return_val_if_fail (namespace != NULL, NULL);
215 fdata.namespace = namespace;
216 fdata.variable = NULL;
218 do {
219 swfdec_as_object_foreach (node->attributes,
220 swfdec_xml_node_foreach_find_namespace, &fdata);
221 node = node->parent;
222 } while (node != NULL && fdata.variable == NULL);
224 if (fdata.variable != NULL) {
225 const char *p;
227 p = strchr (fdata.variable, ':');
228 if (p == NULL || *(p + 1) == '\0')
229 return SWFDEC_AS_STR_EMPTY;
231 return swfdec_as_context_get_string (SWFDEC_AS_OBJECT (node)->context,
232 p + 1);
233 } else {
234 return NULL;
238 static void
239 swfdec_xml_node_get_nodeType (SwfdecAsContext *cx, SwfdecAsObject *object,
240 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
242 if (!SWFDEC_IS_VALID_XML_NODE (object))
243 return;
245 SWFDEC_AS_VALUE_SET_INT (ret, SWFDEC_XML_NODE (object)->type);
248 static void
249 swfdec_xml_node_get_nodeValue (SwfdecAsContext *cx, SwfdecAsObject *object,
250 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
252 if (!SWFDEC_IS_VALID_XML_NODE (object))
253 return;
255 if (SWFDEC_XML_NODE (object)->value != NULL) {
256 SWFDEC_AS_VALUE_SET_STRING (ret, SWFDEC_XML_NODE (object)->value);
257 } else {
258 SWFDEC_AS_VALUE_SET_NULL (ret);
262 static void
263 swfdec_xml_node_set_nodeValue (SwfdecAsContext *cx, SwfdecAsObject *object,
264 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
266 const char *value;
268 if (!SWFDEC_IS_VALID_XML_NODE (object))
269 return;
271 if (argc < 1)
272 return;
274 value = swfdec_as_value_to_string (cx, &argv[0]);
276 SWFDEC_XML_NODE (object)->value = value;
277 SWFDEC_AS_VALUE_SET_STRING (ret, value);
280 static void
281 swfdec_xml_node_get_nodeName (SwfdecAsContext *cx, SwfdecAsObject *object,
282 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
284 if (!SWFDEC_IS_VALID_XML_NODE (object))
285 return;
287 if (SWFDEC_XML_NODE (object)->name != NULL) {
288 SWFDEC_AS_VALUE_SET_STRING (ret, SWFDEC_XML_NODE (object)->name);
289 } else {
290 SWFDEC_AS_VALUE_SET_NULL (ret);
294 static void
295 swfdec_xml_node_set_nodeName (SwfdecAsContext *cx, SwfdecAsObject *object,
296 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
298 const char *name;
300 if (!SWFDEC_IS_VALID_XML_NODE (object))
301 return;
303 if (argc < 1)
304 return;
306 // special case
307 if (SWFDEC_AS_VALUE_IS_UNDEFINED (&argv[0]))
308 return;
310 name = swfdec_as_value_to_string (cx, &argv[0]);
312 SWFDEC_XML_NODE (object)->name = name;
313 SWFDEC_AS_VALUE_SET_STRING (ret, name);
316 static const char *
317 swfdec_xml_node_get_prefix (SwfdecXmlNode *node)
319 const char *p;
321 g_return_val_if_fail (SWFDEC_IS_VALID_XML_NODE (node), NULL);
323 if (node->name == NULL)
324 return NULL;
326 p = strchr (node->name, ':');
327 if (p == NULL || *(p + 1) == '\0')
328 return NULL;
330 return swfdec_as_context_give_string (SWFDEC_AS_OBJECT (node)->context,
331 g_strndup (node->name, p - node->name));
334 static void
335 swfdec_xml_node_do_get_prefix (SwfdecAsContext *cx, SwfdecAsObject *object,
336 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
338 const char *prefix;
340 if (!SWFDEC_IS_VALID_XML_NODE (object))
341 return;
343 if (SWFDEC_XML_NODE (object)->name == NULL) {
344 SWFDEC_AS_VALUE_SET_NULL (ret);
345 return;
348 prefix = swfdec_xml_node_get_prefix (SWFDEC_XML_NODE (object));
349 if (prefix != NULL) {
350 SWFDEC_AS_VALUE_SET_STRING (ret, prefix);
351 } else {
352 SWFDEC_AS_VALUE_SET_STRING (ret, SWFDEC_AS_STR_EMPTY);
356 static void
357 swfdec_xml_node_get_localName (SwfdecAsContext *cx, SwfdecAsObject *object,
358 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
360 const char *p, *name;
362 if (!SWFDEC_IS_VALID_XML_NODE (object))
363 return;
365 if (SWFDEC_XML_NODE (object)->name == NULL) {
366 SWFDEC_AS_VALUE_SET_NULL (ret);
367 return;
370 name = SWFDEC_XML_NODE (object)->name;
371 p = strchr (name, ':');
372 if (p == NULL || *(p + 1) == '\0') {
373 SWFDEC_AS_VALUE_SET_STRING (ret, name);
374 return;
376 p++;
378 SWFDEC_AS_VALUE_SET_STRING (ret,
379 swfdec_as_context_give_string (cx, g_strdup (p)));
382 static void
383 swfdec_xml_node_get_namespaceURI (SwfdecAsContext *cx, SwfdecAsObject *object,
384 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
386 const char *uri;
388 if (!SWFDEC_IS_VALID_XML_NODE (object))
389 return;
391 if (SWFDEC_XML_NODE (object)->name == NULL) {
392 SWFDEC_AS_VALUE_SET_NULL (ret);
393 return;
396 uri = swfdec_xml_node_getNamespaceForPrefix (SWFDEC_XML_NODE (object),
397 swfdec_xml_node_get_prefix (SWFDEC_XML_NODE (object)));
398 if (uri != NULL) {
399 SWFDEC_AS_VALUE_SET_STRING (ret, uri);
400 } else {
401 SWFDEC_AS_VALUE_SET_STRING (ret, SWFDEC_AS_STR_EMPTY);
405 static void
406 swfdec_xml_node_get_attributes (SwfdecAsContext *cx, SwfdecAsObject *object,
407 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
409 if (!SWFDEC_IS_VALID_XML_NODE (object))
410 return;
412 SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_XML_NODE (object)->attributes);
415 static void
416 swfdec_xml_node_get_parentNode (SwfdecAsContext *cx, SwfdecAsObject *object,
417 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
419 if (!SWFDEC_IS_VALID_XML_NODE (object))
420 return;
422 if (SWFDEC_XML_NODE (object)->parent != NULL) {
423 SWFDEC_AS_VALUE_SET_OBJECT (ret,
424 SWFDEC_AS_OBJECT (SWFDEC_XML_NODE (object)->parent));
425 } else {
426 SWFDEC_AS_VALUE_SET_NULL (ret);
430 static SwfdecXmlNode *
431 swfdec_xml_node_previousSibling (SwfdecXmlNode *node)
433 gint32 i;
435 if (node->parent == NULL)
436 return NULL;
438 i = swfdec_xml_node_index_of_child (node->parent, node);
439 g_assert (i >= 0);
441 if (i <= 0)
442 return NULL;
444 return swfdec_xml_node_get_child (node->parent, i - 1);
447 static void
448 swfdec_xml_node_get_previousSibling (SwfdecAsContext *cx,
449 SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
451 SwfdecXmlNode *sibling;
453 if (!SWFDEC_IS_VALID_XML_NODE (object))
454 return;
456 sibling = swfdec_xml_node_previousSibling (SWFDEC_XML_NODE (object));
457 if (sibling != NULL) {
458 SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (sibling));
459 } else {
460 SWFDEC_AS_VALUE_SET_NULL (ret);
464 static SwfdecXmlNode *
465 swfdec_xml_node_nextSibling (SwfdecXmlNode *node)
467 gint32 i;
469 if (node->parent == NULL)
470 return NULL;
472 i = swfdec_xml_node_index_of_child (node->parent, node);
473 g_assert (i >= 0);
475 return swfdec_xml_node_get_child (node->parent, i + 1);
478 static void
479 swfdec_xml_node_get_nextSibling (SwfdecAsContext *cx, SwfdecAsObject *object,
480 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
482 SwfdecXmlNode *sibling;
484 if (!SWFDEC_IS_VALID_XML_NODE (object))
485 return;
487 sibling = swfdec_xml_node_nextSibling (SWFDEC_XML_NODE (object));
488 if (sibling != NULL) {
489 SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (sibling));
490 } else {
491 SWFDEC_AS_VALUE_SET_NULL (ret);
495 static void
496 swfdec_xml_node_get_firstChild (SwfdecAsContext *cx, SwfdecAsObject *object,
497 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
499 SwfdecXmlNode *child;
501 if (!SWFDEC_IS_VALID_XML_NODE (object))
502 return;
504 child = swfdec_xml_node_get_child (SWFDEC_XML_NODE (object), 0);
505 if (child != NULL) {
506 SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (child));
507 } else {
508 SWFDEC_AS_VALUE_SET_NULL (ret);
512 static void
513 swfdec_xml_node_get_lastChild (SwfdecAsContext *cx, SwfdecAsObject *object,
514 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
516 gint32 num;
517 SwfdecXmlNode *child;
519 if (!SWFDEC_IS_VALID_XML_NODE (object))
520 return;
522 num = swfdec_xml_node_num_children (SWFDEC_XML_NODE (object));
523 if (num == 0) {
524 SWFDEC_AS_VALUE_SET_NULL (ret);
525 return;
528 child = swfdec_xml_node_get_child (SWFDEC_XML_NODE (object), num - 1);
529 g_assert (child != NULL);
531 SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (child));
534 static void
535 swfdec_xml_node_get_childNodes (SwfdecAsContext *cx, SwfdecAsObject *object,
536 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
538 if (!SWFDEC_IS_VALID_XML_NODE (object))
539 return;
541 SWFDEC_AS_VALUE_SET_OBJECT (ret,
542 SWFDEC_AS_OBJECT (SWFDEC_XML_NODE (object)->childNodes));
545 SWFDEC_AS_NATIVE (253, 7, swfdec_xml_node_do_getNamespaceForPrefix)
546 void
547 swfdec_xml_node_do_getNamespaceForPrefix (SwfdecAsContext *cx,
548 SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
550 const char *namespace;
552 if (!SWFDEC_IS_VALID_XML_NODE (object))
553 return;
555 if (argc < 1) {
556 SWFDEC_AS_VALUE_SET_NULL (ret);
557 return;
560 namespace = swfdec_xml_node_getNamespaceForPrefix (SWFDEC_XML_NODE (object),
561 swfdec_as_value_to_string (cx, &argv[0]));
563 if (namespace != NULL) {
564 SWFDEC_AS_VALUE_SET_STRING (ret, namespace);
565 } else {
566 SWFDEC_AS_VALUE_SET_NULL (ret);
570 SWFDEC_AS_NATIVE (253, 8, swfdec_xml_node_do_getPrefixForNamespace)
571 void
572 swfdec_xml_node_do_getPrefixForNamespace (SwfdecAsContext *cx,
573 SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
575 const char *prefix;
577 if (!SWFDEC_IS_VALID_XML_NODE (object))
578 return;
580 if (argc < 1) {
581 SWFDEC_AS_VALUE_SET_NULL (ret);
582 return;
585 prefix = swfdec_xml_node_getPrefixForNamespace (SWFDEC_XML_NODE (object),
586 swfdec_as_value_to_string (cx, &argv[0]));
588 if (prefix != NULL) {
589 SWFDEC_AS_VALUE_SET_STRING (ret, prefix);
590 } else {
591 SWFDEC_AS_VALUE_SET_NULL (ret);
595 static gboolean
596 swfdec_xml_node_foreach_copy_attributes (SwfdecAsObject *object,
597 const char *variable, SwfdecAsValue *value, guint flags, gpointer data)
599 SwfdecAsObject *target = data;
600 swfdec_as_object_set_variable (target, variable, value);
601 return TRUE;
604 static void
605 swfdec_xml_node_copy_attributes (SwfdecXmlNode *node, SwfdecXmlNode *target)
607 swfdec_as_object_foreach (node->attributes,
608 swfdec_xml_node_foreach_copy_attributes, target->attributes);
611 static SwfdecXmlNode *
612 swfdec_xml_node_clone (SwfdecAsContext *cx, SwfdecXmlNode *node, gboolean deep)
614 SwfdecXmlNode *new;
616 g_assert (SWFDEC_IS_AS_CONTEXT (cx));
617 g_assert (SWFDEC_IS_VALID_XML_NODE (node));
619 new = swfdec_xml_node_new (cx, SWFDEC_XML_NODE_ELEMENT, SWFDEC_AS_STR_EMPTY);
621 new->valid = TRUE;
622 new->type = node->type;
623 new->name = node->name;
624 new->value = node->value;
626 swfdec_xml_node_copy_attributes (node, new);
628 if (deep) {
629 SwfdecAsValue val;
630 SwfdecXmlNode *child, *child_new;
631 gint32 num, i;
633 num = swfdec_xml_node_num_children (node);
635 for (i = 0; i < num; i++) {
636 child = swfdec_xml_node_get_child (node, i);
637 child_new = swfdec_xml_node_clone (cx, child, TRUE);
638 child_new->parent = new;
639 SWFDEC_AS_VALUE_SET_OBJECT (&val, SWFDEC_AS_OBJECT (child_new));
640 swfdec_as_array_push (new->children, &val);
643 swfdec_xml_node_update_childNodes (new);
646 return new;
649 SWFDEC_AS_NATIVE (253, 1, swfdec_xml_node_cloneNode)
650 void
651 swfdec_xml_node_cloneNode (SwfdecAsContext *cx, SwfdecAsObject *object,
652 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
654 gboolean deep;
655 SwfdecXmlNode *new;
657 if (!SWFDEC_IS_VALID_XML_NODE (object))
658 return;
660 if (argc >= 1) {
661 deep = swfdec_as_value_to_boolean (cx, &argv[0]);
662 } else {
663 deep = FALSE;
666 new = swfdec_xml_node_clone (cx, SWFDEC_XML_NODE (object), deep);
667 SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (new));
670 void
671 swfdec_xml_node_removeNode (SwfdecXmlNode *node)
673 gint32 i;
675 g_return_if_fail (SWFDEC_IS_VALID_XML_NODE (node));
677 if (node->parent == NULL)
678 return;
680 i = swfdec_xml_node_index_of_child (node->parent, node);
681 g_assert (i >= 0);
683 swfdec_as_array_remove (node->parent->children, i);
684 swfdec_xml_node_update_childNodes (node->parent);
685 node->parent = NULL;
688 SWFDEC_AS_NATIVE (253, 2, swfdec_xml_node_do_removeNode)
689 void
690 swfdec_xml_node_do_removeNode (SwfdecAsContext *cx, SwfdecAsObject *object,
691 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
693 if (!SWFDEC_IS_VALID_XML_NODE (object))
694 return;
696 swfdec_xml_node_removeNode (SWFDEC_XML_NODE (object));
699 void
700 swfdec_xml_node_removeChildren (SwfdecXmlNode *node)
702 gint32 num, i;
704 g_return_if_fail (SWFDEC_IS_VALID_XML_NODE (node));
706 num = swfdec_xml_node_num_children (node);
708 for (i = 0; i < num; i++) {
709 swfdec_xml_node_removeNode (swfdec_xml_node_get_child (node, 0));
713 static void
714 swfdec_xml_node_insertAt (SwfdecXmlNode *node, SwfdecXmlNode *child, gint32 ind)
716 SwfdecAsValue val;
718 g_assert (SWFDEC_IS_VALID_XML_NODE (node));
719 g_assert (SWFDEC_IS_VALID_XML_NODE (child));
720 g_assert (ind >= 0);
722 // remove the previous parent of the child
723 swfdec_xml_node_removeNode (child);
725 // insert child to node's childNodes array
726 SWFDEC_AS_VALUE_SET_OBJECT (&val, SWFDEC_AS_OBJECT (child));
727 swfdec_as_array_insert (node->children, ind, &val);
728 swfdec_xml_node_update_childNodes (node);
730 // set node as parent of child
731 child->parent = node;
734 SWFDEC_AS_NATIVE (253, 3, swfdec_xml_node_insertBefore)
735 void
736 swfdec_xml_node_insertBefore (SwfdecAsContext *cx, SwfdecAsObject *object,
737 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
739 gint32 i;
740 SwfdecAsObject *child, *point;
742 if (!SWFDEC_IS_VALID_XML_NODE (object))
743 return;
745 if (argc < 2)
746 return;
748 if (!SWFDEC_AS_VALUE_IS_OBJECT (&argv[0]))
749 return;
751 child = SWFDEC_AS_VALUE_GET_OBJECT (&argv[0]);
752 if (!SWFDEC_IS_VALID_XML_NODE (child))
753 return;
755 // special case
756 if (swfdec_xml_node_index_of_child (SWFDEC_XML_NODE (object),
757 SWFDEC_XML_NODE (child)) != -1)
758 return;
760 if (!SWFDEC_AS_VALUE_IS_OBJECT (&argv[1]))
761 return;
763 point = SWFDEC_AS_VALUE_GET_OBJECT (&argv[1]);
764 if (!SWFDEC_IS_VALID_XML_NODE (point))
765 return;
767 i = swfdec_xml_node_index_of_child (SWFDEC_XML_NODE (object),
768 SWFDEC_XML_NODE (point));
770 if (i != -1) {
771 swfdec_xml_node_insertAt (SWFDEC_XML_NODE (object),
772 SWFDEC_XML_NODE (child), i);
776 void
777 swfdec_xml_node_appendChild (SwfdecXmlNode *node, SwfdecXmlNode *child)
779 SwfdecAsValue val;
781 g_return_if_fail (SWFDEC_IS_VALID_XML_NODE (node));
782 g_return_if_fail (SWFDEC_IS_VALID_XML_NODE (child));
783 g_return_if_fail (node->children != NULL);
785 // remove the previous parent of the child
786 swfdec_xml_node_removeNode (child);
788 // append child to node's childNodes array
789 SWFDEC_AS_VALUE_SET_OBJECT (&val, SWFDEC_AS_OBJECT (child));
790 swfdec_as_array_push (node->children, &val);
791 swfdec_xml_node_update_childNodes (node);
793 // set node as parent of child
794 child->parent = node;
797 SWFDEC_AS_NATIVE (253, 4, swfdec_xml_node_do_appendChild)
798 void
799 swfdec_xml_node_do_appendChild (SwfdecAsContext *cx, SwfdecAsObject *object,
800 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
802 SwfdecAsObject *child;
804 if (!SWFDEC_IS_VALID_XML_NODE (object))
805 return;
807 if (argc < 1)
808 return;
810 if (!SWFDEC_AS_VALUE_IS_OBJECT (&argv[0]))
811 return;
813 child = SWFDEC_AS_VALUE_GET_OBJECT (&argv[0]);
814 if (!SWFDEC_IS_VALID_XML_NODE (child))
815 return;
817 // special case
818 if (swfdec_xml_node_index_of_child (SWFDEC_XML_NODE (object),
819 SWFDEC_XML_NODE (child)) != -1)
820 return;
822 swfdec_xml_node_appendChild (SWFDEC_XML_NODE (object),
823 SWFDEC_XML_NODE (child));
826 SWFDEC_AS_NATIVE (253, 5, swfdec_xml_node_hasChildNodes)
827 void
828 swfdec_xml_node_hasChildNodes (SwfdecAsContext *cx, SwfdecAsObject *object,
829 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
831 if (!SWFDEC_IS_VALID_XML_NODE (object))
832 return;
834 if (swfdec_xml_node_num_children (SWFDEC_XML_NODE (object)) > 0) {
835 SWFDEC_AS_VALUE_SET_BOOLEAN (ret, TRUE);
836 } else {
837 SWFDEC_AS_VALUE_SET_BOOLEAN (ret, FALSE);
841 static gboolean
842 swfdec_xml_node_foreach_string_append_attribute (SwfdecAsObject *object,
843 const char *variable, SwfdecAsValue *value, guint flags, gpointer data)
845 GString *string = *(GString **)data;
846 char *escaped;
848 string = g_string_append (string, " ");
849 string = g_string_append (string, variable);
850 string = g_string_append (string, "=\"");
851 escaped =
852 swfdec_xml_escape (swfdec_as_value_to_string (object->context, value));
853 string = g_string_append (string, escaped);
854 g_free (escaped);
855 string = g_string_append (string, "\"");
857 return TRUE;
860 static const char *
861 swfdec_xml_node_toString (SwfdecXmlNode *node)
863 GString *string;
864 SwfdecAsObject *object;
866 g_assert (SWFDEC_IS_VALID_XML_NODE (node));
868 object = SWFDEC_AS_OBJECT (node);
870 string = g_string_new ("");
871 if (SWFDEC_IS_XML (node)) {
872 if (SWFDEC_XML (node)->xmlDecl != NULL)
873 string = g_string_append (string, SWFDEC_XML (node)->xmlDecl);
874 if (SWFDEC_XML (node)->docTypeDecl != NULL)
875 string = g_string_append (string, SWFDEC_XML (node)->docTypeDecl);
878 switch (node->type) {
879 case SWFDEC_XML_NODE_ELEMENT:
881 SwfdecXmlNode *child;
882 gint32 i, num;
883 gboolean visible;
885 if (node->name == NULL) {
886 visible = FALSE;
887 } else {
888 visible = TRUE;
891 if (visible) {
892 string = g_string_append (string, "<");
893 string = g_string_append (string, node->name);
895 swfdec_as_object_foreach (node->attributes,
896 swfdec_xml_node_foreach_string_append_attribute, &string);
899 num = swfdec_xml_node_num_children (node);
901 if (num > 0) {
902 if (visible)
903 string = g_string_append (string, ">");
905 for (i = 0; i < num; i++) {
906 child = swfdec_xml_node_get_child (node, i);
907 g_assert (child != NULL);
908 string = g_string_append (string, swfdec_xml_node_toString (child));
911 if (visible) {
912 string = g_string_append (string, "</");
913 string = g_string_append (string, node->name);
914 string = g_string_append (string, ">");
916 } else {
917 if (visible)
918 string = g_string_append (string, " />");
921 break;
923 case SWFDEC_XML_NODE_TEXT:
924 default:
926 char *escaped = swfdec_xml_escape (node->value);
927 string = g_string_append (string, escaped);
928 g_free (escaped);
929 break;
933 return swfdec_as_context_give_string (object->context,
934 g_string_free (string, FALSE));
937 SWFDEC_AS_NATIVE (253, 6, swfdec_xml_node_do_toString)
938 void
939 swfdec_xml_node_do_toString (SwfdecAsContext *cx, SwfdecAsObject *object,
940 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
942 if (!SWFDEC_IS_VALID_XML_NODE (object))
943 return;
945 SWFDEC_AS_VALUE_SET_STRING (ret,
946 swfdec_xml_node_toString (SWFDEC_XML_NODE (object)));
949 void
950 swfdec_xml_node_init_properties (SwfdecXmlNode *node, int type,
951 const char* value)
953 SwfdecAsObject *object;
955 g_return_if_fail (SWFDEC_IS_XML_NODE (node));
956 g_return_if_fail (value != NULL);
958 object = SWFDEC_AS_OBJECT (node);
960 node->valid = TRUE;
961 node->parent = NULL;
962 // FIXME: use _global.Array constructor?
963 node->children = SWFDEC_AS_ARRAY (swfdec_as_array_new (object->context));
964 node->attributes = swfdec_as_object_new_empty (object->context);
965 node->type = type;
966 if (node->type == SWFDEC_XML_NODE_ELEMENT) {
967 node->name = value;
968 } else {
969 node->value = value;
972 node->childNodes = SWFDEC_AS_ARRAY (swfdec_as_array_new (object->context));
975 SwfdecXmlNode *
976 swfdec_xml_node_new (SwfdecAsContext *context, SwfdecXmlNodeType type,
977 const char* value)
979 SwfdecAsValue val;
980 SwfdecXmlNode *node;
981 guint size;
983 g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
985 size = sizeof (SwfdecXmlNode);
986 if (!swfdec_as_context_use_mem (context, size))
987 return NULL;
988 node = g_object_new (SWFDEC_TYPE_XML_NODE, NULL);
989 swfdec_as_object_add (SWFDEC_AS_OBJECT (node), context, size);
990 swfdec_as_object_get_variable (context->global, SWFDEC_AS_STR_XMLNode, &val);
991 if (!SWFDEC_AS_VALUE_IS_OBJECT (&val))
992 return NULL;
993 swfdec_as_object_set_constructor (SWFDEC_AS_OBJECT (node), SWFDEC_AS_VALUE_GET_OBJECT (&val));
995 swfdec_xml_node_init_properties (node, type,
996 swfdec_as_context_get_string (SWFDEC_AS_OBJECT (node)->context, value));
998 return node;
1001 static void
1002 swfdec_xml_node_add_variable (SwfdecAsObject *object, const char *variable,
1003 SwfdecAsNative get, SwfdecAsNative set)
1005 SwfdecAsFunction *get_func, *set_func;
1007 g_return_if_fail (SWFDEC_IS_AS_OBJECT (object));
1008 g_return_if_fail (variable != NULL);
1009 g_return_if_fail (get != NULL);
1011 get_func =
1012 swfdec_as_native_function_new (object->context, variable, get, 0, NULL);
1013 if (get_func == NULL)
1014 return;
1016 if (set != NULL) {
1017 set_func =
1018 swfdec_as_native_function_new (object->context, variable, set, 0, NULL);
1019 } else {
1020 set_func = NULL;
1023 swfdec_as_object_add_variable (object, variable, get_func, set_func, 0);
1026 SWFDEC_AS_CONSTRUCTOR (253, 0, swfdec_xml_node_construct, swfdec_xml_node_get_type)
1027 void
1028 swfdec_xml_node_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
1029 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
1031 if (!swfdec_as_context_is_constructing (cx)) {
1032 SWFDEC_FIXME ("What do we do if not constructing?");
1033 return;
1036 g_assert (SWFDEC_IS_XML_NODE (object));
1038 if (!SWFDEC_PLAYER (cx)->xml_node_properties_initialized) {
1039 SwfdecAsValue val;
1040 SwfdecAsObject *proto;
1042 swfdec_as_object_get_variable (object, SWFDEC_AS_STR___proto__, &val);
1043 g_return_if_fail (SWFDEC_AS_VALUE_IS_OBJECT (&val));
1044 proto = SWFDEC_AS_VALUE_GET_OBJECT (&val);
1046 swfdec_xml_node_add_variable (proto, SWFDEC_AS_STR_nodeType,
1047 swfdec_xml_node_get_nodeType, NULL);
1048 swfdec_xml_node_add_variable (proto, SWFDEC_AS_STR_nodeValue,
1049 swfdec_xml_node_get_nodeValue, swfdec_xml_node_set_nodeValue);
1050 swfdec_xml_node_add_variable (proto, SWFDEC_AS_STR_nodeName,
1051 swfdec_xml_node_get_nodeName, swfdec_xml_node_set_nodeName);
1052 swfdec_xml_node_add_variable (proto, SWFDEC_AS_STR_prefix,
1053 swfdec_xml_node_do_get_prefix, NULL);
1054 swfdec_xml_node_add_variable (proto, SWFDEC_AS_STR_localName,
1055 swfdec_xml_node_get_localName, NULL);
1056 swfdec_xml_node_add_variable (proto, SWFDEC_AS_STR_namespaceURI,
1057 swfdec_xml_node_get_namespaceURI, NULL);
1058 swfdec_xml_node_add_variable (proto, SWFDEC_AS_STR_attributes,
1059 swfdec_xml_node_get_attributes, NULL);
1060 swfdec_xml_node_add_variable (proto, SWFDEC_AS_STR_parentNode,
1061 swfdec_xml_node_get_parentNode, NULL);
1062 swfdec_xml_node_add_variable (proto, SWFDEC_AS_STR_previousSibling,
1063 swfdec_xml_node_get_previousSibling, NULL);
1064 swfdec_xml_node_add_variable (proto, SWFDEC_AS_STR_nextSibling,
1065 swfdec_xml_node_get_nextSibling, NULL);
1066 swfdec_xml_node_add_variable (proto, SWFDEC_AS_STR_firstChild,
1067 swfdec_xml_node_get_firstChild, NULL);
1068 swfdec_xml_node_add_variable (proto, SWFDEC_AS_STR_lastChild,
1069 swfdec_xml_node_get_lastChild, NULL);
1070 swfdec_xml_node_add_variable (proto, SWFDEC_AS_STR_childNodes,
1071 swfdec_xml_node_get_childNodes, NULL);
1073 SWFDEC_PLAYER (cx)->xml_node_properties_initialized = TRUE;
1076 if (argc < 2)
1077 return;
1079 // special case
1080 if (SWFDEC_AS_VALUE_IS_UNDEFINED (&argv[0]) ||
1081 SWFDEC_AS_VALUE_IS_UNDEFINED (&argv[1]))
1082 return;
1084 swfdec_xml_node_init_properties (SWFDEC_XML_NODE (object),
1085 swfdec_as_value_to_integer (cx, &argv[0]),
1086 swfdec_as_value_to_string (cx, &argv[1]));
1088 SWFDEC_AS_VALUE_SET_OBJECT (ret, object);