source: trunk/third/glib2/glib/gnode.c @ 18159

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