/src/tinysparql/subprojects/glib-2.80.3/glib/gnode.c
Line | Count | Source (jump to first uncovered 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 | | * SPDX-License-Identifier: LGPL-2.1-or-later |
8 | | * |
9 | | * This library is free software; you can redistribute it and/or |
10 | | * modify it under the terms of the GNU Lesser General Public |
11 | | * License as published by the Free Software Foundation; either |
12 | | * version 2.1 of the License, or (at your option) any later version. |
13 | | * |
14 | | * This library is distributed in the hope that it will be useful, |
15 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
17 | | * Lesser General Public License for more details. |
18 | | * |
19 | | * You should have received a copy of the GNU Lesser General Public |
20 | | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
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 "gnode.h" |
37 | | |
38 | | #include "gslice.h" |
39 | | |
40 | | #include "gtestutils.h" |
41 | | |
42 | | /** |
43 | | * GNode: |
44 | | * @data: contains the actual data of the node. |
45 | | * @next: points to the node's next sibling (a sibling is another |
46 | | * #GNode with the same parent). |
47 | | * @prev: points to the node's previous sibling. |
48 | | * @parent: points to the parent of the #GNode, or is %NULL if the |
49 | | * #GNode is the root of the tree. |
50 | | * @children: points to the first child of the #GNode. The other |
51 | | * children are accessed by using the @next pointer of each |
52 | | * child. |
53 | | * |
54 | | * The #GNode struct represents one node in a [n-ary tree][glib-N-ary-Trees]. |
55 | | **/ |
56 | | |
57 | 0 | #define g_node_alloc0() g_slice_new0 (GNode) |
58 | 0 | #define g_node_free(node) g_slice_free (GNode, node) |
59 | | |
60 | | /* --- functions --- */ |
61 | | /** |
62 | | * g_node_new: |
63 | | * @data: the data of the new node |
64 | | * |
65 | | * Creates a new #GNode containing the given data. |
66 | | * Used to create the first node in a tree. |
67 | | * |
68 | | * Returns: a new #GNode |
69 | | */ |
70 | | GNode* |
71 | | g_node_new (gpointer data) |
72 | 0 | { |
73 | 0 | GNode *node = g_node_alloc0 (); |
74 | 0 | node->data = data; |
75 | 0 | return node; |
76 | 0 | } |
77 | | |
78 | | static void |
79 | | g_nodes_free (GNode *node) |
80 | 0 | { |
81 | 0 | while (node) |
82 | 0 | { |
83 | 0 | GNode *next = node->next; |
84 | 0 | if (node->children) |
85 | 0 | g_nodes_free (node->children); |
86 | 0 | g_node_free (node); |
87 | 0 | node = next; |
88 | 0 | } |
89 | 0 | } |
90 | | |
91 | | /** |
92 | | * g_node_destroy: |
93 | | * @root: the root of the tree/subtree to destroy |
94 | | * |
95 | | * Removes @root and its children from the tree, freeing any memory |
96 | | * allocated. |
97 | | */ |
98 | | void |
99 | | g_node_destroy (GNode *root) |
100 | 0 | { |
101 | 0 | g_return_if_fail (root != NULL); |
102 | | |
103 | 0 | if (!G_NODE_IS_ROOT (root)) |
104 | 0 | g_node_unlink (root); |
105 | | |
106 | 0 | g_nodes_free (root); |
107 | 0 | } |
108 | | |
109 | | /** |
110 | | * g_node_unlink: |
111 | | * @node: the #GNode to unlink, which becomes the root of a new tree |
112 | | * |
113 | | * Unlinks a #GNode from a tree, resulting in two separate trees. |
114 | | */ |
115 | | void |
116 | | g_node_unlink (GNode *node) |
117 | 5.50M | { |
118 | 5.50M | g_return_if_fail (node != NULL); |
119 | | |
120 | 5.50M | if (node->prev) |
121 | 2.84M | node->prev->next = node->next; |
122 | 2.66M | else if (node->parent) |
123 | 2.66M | node->parent->children = node->next; |
124 | 5.50M | node->parent = NULL; |
125 | 5.50M | if (node->next) |
126 | 0 | { |
127 | 0 | node->next->prev = node->prev; |
128 | 0 | node->next = NULL; |
129 | 0 | } |
130 | 5.50M | node->prev = NULL; |
131 | 5.50M | } |
132 | | |
133 | | /** |
134 | | * g_node_copy_deep: |
135 | | * @node: a #GNode |
136 | | * @copy_func: (scope call): the function which is called to copy the data |
137 | | * inside each node, or %NULL to use the original data. |
138 | | * @data: data to pass to @copy_func |
139 | | * |
140 | | * Recursively copies a #GNode and its data. |
141 | | * |
142 | | * Returns: a new #GNode containing copies of the data in @node. |
143 | | * |
144 | | * Since: 2.4 |
145 | | **/ |
146 | | GNode* |
147 | | g_node_copy_deep (GNode *node, |
148 | | GCopyFunc copy_func, |
149 | | gpointer data) |
150 | 0 | { |
151 | 0 | GNode *new_node = NULL; |
152 | |
|
153 | 0 | if (copy_func == NULL) |
154 | 0 | return g_node_copy (node); |
155 | | |
156 | 0 | if (node) |
157 | 0 | { |
158 | 0 | GNode *child, *new_child; |
159 | | |
160 | 0 | new_node = g_node_new (copy_func (node->data, data)); |
161 | | |
162 | 0 | for (child = g_node_last_child (node); child; child = child->prev) |
163 | 0 | { |
164 | 0 | new_child = g_node_copy_deep (child, copy_func, data); |
165 | 0 | g_node_prepend (new_node, new_child); |
166 | 0 | } |
167 | 0 | } |
168 | | |
169 | 0 | return new_node; |
170 | 0 | } |
171 | | |
172 | | /** |
173 | | * g_node_copy: |
174 | | * @node: a #GNode |
175 | | * |
176 | | * Recursively copies a #GNode (but does not deep-copy the data inside the |
177 | | * nodes, see g_node_copy_deep() if you need that). |
178 | | * |
179 | | * Returns: a new #GNode containing the same data pointers |
180 | | */ |
181 | | GNode* |
182 | | g_node_copy (GNode *node) |
183 | 0 | { |
184 | 0 | GNode *new_node = NULL; |
185 | | |
186 | 0 | if (node) |
187 | 0 | { |
188 | 0 | GNode *child; |
189 | | |
190 | 0 | new_node = g_node_new (node->data); |
191 | | |
192 | 0 | for (child = g_node_last_child (node); child; child = child->prev) |
193 | 0 | g_node_prepend (new_node, g_node_copy (child)); |
194 | 0 | } |
195 | | |
196 | 0 | return new_node; |
197 | 0 | } |
198 | | |
199 | | /** |
200 | | * g_node_insert: |
201 | | * @parent: the #GNode to place @node under |
202 | | * @position: the position to place @node at, with respect to its siblings |
203 | | * If position is -1, @node is inserted as the last child of @parent |
204 | | * @node: the #GNode to insert |
205 | | * |
206 | | * Inserts a #GNode beneath the parent at the given position. |
207 | | * |
208 | | * Returns: the inserted #GNode |
209 | | */ |
210 | | GNode* |
211 | | g_node_insert (GNode *parent, |
212 | | gint position, |
213 | | GNode *node) |
214 | 0 | { |
215 | 0 | g_return_val_if_fail (parent != NULL, node); |
216 | 0 | g_return_val_if_fail (node != NULL, node); |
217 | 0 | g_return_val_if_fail (G_NODE_IS_ROOT (node), node); |
218 | | |
219 | 0 | if (position > 0) |
220 | 0 | return g_node_insert_before (parent, |
221 | 0 | g_node_nth_child (parent, position), |
222 | 0 | node); |
223 | 0 | else if (position == 0) |
224 | 0 | return g_node_prepend (parent, node); |
225 | 0 | else /* if (position < 0) */ |
226 | 0 | return g_node_append (parent, node); |
227 | 0 | } |
228 | | |
229 | | /** |
230 | | * g_node_insert_before: |
231 | | * @parent: the #GNode to place @node under |
232 | | * @sibling: the sibling #GNode to place @node before. |
233 | | * If sibling is %NULL, the node is inserted as the last child of @parent. |
234 | | * @node: the #GNode to insert |
235 | | * |
236 | | * Inserts a #GNode beneath the parent before the given sibling. |
237 | | * |
238 | | * Returns: the inserted #GNode |
239 | | */ |
240 | | GNode* |
241 | | g_node_insert_before (GNode *parent, |
242 | | GNode *sibling, |
243 | | GNode *node) |
244 | 114M | { |
245 | 114M | g_return_val_if_fail (parent != NULL, node); |
246 | 114M | g_return_val_if_fail (node != NULL, node); |
247 | 114M | g_return_val_if_fail (G_NODE_IS_ROOT (node), node); |
248 | 114M | if (sibling) |
249 | 114M | g_return_val_if_fail (sibling->parent == parent, node); |
250 | | |
251 | 114M | node->parent = parent; |
252 | | |
253 | 114M | if (sibling) |
254 | 0 | { |
255 | 0 | if (sibling->prev) |
256 | 0 | { |
257 | 0 | node->prev = sibling->prev; |
258 | 0 | node->prev->next = node; |
259 | 0 | node->next = sibling; |
260 | 0 | sibling->prev = node; |
261 | 0 | } |
262 | 0 | else |
263 | 0 | { |
264 | 0 | node->parent->children = node; |
265 | 0 | node->next = sibling; |
266 | 0 | sibling->prev = node; |
267 | 0 | } |
268 | 0 | } |
269 | 114M | else |
270 | 114M | { |
271 | 114M | if (parent->children) |
272 | 10.2M | { |
273 | 10.2M | sibling = parent->children; |
274 | 125M | while (sibling->next) |
275 | 115M | sibling = sibling->next; |
276 | 10.2M | node->prev = sibling; |
277 | 10.2M | sibling->next = node; |
278 | 10.2M | } |
279 | 104M | else |
280 | 104M | node->parent->children = node; |
281 | 114M | } |
282 | | |
283 | 114M | return node; |
284 | 114M | } |
285 | | |
286 | | /** |
287 | | * g_node_insert_after: |
288 | | * @parent: the #GNode to place @node under |
289 | | * @sibling: the sibling #GNode to place @node after. |
290 | | * If sibling is %NULL, the node is inserted as the first child of @parent. |
291 | | * @node: the #GNode to insert |
292 | | * |
293 | | * Inserts a #GNode beneath the parent after the given sibling. |
294 | | * |
295 | | * Returns: the inserted #GNode |
296 | | */ |
297 | | GNode* |
298 | | g_node_insert_after (GNode *parent, |
299 | | GNode *sibling, |
300 | | GNode *node) |
301 | 0 | { |
302 | 0 | g_return_val_if_fail (parent != NULL, node); |
303 | 0 | g_return_val_if_fail (node != NULL, node); |
304 | 0 | g_return_val_if_fail (G_NODE_IS_ROOT (node), node); |
305 | 0 | if (sibling) |
306 | 0 | g_return_val_if_fail (sibling->parent == parent, node); |
307 | | |
308 | 0 | node->parent = parent; |
309 | |
|
310 | 0 | if (sibling) |
311 | 0 | { |
312 | 0 | if (sibling->next) |
313 | 0 | { |
314 | 0 | sibling->next->prev = node; |
315 | 0 | } |
316 | 0 | node->next = sibling->next; |
317 | 0 | node->prev = sibling; |
318 | 0 | sibling->next = node; |
319 | 0 | } |
320 | 0 | else |
321 | 0 | { |
322 | 0 | if (parent->children) |
323 | 0 | { |
324 | 0 | node->next = parent->children; |
325 | 0 | parent->children->prev = node; |
326 | 0 | } |
327 | 0 | parent->children = node; |
328 | 0 | } |
329 | |
|
330 | 0 | return node; |
331 | 0 | } |
332 | | |
333 | | /** |
334 | | * g_node_prepend: |
335 | | * @parent: the #GNode to place the new #GNode under |
336 | | * @node: the #GNode to insert |
337 | | * |
338 | | * Inserts a #GNode as the first child of the given parent. |
339 | | * |
340 | | * Returns: the inserted #GNode |
341 | | */ |
342 | | GNode* |
343 | | g_node_prepend (GNode *parent, |
344 | | GNode *node) |
345 | 0 | { |
346 | 0 | g_return_val_if_fail (parent != NULL, node); |
347 | | |
348 | 0 | return g_node_insert_before (parent, parent->children, node); |
349 | 0 | } |
350 | | |
351 | | /** |
352 | | * g_node_get_root: |
353 | | * @node: a #GNode |
354 | | * |
355 | | * Gets the root of a tree. |
356 | | * |
357 | | * Returns: the root of the tree |
358 | | */ |
359 | | GNode* |
360 | | g_node_get_root (GNode *node) |
361 | 0 | { |
362 | 0 | g_return_val_if_fail (node != NULL, NULL); |
363 | | |
364 | 0 | while (node->parent) |
365 | 0 | node = node->parent; |
366 | | |
367 | 0 | return node; |
368 | 0 | } |
369 | | |
370 | | /** |
371 | | * g_node_is_ancestor: |
372 | | * @node: a #GNode |
373 | | * @descendant: a #GNode |
374 | | * |
375 | | * Returns %TRUE if @node is an ancestor of @descendant. |
376 | | * This is true if node is the parent of @descendant, |
377 | | * or if node is the grandparent of @descendant etc. |
378 | | * |
379 | | * Returns: %TRUE if @node is an ancestor of @descendant |
380 | | */ |
381 | | gboolean |
382 | | g_node_is_ancestor (GNode *node, |
383 | | GNode *descendant) |
384 | 0 | { |
385 | 0 | g_return_val_if_fail (node != NULL, FALSE); |
386 | 0 | g_return_val_if_fail (descendant != NULL, FALSE); |
387 | | |
388 | 0 | while (descendant) |
389 | 0 | { |
390 | 0 | if (descendant->parent == node) |
391 | 0 | return TRUE; |
392 | | |
393 | 0 | descendant = descendant->parent; |
394 | 0 | } |
395 | | |
396 | 0 | return FALSE; |
397 | 0 | } |
398 | | |
399 | | /** |
400 | | * g_node_depth: |
401 | | * @node: a #GNode |
402 | | * |
403 | | * Gets the depth of a #GNode. |
404 | | * |
405 | | * If @node is %NULL the depth is 0. The root node has a depth of 1. |
406 | | * For the children of the root node the depth is 2. And so on. |
407 | | * |
408 | | * Returns: the depth of the #GNode |
409 | | */ |
410 | | guint |
411 | | g_node_depth (GNode *node) |
412 | 0 | { |
413 | 0 | guint depth = 0; |
414 | | |
415 | 0 | while (node) |
416 | 0 | { |
417 | 0 | depth++; |
418 | 0 | node = node->parent; |
419 | 0 | } |
420 | | |
421 | 0 | return depth; |
422 | 0 | } |
423 | | |
424 | | /** |
425 | | * g_node_reverse_children: |
426 | | * @node: a #GNode. |
427 | | * |
428 | | * Reverses the order of the children of a #GNode. |
429 | | * (It doesn't change the order of the grandchildren.) |
430 | | */ |
431 | | void |
432 | | g_node_reverse_children (GNode *node) |
433 | 0 | { |
434 | 0 | GNode *child; |
435 | 0 | GNode *last; |
436 | | |
437 | 0 | g_return_if_fail (node != NULL); |
438 | | |
439 | 0 | child = node->children; |
440 | 0 | last = NULL; |
441 | 0 | while (child) |
442 | 0 | { |
443 | 0 | last = child; |
444 | 0 | child = last->next; |
445 | 0 | last->next = last->prev; |
446 | 0 | last->prev = child; |
447 | 0 | } |
448 | 0 | node->children = last; |
449 | 0 | } |
450 | | |
451 | | /** |
452 | | * g_node_max_height: |
453 | | * @root: a #GNode |
454 | | * |
455 | | * Gets the maximum height of all branches beneath a #GNode. |
456 | | * This is the maximum distance from the #GNode to all leaf nodes. |
457 | | * |
458 | | * If @root is %NULL, 0 is returned. If @root has no children, |
459 | | * 1 is returned. If @root has children, 2 is returned. And so on. |
460 | | * |
461 | | * Returns: the maximum height of the tree beneath @root |
462 | | */ |
463 | | guint |
464 | | g_node_max_height (GNode *root) |
465 | 0 | { |
466 | 0 | GNode *child; |
467 | 0 | guint max_height = 0; |
468 | | |
469 | 0 | if (!root) |
470 | 0 | return 0; |
471 | | |
472 | 0 | child = root->children; |
473 | 0 | while (child) |
474 | 0 | { |
475 | 0 | guint tmp_height; |
476 | | |
477 | 0 | tmp_height = g_node_max_height (child); |
478 | 0 | if (tmp_height > max_height) |
479 | 0 | max_height = tmp_height; |
480 | 0 | child = child->next; |
481 | 0 | } |
482 | | |
483 | 0 | return max_height + 1; |
484 | 0 | } |
485 | | |
486 | | static gboolean |
487 | | g_node_traverse_pre_order (GNode *node, |
488 | | GTraverseFlags flags, |
489 | | GNodeTraverseFunc func, |
490 | | gpointer data) |
491 | 0 | { |
492 | 0 | if (node->children) |
493 | 0 | { |
494 | 0 | GNode *child; |
495 | | |
496 | 0 | if ((flags & G_TRAVERSE_NON_LEAFS) && |
497 | 0 | func (node, data)) |
498 | 0 | return TRUE; |
499 | | |
500 | 0 | child = node->children; |
501 | 0 | while (child) |
502 | 0 | { |
503 | 0 | GNode *current; |
504 | | |
505 | 0 | current = child; |
506 | 0 | child = current->next; |
507 | 0 | if (g_node_traverse_pre_order (current, flags, func, data)) |
508 | 0 | return TRUE; |
509 | 0 | } |
510 | 0 | } |
511 | 0 | else if ((flags & G_TRAVERSE_LEAFS) && |
512 | 0 | func (node, data)) |
513 | 0 | return TRUE; |
514 | | |
515 | 0 | return FALSE; |
516 | 0 | } |
517 | | |
518 | | static gboolean |
519 | | g_node_depth_traverse_pre_order (GNode *node, |
520 | | GTraverseFlags flags, |
521 | | guint depth, |
522 | | GNodeTraverseFunc func, |
523 | | gpointer data) |
524 | 0 | { |
525 | 0 | if (node->children) |
526 | 0 | { |
527 | 0 | GNode *child; |
528 | | |
529 | 0 | if ((flags & G_TRAVERSE_NON_LEAFS) && |
530 | 0 | func (node, data)) |
531 | 0 | return TRUE; |
532 | | |
533 | 0 | depth--; |
534 | 0 | if (!depth) |
535 | 0 | return FALSE; |
536 | | |
537 | 0 | child = node->children; |
538 | 0 | while (child) |
539 | 0 | { |
540 | 0 | GNode *current; |
541 | | |
542 | 0 | current = child; |
543 | 0 | child = current->next; |
544 | 0 | if (g_node_depth_traverse_pre_order (current, flags, depth, func, data)) |
545 | 0 | return TRUE; |
546 | 0 | } |
547 | 0 | } |
548 | 0 | else if ((flags & G_TRAVERSE_LEAFS) && |
549 | 0 | func (node, data)) |
550 | 0 | return TRUE; |
551 | | |
552 | 0 | return FALSE; |
553 | 0 | } |
554 | | |
555 | | static gboolean |
556 | | g_node_traverse_post_order (GNode *node, |
557 | | GTraverseFlags flags, |
558 | | GNodeTraverseFunc func, |
559 | | gpointer data) |
560 | 0 | { |
561 | 0 | if (node->children) |
562 | 0 | { |
563 | 0 | GNode *child; |
564 | | |
565 | 0 | child = node->children; |
566 | 0 | while (child) |
567 | 0 | { |
568 | 0 | GNode *current; |
569 | | |
570 | 0 | current = child; |
571 | 0 | child = current->next; |
572 | 0 | if (g_node_traverse_post_order (current, flags, func, data)) |
573 | 0 | return TRUE; |
574 | 0 | } |
575 | | |
576 | 0 | if ((flags & G_TRAVERSE_NON_LEAFS) && |
577 | 0 | func (node, data)) |
578 | 0 | return TRUE; |
579 | | |
580 | 0 | } |
581 | 0 | else if ((flags & G_TRAVERSE_LEAFS) && |
582 | 0 | func (node, data)) |
583 | 0 | return TRUE; |
584 | | |
585 | 0 | return FALSE; |
586 | 0 | } |
587 | | |
588 | | static gboolean |
589 | | g_node_depth_traverse_post_order (GNode *node, |
590 | | GTraverseFlags flags, |
591 | | guint depth, |
592 | | GNodeTraverseFunc func, |
593 | | gpointer data) |
594 | 0 | { |
595 | 0 | if (node->children) |
596 | 0 | { |
597 | 0 | depth--; |
598 | 0 | if (depth) |
599 | 0 | { |
600 | 0 | GNode *child; |
601 | | |
602 | 0 | child = node->children; |
603 | 0 | while (child) |
604 | 0 | { |
605 | 0 | GNode *current; |
606 | | |
607 | 0 | current = child; |
608 | 0 | child = current->next; |
609 | 0 | if (g_node_depth_traverse_post_order (current, flags, depth, func, data)) |
610 | 0 | return TRUE; |
611 | 0 | } |
612 | 0 | } |
613 | | |
614 | 0 | if ((flags & G_TRAVERSE_NON_LEAFS) && |
615 | 0 | func (node, data)) |
616 | 0 | return TRUE; |
617 | | |
618 | 0 | } |
619 | 0 | else if ((flags & G_TRAVERSE_LEAFS) && |
620 | 0 | func (node, data)) |
621 | 0 | return TRUE; |
622 | | |
623 | 0 | return FALSE; |
624 | 0 | } |
625 | | |
626 | | static gboolean |
627 | | g_node_traverse_in_order (GNode *node, |
628 | | GTraverseFlags flags, |
629 | | GNodeTraverseFunc func, |
630 | | gpointer data) |
631 | 0 | { |
632 | 0 | if (node->children) |
633 | 0 | { |
634 | 0 | GNode *child; |
635 | 0 | GNode *current; |
636 | | |
637 | 0 | child = node->children; |
638 | 0 | current = child; |
639 | 0 | child = current->next; |
640 | | |
641 | 0 | if (g_node_traverse_in_order (current, flags, func, data)) |
642 | 0 | return TRUE; |
643 | | |
644 | 0 | if ((flags & G_TRAVERSE_NON_LEAFS) && |
645 | 0 | func (node, data)) |
646 | 0 | return TRUE; |
647 | | |
648 | 0 | while (child) |
649 | 0 | { |
650 | 0 | current = child; |
651 | 0 | child = current->next; |
652 | 0 | if (g_node_traverse_in_order (current, flags, func, data)) |
653 | 0 | return TRUE; |
654 | 0 | } |
655 | 0 | } |
656 | 0 | else if ((flags & G_TRAVERSE_LEAFS) && |
657 | 0 | func (node, data)) |
658 | 0 | return TRUE; |
659 | | |
660 | 0 | return FALSE; |
661 | 0 | } |
662 | | |
663 | | static gboolean |
664 | | g_node_depth_traverse_in_order (GNode *node, |
665 | | GTraverseFlags flags, |
666 | | guint depth, |
667 | | GNodeTraverseFunc func, |
668 | | gpointer data) |
669 | 0 | { |
670 | 0 | if (node->children) |
671 | 0 | { |
672 | 0 | depth--; |
673 | 0 | if (depth) |
674 | 0 | { |
675 | 0 | GNode *child; |
676 | 0 | GNode *current; |
677 | | |
678 | 0 | child = node->children; |
679 | 0 | current = child; |
680 | 0 | child = current->next; |
681 | | |
682 | 0 | if (g_node_depth_traverse_in_order (current, flags, depth, func, data)) |
683 | 0 | return TRUE; |
684 | | |
685 | 0 | if ((flags & G_TRAVERSE_NON_LEAFS) && |
686 | 0 | func (node, data)) |
687 | 0 | return TRUE; |
688 | | |
689 | 0 | while (child) |
690 | 0 | { |
691 | 0 | current = child; |
692 | 0 | child = current->next; |
693 | 0 | if (g_node_depth_traverse_in_order (current, flags, depth, func, data)) |
694 | 0 | return TRUE; |
695 | 0 | } |
696 | 0 | } |
697 | 0 | else if ((flags & G_TRAVERSE_NON_LEAFS) && |
698 | 0 | func (node, data)) |
699 | 0 | return TRUE; |
700 | 0 | } |
701 | 0 | else if ((flags & G_TRAVERSE_LEAFS) && |
702 | 0 | func (node, data)) |
703 | 0 | return TRUE; |
704 | | |
705 | 0 | return FALSE; |
706 | 0 | } |
707 | | |
708 | | static gboolean |
709 | | g_node_traverse_level (GNode *node, |
710 | | GTraverseFlags flags, |
711 | | guint level, |
712 | | GNodeTraverseFunc func, |
713 | | gpointer data, |
714 | | gboolean *more_levels) |
715 | 0 | { |
716 | 0 | if (level == 0) |
717 | 0 | { |
718 | 0 | if (node->children) |
719 | 0 | { |
720 | 0 | *more_levels = TRUE; |
721 | 0 | return (flags & G_TRAVERSE_NON_LEAFS) && func (node, data); |
722 | 0 | } |
723 | 0 | else |
724 | 0 | { |
725 | 0 | return (flags & G_TRAVERSE_LEAFS) && func (node, data); |
726 | 0 | } |
727 | 0 | } |
728 | 0 | else |
729 | 0 | { |
730 | 0 | node = node->children; |
731 | | |
732 | 0 | while (node) |
733 | 0 | { |
734 | 0 | if (g_node_traverse_level (node, flags, level - 1, func, data, more_levels)) |
735 | 0 | return TRUE; |
736 | | |
737 | 0 | node = node->next; |
738 | 0 | } |
739 | 0 | } |
740 | | |
741 | 0 | return FALSE; |
742 | 0 | } |
743 | | |
744 | | static gboolean |
745 | | g_node_depth_traverse_level (GNode *node, |
746 | | GTraverseFlags flags, |
747 | | gint depth, |
748 | | GNodeTraverseFunc func, |
749 | | gpointer data) |
750 | 0 | { |
751 | 0 | guint level; |
752 | 0 | gboolean more_levels; |
753 | |
|
754 | 0 | level = 0; |
755 | 0 | while (depth < 0 || level != (guint) depth) |
756 | 0 | { |
757 | 0 | more_levels = FALSE; |
758 | 0 | if (g_node_traverse_level (node, flags, level, func, data, &more_levels)) |
759 | 0 | return TRUE; |
760 | 0 | if (!more_levels) |
761 | 0 | break; |
762 | 0 | level++; |
763 | 0 | } |
764 | 0 | return FALSE; |
765 | 0 | } |
766 | | |
767 | | /** |
768 | | * g_node_traverse: |
769 | | * @root: the root #GNode of the tree to traverse |
770 | | * @order: the order in which nodes are visited - %G_IN_ORDER, |
771 | | * %G_PRE_ORDER, %G_POST_ORDER, or %G_LEVEL_ORDER. |
772 | | * @flags: which types of children are to be visited, one of |
773 | | * %G_TRAVERSE_ALL, %G_TRAVERSE_LEAVES and %G_TRAVERSE_NON_LEAVES |
774 | | * @max_depth: the maximum depth of the traversal. Nodes below this |
775 | | * depth will not be visited. If max_depth is -1 all nodes in |
776 | | * the tree are visited. If depth is 1, only the root is visited. |
777 | | * If depth is 2, the root and its children are visited. And so on. |
778 | | * @func: (scope call): the function to call for each visited #GNode |
779 | | * @data: user data to pass to the function |
780 | | * |
781 | | * Traverses a tree starting at the given root #GNode. |
782 | | * It calls the given function for each node visited. |
783 | | * The traversal can be halted at any point by returning %TRUE from @func. |
784 | | * @func must not do anything that would modify the structure of the tree. |
785 | | */ |
786 | | |
787 | | /** |
788 | | * GTraverseType: |
789 | | * @G_IN_ORDER: vists a node's left child first, then the node itself, |
790 | | * then its right child. This is the one to use if you |
791 | | * want the output sorted according to the compare |
792 | | * function. |
793 | | * @G_PRE_ORDER: visits a node, then its children. |
794 | | * @G_POST_ORDER: visits the node's children, then the node itself. |
795 | | * @G_LEVEL_ORDER: is not implemented for |
796 | | * [balanced binary trees][glib-Balanced-Binary-Trees]. |
797 | | * For [n-ary trees][glib-N-ary-Trees], it |
798 | | * vists the root node first, then its children, then |
799 | | * its grandchildren, and so on. Note that this is less |
800 | | * efficient than the other orders. |
801 | | * |
802 | | * Specifies the type of traversal performed by g_tree_traverse(), |
803 | | * g_node_traverse() and g_node_find(). The different orders are |
804 | | * illustrated here: |
805 | | * - In order: A, B, C, D, E, F, G, H, I |
806 | | *  |
807 | | * - Pre order: F, B, A, D, C, E, G, I, H |
808 | | *  |
809 | | * - Post order: A, C, E, D, B, H, I, G, F |
810 | | *  |
811 | | * - Level order: F, B, G, A, D, I, C, E, H |
812 | | *  |
813 | | */ |
814 | | |
815 | | /** |
816 | | * GTraverseFlags: |
817 | | * @G_TRAVERSE_LEAVES: only leaf nodes should be visited. This name has |
818 | | * been introduced in 2.6, for older version use |
819 | | * %G_TRAVERSE_LEAFS. |
820 | | * @G_TRAVERSE_NON_LEAVES: only non-leaf nodes should be visited. This |
821 | | * name has been introduced in 2.6, for older |
822 | | * version use %G_TRAVERSE_NON_LEAFS. |
823 | | * @G_TRAVERSE_ALL: all nodes should be visited. |
824 | | * @G_TRAVERSE_MASK: a mask of all traverse flags. |
825 | | * @G_TRAVERSE_LEAFS: identical to %G_TRAVERSE_LEAVES. |
826 | | * @G_TRAVERSE_NON_LEAFS: identical to %G_TRAVERSE_NON_LEAVES. |
827 | | * |
828 | | * Specifies which nodes are visited during several of the tree |
829 | | * functions, including g_node_traverse() and g_node_find(). |
830 | | **/ |
831 | | /** |
832 | | * GNodeTraverseFunc: |
833 | | * @node: a #GNode. |
834 | | * @data: user data passed to g_node_traverse(). |
835 | | * |
836 | | * Specifies the type of function passed to g_node_traverse(). The |
837 | | * function is called with each of the nodes visited, together with the |
838 | | * user data passed to g_node_traverse(). If the function returns |
839 | | * %TRUE, then the traversal is stopped. |
840 | | * |
841 | | * Returns: %TRUE to stop the traversal. |
842 | | **/ |
843 | | void |
844 | | g_node_traverse (GNode *root, |
845 | | GTraverseType order, |
846 | | GTraverseFlags flags, |
847 | | gint depth, |
848 | | GNodeTraverseFunc func, |
849 | | gpointer data) |
850 | 0 | { |
851 | 0 | g_return_if_fail (root != NULL); |
852 | 0 | g_return_if_fail (func != NULL); |
853 | 0 | g_return_if_fail (order <= G_LEVEL_ORDER); |
854 | 0 | g_return_if_fail (flags <= G_TRAVERSE_MASK); |
855 | 0 | g_return_if_fail (depth == -1 || depth > 0); |
856 | | |
857 | 0 | switch (order) |
858 | 0 | { |
859 | 0 | case G_PRE_ORDER: |
860 | 0 | if (depth < 0) |
861 | 0 | g_node_traverse_pre_order (root, flags, func, data); |
862 | 0 | else |
863 | 0 | g_node_depth_traverse_pre_order (root, flags, depth, func, data); |
864 | 0 | break; |
865 | 0 | case G_POST_ORDER: |
866 | 0 | if (depth < 0) |
867 | 0 | g_node_traverse_post_order (root, flags, func, data); |
868 | 0 | else |
869 | 0 | g_node_depth_traverse_post_order (root, flags, depth, func, data); |
870 | 0 | break; |
871 | 0 | case G_IN_ORDER: |
872 | 0 | if (depth < 0) |
873 | 0 | g_node_traverse_in_order (root, flags, func, data); |
874 | 0 | else |
875 | 0 | g_node_depth_traverse_in_order (root, flags, depth, func, data); |
876 | 0 | break; |
877 | 0 | case G_LEVEL_ORDER: |
878 | 0 | g_node_depth_traverse_level (root, flags, depth, func, data); |
879 | 0 | break; |
880 | 0 | } |
881 | 0 | } |
882 | | |
883 | | static gboolean |
884 | | g_node_find_func (GNode *node, |
885 | | gpointer data) |
886 | 0 | { |
887 | 0 | gpointer *d = data; |
888 | | |
889 | 0 | if (*d != node->data) |
890 | 0 | return FALSE; |
891 | | |
892 | 0 | *(++d) = node; |
893 | | |
894 | 0 | return TRUE; |
895 | 0 | } |
896 | | |
897 | | /** |
898 | | * g_node_find: |
899 | | * @root: the root #GNode of the tree to search |
900 | | * @order: the order in which nodes are visited - %G_IN_ORDER, |
901 | | * %G_PRE_ORDER, %G_POST_ORDER, or %G_LEVEL_ORDER |
902 | | * @flags: which types of children are to be searched, one of |
903 | | * %G_TRAVERSE_ALL, %G_TRAVERSE_LEAVES and %G_TRAVERSE_NON_LEAVES |
904 | | * @data: the data to find |
905 | | * |
906 | | * Finds a #GNode in a tree. |
907 | | * |
908 | | * Returns: the found #GNode, or %NULL if the data is not found |
909 | | */ |
910 | | GNode* |
911 | | g_node_find (GNode *root, |
912 | | GTraverseType order, |
913 | | GTraverseFlags flags, |
914 | | gpointer data) |
915 | 0 | { |
916 | 0 | gpointer d[2]; |
917 | | |
918 | 0 | g_return_val_if_fail (root != NULL, NULL); |
919 | 0 | g_return_val_if_fail (order <= G_LEVEL_ORDER, NULL); |
920 | 0 | g_return_val_if_fail (flags <= G_TRAVERSE_MASK, NULL); |
921 | | |
922 | 0 | d[0] = data; |
923 | 0 | d[1] = NULL; |
924 | | |
925 | 0 | g_node_traverse (root, order, flags, -1, g_node_find_func, d); |
926 | | |
927 | 0 | return d[1]; |
928 | 0 | } |
929 | | |
930 | | static void |
931 | | g_node_count_func (GNode *node, |
932 | | GTraverseFlags flags, |
933 | | guint *n) |
934 | 0 | { |
935 | 0 | if (node->children) |
936 | 0 | { |
937 | 0 | GNode *child; |
938 | | |
939 | 0 | if (flags & G_TRAVERSE_NON_LEAFS) |
940 | 0 | (*n)++; |
941 | | |
942 | 0 | child = node->children; |
943 | 0 | while (child) |
944 | 0 | { |
945 | 0 | g_node_count_func (child, flags, n); |
946 | 0 | child = child->next; |
947 | 0 | } |
948 | 0 | } |
949 | 0 | else if (flags & G_TRAVERSE_LEAFS) |
950 | 0 | (*n)++; |
951 | 0 | } |
952 | | |
953 | | /** |
954 | | * g_node_n_nodes: |
955 | | * @root: a #GNode |
956 | | * @flags: which types of children are to be counted, one of |
957 | | * %G_TRAVERSE_ALL, %G_TRAVERSE_LEAVES and %G_TRAVERSE_NON_LEAVES |
958 | | * |
959 | | * Gets the number of nodes in a tree. |
960 | | * |
961 | | * Returns: the number of nodes in the tree |
962 | | */ |
963 | | guint |
964 | | g_node_n_nodes (GNode *root, |
965 | | GTraverseFlags flags) |
966 | 0 | { |
967 | 0 | guint n = 0; |
968 | | |
969 | 0 | g_return_val_if_fail (root != NULL, 0); |
970 | 0 | g_return_val_if_fail (flags <= G_TRAVERSE_MASK, 0); |
971 | | |
972 | 0 | g_node_count_func (root, flags, &n); |
973 | | |
974 | 0 | return n; |
975 | 0 | } |
976 | | |
977 | | /** |
978 | | * g_node_last_child: |
979 | | * @node: a #GNode (must not be %NULL) |
980 | | * |
981 | | * Gets the last child of a #GNode. |
982 | | * |
983 | | * Returns: the last child of @node, or %NULL if @node has no children |
984 | | */ |
985 | | GNode* |
986 | | g_node_last_child (GNode *node) |
987 | 0 | { |
988 | 0 | g_return_val_if_fail (node != NULL, NULL); |
989 | | |
990 | 0 | node = node->children; |
991 | 0 | if (node) |
992 | 0 | while (node->next) |
993 | 0 | node = node->next; |
994 | | |
995 | 0 | return node; |
996 | 0 | } |
997 | | |
998 | | /** |
999 | | * g_node_nth_child: |
1000 | | * @node: a #GNode |
1001 | | * @n: the index of the desired child |
1002 | | * |
1003 | | * Gets a child of a #GNode, using the given index. |
1004 | | * The first child is at index 0. If the index is |
1005 | | * too big, %NULL is returned. |
1006 | | * |
1007 | | * Returns: the child of @node at index @n |
1008 | | */ |
1009 | | GNode* |
1010 | | g_node_nth_child (GNode *node, |
1011 | | guint n) |
1012 | 0 | { |
1013 | 0 | g_return_val_if_fail (node != NULL, NULL); |
1014 | | |
1015 | 0 | node = node->children; |
1016 | 0 | if (node) |
1017 | 0 | while ((n-- > 0) && node) |
1018 | 0 | node = node->next; |
1019 | | |
1020 | 0 | return node; |
1021 | 0 | } |
1022 | | |
1023 | | /** |
1024 | | * g_node_n_children: |
1025 | | * @node: a #GNode |
1026 | | * |
1027 | | * Gets the number of children of a #GNode. |
1028 | | * |
1029 | | * Returns: the number of children of @node |
1030 | | */ |
1031 | | guint |
1032 | | g_node_n_children (GNode *node) |
1033 | 0 | { |
1034 | 0 | guint n = 0; |
1035 | | |
1036 | 0 | g_return_val_if_fail (node != NULL, 0); |
1037 | | |
1038 | 0 | node = node->children; |
1039 | 0 | while (node) |
1040 | 0 | { |
1041 | 0 | n++; |
1042 | 0 | node = node->next; |
1043 | 0 | } |
1044 | | |
1045 | 0 | return n; |
1046 | 0 | } |
1047 | | |
1048 | | /** |
1049 | | * g_node_find_child: |
1050 | | * @node: a #GNode |
1051 | | * @flags: which types of children are to be searched, one of |
1052 | | * %G_TRAVERSE_ALL, %G_TRAVERSE_LEAVES and %G_TRAVERSE_NON_LEAVES |
1053 | | * @data: the data to find |
1054 | | * |
1055 | | * Finds the first child of a #GNode with the given data. |
1056 | | * |
1057 | | * Returns: the found child #GNode, or %NULL if the data is not found |
1058 | | */ |
1059 | | GNode* |
1060 | | g_node_find_child (GNode *node, |
1061 | | GTraverseFlags flags, |
1062 | | gpointer data) |
1063 | 0 | { |
1064 | 0 | g_return_val_if_fail (node != NULL, NULL); |
1065 | 0 | g_return_val_if_fail (flags <= G_TRAVERSE_MASK, NULL); |
1066 | | |
1067 | 0 | node = node->children; |
1068 | 0 | while (node) |
1069 | 0 | { |
1070 | 0 | if (node->data == data) |
1071 | 0 | { |
1072 | 0 | if (G_NODE_IS_LEAF (node)) |
1073 | 0 | { |
1074 | 0 | if (flags & G_TRAVERSE_LEAFS) |
1075 | 0 | return node; |
1076 | 0 | } |
1077 | 0 | else |
1078 | 0 | { |
1079 | 0 | if (flags & G_TRAVERSE_NON_LEAFS) |
1080 | 0 | return node; |
1081 | 0 | } |
1082 | 0 | } |
1083 | 0 | node = node->next; |
1084 | 0 | } |
1085 | | |
1086 | 0 | return NULL; |
1087 | 0 | } |
1088 | | |
1089 | | /** |
1090 | | * g_node_child_position: |
1091 | | * @node: a #GNode |
1092 | | * @child: a child of @node |
1093 | | * |
1094 | | * Gets the position of a #GNode with respect to its siblings. |
1095 | | * @child must be a child of @node. The first child is numbered 0, |
1096 | | * the second 1, and so on. |
1097 | | * |
1098 | | * Returns: the position of @child with respect to its siblings |
1099 | | */ |
1100 | | gint |
1101 | | g_node_child_position (GNode *node, |
1102 | | GNode *child) |
1103 | 0 | { |
1104 | 0 | guint n = 0; |
1105 | | |
1106 | 0 | g_return_val_if_fail (node != NULL, -1); |
1107 | 0 | g_return_val_if_fail (child != NULL, -1); |
1108 | 0 | g_return_val_if_fail (child->parent == node, -1); |
1109 | | |
1110 | 0 | node = node->children; |
1111 | 0 | while (node) |
1112 | 0 | { |
1113 | 0 | if (node == child) |
1114 | 0 | return n; |
1115 | 0 | n++; |
1116 | 0 | node = node->next; |
1117 | 0 | } |
1118 | | |
1119 | 0 | return -1; |
1120 | 0 | } |
1121 | | |
1122 | | /** |
1123 | | * g_node_child_index: |
1124 | | * @node: a #GNode |
1125 | | * @data: the data to find |
1126 | | * |
1127 | | * Gets the position of the first child of a #GNode |
1128 | | * which contains the given data. |
1129 | | * |
1130 | | * Returns: the index of the child of @node which contains |
1131 | | * @data, or -1 if the data is not found |
1132 | | */ |
1133 | | gint |
1134 | | g_node_child_index (GNode *node, |
1135 | | gpointer data) |
1136 | 0 | { |
1137 | 0 | guint n = 0; |
1138 | | |
1139 | 0 | g_return_val_if_fail (node != NULL, -1); |
1140 | | |
1141 | 0 | node = node->children; |
1142 | 0 | while (node) |
1143 | 0 | { |
1144 | 0 | if (node->data == data) |
1145 | 0 | return n; |
1146 | 0 | n++; |
1147 | 0 | node = node->next; |
1148 | 0 | } |
1149 | | |
1150 | 0 | return -1; |
1151 | 0 | } |
1152 | | |
1153 | | /** |
1154 | | * g_node_first_sibling: |
1155 | | * @node: a #GNode |
1156 | | * |
1157 | | * Gets the first sibling of a #GNode. |
1158 | | * This could possibly be the node itself. |
1159 | | * |
1160 | | * Returns: the first sibling of @node |
1161 | | */ |
1162 | | GNode* |
1163 | | g_node_first_sibling (GNode *node) |
1164 | 0 | { |
1165 | 0 | g_return_val_if_fail (node != NULL, NULL); |
1166 | | |
1167 | 0 | if (node->parent) |
1168 | 0 | return node->parent->children; |
1169 | | |
1170 | 0 | while (node->prev) |
1171 | 0 | node = node->prev; |
1172 | | |
1173 | 0 | return node; |
1174 | 0 | } |
1175 | | |
1176 | | /** |
1177 | | * g_node_last_sibling: |
1178 | | * @node: a #GNode |
1179 | | * |
1180 | | * Gets the last sibling of a #GNode. |
1181 | | * This could possibly be the node itself. |
1182 | | * |
1183 | | * Returns: the last sibling of @node |
1184 | | */ |
1185 | | GNode* |
1186 | | g_node_last_sibling (GNode *node) |
1187 | 0 | { |
1188 | 0 | g_return_val_if_fail (node != NULL, NULL); |
1189 | | |
1190 | 0 | while (node->next) |
1191 | 0 | node = node->next; |
1192 | | |
1193 | 0 | return node; |
1194 | 0 | } |
1195 | | |
1196 | | /** |
1197 | | * g_node_children_foreach: |
1198 | | * @node: a #GNode |
1199 | | * @flags: which types of children are to be visited, one of |
1200 | | * %G_TRAVERSE_ALL, %G_TRAVERSE_LEAVES and %G_TRAVERSE_NON_LEAVES |
1201 | | * @func: (scope call): the function to call for each visited node |
1202 | | * @data: user data to pass to the function |
1203 | | * |
1204 | | * Calls a function for each of the children of a #GNode. Note that it |
1205 | | * doesn't descend beneath the child nodes. @func must not do anything |
1206 | | * that would modify the structure of the tree. |
1207 | | */ |
1208 | | /** |
1209 | | * GNodeForeachFunc: |
1210 | | * @node: a #GNode. |
1211 | | * @data: user data passed to g_node_children_foreach(). |
1212 | | * |
1213 | | * Specifies the type of function passed to g_node_children_foreach(). |
1214 | | * The function is called with each child node, together with the user |
1215 | | * data passed to g_node_children_foreach(). |
1216 | | **/ |
1217 | | void |
1218 | | g_node_children_foreach (GNode *node, |
1219 | | GTraverseFlags flags, |
1220 | | GNodeForeachFunc func, |
1221 | | gpointer data) |
1222 | 0 | { |
1223 | 0 | g_return_if_fail (node != NULL); |
1224 | 0 | g_return_if_fail (flags <= G_TRAVERSE_MASK); |
1225 | 0 | g_return_if_fail (func != NULL); |
1226 | | |
1227 | 0 | node = node->children; |
1228 | 0 | while (node) |
1229 | 0 | { |
1230 | 0 | GNode *current; |
1231 | | |
1232 | 0 | current = node; |
1233 | 0 | node = current->next; |
1234 | 0 | if (G_NODE_IS_LEAF (current)) |
1235 | 0 | { |
1236 | 0 | if (flags & G_TRAVERSE_LEAFS) |
1237 | 0 | func (current, data); |
1238 | 0 | } |
1239 | 0 | else |
1240 | 0 | { |
1241 | 0 | if (flags & G_TRAVERSE_NON_LEAFS) |
1242 | 0 | func (current, data); |
1243 | 0 | } |
1244 | 0 | } |
1245 | 0 | } |