Use the new GRealThread member "context" instead of a GStaticPrivate to
[platform/upstream/glib.git] / gnode.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * GNode: N-way tree implementation.
5  * Copyright (C) 1998 Tim Janik
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /*
24  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
25  * file for a list of people on the GLib Team.  See the ChangeLog
26  * files for a list of changes.  These files are distributed with
27  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
28  */
29
30 /* 
31  * MT safe
32  */
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 #include "glib.h"
39
40 #ifndef DISABLE_MEM_POOLS
41 /* node allocation
42  */
43 struct _GAllocator /* from gmem.c */
44 {
45   gchar         *name;
46   guint16        n_preallocs;
47   guint          is_unused : 1;
48   guint          type : 4;
49   GAllocator    *last;
50   GMemChunk     *mem_chunk;
51   GNode         *free_nodes; /* implementation specific */
52 };
53
54 G_LOCK_DEFINE_STATIC (current_allocator);
55 static GAllocator *current_allocator = NULL;
56
57 /* HOLDS: current_allocator_lock */
58 static void
59 g_node_validate_allocator (GAllocator *allocator)
60 {
61   g_return_if_fail (allocator != NULL);
62   g_return_if_fail (allocator->is_unused == TRUE);
63
64   if (allocator->type != G_ALLOCATOR_NODE)
65     {
66       allocator->type = G_ALLOCATOR_NODE;
67       if (allocator->mem_chunk)
68         {
69           g_mem_chunk_destroy (allocator->mem_chunk);
70           allocator->mem_chunk = NULL;
71         }
72     }
73
74   if (!allocator->mem_chunk)
75     {
76       allocator->mem_chunk = g_mem_chunk_new (allocator->name,
77                                               sizeof (GNode),
78                                               sizeof (GNode) * allocator->n_preallocs,
79                                               G_ALLOC_ONLY);
80       allocator->free_nodes = NULL;
81     }
82
83   allocator->is_unused = FALSE;
84 }
85
86 void
87 g_node_push_allocator (GAllocator *allocator)
88 {
89   G_LOCK (current_allocator);
90   g_node_validate_allocator (allocator);
91   allocator->last = current_allocator;
92   current_allocator = allocator;
93   G_UNLOCK (current_allocator);
94 }
95
96 void
97 g_node_pop_allocator (void)
98 {
99   G_LOCK (current_allocator);
100   if (current_allocator)
101     {
102       GAllocator *allocator;
103
104       allocator = current_allocator;
105       current_allocator = allocator->last;
106       allocator->last = NULL;
107       allocator->is_unused = TRUE;
108     }
109   G_UNLOCK (current_allocator);
110 }
111
112
113 /* --- functions --- */
114 GNode*
115 g_node_new (gpointer data)
116 {
117   GNode *node;
118
119   G_LOCK (current_allocator);
120   if (!current_allocator)
121     {
122        GAllocator *allocator = g_allocator_new ("GLib default GNode allocator",
123                                                 128);
124        g_node_validate_allocator (allocator);
125        allocator->last = NULL;
126        current_allocator = allocator;
127     }
128   if (!current_allocator->free_nodes)
129     node = g_chunk_new (GNode, current_allocator->mem_chunk);
130   else
131     {
132       node = current_allocator->free_nodes;
133       current_allocator->free_nodes = node->next;
134     }
135   G_UNLOCK (current_allocator);
136   
137   node->data = data;
138   node->next = NULL;
139   node->prev = NULL;
140   node->parent = NULL;
141   node->children = NULL;
142   
143   return node;
144 }
145
146 static void
147 g_nodes_free (GNode *node)
148 {
149   GNode *parent;
150
151   parent = node;
152   while (1)
153     {
154       if (parent->children)
155         g_nodes_free (parent->children);
156
157 #ifdef ENABLE_GC_FRIENDLY
158       parent->data = NULL;
159       parent->prev = NULL;
160       parent->parent = NULL;
161       parent->children = NULL;
162 #endif /* ENABLE_GC_FRIENDLY */
163
164       if (parent->next)
165         parent = parent->next;
166       else
167         break;
168     }
169   
170   G_LOCK (current_allocator);
171   parent->next = current_allocator->free_nodes;
172   current_allocator->free_nodes = node;
173   G_UNLOCK (current_allocator);
174 }
175 #else /* DISABLE_MEM_POOLS */
176
177 GNode*
178 g_node_new (gpointer data)
179 {
180   GNode *node;
181
182   node = g_new0 (GNode, 1);
183   
184   node->data = data;
185   
186   return node;
187 }
188
189 static void
190 g_nodes_free (GNode *root)
191 {
192   GNode *node, *next;
193   
194   node = root;
195   while (node != NULL)
196     {
197       next = node->next;
198       g_nodes_free (node->children);
199       g_free (node);
200       node = next;
201     }
202 }
203 #endif
204
205 void
206 g_node_destroy (GNode *root)
207 {
208   g_return_if_fail (root != NULL);
209   
210   if (!G_NODE_IS_ROOT (root))
211     g_node_unlink (root);
212   
213   g_nodes_free (root);
214 }
215
216 void
217 g_node_unlink (GNode *node)
218 {
219   g_return_if_fail (node != NULL);
220   
221   if (node->prev)
222     node->prev->next = node->next;
223   else if (node->parent)
224     node->parent->children = node->next;
225   node->parent = NULL;
226   if (node->next)
227     {
228       node->next->prev = node->prev;
229       node->next = NULL;
230     }
231   node->prev = NULL;
232 }
233
234 GNode*
235 g_node_copy (GNode *node)
236 {
237   GNode *new_node = NULL;
238   
239   if (node)
240     {
241       GNode *child;
242       
243       new_node = g_node_new (node->data);
244       
245       for (child = g_node_last_child (node); child; child = child->prev)
246         g_node_prepend (new_node, g_node_copy (child));
247     }
248   
249   return new_node;
250 }
251
252 GNode*
253 g_node_insert (GNode *parent,
254                gint   position,
255                GNode *node)
256 {
257   g_return_val_if_fail (parent != NULL, node);
258   g_return_val_if_fail (node != NULL, node);
259   g_return_val_if_fail (G_NODE_IS_ROOT (node), node);
260   
261   if (position > 0)
262     return g_node_insert_before (parent,
263                                  g_node_nth_child (parent, position),
264                                  node);
265   else if (position == 0)
266     return g_node_prepend (parent, node);
267   else /* if (position < 0) */
268     return g_node_append (parent, node);
269 }
270
271 GNode*
272 g_node_insert_before (GNode *parent,
273                       GNode *sibling,
274                       GNode *node)
275 {
276   g_return_val_if_fail (parent != NULL, node);
277   g_return_val_if_fail (node != NULL, node);
278   g_return_val_if_fail (G_NODE_IS_ROOT (node), node);
279   if (sibling)
280     g_return_val_if_fail (sibling->parent == parent, node);
281   
282   node->parent = parent;
283   
284   if (sibling)
285     {
286       if (sibling->prev)
287         {
288           node->prev = sibling->prev;
289           node->prev->next = node;
290           node->next = sibling;
291           sibling->prev = node;
292         }
293       else
294         {
295           node->parent->children = node;
296           node->next = sibling;
297           sibling->prev = node;
298         }
299     }
300   else
301     {
302       if (parent->children)
303         {
304           sibling = parent->children;
305           while (sibling->next)
306             sibling = sibling->next;
307           node->prev = sibling;
308           sibling->next = node;
309         }
310       else
311         node->parent->children = node;
312     }
313
314   return node;
315 }
316
317 GNode*
318 g_node_insert_after (GNode *parent,
319                      GNode *sibling,
320                      GNode *node)
321 {
322   g_return_val_if_fail (parent != NULL, node);
323   g_return_val_if_fail (node != NULL, node);
324   g_return_val_if_fail (G_NODE_IS_ROOT (node), node);
325   if (sibling)
326     g_return_val_if_fail (sibling->parent == parent, node);
327
328   node->parent = parent;
329
330   if (sibling)
331     {
332       if (sibling->next)
333         {
334           sibling->next->prev = node;
335         }
336       node->next = sibling->next;
337       node->prev = sibling;
338       sibling->next = node;
339     }
340   else
341     {
342       if (parent->children)
343         {
344           node->next = parent->children;
345           parent->children->prev = node;
346         }
347       parent->children = node;
348     }
349
350   return node;
351 }
352
353 GNode*
354 g_node_prepend (GNode *parent,
355                 GNode *node)
356 {
357   g_return_val_if_fail (parent != NULL, node);
358   
359   return g_node_insert_before (parent, parent->children, node);
360 }
361
362 GNode*
363 g_node_get_root (GNode *node)
364 {
365   g_return_val_if_fail (node != NULL, NULL);
366   
367   while (node->parent)
368     node = node->parent;
369   
370   return node;
371 }
372
373 gboolean
374 g_node_is_ancestor (GNode *node,
375                     GNode *descendant)
376 {
377   g_return_val_if_fail (node != NULL, FALSE);
378   g_return_val_if_fail (descendant != NULL, FALSE);
379   
380   while (descendant)
381     {
382       if (descendant->parent == node)
383         return TRUE;
384       
385       descendant = descendant->parent;
386     }
387   
388   return FALSE;
389 }
390
391 /* returns 1 for root, 2 for first level children,
392  * 3 for children's children...
393  */
394 guint
395 g_node_depth (GNode *node)
396 {
397   register guint depth = 0;
398   
399   while (node)
400     {
401       depth++;
402       node = node->parent;
403     }
404   
405   return depth;
406 }
407
408 void
409 g_node_reverse_children (GNode *node)
410 {
411   GNode *child;
412   GNode *last;
413   
414   g_return_if_fail (node != NULL);
415   
416   child = node->children;
417   last = NULL;
418   while (child)
419     {
420       last = child;
421       child = last->next;
422       last->next = last->prev;
423       last->prev = child;
424     }
425   node->children = last;
426 }
427
428 guint
429 g_node_max_height (GNode *root)
430 {
431   register GNode *child;
432   register guint max_height = 0;
433   
434   if (!root)
435     return 0;
436   
437   child = root->children;
438   while (child)
439     {
440       register guint tmp_height;
441       
442       tmp_height = g_node_max_height (child);
443       if (tmp_height > max_height)
444         max_height = tmp_height;
445       child = child->next;
446     }
447   
448   return max_height + 1;
449 }
450
451 static gboolean
452 g_node_traverse_pre_order (GNode            *node,
453                            GTraverseFlags    flags,
454                            GNodeTraverseFunc func,
455                            gpointer          data)
456 {
457   if (node->children)
458     {
459       GNode *child;
460       
461       if ((flags & G_TRAVERSE_NON_LEAFS) &&
462           func (node, data))
463         return TRUE;
464       
465       child = node->children;
466       while (child)
467         {
468           register GNode *current;
469           
470           current = child;
471           child = current->next;
472           if (g_node_traverse_pre_order (current, flags, func, data))
473             return TRUE;
474         }
475     }
476   else if ((flags & G_TRAVERSE_LEAFS) &&
477            func (node, data))
478     return TRUE;
479   
480   return FALSE;
481 }
482
483 static gboolean
484 g_node_depth_traverse_pre_order (GNode            *node,
485                                  GTraverseFlags    flags,
486                                  guint             depth,
487                                  GNodeTraverseFunc func,
488                                  gpointer          data)
489 {
490   if (node->children)
491     {
492       GNode *child;
493       
494       if ((flags & G_TRAVERSE_NON_LEAFS) &&
495           func (node, data))
496         return TRUE;
497       
498       depth--;
499       if (!depth)
500         return FALSE;
501       
502       child = node->children;
503       while (child)
504         {
505           register GNode *current;
506           
507           current = child;
508           child = current->next;
509           if (g_node_depth_traverse_pre_order (current, flags, depth, func, data))
510             return TRUE;
511         }
512     }
513   else if ((flags & G_TRAVERSE_LEAFS) &&
514            func (node, data))
515     return TRUE;
516   
517   return FALSE;
518 }
519
520 static gboolean
521 g_node_traverse_post_order (GNode            *node,
522                             GTraverseFlags    flags,
523                             GNodeTraverseFunc func,
524                             gpointer          data)
525 {
526   if (node->children)
527     {
528       GNode *child;
529       
530       child = node->children;
531       while (child)
532         {
533           register GNode *current;
534           
535           current = child;
536           child = current->next;
537           if (g_node_traverse_post_order (current, flags, func, data))
538             return TRUE;
539         }
540       
541       if ((flags & G_TRAVERSE_NON_LEAFS) &&
542           func (node, data))
543         return TRUE;
544       
545     }
546   else if ((flags & G_TRAVERSE_LEAFS) &&
547            func (node, data))
548     return TRUE;
549   
550   return FALSE;
551 }
552
553 static gboolean
554 g_node_depth_traverse_post_order (GNode            *node,
555                                   GTraverseFlags    flags,
556                                   guint             depth,
557                                   GNodeTraverseFunc func,
558                                   gpointer          data)
559 {
560   if (node->children)
561     {
562       depth--;
563       if (depth)
564         {
565           GNode *child;
566           
567           child = node->children;
568           while (child)
569             {
570               register GNode *current;
571               
572               current = child;
573               child = current->next;
574               if (g_node_depth_traverse_post_order (current, flags, depth, func, data))
575                 return TRUE;
576             }
577         }
578       
579       if ((flags & G_TRAVERSE_NON_LEAFS) &&
580           func (node, data))
581         return TRUE;
582       
583     }
584   else if ((flags & G_TRAVERSE_LEAFS) &&
585            func (node, data))
586     return TRUE;
587   
588   return FALSE;
589 }
590
591 static gboolean
592 g_node_traverse_in_order (GNode            *node,
593                           GTraverseFlags    flags,
594                           GNodeTraverseFunc func,
595                           gpointer          data)
596 {
597   if (node->children)
598     {
599       GNode *child;
600       register GNode *current;
601       
602       child = node->children;
603       current = child;
604       child = current->next;
605       
606       if (g_node_traverse_in_order (current, flags, func, data))
607         return TRUE;
608       
609       if ((flags & G_TRAVERSE_NON_LEAFS) &&
610           func (node, data))
611         return TRUE;
612       
613       while (child)
614         {
615           current = child;
616           child = current->next;
617           if (g_node_traverse_in_order (current, flags, func, data))
618             return TRUE;
619         }
620     }
621   else if ((flags & G_TRAVERSE_LEAFS) &&
622            func (node, data))
623     return TRUE;
624   
625   return FALSE;
626 }
627
628 static gboolean
629 g_node_depth_traverse_in_order (GNode            *node,
630                                 GTraverseFlags    flags,
631                                 guint             depth,
632                                 GNodeTraverseFunc func,
633                                 gpointer          data)
634 {
635   if (node->children)
636     {
637       depth--;
638       if (depth)
639         {
640           GNode *child;
641           register GNode *current;
642           
643           child = node->children;
644           current = child;
645           child = current->next;
646           
647           if (g_node_depth_traverse_in_order (current, flags, depth, func, data))
648             return TRUE;
649           
650           if ((flags & G_TRAVERSE_NON_LEAFS) &&
651               func (node, data))
652             return TRUE;
653           
654           while (child)
655             {
656               current = child;
657               child = current->next;
658               if (g_node_depth_traverse_in_order (current, flags, depth, func, data))
659                 return TRUE;
660             }
661         }
662       else if ((flags & G_TRAVERSE_NON_LEAFS) &&
663                func (node, data))
664         return TRUE;
665     }
666   else if ((flags & G_TRAVERSE_LEAFS) &&
667            func (node, data))
668     return TRUE;
669   
670   return FALSE;
671 }
672
673 static gboolean
674 g_node_traverse_children (GNode             *node,
675                           GTraverseFlags     flags,
676                           GNodeTraverseFunc  func,
677                           gpointer           data)
678 {
679   GNode *child;
680   
681   child = node->children;
682   
683   while (child)
684     {
685       register GNode *current;
686       
687       current = child;
688       child = current->next;
689       
690       if (current->children)
691         {
692           if ((flags & G_TRAVERSE_NON_LEAFS) &&
693               func (current, data))
694             return TRUE;
695         }
696       else if ((flags & G_TRAVERSE_LEAFS) &&
697                func (current, data))
698         return TRUE;
699     }
700   
701   child = node->children;
702   
703   while (child)
704     {
705       register GNode *current;
706       
707       current = child;
708       child = current->next;
709       
710       if (current->children &&
711           g_node_traverse_children (current, flags, func, data))
712         return TRUE;
713     }
714   
715   return FALSE;
716 }
717
718 static gboolean
719 g_node_depth_traverse_children (GNode            *node,
720                                 GTraverseFlags    flags,
721                                 guint             depth,
722                                 GNodeTraverseFunc func,
723                                 gpointer          data)
724 {
725   GNode *child;
726   
727   child = node->children;
728   
729   while (child)
730     {
731       register GNode *current;
732       
733       current = child;
734       child = current->next;
735       
736       if (current->children)
737         {
738           if ((flags & G_TRAVERSE_NON_LEAFS) &&
739               func (current, data))
740             return TRUE;
741         }
742       else if ((flags & G_TRAVERSE_LEAFS) &&
743                func (current, data))
744         return TRUE;
745     }
746   
747   depth--;
748   if (!depth)
749     return FALSE;
750   
751   child = node->children;
752   
753   while (child)
754     {
755       register GNode *current;
756       
757       current = child;
758       child = current->next;
759       
760       if (current->children &&
761           g_node_depth_traverse_children (current, flags, depth, func, data))
762         return TRUE;
763     }
764   
765   return FALSE;
766 }
767
768 void
769 g_node_traverse (GNode            *root,
770                  GTraverseType     order,
771                  GTraverseFlags    flags,
772                  gint              depth,
773                  GNodeTraverseFunc func,
774                  gpointer          data)
775 {
776   g_return_if_fail (root != NULL);
777   g_return_if_fail (func != NULL);
778   g_return_if_fail (order <= G_LEVEL_ORDER);
779   g_return_if_fail (flags <= G_TRAVERSE_MASK);
780   g_return_if_fail (depth == -1 || depth > 0);
781   
782   switch (order)
783     {
784     case G_PRE_ORDER:
785       if (depth < 0)
786         g_node_traverse_pre_order (root, flags, func, data);
787       else
788         g_node_depth_traverse_pre_order (root, flags, depth, func, data);
789       break;
790     case G_POST_ORDER:
791       if (depth < 0)
792         g_node_traverse_post_order (root, flags, func, data);
793       else
794         g_node_depth_traverse_post_order (root, flags, depth, func, data);
795       break;
796     case G_IN_ORDER:
797       if (depth < 0)
798         g_node_traverse_in_order (root, flags, func, data);
799       else
800         g_node_depth_traverse_in_order (root, flags, depth, func, data);
801       break;
802     case G_LEVEL_ORDER:
803       if (root->children)
804         {
805           if (!((flags & G_TRAVERSE_NON_LEAFS) &&
806                 func (root, data)))
807             {
808               if (depth < 0)
809                 g_node_traverse_children (root, flags, func, data);
810               else
811                 {
812                   depth--;
813                   if (depth)
814                     g_node_depth_traverse_children (root, flags, depth, func, data);
815                 }
816             }
817         }
818       else if (flags & G_TRAVERSE_LEAFS)
819         func (root, data);
820       break;
821     }
822 }
823
824 static gboolean
825 g_node_find_func (GNode   *node,
826                   gpointer data)
827 {
828   register gpointer *d = data;
829   
830   if (*d != node->data)
831     return FALSE;
832   
833   *(++d) = node;
834   
835   return TRUE;
836 }
837
838 GNode*
839 g_node_find (GNode             *root,
840              GTraverseType      order,
841              GTraverseFlags     flags,
842              gpointer           data)
843 {
844   gpointer d[2];
845   
846   g_return_val_if_fail (root != NULL, NULL);
847   g_return_val_if_fail (order <= G_LEVEL_ORDER, NULL);
848   g_return_val_if_fail (flags <= G_TRAVERSE_MASK, NULL);
849   
850   d[0] = data;
851   d[1] = NULL;
852   
853   g_node_traverse (root, order, flags, -1, g_node_find_func, d);
854   
855   return d[1];
856 }
857
858 static void
859 g_node_count_func (GNode         *node,
860                    GTraverseFlags flags,
861                    guint         *n)
862 {
863   if (node->children)
864     {
865       GNode *child;
866       
867       if (flags & G_TRAVERSE_NON_LEAFS)
868         (*n)++;
869       
870       child = node->children;
871       while (child)
872         {
873           g_node_count_func (child, flags, n);
874           child = child->next;
875         }
876     }
877   else if (flags & G_TRAVERSE_LEAFS)
878     (*n)++;
879 }
880
881 guint
882 g_node_n_nodes (GNode         *root,
883                 GTraverseFlags flags)
884 {
885   guint n = 0;
886   
887   g_return_val_if_fail (root != NULL, 0);
888   g_return_val_if_fail (flags <= G_TRAVERSE_MASK, 0);
889   
890   g_node_count_func (root, flags, &n);
891   
892   return n;
893 }
894
895 GNode*
896 g_node_last_child (GNode *node)
897 {
898   g_return_val_if_fail (node != NULL, NULL);
899   
900   node = node->children;
901   if (node)
902     while (node->next)
903       node = node->next;
904   
905   return node;
906 }
907
908 GNode*
909 g_node_nth_child (GNode *node,
910                   guint  n)
911 {
912   g_return_val_if_fail (node != NULL, NULL);
913   
914   node = node->children;
915   if (node)
916     while ((n-- > 0) && node)
917       node = node->next;
918   
919   return node;
920 }
921
922 guint
923 g_node_n_children (GNode *node)
924 {
925   guint n = 0;
926   
927   g_return_val_if_fail (node != NULL, 0);
928   
929   node = node->children;
930   while (node)
931     {
932       n++;
933       node = node->next;
934     }
935   
936   return n;
937 }
938
939 GNode*
940 g_node_find_child (GNode         *node,
941                    GTraverseFlags flags,
942                    gpointer       data)
943 {
944   g_return_val_if_fail (node != NULL, NULL);
945   g_return_val_if_fail (flags <= G_TRAVERSE_MASK, NULL);
946   
947   node = node->children;
948   while (node)
949     {
950       if (node->data == data)
951         {
952           if (G_NODE_IS_LEAF (node))
953             {
954               if (flags & G_TRAVERSE_LEAFS)
955                 return node;
956             }
957           else
958             {
959               if (flags & G_TRAVERSE_NON_LEAFS)
960                 return node;
961             }
962         }
963       node = node->next;
964     }
965   
966   return NULL;
967 }
968
969 gint
970 g_node_child_position (GNode *node,
971                        GNode *child)
972 {
973   register guint n = 0;
974   
975   g_return_val_if_fail (node != NULL, -1);
976   g_return_val_if_fail (child != NULL, -1);
977   g_return_val_if_fail (child->parent == node, -1);
978   
979   node = node->children;
980   while (node)
981     {
982       if (node == child)
983         return n;
984       n++;
985       node = node->next;
986     }
987   
988   return -1;
989 }
990
991 gint
992 g_node_child_index (GNode   *node,
993                     gpointer data)
994 {
995   register guint n = 0;
996   
997   g_return_val_if_fail (node != NULL, -1);
998   
999   node = node->children;
1000   while (node)
1001     {
1002       if (node->data == data)
1003         return n;
1004       n++;
1005       node = node->next;
1006     }
1007   
1008   return -1;
1009 }
1010
1011 GNode*
1012 g_node_first_sibling (GNode *node)
1013 {
1014   g_return_val_if_fail (node != NULL, NULL);
1015   
1016   if (node->parent)
1017     return node->parent->children;
1018   
1019   while (node->prev)
1020     node = node->prev;
1021   
1022   return node;
1023 }
1024
1025 GNode*
1026 g_node_last_sibling (GNode *node)
1027 {
1028   g_return_val_if_fail (node != NULL, NULL);
1029   
1030   while (node->next)
1031     node = node->next;
1032   
1033   return node;
1034 }
1035
1036 void
1037 g_node_children_foreach (GNode           *node,
1038                          GTraverseFlags   flags,
1039                          GNodeForeachFunc func,
1040                          gpointer         data)
1041 {
1042   g_return_if_fail (node != NULL);
1043   g_return_if_fail (flags <= G_TRAVERSE_MASK);
1044   g_return_if_fail (func != NULL);
1045   
1046   node = node->children;
1047   while (node)
1048     {
1049       register GNode *current;
1050       
1051       current = node;
1052       node = current->next;
1053       if (G_NODE_IS_LEAF (current))
1054         {
1055           if (flags & G_TRAVERSE_LEAFS)
1056             func (current, data);
1057         }
1058       else
1059         {
1060           if (flags & G_TRAVERSE_NON_LEAFS)
1061             func (current, data);
1062         }
1063     }
1064 }