2 * Wireshark Memory Manager Red-Black Tree
3 * Based on the red-black tree implementation in epan/emem.*
4 * Copyright 2013, Evan Huus <eapache@gmail.com>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
20 #include "wmem_core.h"
21 #include "wmem_strutl.h"
22 #include "wmem_tree.h"
23 #include "wmem_tree-int.h"
24 #include "wmem_user_cb.h"
26 static wmem_tree_node_t
*
27 node_uncle(wmem_tree_node_t
*node
)
29 wmem_tree_node_t
*parent
, *grandparent
;
31 parent
= node
->parent
;
36 grandparent
= parent
->parent
;
37 if (grandparent
== NULL
) {
41 if (parent
== grandparent
->left
) {
42 return grandparent
->right
;
45 return grandparent
->left
;
49 static void rb_insert_case1(wmem_tree_t
*tree
, wmem_tree_node_t
*node
);
50 static void rb_insert_case2(wmem_tree_t
*tree
, wmem_tree_node_t
*node
);
53 rotate_left(wmem_tree_t
*tree
, wmem_tree_node_t
*node
)
56 if (node
->parent
->left
== node
) {
57 node
->parent
->left
= node
->right
;
60 node
->parent
->right
= node
->right
;
64 tree
->root
= node
->right
;
67 node
->right
->parent
= node
->parent
;
68 node
->parent
= node
->right
;
69 node
->right
= node
->right
->left
;
71 node
->right
->parent
= node
;
73 node
->parent
->left
= node
;
75 if (tree
->post_rotation_cb
) {
76 tree
->post_rotation_cb (node
);
81 rotate_right(wmem_tree_t
*tree
, wmem_tree_node_t
*node
)
84 if (node
->parent
->left
== node
) {
85 node
->parent
->left
= node
->left
;
88 node
->parent
->right
= node
->left
;
92 tree
->root
= node
->left
;
95 node
->left
->parent
= node
->parent
;
96 node
->parent
= node
->left
;
97 node
->left
= node
->left
->right
;
99 node
->left
->parent
= node
;
101 node
->parent
->right
= node
;
104 if (tree
->post_rotation_cb
) {
105 tree
->post_rotation_cb (node
);
110 rb_insert_case5(wmem_tree_t
*tree
, wmem_tree_node_t
*node
)
112 wmem_tree_node_t
*parent
, *grandparent
;
114 parent
= node
->parent
;
115 grandparent
= parent
->parent
;
117 parent
->color
= WMEM_NODE_COLOR_BLACK
;
118 grandparent
->color
= WMEM_NODE_COLOR_RED
;
120 if (node
== parent
->left
&& parent
== grandparent
->left
) {
121 rotate_right(tree
, grandparent
);
124 rotate_left(tree
, grandparent
);
129 rb_insert_case4(wmem_tree_t
*tree
, wmem_tree_node_t
*node
)
131 wmem_tree_node_t
*parent
, *grandparent
;
133 parent
= node
->parent
;
134 grandparent
= parent
->parent
;
139 if (node
== parent
->right
&& parent
== grandparent
->left
) {
140 rotate_left(tree
, parent
);
143 else if (node
== parent
->left
&& parent
== grandparent
->right
) {
144 rotate_right(tree
, parent
);
148 rb_insert_case5(tree
, node
);
152 rb_insert_case3(wmem_tree_t
*tree
, wmem_tree_node_t
*node
)
154 wmem_tree_node_t
*parent
, *grandparent
, *uncle
;
156 uncle
= node_uncle(node
);
158 if (uncle
&& uncle
->color
== WMEM_NODE_COLOR_RED
) {
159 parent
= node
->parent
;
160 grandparent
= parent
->parent
;
162 parent
->color
= WMEM_NODE_COLOR_BLACK
;
163 uncle
->color
= WMEM_NODE_COLOR_BLACK
;
164 grandparent
->color
= WMEM_NODE_COLOR_RED
;
166 rb_insert_case1(tree
, grandparent
);
169 rb_insert_case4(tree
, node
);
174 rb_insert_case2(wmem_tree_t
*tree
, wmem_tree_node_t
*node
)
176 /* parent is always non-NULL here */
177 if (node
->parent
->color
== WMEM_NODE_COLOR_RED
) {
178 rb_insert_case3(tree
, node
);
183 rb_insert_case1(wmem_tree_t
*tree
, wmem_tree_node_t
*node
)
185 wmem_tree_node_t
*parent
= node
->parent
;
187 if (parent
== NULL
) {
188 node
->color
= WMEM_NODE_COLOR_BLACK
;
191 rb_insert_case2(tree
, node
);
196 rb_remove_doubleblack(wmem_tree_t
*tree
, wmem_tree_node_t
*node
)
198 wmem_tree_node_t
*parent
= node
->parent
;
199 wmem_tree_node_t
*sib
, *c_nephew
, *d_nephew
;
203 if (node
== parent
->left
) {
208 parent
->right
= NULL
;
211 for (node
= NULL
; parent
; parent
= node
->parent
) {
213 left
= (node
== parent
->left
);
217 c_nephew
= sib
->left
;
218 d_nephew
= sib
->right
;
221 c_nephew
= sib
->right
;
222 d_nephew
= sib
->left
;
224 if (sib
&& sib
->color
== WMEM_NODE_COLOR_RED
) {
227 } else if (d_nephew
&& d_nephew
->color
== WMEM_NODE_COLOR_RED
) {
230 } else if (c_nephew
&& c_nephew
->color
== WMEM_NODE_COLOR_RED
) {
231 // C red, Sib, D black
233 } else if (parent
->color
== WMEM_NODE_COLOR_RED
) {
234 // Parent red, Sib, D, C black
238 sib
->color
= WMEM_NODE_COLOR_RED
;
247 rotate_left(tree
, parent
);
249 rotate_right(tree
, parent
);
251 parent
->color
= WMEM_NODE_COLOR_RED
;
252 sib
->color
= WMEM_NODE_COLOR_BLACK
;
254 d_nephew
= left
? sib
->right
: sib
->left
;
255 if (d_nephew
&& d_nephew
->color
== WMEM_NODE_COLOR_RED
)
257 c_nephew
= left
? sib
->left
: sib
->right
;
258 if (c_nephew
&& c_nephew
->color
== WMEM_NODE_COLOR_RED
)
262 sib
->color
= WMEM_NODE_COLOR_RED
;
263 parent
->color
= WMEM_NODE_COLOR_BLACK
;
268 rotate_right(tree
, sib
);
270 rotate_left(tree
, sib
);
272 sib
->color
= WMEM_NODE_COLOR_RED
;
273 c_nephew
->color
= WMEM_NODE_COLOR_BLACK
;
276 // D red and sib black;
280 rotate_left(tree
, parent
);
282 rotate_right(tree
, parent
);
284 sib
->color
= parent
->color
;
285 parent
->color
= WMEM_NODE_COLOR_BLACK
;
286 d_nephew
->color
= WMEM_NODE_COLOR_BLACK
;
291 rb_remove_node(wmem_tree_t
*tree
, wmem_tree_node_t
*node
, bool free_key
)
293 wmem_tree_node_t
*temp_node
;
294 /* First, if the node has both children, swap the key and data
295 * with the in-order successor and delete that node instead.
297 if (node
->left
&& node
->right
) {
298 temp_node
= node
->right
;
299 while (temp_node
->left
) {
300 temp_node
= temp_node
->left
;
302 node
->key
= temp_node
->key
;
303 node
->data
= temp_node
->data
;
307 wmem_node_color_t child_color
= WMEM_NODE_COLOR_BLACK
;
308 /* node now has one child at most. */
310 temp_node
= node
->left
;
311 ws_assert(node
->right
== NULL
);
313 temp_node
= node
->right
;
315 /* If there is a child, then the child must be red and original
316 * node black, or else the R-B tree assumptions are wrong and
317 * there's a problem elsewhere in the code. */
319 child_color
= temp_node
->color
;
320 ws_assert(child_color
== WMEM_NODE_COLOR_RED
);
321 ws_assert(node
->color
== WMEM_NODE_COLOR_BLACK
);
322 temp_node
->parent
= node
->parent
;
323 temp_node
->color
= WMEM_NODE_COLOR_BLACK
;
326 if (temp_node
== NULL
&&
327 node
->color
== WMEM_NODE_COLOR_BLACK
&& node
->parent
) {
329 /* Removing will create a "double black" imbalance in the tree and
330 * we will need to rectify it to keep this a R-B tree.
331 * This function removes and does any necessary rotations.
333 rb_remove_doubleblack(tree
, node
);
335 // Now remove the node from the tree.
337 if (node
== node
->parent
->left
) {
338 node
->parent
->left
= temp_node
;
340 node
->parent
->right
= temp_node
;
343 tree
->root
= temp_node
;
347 /* Freeing memory is only strictly necessary for a NULL allocator.
348 * The key is copied in a string tree, a GUINT_TO_POINTER in a
349 * 32 bit integer tree, and used uncopied in a generic tree, so
350 * it should be freed in the first case but not the others.
351 * The value is returned, so not freed under any circumstance.
354 wmem_free(tree
->data_allocator
, (void *)node
->key
);
356 wmem_free(tree
->data_allocator
, node
);
360 wmem_tree_new(wmem_allocator_t
*allocator
)
364 tree
= wmem_new0(allocator
, wmem_tree_t
);
365 tree
->metadata_allocator
= allocator
;
366 tree
->data_allocator
= allocator
;
372 wmem_tree_reset_cb(wmem_allocator_t
*allocator _U_
, wmem_cb_event_t event
,
375 wmem_tree_t
*tree
= (wmem_tree_t
*)user_data
;
379 if (event
== WMEM_CB_DESTROY_EVENT
) {
380 wmem_unregister_callback(tree
->metadata_allocator
, tree
->metadata_scope_cb_id
);
381 wmem_free(tree
->metadata_allocator
, tree
);
388 wmem_tree_destroy_cb(wmem_allocator_t
*allocator _U_
, wmem_cb_event_t event _U_
,
391 wmem_tree_t
*tree
= (wmem_tree_t
*)user_data
;
393 wmem_unregister_callback(tree
->data_allocator
, tree
->data_scope_cb_id
);
399 wmem_tree_new_autoreset(wmem_allocator_t
*metadata_scope
, wmem_allocator_t
*data_scope
)
403 tree
= wmem_new0(metadata_scope
, wmem_tree_t
);
404 tree
->metadata_allocator
= metadata_scope
;
405 tree
->data_allocator
= data_scope
;
407 tree
->metadata_scope_cb_id
= wmem_register_callback(metadata_scope
, wmem_tree_destroy_cb
,
409 tree
->data_scope_cb_id
= wmem_register_callback(data_scope
, wmem_tree_reset_cb
,
416 free_tree_node(wmem_allocator_t
*allocator
, wmem_tree_node_t
* node
, bool free_keys
, bool free_values
)
423 free_tree_node(allocator
, node
->left
, free_keys
, free_values
);
426 if (node
->is_subtree
) {
427 wmem_tree_destroy((wmem_tree_t
*)node
->data
, free_keys
, free_values
);
432 free_tree_node(allocator
, node
->right
, free_keys
, free_values
);
436 wmem_free(allocator
, (void*)node
->key
);
440 wmem_free(allocator
, node
->data
);
442 wmem_free(allocator
, node
);
446 wmem_tree_destroy(wmem_tree_t
*tree
, bool free_keys
, bool free_values
)
448 free_tree_node(tree
->data_allocator
, tree
->root
, free_keys
, free_values
);
449 if (tree
->metadata_allocator
) {
450 wmem_unregister_callback(tree
->metadata_allocator
, tree
->metadata_scope_cb_id
);
452 if (tree
->data_allocator
) {
453 wmem_unregister_callback(tree
->data_allocator
, tree
->data_scope_cb_id
);
455 wmem_free(tree
->metadata_allocator
, tree
);
459 wmem_tree_is_empty(wmem_tree_t
*tree
)
461 return tree
->root
== NULL
;
465 count_nodes(const void *key _U_
, void *value _U_
, void *userdata
)
467 unsigned* count
= (unsigned*)userdata
;
473 wmem_tree_count(wmem_tree_t
* tree
)
477 /* Recursing through the tree counting each node is the simplest approach.
478 We don't keep track of the count within the tree because it can get
479 complicated with subtrees within the tree */
480 wmem_tree_foreach(tree
, count_nodes
, &count
);
485 static wmem_tree_node_t
*
486 create_node(wmem_allocator_t
*allocator
, wmem_tree_node_t
*parent
, const void *key
,
487 void *data
, wmem_node_color_t color
, bool is_subtree
)
489 wmem_tree_node_t
*node
;
491 node
= wmem_new(allocator
, wmem_tree_node_t
);
495 node
->parent
= parent
;
501 node
->is_subtree
= is_subtree
;
502 node
->is_removed
= false;
507 #define CREATE_DATA(TRANSFORM, DATA) ((TRANSFORM) ? (TRANSFORM)(DATA) : (DATA))
511 * return inserted node
513 static wmem_tree_node_t
*
514 lookup_or_insert32_node(wmem_tree_t
*tree
, uint32_t key
,
515 void*(*func
)(void*), void* data
, bool is_subtree
, bool replace
)
517 wmem_tree_node_t
*node
= tree
->root
;
518 wmem_tree_node_t
*new_node
= NULL
;
520 /* is this the first node ?*/
522 new_node
= create_node(tree
->data_allocator
, NULL
, GUINT_TO_POINTER(key
),
523 CREATE_DATA(func
, data
), WMEM_NODE_COLOR_BLACK
, is_subtree
);
524 tree
->root
= new_node
;
528 /* it was not the new root so walk the tree until we find where to
529 * insert this new leaf.
532 /* this node already exists, so just return the data pointer*/
533 if (key
== GPOINTER_TO_UINT(node
->key
)) {
535 node
->data
= CREATE_DATA(func
, data
);
539 else if (key
< GPOINTER_TO_UINT(node
->key
)) {
544 /* new node to the left */
545 new_node
= create_node(tree
->data_allocator
, node
, GUINT_TO_POINTER(key
),
546 CREATE_DATA(func
, data
), WMEM_NODE_COLOR_RED
,
548 node
->left
= new_node
;
551 else if (key
> GPOINTER_TO_UINT(node
->key
)) {
556 /* new node to the right */
557 new_node
= create_node(tree
->data_allocator
, node
, GUINT_TO_POINTER(key
),
558 CREATE_DATA(func
, data
), WMEM_NODE_COLOR_RED
,
560 node
->right
= new_node
;
565 /* node will now point to the newly created node */
566 rb_insert_case1(tree
, new_node
);
573 lookup_or_insert32(wmem_tree_t
*tree
, uint32_t key
,
574 void*(*func
)(void*), void* data
, bool is_subtree
, bool replace
)
576 wmem_tree_node_t
*node
= lookup_or_insert32_node(tree
, key
, func
, data
, is_subtree
, replace
);
581 wmem_tree_lookup(wmem_tree_t
*tree
, const void *key
, compare_func cmp
)
583 wmem_tree_node_t
*node
;
585 if (tree
== NULL
|| key
== NULL
) {
592 int result
= cmp(key
, node
->key
);
596 else if (result
< 0) {
599 else if (result
> 0) {
608 wmem_tree_insert_node(wmem_tree_t
*tree
, const void *key
, void *data
, compare_func cmp
)
610 wmem_tree_node_t
*node
= tree
->root
;
611 wmem_tree_node_t
*new_node
= NULL
;
613 /* is this the first node ?*/
615 tree
->root
= create_node(tree
->data_allocator
, node
, key
,
616 data
, WMEM_NODE_COLOR_BLACK
, false);
620 /* it was not the new root so walk the tree until we find where to
621 * insert this new leaf.
624 int result
= cmp(key
, node
->key
);
627 node
->is_removed
= data
? false : true;
630 else if (result
< 0) {
635 new_node
= create_node(tree
->data_allocator
, node
, key
,
636 data
, WMEM_NODE_COLOR_RED
, false);
637 node
->left
= new_node
;
640 else if (result
> 0) {
645 /* new node to the right */
646 new_node
= create_node(tree
->data_allocator
, node
, key
,
647 data
, WMEM_NODE_COLOR_RED
, false);
648 node
->right
= new_node
;
653 /* node will now point to the newly created node */
654 rb_insert_case1(tree
, new_node
);
660 wmem_tree_insert32(wmem_tree_t
*tree
, uint32_t key
, void *data
)
662 lookup_or_insert32(tree
, key
, NULL
, data
, false, true);
665 bool wmem_tree_contains32(wmem_tree_t
*tree
, uint32_t key
)
671 wmem_tree_node_t
*node
= tree
->root
;
674 if (key
== GPOINTER_TO_UINT(node
->key
)) {
677 else if (key
< GPOINTER_TO_UINT(node
->key
)) {
680 else if (key
> GPOINTER_TO_UINT(node
->key
)) {
688 static wmem_tree_node_t
*
689 wmem_tree_lookup32_node(wmem_tree_t
*tree
, uint32_t key
)
695 wmem_tree_node_t
*node
= tree
->root
;
698 if (key
== GPOINTER_TO_UINT(node
->key
)) {
701 else if (key
< GPOINTER_TO_UINT(node
->key
)) {
704 else if (key
> GPOINTER_TO_UINT(node
->key
)) {
713 wmem_tree_lookup32(wmem_tree_t
*tree
, uint32_t key
)
715 wmem_tree_node_t
*node
= wmem_tree_lookup32_node(tree
, key
);
722 static wmem_tree_node_t
*
723 wmem_tree_lookup32_le_node(wmem_tree_t
*tree
, uint32_t key
)
729 wmem_tree_node_t
*node
= tree
->root
;
732 if (key
== GPOINTER_TO_UINT(node
->key
)) {
735 else if (key
< GPOINTER_TO_UINT(node
->key
)) {
736 if (node
->left
== NULL
) {
741 else if (key
> GPOINTER_TO_UINT(node
->key
)) {
742 if (node
->right
== NULL
) {
753 /* If we are still at the root of the tree this means that this node
754 * is either smaller than the search key and then we return this
755 * node or else there is no smaller key available and then
758 if (node
->parent
== NULL
) {
759 if (key
> GPOINTER_TO_UINT(node
->key
)) {
766 if (GPOINTER_TO_UINT(node
->key
) <= key
) {
767 /* if our key is <= the search key, we have the right node */
770 else if (node
== node
->parent
->left
) {
771 /* our key is bigger than the search key and we're a left child,
772 * we have to check if any of our ancestors are smaller. */
774 if (key
> GPOINTER_TO_UINT(node
->key
)) {
782 /* our key is bigger than the search key and we're a right child,
783 * our parent is the one we want */
789 wmem_tree_lookup32_le(wmem_tree_t
*tree
, uint32_t key
)
791 wmem_tree_node_t
*node
= wmem_tree_lookup32_le_node(tree
, key
);
800 wmem_tree_lookup32_le_full(wmem_tree_t
*tree
, uint32_t key
, uint32_t *orig_key
)
802 wmem_tree_node_t
*node
= wmem_tree_lookup32_le_node(tree
, key
);
807 *orig_key
= GPOINTER_TO_UINT(node
->key
);
811 static wmem_tree_node_t
*
812 wmem_tree_lookup32_ge_node(wmem_tree_t
*tree
, uint32_t key
)
818 wmem_tree_node_t
*node
= tree
->root
;
821 if (key
== GPOINTER_TO_UINT(node
->key
)) {
824 else if (key
< GPOINTER_TO_UINT(node
->key
)) {
825 if (node
->left
== NULL
) {
830 else if (key
> GPOINTER_TO_UINT(node
->key
)) {
831 if (node
->right
== NULL
) {
842 /* If we are still at the root of the tree this means that this node
843 * is either greater than the search key and then we return this
844 * node or else there is no greater key available and then
847 if (node
->parent
== NULL
) {
848 if (key
< GPOINTER_TO_UINT(node
->key
)) {
855 if (GPOINTER_TO_UINT(node
->key
) >= key
) {
856 /* if our key is >= the search key, we have the right node */
859 else if (node
== node
->parent
->right
) {
860 /* our key is smaller than the search key and we're a right child,
861 * we have to check if any of our ancestors are bigger. */
863 if (key
< GPOINTER_TO_UINT(node
->key
)) {
871 /* our key is smaller than the search key and we're a left child,
872 * our parent is the one we want */
878 wmem_tree_lookup32_ge(wmem_tree_t
*tree
, uint32_t key
)
880 wmem_tree_node_t
*node
= wmem_tree_lookup32_ge_node(tree
, key
);
889 wmem_tree_lookup32_ge_full(wmem_tree_t
*tree
, uint32_t key
, uint32_t *orig_key
)
891 wmem_tree_node_t
*node
= wmem_tree_lookup32_ge_node(tree
, key
);
896 *orig_key
= GPOINTER_TO_UINT(node
->key
);
901 wmem_tree_remove32(wmem_tree_t
*tree
, uint32_t key
)
903 wmem_tree_node_t
*node
= wmem_tree_lookup32_node(tree
, key
);
908 void *ret
= node
->data
;
910 /* Remove the node. Do not free the key, because it is a
911 * GPOINTER_TO_UINT. The value we return.
913 rb_remove_node(tree
, node
, false);
919 wmem_tree_insert_string(wmem_tree_t
* tree
, const char* k
, void* v
, uint32_t flags
)
924 key
= wmem_strdup(tree
->data_allocator
, k
);
926 if (flags
& WMEM_TREE_STRING_NOCASE
) {
927 cmp
= (compare_func
)g_ascii_strcasecmp
;
929 cmp
= (compare_func
)strcmp
;
932 wmem_tree_insert_node(tree
, key
, v
, cmp
);
936 wmem_tree_lookup_string(wmem_tree_t
* tree
, const char* k
, uint32_t flags
)
940 if (flags
& WMEM_TREE_STRING_NOCASE
) {
941 cmp
= (compare_func
)g_ascii_strcasecmp
;
943 cmp
= (compare_func
)strcmp
;
946 return wmem_tree_lookup(tree
, k
, cmp
);
950 wmem_tree_remove_string(wmem_tree_t
* tree
, const char* k
, uint32_t flags
)
952 void *ret
= wmem_tree_lookup_string(tree
, k
, flags
);
954 /* Not really a remove, but set data to NULL to mark node with is_removed */
955 wmem_tree_insert_string(tree
, k
, NULL
, flags
);
961 create_sub_tree(void* d
)
963 return wmem_tree_new(((wmem_tree_t
*)d
)->data_allocator
);
967 wmem_tree_insert32_array(wmem_tree_t
*tree
, wmem_tree_key_t
*key
, void *data
)
969 wmem_tree_t
*insert_tree
= NULL
;
970 wmem_tree_key_t
*cur_key
;
971 uint32_t i
, insert_key32
= 0;
973 for (cur_key
= key
; cur_key
->length
> 0; cur_key
++) {
974 for (i
= 0; i
< cur_key
->length
; i
++) {
975 /* Insert using the previous key32 */
979 insert_tree
= (wmem_tree_t
*)lookup_or_insert32(insert_tree
,
980 insert_key32
, create_sub_tree
, tree
, true, false);
982 insert_key32
= cur_key
->key
[i
];
986 ws_assert(insert_tree
);
988 wmem_tree_insert32(insert_tree
, insert_key32
, data
);
992 wmem_tree_lookup32_array_helper(wmem_tree_t
*tree
, wmem_tree_key_t
*key
,
993 void*(*helper
)(wmem_tree_t
*, uint32_t))
995 wmem_tree_t
*lookup_tree
= NULL
;
996 wmem_tree_key_t
*cur_key
;
997 uint32_t i
, lookup_key32
= 0;
1003 for (cur_key
= key
; cur_key
->length
> 0; cur_key
++) {
1004 for (i
= 0; i
< cur_key
->length
; i
++) {
1005 /* Lookup using the previous key32 */
1011 (wmem_tree_t
*)(*helper
)(lookup_tree
, lookup_key32
);
1016 lookup_key32
= cur_key
->key
[i
];
1020 /* Assert if we didn't get any valid keys */
1021 ws_assert(lookup_tree
);
1023 return (*helper
)(lookup_tree
, lookup_key32
);
1027 wmem_tree_lookup32_array(wmem_tree_t
*tree
, wmem_tree_key_t
*key
)
1029 return wmem_tree_lookup32_array_helper(tree
, key
, wmem_tree_lookup32
);
1033 wmem_tree_lookup32_array_le(wmem_tree_t
*tree
, wmem_tree_key_t
*key
)
1035 return wmem_tree_lookup32_array_helper(tree
, key
, wmem_tree_lookup32_le
);
1039 wmem_tree_foreach_nodes(wmem_tree_node_t
* node
, wmem_foreach_func callback
,
1042 bool stop_traverse
= false;
1049 if (wmem_tree_foreach_nodes(node
->left
, callback
, user_data
)) {
1054 if (node
->is_subtree
) {
1055 stop_traverse
= wmem_tree_foreach((wmem_tree_t
*)node
->data
,
1056 callback
, user_data
);
1057 } else if (!node
->is_removed
) {
1058 /* No callback for "removed" nodes */
1059 stop_traverse
= callback(node
->key
, node
->data
, user_data
);
1062 if (stop_traverse
) {
1067 if (wmem_tree_foreach_nodes(node
->right
, callback
, user_data
)) {
1076 wmem_tree_foreach(wmem_tree_t
* tree
, wmem_foreach_func callback
,
1082 return wmem_tree_foreach_nodes(tree
->root
, callback
, user_data
);
1085 static void wmem_print_subtree(wmem_tree_t
*tree
, uint32_t level
, wmem_printer_func key_printer
, wmem_printer_func data_printer
);
1088 wmem_print_indent(uint32_t level
) {
1090 for (i
=0; i
<level
; i
++) {
1096 wmem_tree_print_nodes(const char *prefix
, wmem_tree_node_t
*node
, uint32_t level
,
1097 wmem_printer_func key_printer
, wmem_printer_func data_printer
)
1102 wmem_print_indent(level
);
1104 printf("%sNODE:%p parent:%p left:%p right:%p colour:%s key:%p %s:%p\n",
1106 (void *)node
, (void *)node
->parent
,
1107 (void *)node
->left
, (void *)node
->right
,
1108 node
->color
?"Black":"Red", node
->key
,
1109 node
->is_subtree
?"tree":"data", node
->data
);
1111 wmem_print_indent(level
);
1112 key_printer(node
->key
);
1115 if (data_printer
&& !node
->is_subtree
) {
1116 wmem_print_indent(level
);
1117 data_printer(node
->data
);
1122 wmem_tree_print_nodes("L-", node
->left
, level
+1, key_printer
, data_printer
);
1124 wmem_tree_print_nodes("R-", node
->right
, level
+1, key_printer
, data_printer
);
1126 if (node
->is_subtree
)
1127 wmem_print_subtree((wmem_tree_t
*)node
->data
, level
+1, key_printer
, data_printer
);
1132 wmem_print_subtree(wmem_tree_t
*tree
, uint32_t level
, wmem_printer_func key_printer
, wmem_printer_func data_printer
)
1137 wmem_print_indent(level
);
1139 printf("WMEM tree:%p root:%p\n", (void *)tree
, (void *)tree
->root
);
1141 wmem_tree_print_nodes("Root-", tree
->root
, level
, key_printer
, data_printer
);
1146 wmem_print_tree(wmem_tree_t
*tree
, wmem_printer_func key_printer
, wmem_printer_func data_printer
)
1148 wmem_print_subtree(tree
, 0, key_printer
, data_printer
);
1151 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1156 * indent-tabs-mode: nil
1159 * vi: set shiftwidth=4 tabstop=8 expandtab:
1160 * :indentSize=4:tabSize=8:noTabs=true: