1 /* Aravis
2  *
3  * Copyright © 2007-2010 Emmanuel Pacaud
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  *
20  * Author:
21  * 	Emmanuel Pacaud <emmanuel@gnome.org>
22  */
23 
24 /**
25  * SECTION:arvdomnode
26  * @short_description: Base class for DOM nodes
27  */
28 
29 #include <arvdomnode.h>
30 #include <arvdomnodelist.h>
31 #include <arvdomdocument.h>
32 #include <arvdebug.h>
33 #include <glib/gprintf.h>
34 #include <stdio.h>
35 
36 /* ArvDomNodeChildList */
37 
38 
39 #define ARV_TYPE_DOM_NODE_CHILD_LIST             (arv_dom_node_child_list_get_type ())
40 #define ARV_DOM_NODE_CHILD_LIST(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), ARV_TYPE_DOM_NODE_CHILD_LIST, ArvDomNodeChildList))
41 #define ARV_DOM_NODE_CHILD_LIST_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), ARV_TYPE_DOM_NODE_CHILD_LIST, ArvDomNodeChildListClass))
42 #define ARV_IS_DOM_NODE_CHILD_LIST(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ARV_TYPE_DOM_NODE_CHILD_LIST))
43 #define ARV_IS_DOM_NODE_CHILD_LIST_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), ARV_TYPE_DOM_NODE_CHILD_LIST))
44 #define ARV_DOM_NODE_CHILD_LIST_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), ARV_TYPE_DOM_NODE_CHILD_LIST, ArvDomNodeChildListClass))
45 
46 typedef struct _ArvDomNodeChildListClass ArvDomNodeChildListClass;
47 
48 typedef struct {
49 	ArvDomNodeList base;
50 
51 	ArvDomNode *parent_node;
52 } ArvDomNodeChildList;
53 
54 struct _ArvDomNodeChildListClass {
55 	ArvDomNodeListClass parent_class;
56 };
57 
58 GType arv_dom_node_child_list_get_type (void);
59 
60 static GObjectClass *child_list_parent_class = NULL;
61 
62 static void
arv_dom_node_child_list_weak_notify_cb(void * user_data,GObject * object)63 arv_dom_node_child_list_weak_notify_cb (void *user_data, GObject *object)
64 {
65 	ArvDomNodeChildList *list = user_data;
66 
67 	list->parent_node = NULL;
68 }
69 
70 static ArvDomNode *
arv_dom_node_child_list_get_item(ArvDomNodeList * list,unsigned int index)71 arv_dom_node_child_list_get_item (ArvDomNodeList *list, unsigned int index)
72 {
73 	ArvDomNodeChildList *child_list = ARV_DOM_NODE_CHILD_LIST (list);
74 	ArvDomNode *iter;
75 	unsigned int i = 0;
76 
77 	if (child_list->parent_node == NULL)
78 		return NULL;
79 
80 	for (iter = child_list->parent_node->first_child; iter != NULL; iter = iter->next_sibling) {
81 		if (i == index)
82 			return iter;
83 		i++;
84 	}
85 
86 	return NULL;
87 }
88 
89 static unsigned int
arv_dom_node_child_list_get_length(ArvDomNodeList * list)90 arv_dom_node_child_list_get_length (ArvDomNodeList *list)
91 {
92 	ArvDomNodeChildList *child_list = ARV_DOM_NODE_CHILD_LIST (list);
93 	ArvDomNode *iter;
94 	unsigned int length = 0;
95 
96 	if (child_list->parent_node == NULL)
97 		return 0;
98 
99 	for (iter = child_list->parent_node->first_child; iter != NULL; iter = iter->next_sibling)
100 		length++;
101 
102 	return length;
103 }
104 
105 ArvDomNodeList *
arv_dom_node_child_list_new(ArvDomNode * parent_node)106 arv_dom_node_child_list_new (ArvDomNode *parent_node)
107 {
108 	ArvDomNodeChildList *list;
109 
110 	g_return_val_if_fail (ARV_IS_DOM_NODE (parent_node), NULL);
111 
112 	list = g_object_new (ARV_TYPE_DOM_NODE_CHILD_LIST, NULL);
113 	list->parent_node = parent_node;
114 
115 	g_object_weak_ref (G_OBJECT (parent_node), arv_dom_node_child_list_weak_notify_cb, list);
116 
117 	return ARV_DOM_NODE_LIST (list);
118 }
119 
120 static void
arv_dom_node_child_list_init(ArvDomNodeChildList * list)121 arv_dom_node_child_list_init (ArvDomNodeChildList *list)
122 {
123 }
124 
125 static void
arv_dom_node_child_list_finalize(GObject * object)126 arv_dom_node_child_list_finalize (GObject *object)
127 {
128 	ArvDomNodeChildList *list = ARV_DOM_NODE_CHILD_LIST (object);
129 
130 	if (list->parent_node != NULL) {
131 		g_object_weak_unref (G_OBJECT (list->parent_node), arv_dom_node_child_list_weak_notify_cb, list);
132 		list->parent_node = NULL;
133 	}
134 
135 	child_list_parent_class->finalize (object);
136 }
137 
138 static void
arv_dom_node_child_list_class_init(ArvDomNodeChildListClass * klass)139 arv_dom_node_child_list_class_init (ArvDomNodeChildListClass *klass)
140 {
141 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
142 	ArvDomNodeListClass *node_list_class = ARV_DOM_NODE_LIST_CLASS (klass);
143 
144 	child_list_parent_class = g_type_class_peek_parent (klass);
145 
146 	object_class->finalize = arv_dom_node_child_list_finalize;
147 
148 	node_list_class->get_item = arv_dom_node_child_list_get_item;
149 	node_list_class->get_length = arv_dom_node_child_list_get_length;
150 }
151 
152 G_DEFINE_TYPE (ArvDomNodeChildList, arv_dom_node_child_list, ARV_TYPE_DOM_NODE_LIST)
153 
154 static GObjectClass *parent_class = NULL;
155 
156 /* ArvDomNode implementation */
157 
158 
159 /**
160  * arv_dom_node_get_node_name:
161  * @self: a #ArvDomNode
162  *
163  * Gets the node name.
164  *
165  * Return value: the node name.
166  */
167 
168 const char*
arv_dom_node_get_node_name(ArvDomNode * self)169 arv_dom_node_get_node_name (ArvDomNode* self)
170 {
171 	ArvDomNodeClass *node_class = ARV_DOM_NODE_GET_CLASS (self);
172 
173 	g_return_val_if_fail (node_class != NULL, NULL);
174 
175 	if (node_class->get_node_name)
176 		return node_class->get_node_name (self);
177 
178 	return NULL;
179 }
180 
181 /**
182  * arv_dom_node_get_node_value:
183  * @self: a #ArvDomNode
184  *
185  * Gets the node value.
186  *
187  * Return value: the node value.
188  */
189 
190 const char*
arv_dom_node_get_node_value(ArvDomNode * self)191 arv_dom_node_get_node_value (ArvDomNode* self)
192 {
193 	ArvDomNodeClass *node_class = ARV_DOM_NODE_GET_CLASS (self);
194 
195 	g_return_val_if_fail (node_class != NULL, NULL);
196 
197 	if (node_class->get_node_value)
198 		return node_class->get_node_value (self);
199 
200 	return NULL;
201 }
202 
203 void
arv_dom_node_set_node_value(ArvDomNode * self,const char * new_value)204 arv_dom_node_set_node_value (ArvDomNode* self, const char* new_value)
205 {
206 	ArvDomNodeClass *node_class = ARV_DOM_NODE_GET_CLASS (self);
207 
208 	g_return_if_fail (node_class != NULL);
209 	g_return_if_fail (new_value != NULL);
210 
211 	if (node_class->set_node_value)
212 		node_class->set_node_value (self, new_value);
213 }
214 
arv_dom_node_get_node_type(ArvDomNode * self)215 ArvDomNodeType arv_dom_node_get_node_type (ArvDomNode* self)
216 {
217 	ArvDomNodeClass *node_class = ARV_DOM_NODE_GET_CLASS (self);
218 
219 	g_return_val_if_fail (node_class != NULL, 0);
220 
221 	if (node_class->get_node_type)
222 		return node_class->get_node_type (self);
223 
224 	return 0;
225 }
226 
227 /**
228  * arv_dom_node_get_parent_node:
229  * @self: a #ArvDomNode
230  *
231  * Get the parent node of @self.
232  *
233  * Returns: (transfer none): @self parent.
234  */
235 
236 ArvDomNode*
arv_dom_node_get_parent_node(ArvDomNode * self)237 arv_dom_node_get_parent_node (ArvDomNode* self)
238 {
239 	g_return_val_if_fail (ARV_IS_DOM_NODE (self), NULL);
240 
241 	return self->parent_node;
242 }
243 
244 /**
245  * arv_dom_node_get_child_nodes:
246  * @self: a #ArvDomNode
247  *
248  * Returns: (transfer none): a #ArvDomNodeList, NULL on error.
249  */
250 
251 ArvDomNodeList*
arv_dom_node_get_child_nodes(ArvDomNode * self)252 arv_dom_node_get_child_nodes (ArvDomNode* self)
253 {
254 	ArvDomNodeList *list;
255 
256 	g_return_val_if_fail (ARV_IS_DOM_NODE (self), NULL);
257 
258 	list = g_object_get_data (G_OBJECT (self), "child-nodes");
259 
260 	if (list == NULL) {
261 		list = arv_dom_node_child_list_new (self);
262 		g_object_set_data_full (G_OBJECT (self), "child-nodes", list, g_object_unref);
263 	}
264 
265 	return list;
266 }
267 
268 /**
269  * arv_dom_node_get_first_child:
270  * @self: a #ArvDomNode
271  *
272  * Returns: (transfer none): @self first child.
273  */
274 
275 ArvDomNode*
arv_dom_node_get_first_child(ArvDomNode * self)276 arv_dom_node_get_first_child (ArvDomNode* self)
277 {
278 	g_return_val_if_fail (ARV_IS_DOM_NODE (self), NULL);
279 
280 	return self->first_child;
281 }
282 
283 /**
284  * arv_dom_node_get_last_child:
285  * @self: a #ArvDomNode
286  *
287  * Returns: (transfer none): @self last child.
288  */
289 
290 ArvDomNode*
arv_dom_node_get_last_child(ArvDomNode * self)291 arv_dom_node_get_last_child (ArvDomNode* self)
292 {
293 	g_return_val_if_fail (ARV_IS_DOM_NODE (self), NULL);
294 
295 	return self->last_child;
296 }
297 
298 /**
299  * arv_dom_node_get_previous_sibling:
300  * @self: a #ArvDomNode
301  *
302  * Returns: (transfer none): @self previous sibling.
303  */
304 
305 ArvDomNode*
arv_dom_node_get_previous_sibling(ArvDomNode * self)306 arv_dom_node_get_previous_sibling (ArvDomNode* self)
307 {
308 	g_return_val_if_fail (ARV_IS_DOM_NODE (self), NULL);
309 
310 	return self->previous_sibling;
311 }
312 
313 /**
314  * arv_dom_node_get_next_sibling:
315  * @self: a #ArvDomNode
316  *
317  * Returns: (transfer none): @self next sibling.
318  */
319 
320 ArvDomNode*
arv_dom_node_get_next_sibling(ArvDomNode * self)321 arv_dom_node_get_next_sibling (ArvDomNode* self)
322 {
323 	g_return_val_if_fail (ARV_IS_DOM_NODE (self), NULL);
324 
325 	return self->next_sibling;
326 }
327 
328 /*ArvDomNamedNodeMap**/
329 /*arv_dom_node_get_attributes (ArvDomNode* self)*/
330 /*{*/
331 /*        return ARV_DOM_NODE_GET_CLASS (self)->get_attributes (self);*/
332 /*}*/
333 
334 
335 /**
336  * arv_dom_node_get_owner_document:
337  * @self: a #ArvDomNode
338  *
339  * Returns: (transfer none): @self owner document.
340  */
341 
342 ArvDomDocument*
arv_dom_node_get_owner_document(ArvDomNode * self)343 arv_dom_node_get_owner_document (ArvDomNode* self)
344 {
345 	ArvDomNode *parent;
346 
347 	g_return_val_if_fail (ARV_IS_DOM_NODE (self), NULL);
348 
349 	for (parent = self;
350 	     parent != NULL &&
351 	     !ARV_IS_DOM_DOCUMENT (parent);
352 	     parent = parent->parent_node);
353 
354 	return ARV_DOM_DOCUMENT (parent);
355 }
356 
357 /**
358  * arv_dom_node_insert_before:
359  * @self: a #ArvDomNode
360  * @new_child: (transfer full): node to insert
361  * @ref_child: (transfer none): reference node, i.e., the node before which the new node must be inserted.
362  *
363  * Inserts the node @new_child before the existing child node @ref_child. If
364  * @ref_child is null, insert @new_child at the end of the list of children.
365  * If the @new_child is already in the tree, it is first removed.
366  *
367  * Returns: (transfer none): the inserted node.
368  */
369 
370 /* TODO:
371  * If @new_child is a #LsmDocumentFragment object, all of its children are inserted,
372  * in the same order, before @ref_child.
373  * Check if new_child is an ancestor of self.
374  */
375 
376 ArvDomNode*
arv_dom_node_insert_before(ArvDomNode * self,ArvDomNode * new_child,ArvDomNode * ref_child)377 arv_dom_node_insert_before (ArvDomNode* self, ArvDomNode* new_child, ArvDomNode* ref_child)
378 {
379 	ArvDomNodeClass *node_class;
380 
381 	if (ref_child == NULL)
382 		arv_dom_node_append_child (self, new_child);
383 
384 	g_return_val_if_fail (ARV_IS_DOM_NODE (new_child), NULL);
385 
386 	if (new_child->parent_node != NULL)
387 		arv_dom_node_remove_child (self, new_child);
388 
389 	if (!ARV_IS_DOM_NODE (self)) {
390 		g_critical ("%s: self is not a ArvDomNode", G_STRFUNC);
391 		g_object_unref (new_child);
392 		return NULL;
393 	}
394 
395 	if (!ARV_IS_DOM_NODE (ref_child)) {
396 		g_critical ("%s: ref_child is not a ArvDomNode", G_STRFUNC);
397 		g_object_unref (new_child);
398 		return NULL;
399 	}
400 
401 	if (ref_child->parent_node != self) {
402 		arv_debug_dom ("[ArvDomNode::insert_before] Ref child '%s' doesn't belong to '%s'",
403 			   arv_dom_node_get_node_name (ref_child),
404 			   arv_dom_node_get_node_name (self));
405 		g_object_unref (new_child);
406 		return NULL;
407 	}
408 
409 	if (!ARV_DOM_NODE_GET_CLASS (self)->can_append_child (self, new_child)) {
410 		arv_log_dom ("[ArvDomNode::insert_before] Can't append '%s' to '%s'",
411 			   arv_dom_node_get_node_name (new_child),
412 			   arv_dom_node_get_node_name (self));
413 		g_object_unref (new_child);
414 		return NULL;
415 	}
416 
417 	new_child->parent_node = self;
418 	new_child->next_sibling = ref_child;
419 	new_child->previous_sibling = ref_child->previous_sibling;
420 
421 	if (ref_child->previous_sibling == NULL)
422 		self->first_child = new_child;
423 	else
424 		ref_child->previous_sibling->next_sibling = new_child;
425 
426 	ref_child->previous_sibling = new_child;
427 
428 	node_class = ARV_DOM_NODE_GET_CLASS (self);
429 
430 	if (node_class->post_new_child)
431 		node_class->post_new_child (self, new_child);
432 
433 	arv_dom_node_changed (self);
434 
435 	return new_child;
436 }
437 
438 /**
439  * arv_dom_node_replace_child:
440  * @self: a #ArvDomNode
441  * @new_child: (transfer full): a replacement node
442  * @old_child: (transfer none): node to replace
443  *
444  * Replaces the child node @old_child with @new_child in the list of children,
445  * and returns the @old_child node.
446  * If the @new_child is already in the tree, it is first removed.
447  *
448  * Returns: (transfer full): the replaced node.
449  */
450 
451 /* TODO:
452  * Check if new_child is an ancestor of self.
453  */
454 
455 ArvDomNode*
arv_dom_node_replace_child(ArvDomNode * self,ArvDomNode * new_child,ArvDomNode * old_child)456 arv_dom_node_replace_child (ArvDomNode* self, ArvDomNode* new_child, ArvDomNode* old_child)
457 {
458 	ArvDomNode *next_sibling;
459 	ArvDomNode *node;
460 
461 	if (new_child == NULL)
462 		return arv_dom_node_remove_child (self, old_child);
463 
464 	if (!ARV_IS_DOM_NODE (new_child)) {
465 		g_critical ("%s: new_child is not a ArvDomNode", G_STRFUNC);
466 		if (ARV_IS_DOM_NODE (old_child))
467 			g_object_unref (old_child);
468 		return NULL;
469 	}
470 
471 	if (new_child->parent_node != NULL)
472 		arv_dom_node_remove_child (self, new_child);
473 
474 	if (old_child == NULL) {
475 		arv_debug_dom ("[ArvDomNode::replace_child] old_child == NULL)");
476 		g_object_unref (new_child);
477 		return NULL;
478 	}
479 
480 	if (!ARV_IS_DOM_NODE (old_child)) {
481 		g_critical ("%s: old_child is not a ArvDomNode", G_STRFUNC);
482 		g_object_unref (new_child);
483 		return NULL;
484 	}
485 
486 	if (!ARV_IS_DOM_NODE (self)) {
487 		g_critical ("%s: self is not a ArvDomNode", G_STRFUNC);
488 		g_object_unref (new_child);
489 		g_object_unref (old_child);
490 		return NULL;
491 	}
492 
493 	if (old_child->parent_node != self) {
494 		g_object_unref (new_child);
495 		g_object_unref (old_child);
496 		return NULL;
497 	}
498 
499 	next_sibling = old_child->next_sibling;
500 
501 	node = arv_dom_node_remove_child (self, old_child);
502 	if (node != old_child) {
503 		g_object_unref (new_child);
504 		g_object_unref (old_child);
505 		return NULL;
506 	}
507 
508 	if (next_sibling == NULL)
509 		arv_dom_node_append_child (self, new_child);
510 	else
511 		arv_dom_node_insert_before (self, new_child, next_sibling);
512 
513 	return old_child;
514 }
515 
516 /**
517  * arv_dom_node_remove_child:
518  * @self: a #ArvDomNode
519  * @old_child: (transfer none): node to remove.
520  *
521  * Removes the child node indicated by @old_child from the list of children, and returns it.
522  *
523  * Returns: (transfer full): the removed node.
524  */
525 
526 ArvDomNode*
arv_dom_node_remove_child(ArvDomNode * self,ArvDomNode * old_child)527 arv_dom_node_remove_child (ArvDomNode* self, ArvDomNode* old_child)
528 {
529 	ArvDomNode *node;
530 	ArvDomNodeClass *node_class;
531 
532 	g_return_val_if_fail (ARV_IS_DOM_NODE (self), NULL);
533 
534 	if (old_child == NULL)
535 		return NULL;
536 
537 	g_return_val_if_fail (ARV_IS_DOM_NODE (old_child), NULL);
538 
539 	for (node = self->first_child;
540 	     node != NULL && node != old_child;
541 	     node = node->next_sibling);
542 
543 	if (node == NULL)
544 		return NULL;
545 
546 	node_class = ARV_DOM_NODE_GET_CLASS (self);
547 
548 	if (node_class->pre_remove_child)
549 		node_class->pre_remove_child (self, old_child);
550 
551 	if (self->first_child == old_child)
552 		self->first_child = old_child->next_sibling;
553 	if (self->last_child == old_child)
554 		self->last_child = old_child->previous_sibling;
555 
556 	if (old_child->next_sibling != NULL)
557 		old_child->next_sibling->previous_sibling = old_child->previous_sibling;
558 	if (old_child->previous_sibling != NULL)
559 		old_child->previous_sibling->next_sibling = old_child->next_sibling;
560 
561 	old_child->parent_node = NULL;
562 	old_child->next_sibling = NULL;
563 	old_child->previous_sibling = NULL;
564 
565 	arv_dom_node_changed (self);
566 
567 	return old_child;
568 }
569 
570 /**
571  * arv_dom_node_append_child:
572  * @self: a #ArvDomNode
573  * @new_child: (transfer full): node to append
574  *
575  * Adds the node @new_child to the end of the list of children of this node.
576  * If the @new_child is already in the tree, it is first removed.
577  *
578  * Returns: (transfer none): the added node.
579  */
580 
581 ArvDomNode *
arv_dom_node_append_child(ArvDomNode * self,ArvDomNode * new_child)582 arv_dom_node_append_child (ArvDomNode* self, ArvDomNode* new_child)
583 {
584 	ArvDomNodeClass *node_class;
585 
586 	if (new_child == NULL)
587 		return NULL;
588 
589 	g_return_val_if_fail (ARV_IS_DOM_NODE (new_child), NULL);
590 
591 	if (!ARV_IS_DOM_NODE (self)) {
592 		g_critical ("%s: self is not a ArvDomNode", G_STRFUNC);
593 		g_object_unref (new_child);
594 		return NULL;
595 	}
596 
597 	if (new_child->parent_node != NULL)
598 		arv_dom_node_remove_child (self, new_child);
599 
600 	if (!ARV_DOM_NODE_GET_CLASS (self)->can_append_child (self, new_child)) {
601 		arv_log_dom ("[ArvDomNode::append_child] Can't append '%s' to '%s'",
602 			       arv_dom_node_get_node_name (new_child),
603 			       arv_dom_node_get_node_name (self));
604 		g_object_unref (new_child);
605 		return NULL;
606 	}
607 
608 	if (self->first_child == NULL)
609 		self->first_child = new_child;
610 	if (self->last_child != NULL)
611 		self->last_child->next_sibling = new_child;
612 
613 	new_child->parent_node = self;
614 	new_child->next_sibling = NULL;
615 	new_child->previous_sibling = self->last_child;
616 	self->last_child = new_child;
617 
618 	node_class = ARV_DOM_NODE_GET_CLASS (self);
619 
620 	if (node_class->post_new_child)
621 		node_class->post_new_child (self, new_child);
622 
623 	arv_dom_node_changed (self);
624 
625 	return new_child;
626 }
627 
628 static gboolean
arv_dom_node_can_append_child_default(ArvDomNode * self,ArvDomNode * new_child)629 arv_dom_node_can_append_child_default (ArvDomNode *self, ArvDomNode* new_child)
630 {
631 	return FALSE;
632 }
633 
634 void
arv_dom_node_changed(ArvDomNode * self)635 arv_dom_node_changed (ArvDomNode *self)
636 {
637 	ArvDomNode *parent_node;
638 	ArvDomNode *child_node;
639 	ArvDomNodeClass *node_class;
640 
641 	g_return_if_fail (ARV_IS_DOM_NODE (self));
642 
643 	node_class = ARV_DOM_NODE_GET_CLASS (self);
644 
645 	if (node_class->changed)
646 		node_class->changed (self);
647 
648 	child_node = self;
649 	for (parent_node = self->parent_node;
650 	       parent_node != NULL;
651 	       parent_node = parent_node->parent_node) {
652 		node_class = ARV_DOM_NODE_GET_CLASS (parent_node);
653 		if (node_class->child_changed == NULL ||
654 		    !node_class->child_changed (parent_node, child_node))
655 			break;
656 		child_node = parent_node;
657 	}
658 }
659 
660 gboolean
arv_dom_node_has_child_nodes(ArvDomNode * self)661 arv_dom_node_has_child_nodes (ArvDomNode* self)
662 {
663 	g_return_val_if_fail (ARV_IS_DOM_NODE (self), FALSE);
664 
665 	return self->first_child != NULL;
666 }
667 
668 static void
arv_dom_node_write_to_stream_default(ArvDomNode * self,GOutputStream * stream,GError ** error)669 arv_dom_node_write_to_stream_default (ArvDomNode *self, GOutputStream *stream, GError **error)
670 {
671 	ArvDomNode *child;
672 
673 	for (child = self->first_child; child != NULL; child = child->next_sibling)
674 		arv_dom_node_write_to_stream (child, stream, error);
675 }
676 
677 void
arv_dom_node_write_to_stream(ArvDomNode * self,GOutputStream * stream,GError ** error)678 arv_dom_node_write_to_stream (ArvDomNode *self, GOutputStream *stream, GError **error)
679 {
680 	ArvDomNodeClass *node_class;
681 
682 	g_return_if_fail (ARV_IS_DOM_NODE (self));
683 	g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
684 
685 	node_class = ARV_DOM_NODE_GET_CLASS (self);
686 	if (node_class->write_to_stream != NULL)
687 		node_class->write_to_stream (self, stream, error);
688 }
689 
690 static void
arv_dom_node_init(ArvDomNode * node)691 arv_dom_node_init (ArvDomNode *node)
692 {
693 }
694 
695 static void
arv_dom_node_finalize(GObject * object)696 arv_dom_node_finalize (GObject *object)
697 {
698 	ArvDomNode *node = ARV_DOM_NODE (object);
699 	ArvDomNode *child, *next_child;
700 
701 	child = node->first_child;
702 	while (child != NULL) {
703 		next_child = child->next_sibling;
704 		g_object_unref (child);
705 		child = next_child;
706 	}
707 
708 	parent_class->finalize (object);
709 }
710 
711 /* ArvDomNode class */
712 
713 static void
arv_dom_node_class_init(ArvDomNodeClass * node_class)714 arv_dom_node_class_init (ArvDomNodeClass *node_class)
715 {
716 	GObjectClass *object_class = G_OBJECT_CLASS (node_class);
717 
718 	parent_class = g_type_class_peek_parent (node_class);
719 
720 	object_class->finalize = arv_dom_node_finalize;
721 
722 	node_class->can_append_child = arv_dom_node_can_append_child_default;
723 	node_class->write_to_stream = arv_dom_node_write_to_stream_default;
724 }
725 
726 G_DEFINE_ABSTRACT_TYPE (ArvDomNode, arv_dom_node, G_TYPE_OBJECT)
727