Add a testcase for the previous fix.
[glib.git] / glib / gnode.c
blob90dde6fefc3bf8114727ef8c7113f79f52bee495
1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * GNode: N-way tree implementation.
5 * Copyright (C) 1998 Tim Janik
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.
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.
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.
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/.
30 /*
31 * MT safe
34 #include "config.h"
36 #include "galias.h"
37 #include "glib.h"
39 #ifndef DISABLE_MEM_POOLS
40 /* node allocation
42 struct _GAllocator /* from gmem.c */
44 gchar *name;
45 guint16 n_preallocs;
46 guint is_unused : 1;
47 guint type : 4;
48 GAllocator *last;
49 GMemChunk *mem_chunk;
50 GNode *free_nodes; /* implementation specific */
53 G_LOCK_DEFINE_STATIC (current_allocator);
54 static GAllocator *current_allocator = NULL;
56 /* HOLDS: current_allocator_lock */
57 static void
58 g_node_validate_allocator (GAllocator *allocator)
60 g_return_if_fail (allocator != NULL);
61 g_return_if_fail (allocator->is_unused == TRUE);
63 if (allocator->type != G_ALLOCATOR_NODE)
65 allocator->type = G_ALLOCATOR_NODE;
66 if (allocator->mem_chunk)
68 g_mem_chunk_destroy (allocator->mem_chunk);
69 allocator->mem_chunk = NULL;
73 if (!allocator->mem_chunk)
75 allocator->mem_chunk = g_mem_chunk_new (allocator->name,
76 sizeof (GNode),
77 sizeof (GNode) * allocator->n_preallocs,
78 G_ALLOC_ONLY);
79 allocator->free_nodes = NULL;
82 allocator->is_unused = FALSE;
85 void
86 g_node_push_allocator (GAllocator *allocator)
88 G_LOCK (current_allocator);
89 g_node_validate_allocator (allocator);
90 allocator->last = current_allocator;
91 current_allocator = allocator;
92 G_UNLOCK (current_allocator);
95 void
96 g_node_pop_allocator (void)
98 G_LOCK (current_allocator);
99 if (current_allocator)
101 GAllocator *allocator;
103 allocator = current_allocator;
104 current_allocator = allocator->last;
105 allocator->last = NULL;
106 allocator->is_unused = TRUE;
108 G_UNLOCK (current_allocator);
112 /* --- functions --- */
113 GNode*
114 g_node_new (gpointer data)
116 GNode *node;
118 G_LOCK (current_allocator);
119 if (!current_allocator)
121 GAllocator *allocator = g_allocator_new ("GLib default GNode allocator",
122 128);
123 g_node_validate_allocator (allocator);
124 allocator->last = NULL;
125 current_allocator = allocator;
127 if (!current_allocator->free_nodes)
128 node = g_chunk_new (GNode, current_allocator->mem_chunk);
129 else
131 node = current_allocator->free_nodes;
132 current_allocator->free_nodes = node->next;
134 G_UNLOCK (current_allocator);
136 node->data = data;
137 node->next = NULL;
138 node->prev = NULL;
139 node->parent = NULL;
140 node->children = NULL;
142 return node;
145 static void
146 g_nodes_free (GNode *node)
148 GNode *parent;
150 parent = node;
151 while (1)
153 if (parent->children)
154 g_nodes_free (parent->children);
156 #ifdef ENABLE_GC_FRIENDLY
157 parent->data = NULL;
158 parent->prev = NULL;
159 parent->parent = NULL;
160 parent->children = NULL;
161 #endif /* ENABLE_GC_FRIENDLY */
163 if (parent->next)
164 parent = parent->next;
165 else
166 break;
169 G_LOCK (current_allocator);
170 parent->next = current_allocator->free_nodes;
171 current_allocator->free_nodes = node;
172 G_UNLOCK (current_allocator);
174 #else /* DISABLE_MEM_POOLS */
176 GNode*
177 g_node_new (gpointer data)
179 GNode *node;
181 node = g_new0 (GNode, 1);
183 node->data = data;
185 return node;
188 static void
189 g_nodes_free (GNode *root)
191 GNode *node, *next;
193 node = root;
194 while (node != NULL)
196 next = node->next;
197 g_nodes_free (node->children);
198 g_free (node);
199 node = next;
202 #endif
204 void
205 g_node_destroy (GNode *root)
207 g_return_if_fail (root != NULL);
209 if (!G_NODE_IS_ROOT (root))
210 g_node_unlink (root);
212 g_nodes_free (root);
215 void
216 g_node_unlink (GNode *node)
218 g_return_if_fail (node != NULL);
220 if (node->prev)
221 node->prev->next = node->next;
222 else if (node->parent)
223 node->parent->children = node->next;
224 node->parent = NULL;
225 if (node->next)
227 node->next->prev = node->prev;
228 node->next = NULL;
230 node->prev = NULL;
234 * g_node_copy_deep:
235 * @node: a #GNode
236 * @copy_func: the function which is called to copy the data inside each node,
237 * or %NULL to use the original data.
238 * @data: data to pass to @copy_func
240 * Recursively copies a #GNode and its data.
242 * Return value: a new #GNode containing copies of the data in @node.
244 * Since: 2.4
246 GNode*
247 g_node_copy_deep (GNode *node,
248 GCopyFunc copy_func,
249 gpointer data)
251 GNode *new_node = NULL;
253 if (copy_func == NULL)
254 return g_node_copy (node);
256 if (node)
258 GNode *child, *new_child;
260 new_node = g_node_new (copy_func (node->data, data));
262 for (child = g_node_last_child (node); child; child = child->prev)
264 new_child = g_node_copy_deep (child, copy_func, data);
265 g_node_prepend (new_node, new_child);
269 return new_node;
272 GNode*
273 g_node_copy (GNode *node)
275 GNode *new_node = NULL;
277 if (node)
279 GNode *child;
281 new_node = g_node_new (node->data);
283 for (child = g_node_last_child (node); child; child = child->prev)
284 g_node_prepend (new_node, g_node_copy (child));
287 return new_node;
290 GNode*
291 g_node_insert (GNode *parent,
292 gint position,
293 GNode *node)
295 g_return_val_if_fail (parent != NULL, node);
296 g_return_val_if_fail (node != NULL, node);
297 g_return_val_if_fail (G_NODE_IS_ROOT (node), node);
299 if (position > 0)
300 return g_node_insert_before (parent,
301 g_node_nth_child (parent, position),
302 node);
303 else if (position == 0)
304 return g_node_prepend (parent, node);
305 else /* if (position < 0) */
306 return g_node_append (parent, node);
309 GNode*
310 g_node_insert_before (GNode *parent,
311 GNode *sibling,
312 GNode *node)
314 g_return_val_if_fail (parent != NULL, node);
315 g_return_val_if_fail (node != NULL, node);
316 g_return_val_if_fail (G_NODE_IS_ROOT (node), node);
317 if (sibling)
318 g_return_val_if_fail (sibling->parent == parent, node);
320 node->parent = parent;
322 if (sibling)
324 if (sibling->prev)
326 node->prev = sibling->prev;
327 node->prev->next = node;
328 node->next = sibling;
329 sibling->prev = node;
331 else
333 node->parent->children = node;
334 node->next = sibling;
335 sibling->prev = node;
338 else
340 if (parent->children)
342 sibling = parent->children;
343 while (sibling->next)
344 sibling = sibling->next;
345 node->prev = sibling;
346 sibling->next = node;
348 else
349 node->parent->children = node;
352 return node;
355 GNode*
356 g_node_insert_after (GNode *parent,
357 GNode *sibling,
358 GNode *node)
360 g_return_val_if_fail (parent != NULL, node);
361 g_return_val_if_fail (node != NULL, node);
362 g_return_val_if_fail (G_NODE_IS_ROOT (node), node);
363 if (sibling)
364 g_return_val_if_fail (sibling->parent == parent, node);
366 node->parent = parent;
368 if (sibling)
370 if (sibling->next)
372 sibling->next->prev = node;
374 node->next = sibling->next;
375 node->prev = sibling;
376 sibling->next = node;
378 else
380 if (parent->children)
382 node->next = parent->children;
383 parent->children->prev = node;
385 parent->children = node;
388 return node;
391 GNode*
392 g_node_prepend (GNode *parent,
393 GNode *node)
395 g_return_val_if_fail (parent != NULL, node);
397 return g_node_insert_before (parent, parent->children, node);
400 GNode*
401 g_node_get_root (GNode *node)
403 g_return_val_if_fail (node != NULL, NULL);
405 while (node->parent)
406 node = node->parent;
408 return node;
411 gboolean
412 g_node_is_ancestor (GNode *node,
413 GNode *descendant)
415 g_return_val_if_fail (node != NULL, FALSE);
416 g_return_val_if_fail (descendant != NULL, FALSE);
418 while (descendant)
420 if (descendant->parent == node)
421 return TRUE;
423 descendant = descendant->parent;
426 return FALSE;
429 /* returns 1 for root, 2 for first level children,
430 * 3 for children's children...
432 guint
433 g_node_depth (GNode *node)
435 register guint depth = 0;
437 while (node)
439 depth++;
440 node = node->parent;
443 return depth;
446 void
447 g_node_reverse_children (GNode *node)
449 GNode *child;
450 GNode *last;
452 g_return_if_fail (node != NULL);
454 child = node->children;
455 last = NULL;
456 while (child)
458 last = child;
459 child = last->next;
460 last->next = last->prev;
461 last->prev = child;
463 node->children = last;
466 guint
467 g_node_max_height (GNode *root)
469 register GNode *child;
470 register guint max_height = 0;
472 if (!root)
473 return 0;
475 child = root->children;
476 while (child)
478 register guint tmp_height;
480 tmp_height = g_node_max_height (child);
481 if (tmp_height > max_height)
482 max_height = tmp_height;
483 child = child->next;
486 return max_height + 1;
489 static gboolean
490 g_node_traverse_pre_order (GNode *node,
491 GTraverseFlags flags,
492 GNodeTraverseFunc func,
493 gpointer data)
495 if (node->children)
497 GNode *child;
499 if ((flags & G_TRAVERSE_NON_LEAFS) &&
500 func (node, data))
501 return TRUE;
503 child = node->children;
504 while (child)
506 register GNode *current;
508 current = child;
509 child = current->next;
510 if (g_node_traverse_pre_order (current, flags, func, data))
511 return TRUE;
514 else if ((flags & G_TRAVERSE_LEAFS) &&
515 func (node, data))
516 return TRUE;
518 return FALSE;
521 static gboolean
522 g_node_depth_traverse_pre_order (GNode *node,
523 GTraverseFlags flags,
524 guint depth,
525 GNodeTraverseFunc func,
526 gpointer data)
528 if (node->children)
530 GNode *child;
532 if ((flags & G_TRAVERSE_NON_LEAFS) &&
533 func (node, data))
534 return TRUE;
536 depth--;
537 if (!depth)
538 return FALSE;
540 child = node->children;
541 while (child)
543 register GNode *current;
545 current = child;
546 child = current->next;
547 if (g_node_depth_traverse_pre_order (current, flags, depth, func, data))
548 return TRUE;
551 else if ((flags & G_TRAVERSE_LEAFS) &&
552 func (node, data))
553 return TRUE;
555 return FALSE;
558 static gboolean
559 g_node_traverse_post_order (GNode *node,
560 GTraverseFlags flags,
561 GNodeTraverseFunc func,
562 gpointer data)
564 if (node->children)
566 GNode *child;
568 child = node->children;
569 while (child)
571 register GNode *current;
573 current = child;
574 child = current->next;
575 if (g_node_traverse_post_order (current, flags, func, data))
576 return TRUE;
579 if ((flags & G_TRAVERSE_NON_LEAFS) &&
580 func (node, data))
581 return TRUE;
584 else if ((flags & G_TRAVERSE_LEAFS) &&
585 func (node, data))
586 return TRUE;
588 return FALSE;
591 static gboolean
592 g_node_depth_traverse_post_order (GNode *node,
593 GTraverseFlags flags,
594 guint depth,
595 GNodeTraverseFunc func,
596 gpointer data)
598 if (node->children)
600 depth--;
601 if (depth)
603 GNode *child;
605 child = node->children;
606 while (child)
608 register GNode *current;
610 current = child;
611 child = current->next;
612 if (g_node_depth_traverse_post_order (current, flags, depth, func, data))
613 return TRUE;
617 if ((flags & G_TRAVERSE_NON_LEAFS) &&
618 func (node, data))
619 return TRUE;
622 else if ((flags & G_TRAVERSE_LEAFS) &&
623 func (node, data))
624 return TRUE;
626 return FALSE;
629 static gboolean
630 g_node_traverse_in_order (GNode *node,
631 GTraverseFlags flags,
632 GNodeTraverseFunc func,
633 gpointer data)
635 if (node->children)
637 GNode *child;
638 register GNode *current;
640 child = node->children;
641 current = child;
642 child = current->next;
644 if (g_node_traverse_in_order (current, flags, func, data))
645 return TRUE;
647 if ((flags & G_TRAVERSE_NON_LEAFS) &&
648 func (node, data))
649 return TRUE;
651 while (child)
653 current = child;
654 child = current->next;
655 if (g_node_traverse_in_order (current, flags, func, data))
656 return TRUE;
659 else if ((flags & G_TRAVERSE_LEAFS) &&
660 func (node, data))
661 return TRUE;
663 return FALSE;
666 static gboolean
667 g_node_depth_traverse_in_order (GNode *node,
668 GTraverseFlags flags,
669 guint depth,
670 GNodeTraverseFunc func,
671 gpointer data)
673 if (node->children)
675 depth--;
676 if (depth)
678 GNode *child;
679 register GNode *current;
681 child = node->children;
682 current = child;
683 child = current->next;
685 if (g_node_depth_traverse_in_order (current, flags, depth, func, data))
686 return TRUE;
688 if ((flags & G_TRAVERSE_NON_LEAFS) &&
689 func (node, data))
690 return TRUE;
692 while (child)
694 current = child;
695 child = current->next;
696 if (g_node_depth_traverse_in_order (current, flags, depth, func, data))
697 return TRUE;
700 else if ((flags & G_TRAVERSE_NON_LEAFS) &&
701 func (node, data))
702 return TRUE;
704 else if ((flags & G_TRAVERSE_LEAFS) &&
705 func (node, data))
706 return TRUE;
708 return FALSE;
711 static gboolean
712 g_node_traverse_level (GNode *node,
713 GTraverseFlags flags,
714 guint level,
715 GNodeTraverseFunc func,
716 gpointer data,
717 gboolean *more_levels)
719 if (level == 0)
721 if (node->children)
723 *more_levels = TRUE;
724 return (flags & G_TRAVERSE_NON_LEAFS) && func (node, data);
726 else
728 return (flags & G_TRAVERSE_LEAFS) && func (node, data);
731 else
733 node = node->children;
735 while (node)
737 if (g_node_traverse_level (node, flags, level - 1, func, data, more_levels))
738 return TRUE;
740 node = node->next;
744 return FALSE;
747 static gboolean
748 g_node_depth_traverse_level (GNode *node,
749 GTraverseFlags flags,
750 guint depth,
751 GNodeTraverseFunc func,
752 gpointer data)
754 gint level;
755 gboolean more_levels;
757 level = 0;
758 while (level != depth)
760 more_levels = FALSE;
761 if (g_node_traverse_level (node, flags, level, func, data, &more_levels))
762 return TRUE;
763 if (!more_levels)
764 break;
765 level++;
767 return FALSE;
770 void
771 g_node_traverse (GNode *root,
772 GTraverseType order,
773 GTraverseFlags flags,
774 gint depth,
775 GNodeTraverseFunc func,
776 gpointer data)
778 g_return_if_fail (root != NULL);
779 g_return_if_fail (func != NULL);
780 g_return_if_fail (order <= G_LEVEL_ORDER);
781 g_return_if_fail (flags <= G_TRAVERSE_MASK);
782 g_return_if_fail (depth == -1 || depth > 0);
784 switch (order)
786 case G_PRE_ORDER:
787 if (depth < 0)
788 g_node_traverse_pre_order (root, flags, func, data);
789 else
790 g_node_depth_traverse_pre_order (root, flags, depth, func, data);
791 break;
792 case G_POST_ORDER:
793 if (depth < 0)
794 g_node_traverse_post_order (root, flags, func, data);
795 else
796 g_node_depth_traverse_post_order (root, flags, depth, func, data);
797 break;
798 case G_IN_ORDER:
799 if (depth < 0)
800 g_node_traverse_in_order (root, flags, func, data);
801 else
802 g_node_depth_traverse_in_order (root, flags, depth, func, data);
803 break;
804 case G_LEVEL_ORDER:
805 g_node_depth_traverse_level (root, flags, depth, func, data);
806 break;
810 static gboolean
811 g_node_find_func (GNode *node,
812 gpointer data)
814 register gpointer *d = data;
816 if (*d != node->data)
817 return FALSE;
819 *(++d) = node;
821 return TRUE;
824 GNode*
825 g_node_find (GNode *root,
826 GTraverseType order,
827 GTraverseFlags flags,
828 gpointer data)
830 gpointer d[2];
832 g_return_val_if_fail (root != NULL, NULL);
833 g_return_val_if_fail (order <= G_LEVEL_ORDER, NULL);
834 g_return_val_if_fail (flags <= G_TRAVERSE_MASK, NULL);
836 d[0] = data;
837 d[1] = NULL;
839 g_node_traverse (root, order, flags, -1, g_node_find_func, d);
841 return d[1];
844 static void
845 g_node_count_func (GNode *node,
846 GTraverseFlags flags,
847 guint *n)
849 if (node->children)
851 GNode *child;
853 if (flags & G_TRAVERSE_NON_LEAFS)
854 (*n)++;
856 child = node->children;
857 while (child)
859 g_node_count_func (child, flags, n);
860 child = child->next;
863 else if (flags & G_TRAVERSE_LEAFS)
864 (*n)++;
867 guint
868 g_node_n_nodes (GNode *root,
869 GTraverseFlags flags)
871 guint n = 0;
873 g_return_val_if_fail (root != NULL, 0);
874 g_return_val_if_fail (flags <= G_TRAVERSE_MASK, 0);
876 g_node_count_func (root, flags, &n);
878 return n;
881 GNode*
882 g_node_last_child (GNode *node)
884 g_return_val_if_fail (node != NULL, NULL);
886 node = node->children;
887 if (node)
888 while (node->next)
889 node = node->next;
891 return node;
894 GNode*
895 g_node_nth_child (GNode *node,
896 guint n)
898 g_return_val_if_fail (node != NULL, NULL);
900 node = node->children;
901 if (node)
902 while ((n-- > 0) && node)
903 node = node->next;
905 return node;
908 guint
909 g_node_n_children (GNode *node)
911 guint n = 0;
913 g_return_val_if_fail (node != NULL, 0);
915 node = node->children;
916 while (node)
918 n++;
919 node = node->next;
922 return n;
925 GNode*
926 g_node_find_child (GNode *node,
927 GTraverseFlags flags,
928 gpointer data)
930 g_return_val_if_fail (node != NULL, NULL);
931 g_return_val_if_fail (flags <= G_TRAVERSE_MASK, NULL);
933 node = node->children;
934 while (node)
936 if (node->data == data)
938 if (G_NODE_IS_LEAF (node))
940 if (flags & G_TRAVERSE_LEAFS)
941 return node;
943 else
945 if (flags & G_TRAVERSE_NON_LEAFS)
946 return node;
949 node = node->next;
952 return NULL;
955 gint
956 g_node_child_position (GNode *node,
957 GNode *child)
959 register guint n = 0;
961 g_return_val_if_fail (node != NULL, -1);
962 g_return_val_if_fail (child != NULL, -1);
963 g_return_val_if_fail (child->parent == node, -1);
965 node = node->children;
966 while (node)
968 if (node == child)
969 return n;
970 n++;
971 node = node->next;
974 return -1;
977 gint
978 g_node_child_index (GNode *node,
979 gpointer data)
981 register guint n = 0;
983 g_return_val_if_fail (node != NULL, -1);
985 node = node->children;
986 while (node)
988 if (node->data == data)
989 return n;
990 n++;
991 node = node->next;
994 return -1;
997 GNode*
998 g_node_first_sibling (GNode *node)
1000 g_return_val_if_fail (node != NULL, NULL);
1002 if (node->parent)
1003 return node->parent->children;
1005 while (node->prev)
1006 node = node->prev;
1008 return node;
1011 GNode*
1012 g_node_last_sibling (GNode *node)
1014 g_return_val_if_fail (node != NULL, NULL);
1016 while (node->next)
1017 node = node->next;
1019 return node;
1022 void
1023 g_node_children_foreach (GNode *node,
1024 GTraverseFlags flags,
1025 GNodeForeachFunc func,
1026 gpointer data)
1028 g_return_if_fail (node != NULL);
1029 g_return_if_fail (flags <= G_TRAVERSE_MASK);
1030 g_return_if_fail (func != NULL);
1032 node = node->children;
1033 while (node)
1035 register GNode *current;
1037 current = node;
1038 node = current->next;
1039 if (G_NODE_IS_LEAF (current))
1041 if (flags & G_TRAVERSE_LEAFS)
1042 func (current, data);
1044 else
1046 if (flags & G_TRAVERSE_NON_LEAFS)
1047 func (current, data);