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