Use <envar>, not <envvar>.
[platform/upstream/glib.git] / glib / 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_level (GNode             *node,
675                        GTraverseFlags     flags,
676                        guint              level,
677                        GNodeTraverseFunc func,
678                        gpointer   data,
679                        gboolean         *more_levels)
680 {
681   if (level == 0) 
682     {
683       if (node->children)
684         {
685           *more_levels = TRUE;
686           return (flags & G_TRAVERSE_NON_LEAFS) && func (node, data);
687         }
688       else
689         {
690           return (flags & G_TRAVERSE_LEAFS) && func (node, data);
691         }
692     }
693   else 
694     {
695       node = node->children;
696       
697       while (node)
698         {
699           if (g_node_traverse_level (node, flags, level - 1, func, data, more_levels))
700             return TRUE;
701
702           node = node->next;
703         }
704     }
705
706   return FALSE;
707 }
708
709 static gboolean
710 g_node_depth_traverse_level (GNode               *node,
711                              GTraverseFlags       flags,
712                              guint                depth,
713                              GNodeTraverseFunc func,
714                              gpointer     data)
715 {
716   gint level;
717   gboolean more_levels;
718
719   level = 0;  
720   while (level != depth) 
721     {
722       more_levels = FALSE;
723       if (g_node_traverse_level (node, flags, level, func, data, &more_levels))
724         return TRUE;
725       if (!more_levels)
726         break;
727       level++;
728     }
729   return FALSE;
730 }
731
732 void
733 g_node_traverse (GNode            *root,
734                  GTraverseType     order,
735                  GTraverseFlags    flags,
736                  gint              depth,
737                  GNodeTraverseFunc func,
738                  gpointer          data)
739 {
740   g_return_if_fail (root != NULL);
741   g_return_if_fail (func != NULL);
742   g_return_if_fail (order <= G_LEVEL_ORDER);
743   g_return_if_fail (flags <= G_TRAVERSE_MASK);
744   g_return_if_fail (depth == -1 || depth > 0);
745   
746   switch (order)
747     {
748     case G_PRE_ORDER:
749       if (depth < 0)
750         g_node_traverse_pre_order (root, flags, func, data);
751       else
752         g_node_depth_traverse_pre_order (root, flags, depth, func, data);
753       break;
754     case G_POST_ORDER:
755       if (depth < 0)
756         g_node_traverse_post_order (root, flags, func, data);
757       else
758         g_node_depth_traverse_post_order (root, flags, depth, func, data);
759       break;
760     case G_IN_ORDER:
761       if (depth < 0)
762         g_node_traverse_in_order (root, flags, func, data);
763       else
764         g_node_depth_traverse_in_order (root, flags, depth, func, data);
765       break;
766     case G_LEVEL_ORDER:
767       g_node_depth_traverse_level (root, flags, depth, func, data);
768       break;
769     }
770 }
771
772 static gboolean
773 g_node_find_func (GNode   *node,
774                   gpointer data)
775 {
776   register gpointer *d = data;
777   
778   if (*d != node->data)
779     return FALSE;
780   
781   *(++d) = node;
782   
783   return TRUE;
784 }
785
786 GNode*
787 g_node_find (GNode             *root,
788              GTraverseType      order,
789              GTraverseFlags     flags,
790              gpointer           data)
791 {
792   gpointer d[2];
793   
794   g_return_val_if_fail (root != NULL, NULL);
795   g_return_val_if_fail (order <= G_LEVEL_ORDER, NULL);
796   g_return_val_if_fail (flags <= G_TRAVERSE_MASK, NULL);
797   
798   d[0] = data;
799   d[1] = NULL;
800   
801   g_node_traverse (root, order, flags, -1, g_node_find_func, d);
802   
803   return d[1];
804 }
805
806 static void
807 g_node_count_func (GNode         *node,
808                    GTraverseFlags flags,
809                    guint         *n)
810 {
811   if (node->children)
812     {
813       GNode *child;
814       
815       if (flags & G_TRAVERSE_NON_LEAFS)
816         (*n)++;
817       
818       child = node->children;
819       while (child)
820         {
821           g_node_count_func (child, flags, n);
822           child = child->next;
823         }
824     }
825   else if (flags & G_TRAVERSE_LEAFS)
826     (*n)++;
827 }
828
829 guint
830 g_node_n_nodes (GNode         *root,
831                 GTraverseFlags flags)
832 {
833   guint n = 0;
834   
835   g_return_val_if_fail (root != NULL, 0);
836   g_return_val_if_fail (flags <= G_TRAVERSE_MASK, 0);
837   
838   g_node_count_func (root, flags, &n);
839   
840   return n;
841 }
842
843 GNode*
844 g_node_last_child (GNode *node)
845 {
846   g_return_val_if_fail (node != NULL, NULL);
847   
848   node = node->children;
849   if (node)
850     while (node->next)
851       node = node->next;
852   
853   return node;
854 }
855
856 GNode*
857 g_node_nth_child (GNode *node,
858                   guint  n)
859 {
860   g_return_val_if_fail (node != NULL, NULL);
861   
862   node = node->children;
863   if (node)
864     while ((n-- > 0) && node)
865       node = node->next;
866   
867   return node;
868 }
869
870 guint
871 g_node_n_children (GNode *node)
872 {
873   guint n = 0;
874   
875   g_return_val_if_fail (node != NULL, 0);
876   
877   node = node->children;
878   while (node)
879     {
880       n++;
881       node = node->next;
882     }
883   
884   return n;
885 }
886
887 GNode*
888 g_node_find_child (GNode         *node,
889                    GTraverseFlags flags,
890                    gpointer       data)
891 {
892   g_return_val_if_fail (node != NULL, NULL);
893   g_return_val_if_fail (flags <= G_TRAVERSE_MASK, NULL);
894   
895   node = node->children;
896   while (node)
897     {
898       if (node->data == data)
899         {
900           if (G_NODE_IS_LEAF (node))
901             {
902               if (flags & G_TRAVERSE_LEAFS)
903                 return node;
904             }
905           else
906             {
907               if (flags & G_TRAVERSE_NON_LEAFS)
908                 return node;
909             }
910         }
911       node = node->next;
912     }
913   
914   return NULL;
915 }
916
917 gint
918 g_node_child_position (GNode *node,
919                        GNode *child)
920 {
921   register guint n = 0;
922   
923   g_return_val_if_fail (node != NULL, -1);
924   g_return_val_if_fail (child != NULL, -1);
925   g_return_val_if_fail (child->parent == node, -1);
926   
927   node = node->children;
928   while (node)
929     {
930       if (node == child)
931         return n;
932       n++;
933       node = node->next;
934     }
935   
936   return -1;
937 }
938
939 gint
940 g_node_child_index (GNode   *node,
941                     gpointer data)
942 {
943   register guint n = 0;
944   
945   g_return_val_if_fail (node != NULL, -1);
946   
947   node = node->children;
948   while (node)
949     {
950       if (node->data == data)
951         return n;
952       n++;
953       node = node->next;
954     }
955   
956   return -1;
957 }
958
959 GNode*
960 g_node_first_sibling (GNode *node)
961 {
962   g_return_val_if_fail (node != NULL, NULL);
963   
964   if (node->parent)
965     return node->parent->children;
966   
967   while (node->prev)
968     node = node->prev;
969   
970   return node;
971 }
972
973 GNode*
974 g_node_last_sibling (GNode *node)
975 {
976   g_return_val_if_fail (node != NULL, NULL);
977   
978   while (node->next)
979     node = node->next;
980   
981   return node;
982 }
983
984 void
985 g_node_children_foreach (GNode           *node,
986                          GTraverseFlags   flags,
987                          GNodeForeachFunc func,
988                          gpointer         data)
989 {
990   g_return_if_fail (node != NULL);
991   g_return_if_fail (flags <= G_TRAVERSE_MASK);
992   g_return_if_fail (func != NULL);
993   
994   node = node->children;
995   while (node)
996     {
997       register GNode *current;
998       
999       current = node;
1000       node = current->next;
1001       if (G_NODE_IS_LEAF (current))
1002         {
1003           if (flags & G_TRAVERSE_LEAFS)
1004             func (current, data);
1005         }
1006       else
1007         {
1008           if (flags & G_TRAVERSE_NON_LEAFS)
1009             func (current, data);
1010         }
1011     }
1012 }