Coverage Report

Created: 2025-08-04 07:15

/src/wireshark/wsutil/wmem/wmem_tree.c
Line
Count
Source (jump to first uncovered line)
1
/* wmem_tree.c
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>
5
 *
6
 * Wireshark - Network traffic analyzer
7
 * By Gerald Combs <gerald@wireshark.org>
8
 * Copyright 1998 Gerald Combs
9
 *
10
 * SPDX-License-Identifier: GPL-2.0-or-later
11
 */
12
13
#include "config.h"
14
15
#include <string.h>
16
#include <stdio.h>
17
#include <glib.h>
18
19
#include "wmem-int.h"
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"
25
26
static wmem_tree_node_t *
27
node_uncle(wmem_tree_node_t *node)
28
108k
{
29
108k
    wmem_tree_node_t *parent, *grandparent;
30
31
108k
    parent = node->parent;
32
108k
    if (parent == NULL) {
33
0
        return NULL;
34
0
    }
35
36
108k
    grandparent = parent->parent;
37
108k
    if (grandparent == NULL) {
38
0
        return NULL;
39
0
    }
40
41
108k
    if (parent == grandparent->left) {
42
20.3k
        return grandparent->right;
43
20.3k
    }
44
88.5k
    else {
45
88.5k
        return grandparent->left;
46
88.5k
    }
47
108k
}
48
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);
51
52
static void
53
rotate_left(wmem_tree_t *tree, wmem_tree_node_t *node)
54
53.3k
{
55
53.3k
    if (node->parent) {
56
47.2k
        if (node->parent->left == node) {
57
17.0k
            node->parent->left = node->right;
58
17.0k
        }
59
30.2k
        else {
60
30.2k
            node->parent->right = node->right;
61
30.2k
        }
62
47.2k
    }
63
6.07k
    else {
64
6.07k
        tree->root = node->right;
65
6.07k
    }
66
67
53.3k
    node->right->parent = node->parent;
68
53.3k
    node->parent        = node->right;
69
53.3k
    node->right         = node->right->left;
70
53.3k
    if (node->right) {
71
18.9k
        node->right->parent = node;
72
18.9k
    }
73
53.3k
    node->parent->left = node;
74
75
53.3k
    if (tree->post_rotation_cb) {
76
23
        tree->post_rotation_cb (node);
77
23
    }
78
53.3k
}
79
80
static void
81
rotate_right(wmem_tree_t *tree, wmem_tree_node_t *node)
82
17.4k
{
83
17.4k
    if (node->parent) {
84
16.2k
        if (node->parent->left == node) {
85
4.22k
            node->parent->left = node->left;
86
4.22k
        }
87
12.0k
        else {
88
12.0k
            node->parent->right = node->left;
89
12.0k
        }
90
16.2k
    }
91
1.17k
    else {
92
1.17k
        tree->root = node->left;
93
1.17k
    }
94
95
17.4k
    node->left->parent = node->parent;
96
17.4k
    node->parent       = node->left;
97
17.4k
    node->left         = node->left->right;
98
17.4k
    if (node->left) {
99
5.25k
        node->left->parent = node;
100
5.25k
    }
101
17.4k
    node->parent->right = node;
102
103
104
17.4k
    if (tree->post_rotation_cb) {
105
21
        tree->post_rotation_cb (node);
106
21
    }
107
17.4k
}
108
109
static void
110
rb_insert_case5(wmem_tree_t *tree, wmem_tree_node_t *node)
111
55.8k
{
112
55.8k
    wmem_tree_node_t *parent, *grandparent;
113
114
55.8k
    parent      = node->parent;
115
55.8k
    grandparent = parent->parent;
116
117
55.8k
    parent->color      = WMEM_NODE_COLOR_BLACK;
118
55.8k
    grandparent->color = WMEM_NODE_COLOR_RED;
119
120
55.8k
    if (node == parent->left && parent == grandparent->left) {
121
14.7k
        rotate_right(tree, grandparent);
122
14.7k
    }
123
41.1k
    else {
124
41.1k
        rotate_left(tree, grandparent);
125
41.1k
    }
126
55.8k
}
127
128
static void
129
rb_insert_case4(wmem_tree_t *tree, wmem_tree_node_t *node)
130
55.8k
{
131
55.8k
    wmem_tree_node_t *parent, *grandparent;
132
133
55.8k
    parent      = node->parent;
134
55.8k
    grandparent = parent->parent;
135
55.8k
    if (!grandparent) {
136
0
        return;
137
0
    }
138
139
55.8k
    if (node == parent->right && parent == grandparent->left) {
140
12.2k
        rotate_left(tree, parent);
141
12.2k
        node = node->left;
142
12.2k
    }
143
43.6k
    else if (node == parent->left && parent == grandparent->right) {
144
2.73k
        rotate_right(tree, parent);
145
2.73k
        node = node->right;
146
2.73k
    }
147
148
55.8k
    rb_insert_case5(tree, node);
149
55.8k
}
150
151
static void
152
rb_insert_case3(wmem_tree_t *tree, wmem_tree_node_t *node)
153
108k
{
154
108k
    wmem_tree_node_t *parent, *grandparent, *uncle;
155
156
108k
    uncle = node_uncle(node);
157
158
108k
    if (uncle && uncle->color == WMEM_NODE_COLOR_RED) {
159
53.0k
        parent      = node->parent;
160
53.0k
        grandparent = parent->parent;
161
162
53.0k
        parent->color      = WMEM_NODE_COLOR_BLACK;
163
53.0k
        uncle->color       = WMEM_NODE_COLOR_BLACK;
164
53.0k
        grandparent->color = WMEM_NODE_COLOR_RED;
165
166
53.0k
        rb_insert_case1(tree, grandparent);
167
53.0k
    }
168
55.8k
    else {
169
55.8k
        rb_insert_case4(tree, node);
170
55.8k
    }
171
108k
}
172
173
static void
174
rb_insert_case2(wmem_tree_t *tree, wmem_tree_node_t *node)
175
148k
{
176
    /* parent is always non-NULL here */
177
148k
    if (node->parent->color == WMEM_NODE_COLOR_RED) {
178
108k
        rb_insert_case3(tree, node);
179
108k
    }
180
148k
}
181
182
static void
183
rb_insert_case1(wmem_tree_t *tree, wmem_tree_node_t *node)
184
154k
{
185
154k
    wmem_tree_node_t *parent = node->parent;
186
187
154k
    if (parent == NULL) {
188
5.84k
        node->color = WMEM_NODE_COLOR_BLACK;
189
5.84k
    }
190
148k
    else {
191
148k
        rb_insert_case2(tree, node);
192
148k
    }
193
154k
}
194
195
static void
196
rb_remove_doubleblack(wmem_tree_t *tree, wmem_tree_node_t *node)
197
0
{
198
0
    wmem_tree_node_t *parent = node->parent;
199
0
    wmem_tree_node_t *sib, *c_nephew, *d_nephew;
200
0
    bool left;
201
202
0
    ws_assert(parent);
203
0
    if (node == parent->left) {
204
0
        left = true;
205
0
        parent->left = NULL;
206
0
    } else {
207
0
        left = false;
208
0
        parent->right = NULL;
209
0
    }
210
211
0
    for (node = NULL; parent; parent = node->parent) {
212
0
        if (node) {
213
0
            left = (node == parent->left);
214
0
        }
215
0
        if (left) {
216
0
            sib = parent->right;
217
0
            c_nephew = sib->left;
218
0
            d_nephew = sib->right;
219
0
        } else {
220
0
            sib = parent->left;
221
0
            c_nephew = sib->right;
222
0
            d_nephew = sib->left;
223
0
        }
224
0
        if (sib && sib->color == WMEM_NODE_COLOR_RED) {
225
            // Sib red
226
0
            goto case_d3;
227
0
        } else if (d_nephew && d_nephew->color == WMEM_NODE_COLOR_RED) {
228
            // D red, Sib black
229
0
            goto case_d6;
230
0
        } else if (c_nephew && c_nephew->color == WMEM_NODE_COLOR_RED) {
231
            // C red, Sib, D black
232
0
            goto case_d5;
233
0
        } else if (parent->color == WMEM_NODE_COLOR_RED) {
234
            // Parent red, Sib, D, C black
235
0
            goto case_d4;
236
0
        } else {
237
            // All black
238
0
            sib->color = WMEM_NODE_COLOR_RED;
239
0
            node = parent;
240
0
        }
241
0
    }
242
243
0
    return;
244
245
0
case_d3:
246
0
    if (left) {
247
0
        rotate_left(tree, parent);
248
0
    } else {
249
0
        rotate_right(tree, parent);
250
0
    }
251
0
    parent->color = WMEM_NODE_COLOR_RED;
252
0
    sib->color = WMEM_NODE_COLOR_BLACK;
253
0
    sib = c_nephew;
254
0
    d_nephew = left ? sib->right : sib->left;
255
0
    if (d_nephew && d_nephew->color == WMEM_NODE_COLOR_RED)
256
0
        goto case_d6;
257
0
    c_nephew = left ? sib->left : sib->right;
258
0
    if (c_nephew && c_nephew->color == WMEM_NODE_COLOR_RED)
259
0
        goto case_d5;
260
261
0
case_d4:
262
0
    sib->color = WMEM_NODE_COLOR_RED;
263
0
    parent->color = WMEM_NODE_COLOR_BLACK;
264
0
    return;
265
266
0
case_d5:
267
0
    if (left) {
268
0
        rotate_right(tree, sib);
269
0
    } else {
270
0
        rotate_left(tree, sib);
271
0
    }
272
0
    sib->color = WMEM_NODE_COLOR_RED;
273
0
    c_nephew->color = WMEM_NODE_COLOR_BLACK;
274
0
    d_nephew = sib;
275
0
    sib = c_nephew;
276
    // D red and sib black;
277
278
0
case_d6:
279
0
    if (left) {
280
0
        rotate_left(tree, parent);
281
0
    } else {
282
0
        rotate_right(tree, parent);
283
0
    }
284
0
    sib->color = parent->color;
285
0
    parent->color = WMEM_NODE_COLOR_BLACK;
286
0
    d_nephew->color = WMEM_NODE_COLOR_BLACK;
287
0
    return;
288
0
}
289
290
static void
291
rb_remove_node(wmem_tree_t *tree, wmem_tree_node_t *node, bool free_key)
292
1
{
293
1
    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.
296
     */
297
1
    if (node->left && node->right) {
298
0
        temp_node = node->right;
299
0
        while (temp_node->left) {
300
0
            temp_node = temp_node->left;
301
0
        }
302
0
        node->key = temp_node->key;
303
0
        node->data = temp_node->data;
304
0
        node = temp_node;
305
0
    }
306
307
1
    wmem_node_color_t child_color = WMEM_NODE_COLOR_BLACK;
308
    /* node now has one child at most. */
309
1
    if (node->left) {
310
0
        temp_node = node->left;
311
0
        ws_assert(node->right == NULL);
312
1
    } else {
313
1
        temp_node = node->right;
314
1
    }
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. */
318
1
    if (temp_node) {
319
0
        child_color = temp_node->color;
320
0
        ws_assert(child_color == WMEM_NODE_COLOR_RED);
321
0
        ws_assert(node->color == WMEM_NODE_COLOR_BLACK);
322
0
        temp_node->parent = node->parent;
323
0
        temp_node->color = WMEM_NODE_COLOR_BLACK;
324
0
    }
325
326
1
    if (temp_node == NULL &&
327
1
        node->color == WMEM_NODE_COLOR_BLACK && node->parent) {
328
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.
332
         */
333
0
        rb_remove_doubleblack(tree, node);
334
1
    } else {
335
        // Now remove the node from the tree.
336
1
        if (node->parent) {
337
0
            if (node == node->parent->left) {
338
0
                node->parent->left = temp_node;
339
0
            } else {
340
0
                node->parent->right = temp_node;
341
0
            }
342
1
        } else {
343
1
            tree->root = temp_node;
344
1
        }
345
1
    }
346
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.
352
     */
353
1
    if (free_key) {
354
0
        wmem_free(tree->data_allocator, (void *)node->key);
355
0
    }
356
1
    wmem_free(tree->data_allocator, node);
357
1
}
358
359
wmem_tree_t *
360
wmem_tree_new(wmem_allocator_t *allocator)
361
239k
{
362
239k
    wmem_tree_t *tree;
363
364
239k
    tree = wmem_new0(allocator, wmem_tree_t);
365
239k
    tree->metadata_allocator    = allocator;
366
239k
    tree->data_allocator = allocator;
367
368
239k
    return tree;
369
239k
}
370
371
static bool
372
wmem_tree_reset_cb(wmem_allocator_t *allocator _U_, wmem_cb_event_t event,
373
        void *user_data)
374
0
{
375
0
    wmem_tree_t *tree = (wmem_tree_t *)user_data;
376
377
0
    tree->root = NULL;
378
379
0
    if (event == WMEM_CB_DESTROY_EVENT) {
380
0
        wmem_unregister_callback(tree->metadata_allocator, tree->metadata_scope_cb_id);
381
0
        wmem_free(tree->metadata_allocator, tree);
382
0
    }
383
384
0
    return true;
385
0
}
386
387
static bool
388
wmem_tree_destroy_cb(wmem_allocator_t *allocator _U_, wmem_cb_event_t event _U_,
389
        void *user_data)
390
0
{
391
0
    wmem_tree_t *tree = (wmem_tree_t *)user_data;
392
393
0
    wmem_unregister_callback(tree->data_allocator, tree->data_scope_cb_id);
394
395
0
    return false;
396
0
}
397
398
wmem_tree_t *
399
wmem_tree_new_autoreset(wmem_allocator_t *metadata_scope, wmem_allocator_t *data_scope)
400
1.78k
{
401
1.78k
    wmem_tree_t *tree;
402
403
1.78k
    tree = wmem_new0(metadata_scope, wmem_tree_t);
404
1.78k
    tree->metadata_allocator = metadata_scope;
405
1.78k
    tree->data_allocator = data_scope;
406
407
1.78k
    tree->metadata_scope_cb_id = wmem_register_callback(metadata_scope, wmem_tree_destroy_cb,
408
1.78k
            tree);
409
1.78k
    tree->data_scope_cb_id  = wmem_register_callback(data_scope, wmem_tree_reset_cb,
410
1.78k
            tree);
411
412
1.78k
    return tree;
413
1.78k
}
414
415
static void
416
free_tree_node(wmem_allocator_t *allocator, wmem_tree_node_t* node, bool free_keys, bool free_values)
417
0
{
418
0
    if (node == NULL) {
419
0
        return;
420
0
    }
421
422
0
    if (node->left) {
423
0
        free_tree_node(allocator, node->left, free_keys, free_values);
424
0
    }
425
426
0
    if (node->is_subtree) {
427
0
        wmem_tree_destroy((wmem_tree_t *)node->data, free_keys, free_values);
428
0
        node->data = NULL;
429
0
    }
430
431
0
    if (node->right) {
432
0
        free_tree_node(allocator, node->right, free_keys, free_values);
433
0
    }
434
435
0
    if (free_keys) {
436
0
        wmem_free(allocator, (void*)node->key);
437
0
    }
438
439
0
    if (free_values) {
440
0
        wmem_free(allocator, node->data);
441
0
    }
442
0
    wmem_free(allocator, node);
443
0
}
444
445
void
446
wmem_tree_destroy(wmem_tree_t *tree, bool free_keys, bool free_values)
447
0
{
448
0
    free_tree_node(tree->data_allocator, tree->root, free_keys, free_values);
449
0
    if (tree->metadata_allocator) {
450
0
        wmem_unregister_callback(tree->metadata_allocator, tree->metadata_scope_cb_id);
451
0
    }
452
0
    if (tree->data_allocator) {
453
0
        wmem_unregister_callback(tree->data_allocator, tree->data_scope_cb_id);
454
0
    }
455
0
    wmem_free(tree->metadata_allocator, tree);
456
0
}
457
458
bool
459
wmem_tree_is_empty(wmem_tree_t *tree)
460
0
{
461
0
    return tree->root == NULL;
462
0
}
463
464
static bool
465
count_nodes(const void *key _U_, void *value _U_, void *userdata)
466
0
{
467
0
    unsigned* count = (unsigned*)userdata;
468
0
    (*count)++;
469
0
    return false;
470
0
}
471
472
unsigned
473
wmem_tree_count(wmem_tree_t* tree)
474
0
{
475
0
    unsigned count = 0;
476
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
0
    wmem_tree_foreach(tree, count_nodes, &count);
481
482
0
    return count;
483
0
}
484
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)
488
254k
{
489
254k
    wmem_tree_node_t *node;
490
491
254k
    node = wmem_new(allocator, wmem_tree_node_t);
492
493
254k
    node->left   = NULL;
494
254k
    node->right  = NULL;
495
254k
    node->parent = parent;
496
497
254k
    node->key  = key;
498
254k
    node->data = data;
499
500
254k
    node->color      = color;
501
254k
    node->is_subtree = is_subtree;
502
254k
    node->is_removed = false;
503
504
254k
    return node;
505
254k
}
506
507
255k
#define CREATE_DATA(TRANSFORM, DATA) ((TRANSFORM) ? (TRANSFORM)(DATA) : (DATA))
508
509
510
/**
511
 * return inserted node
512
 */
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)
516
371k
{
517
371k
    wmem_tree_node_t *node     = tree->root;
518
371k
    wmem_tree_node_t *new_node = NULL;
519
520
    /* is this the first node ?*/
521
371k
    if (!node) {
522
152k
        new_node = create_node(tree->data_allocator, NULL, GUINT_TO_POINTER(key),
523
152k
                CREATE_DATA(func, data), WMEM_NODE_COLOR_BLACK, is_subtree);
524
152k
        tree->root = new_node;
525
152k
        return new_node;
526
152k
    }
527
528
    /* it was not the new root so walk the tree until we find where to
529
     * insert this new leaf.
530
     */
531
815k
    while (!new_node) {
532
        /* this node already exists, so just return the data pointer*/
533
741k
        if (key == GPOINTER_TO_UINT(node->key)) {
534
145k
            if (replace) {
535
28.7k
                node->data = CREATE_DATA(func, data);
536
28.7k
            }
537
145k
            return node;
538
145k
        }
539
595k
        else if (key < GPOINTER_TO_UINT(node->key)) {
540
171k
            if (node->left) {
541
150k
                node = node->left;
542
150k
            }
543
20.1k
            else {
544
                /* new node to the left */
545
20.1k
                new_node = create_node(tree->data_allocator, node, GUINT_TO_POINTER(key),
546
20.1k
                        CREATE_DATA(func, data), WMEM_NODE_COLOR_RED,
547
20.1k
                        is_subtree);
548
20.1k
                node->left = new_node;
549
20.1k
            }
550
171k
        }
551
424k
        else if (key > GPOINTER_TO_UINT(node->key)) {
552
424k
            if (node->right) {
553
371k
                node = node->right;
554
371k
            }
555
53.6k
            else {
556
                /* new node to the right */
557
53.6k
                new_node = create_node(tree->data_allocator, node, GUINT_TO_POINTER(key),
558
53.6k
                        CREATE_DATA(func, data), WMEM_NODE_COLOR_RED,
559
53.6k
                        is_subtree);
560
53.6k
                node->right = new_node;
561
53.6k
            }
562
424k
        }
563
741k
    }
564
565
    /* node will now point to the newly created node */
566
73.7k
    rb_insert_case1(tree, new_node);
567
568
73.7k
    return new_node;
569
219k
}
570
571
572
static void *
573
lookup_or_insert32(wmem_tree_t *tree, uint32_t key,
574
        void*(*func)(void*), void* data, bool is_subtree, bool replace)
575
371k
{
576
371k
    wmem_tree_node_t *node = lookup_or_insert32_node(tree, key, func, data, is_subtree, replace);
577
371k
    return node->data;
578
371k
}
579
580
static void *
581
wmem_tree_lookup(wmem_tree_t *tree, const void *key, compare_func cmp)
582
64.6k
{
583
64.6k
    wmem_tree_node_t *node;
584
585
64.6k
    if (tree == NULL || key == NULL) {
586
16.2k
        return NULL;
587
16.2k
    }
588
589
48.4k
    node = tree->root;
590
591
497k
    while (node) {
592
457k
        int result = cmp(key, node->key);
593
457k
        if (result == 0) {
594
7.92k
            return node->data;
595
7.92k
        }
596
449k
        else if (result < 0) {
597
145k
            node = node->left;
598
145k
        }
599
304k
        else if (result > 0) {
600
304k
            node = node->right;
601
304k
        }
602
457k
    }
603
604
40.4k
    return NULL;
605
48.4k
}
606
607
wmem_tree_node_t *
608
wmem_tree_insert_node(wmem_tree_t *tree, const void *key, void *data, compare_func cmp)
609
28.7k
{
610
28.7k
    wmem_tree_node_t *node = tree->root;
611
28.7k
    wmem_tree_node_t *new_node = NULL;
612
613
    /* is this the first node ?*/
614
28.7k
    if (!node) {
615
1.03k
        tree->root = create_node(tree->data_allocator, node, key,
616
1.03k
                data, WMEM_NODE_COLOR_BLACK, false);
617
1.03k
        return tree->root;
618
1.03k
    }
619
620
    /* it was not the new root so walk the tree until we find where to
621
     * insert this new leaf.
622
     */
623
324k
    while (!new_node) {
624
296k
        int result = cmp(key, node->key);
625
296k
        if (result == 0) {
626
68
            node->data = data;
627
68
            node->is_removed = data ? false : true;
628
68
            return node;
629
68
        }
630
296k
        else if (result < 0) {
631
66.7k
            if (node->left) {
632
58.0k
                node = node->left;
633
58.0k
            }
634
8.71k
            else {
635
8.71k
                new_node = create_node(tree->data_allocator, node, key,
636
8.71k
                        data, WMEM_NODE_COLOR_RED, false);
637
8.71k
                node->left = new_node;
638
8.71k
            }
639
66.7k
        }
640
229k
        else if (result > 0) {
641
229k
            if (node->right) {
642
210k
                node = node->right;
643
210k
            }
644
18.8k
            else {
645
                /* new node to the right */
646
18.8k
                new_node = create_node(tree->data_allocator, node, key,
647
18.8k
                        data, WMEM_NODE_COLOR_RED, false);
648
18.8k
                node->right = new_node;
649
18.8k
            }
650
229k
        }
651
296k
    }
652
653
    /* node will now point to the newly created node */
654
27.6k
    rb_insert_case1(tree, new_node);
655
656
27.6k
    return new_node;
657
27.6k
}
658
659
void
660
wmem_tree_insert32(wmem_tree_t *tree, uint32_t key, void *data)
661
200k
{
662
200k
    lookup_or_insert32(tree, key, NULL, data, false, true);
663
200k
}
664
665
bool wmem_tree_contains32(wmem_tree_t *tree, uint32_t key)
666
0
{
667
0
    if (!tree) {
668
0
        return false;
669
0
    }
670
671
0
    wmem_tree_node_t *node = tree->root;
672
673
0
    while (node) {
674
0
        if (key == GPOINTER_TO_UINT(node->key)) {
675
0
            return true;
676
0
        }
677
0
        else if (key < GPOINTER_TO_UINT(node->key)) {
678
0
            node = node->left;
679
0
        }
680
0
        else if (key > GPOINTER_TO_UINT(node->key)) {
681
0
            node = node->right;
682
0
        }
683
0
    }
684
685
0
    return false;
686
0
}
687
688
static wmem_tree_node_t*
689
wmem_tree_lookup32_node(wmem_tree_t *tree, uint32_t key)
690
1.79G
{
691
1.79G
    if (!tree) {
692
0
        return NULL;
693
0
    }
694
695
1.79G
    wmem_tree_node_t *node = tree->root;
696
697
4.80G
    while (node) {
698
4.33G
        if (key == GPOINTER_TO_UINT(node->key)) {
699
1.32G
            return node;
700
1.32G
        }
701
3.01G
        else if (key < GPOINTER_TO_UINT(node->key)) {
702
1.55G
            node = node->left;
703
1.55G
        }
704
1.45G
        else if (key > GPOINTER_TO_UINT(node->key)) {
705
1.45G
            node = node->right;
706
1.45G
        }
707
4.33G
    }
708
709
471M
    return NULL;
710
1.79G
}
711
712
void *
713
wmem_tree_lookup32(wmem_tree_t *tree, uint32_t key)
714
1.79G
{
715
1.79G
    wmem_tree_node_t *node = wmem_tree_lookup32_node(tree, key);
716
1.79G
    if (node == NULL) {
717
471M
        return NULL;
718
471M
    }
719
1.32G
    return node->data;
720
1.79G
}
721
722
static wmem_tree_node_t*
723
wmem_tree_lookup32_le_node(wmem_tree_t *tree, uint32_t key)
724
1.75M
{
725
1.75M
    if (!tree) {
726
0
        return NULL;
727
0
    }
728
729
1.75M
    wmem_tree_node_t *node = tree->root;
730
731
2.85M
    while (node) {
732
2.81M
        if (key == GPOINTER_TO_UINT(node->key)) {
733
165k
            return node;
734
165k
        }
735
2.64M
        else if (key < GPOINTER_TO_UINT(node->key)) {
736
65.9k
            if (node->left == NULL) {
737
10.4k
                break;
738
10.4k
            }
739
55.4k
            node = node->left;
740
55.4k
        }
741
2.58M
        else if (key > GPOINTER_TO_UINT(node->key)) {
742
2.58M
            if (node->right == NULL) {
743
1.53M
                break;
744
1.53M
            }
745
1.04M
            node = node->right;
746
1.04M
        }
747
2.81M
    }
748
749
1.58M
    if (!node) {
750
40.5k
        return NULL;
751
40.5k
    }
752
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
756
     * we return NULL.
757
     */
758
1.54M
    if (node->parent == NULL) {
759
884k
        if (key > GPOINTER_TO_UINT(node->key)) {
760
876k
            return node;
761
876k
        } else {
762
7.53k
            return NULL;
763
7.53k
        }
764
884k
    }
765
766
661k
    if (GPOINTER_TO_UINT(node->key) <= key) {
767
        /* if our key is <= the search key, we have the right node */
768
658k
        return node;
769
658k
    }
770
2.90k
    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. */
773
3.67k
        while (node) {
774
3.46k
            if (key > GPOINTER_TO_UINT(node->key)) {
775
821
                return node;
776
821
            }
777
2.64k
            node=node->parent;
778
2.64k
        }
779
212
        return NULL;
780
1.03k
    }
781
1.87k
    else {
782
        /* our key is bigger than the search key and we're a right child,
783
         * our parent is the one we want */
784
1.87k
        return node->parent;
785
1.87k
    }
786
661k
}
787
788
void *
789
wmem_tree_lookup32_le(wmem_tree_t *tree, uint32_t key)
790
1.75M
{
791
1.75M
    wmem_tree_node_t *node = wmem_tree_lookup32_le_node(tree, key);
792
1.75M
    if (node == NULL) {
793
48.3k
        return NULL;
794
48.3k
    }
795
796
1.70M
    return node->data;
797
1.75M
}
798
799
void *
800
wmem_tree_lookup32_le_full(wmem_tree_t *tree, uint32_t key, uint32_t *orig_key)
801
0
{
802
0
    wmem_tree_node_t *node = wmem_tree_lookup32_le_node(tree, key);
803
0
    if (node == NULL) {
804
0
        return NULL;
805
0
    }
806
807
0
    *orig_key = GPOINTER_TO_UINT(node->key);
808
0
    return node->data;
809
0
}
810
811
static wmem_tree_node_t*
812
wmem_tree_lookup32_ge_node(wmem_tree_t *tree, uint32_t key)
813
0
{
814
0
    if (!tree) {
815
0
        return NULL;
816
0
    }
817
818
0
    wmem_tree_node_t *node = tree->root;
819
820
0
    while (node) {
821
0
        if (key == GPOINTER_TO_UINT(node->key)) {
822
0
            return node;
823
0
        }
824
0
        else if (key < GPOINTER_TO_UINT(node->key)) {
825
0
            if (node->left == NULL) {
826
0
                break;
827
0
            }
828
0
            node = node->left;
829
0
        }
830
0
        else if (key > GPOINTER_TO_UINT(node->key)) {
831
0
            if (node->right == NULL) {
832
0
                break;
833
0
            }
834
0
            node = node->right;
835
0
        }
836
0
    }
837
838
0
    if (!node) {
839
0
        return NULL;
840
0
    }
841
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
845
     * we return NULL.
846
     */
847
0
    if (node->parent == NULL) {
848
0
        if (key < GPOINTER_TO_UINT(node->key)) {
849
0
            return node;
850
0
        } else {
851
0
            return NULL;
852
0
        }
853
0
    }
854
855
0
    if (GPOINTER_TO_UINT(node->key) >= key) {
856
        /* if our key is >= the search key, we have the right node */
857
0
        return node;
858
0
    }
859
0
    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. */
862
0
        while (node) {
863
0
            if (key < GPOINTER_TO_UINT(node->key)) {
864
0
                return node;
865
0
            }
866
0
            node=node->parent;
867
0
        }
868
0
        return NULL;
869
0
    }
870
0
    else {
871
        /* our key is smaller than the search key and we're a left child,
872
         * our parent is the one we want */
873
0
        return node->parent;
874
0
    }
875
0
}
876
877
void *
878
wmem_tree_lookup32_ge(wmem_tree_t *tree, uint32_t key)
879
0
{
880
0
    wmem_tree_node_t *node = wmem_tree_lookup32_ge_node(tree, key);
881
0
    if (node == NULL) {
882
0
        return NULL;
883
0
    }
884
885
0
    return node->data;
886
0
}
887
888
void *
889
wmem_tree_lookup32_ge_full(wmem_tree_t *tree, uint32_t key, uint32_t *orig_key)
890
0
{
891
0
    wmem_tree_node_t *node = wmem_tree_lookup32_ge_node(tree, key);
892
0
    if (node == NULL) {
893
0
        return NULL;
894
0
    }
895
896
0
    *orig_key = GPOINTER_TO_UINT(node->key);
897
0
    return node->data;
898
0
}
899
900
void *
901
wmem_tree_remove32(wmem_tree_t *tree, uint32_t key)
902
2
{
903
2
    wmem_tree_node_t *node = wmem_tree_lookup32_node(tree, key);
904
2
    if (node == NULL) {
905
1
        return NULL;
906
1
    }
907
908
1
    void *ret = node->data;
909
910
    /* Remove the node. Do not free the key, because it is a
911
     * GPOINTER_TO_UINT. The value we return.
912
     */
913
1
    rb_remove_node(tree, node, false);
914
915
1
    return ret;
916
2
}
917
918
void
919
wmem_tree_insert_string(wmem_tree_t* tree, const char* k, void* v, uint32_t flags)
920
27.7k
{
921
27.7k
    char *key;
922
27.7k
    compare_func cmp;
923
924
27.7k
    key = wmem_strdup(tree->data_allocator, k);
925
926
27.7k
    if (flags & WMEM_TREE_STRING_NOCASE) {
927
25.5k
        cmp = (compare_func)g_ascii_strcasecmp;
928
25.5k
    } else {
929
2.23k
        cmp = (compare_func)strcmp;
930
2.23k
    }
931
932
27.7k
    wmem_tree_insert_node(tree, key, v, cmp);
933
27.7k
}
934
935
void *
936
wmem_tree_lookup_string(wmem_tree_t* tree, const char* k, uint32_t flags)
937
64.6k
{
938
64.6k
    compare_func cmp;
939
940
64.6k
    if (flags & WMEM_TREE_STRING_NOCASE) {
941
37.6k
        cmp = (compare_func)g_ascii_strcasecmp;
942
37.6k
    } else {
943
26.9k
        cmp = (compare_func)strcmp;
944
26.9k
    }
945
946
64.6k
    return wmem_tree_lookup(tree, k, cmp);
947
64.6k
}
948
949
void *
950
wmem_tree_remove_string(wmem_tree_t* tree, const char* k, uint32_t flags)
951
0
{
952
0
    void *ret = wmem_tree_lookup_string(tree, k, flags);
953
0
    if (ret) {
954
        /* Not really a remove, but set data to NULL to mark node with is_removed */
955
0
        wmem_tree_insert_string(tree, k, NULL, flags);
956
0
    }
957
0
    return ret;
958
0
}
959
960
static void *
961
create_sub_tree(void* d)
962
54.9k
{
963
54.9k
    return wmem_tree_new(((wmem_tree_t *)d)->data_allocator);
964
54.9k
}
965
966
void
967
wmem_tree_insert32_array(wmem_tree_t *tree, wmem_tree_key_t *key, void *data)
968
49.6k
{
969
49.6k
    wmem_tree_t *insert_tree = NULL;
970
49.6k
    wmem_tree_key_t *cur_key;
971
49.6k
    uint32_t i, insert_key32 = 0;
972
973
248k
    for (cur_key = key; cur_key->length > 0; cur_key++) {
974
420k
        for (i = 0; i < cur_key->length; i++) {
975
            /* Insert using the previous key32 */
976
221k
            if (!insert_tree) {
977
49.6k
                insert_tree = tree;
978
171k
            } else {
979
171k
                insert_tree = (wmem_tree_t *)lookup_or_insert32(insert_tree,
980
171k
                        insert_key32, create_sub_tree, tree, true, false);
981
171k
            }
982
221k
            insert_key32 = cur_key->key[i];
983
221k
        }
984
198k
    }
985
986
49.6k
    ws_assert(insert_tree);
987
988
49.6k
    wmem_tree_insert32(insert_tree, insert_key32, data);
989
49.6k
}
990
991
static void *
992
wmem_tree_lookup32_array_helper(wmem_tree_t *tree, wmem_tree_key_t *key,
993
        void*(*helper)(wmem_tree_t*, uint32_t))
994
473M
{
995
473M
    wmem_tree_t *lookup_tree = NULL;
996
473M
    wmem_tree_key_t *cur_key;
997
473M
    uint32_t i, lookup_key32 = 0;
998
999
473M
    if (!tree || !key) {
1000
0
        return NULL;
1001
0
    }
1002
1003
2.26G
    for (cur_key = key; cur_key->length > 0; cur_key++) {
1004
3.68G
        for (i = 0; i < cur_key->length; i++) {
1005
            /* Lookup using the previous key32 */
1006
1.89G
            if (!lookup_tree) {
1007
473M
                lookup_tree = tree;
1008
473M
            }
1009
1.41G
            else {
1010
1.41G
                lookup_tree =
1011
1.41G
                    (wmem_tree_t *)(*helper)(lookup_tree, lookup_key32);
1012
1.41G
                if (!lookup_tree) {
1013
98.1M
                    return NULL;
1014
98.1M
                }
1015
1.41G
            }
1016
1.79G
            lookup_key32 = cur_key->key[i];
1017
1.79G
        }
1018
1.89G
    }
1019
1020
    /* Assert if we didn't get any valid keys */
1021
374M
    ws_assert(lookup_tree);
1022
1023
374M
    return (*helper)(lookup_tree, lookup_key32);
1024
473M
}
1025
1026
void *
1027
wmem_tree_lookup32_array(wmem_tree_t *tree, wmem_tree_key_t *key)
1028
473M
{
1029
473M
    return wmem_tree_lookup32_array_helper(tree, key, wmem_tree_lookup32);
1030
473M
}
1031
1032
void *
1033
wmem_tree_lookup32_array_le(wmem_tree_t *tree, wmem_tree_key_t *key)
1034
22.6k
{
1035
22.6k
    return wmem_tree_lookup32_array_helper(tree, key, wmem_tree_lookup32_le);
1036
22.6k
}
1037
1038
static bool
1039
wmem_tree_foreach_nodes(wmem_tree_node_t* node, wmem_foreach_func callback,
1040
        void *user_data)
1041
28.5k
{
1042
28.5k
    bool stop_traverse = false;
1043
1044
28.5k
    if (!node) {
1045
0
        return false;
1046
0
    }
1047
1048
28.5k
    if (node->left) {
1049
13.4k
        if (wmem_tree_foreach_nodes(node->left, callback, user_data)) {
1050
0
            return true;
1051
0
        }
1052
13.4k
    }
1053
1054
28.5k
    if (node->is_subtree) {
1055
0
        stop_traverse = wmem_tree_foreach((wmem_tree_t *)node->data,
1056
0
                callback, user_data);
1057
28.5k
    } else if (!node->is_removed) {
1058
        /* No callback for "removed" nodes */
1059
28.5k
        stop_traverse = callback(node->key, node->data, user_data);
1060
28.5k
    }
1061
1062
28.5k
    if (stop_traverse) {
1063
0
        return true;
1064
0
    }
1065
1066
28.5k
    if(node->right) {
1067
14.0k
        if (wmem_tree_foreach_nodes(node->right, callback, user_data)) {
1068
0
            return true;
1069
0
        }
1070
14.0k
    }
1071
1072
28.5k
    return false;
1073
28.5k
}
1074
1075
bool
1076
wmem_tree_foreach(wmem_tree_t* tree, wmem_foreach_func callback,
1077
        void *user_data)
1078
994
{
1079
994
    if(!tree->root)
1080
0
        return false;
1081
1082
994
    return wmem_tree_foreach_nodes(tree->root, callback, user_data);
1083
994
}
1084
1085
static void wmem_print_subtree(wmem_tree_t *tree, uint32_t level, wmem_printer_func key_printer, wmem_printer_func data_printer);
1086
1087
static void
1088
0
wmem_print_indent(uint32_t level) {
1089
0
    uint32_t i;
1090
0
    for (i=0; i<level; i++) {
1091
0
        printf("    ");
1092
0
    }
1093
0
}
1094
1095
static void
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)
1098
0
{
1099
0
    if (!node)
1100
0
        return;
1101
1102
0
    wmem_print_indent(level);
1103
1104
0
    printf("%sNODE:%p parent:%p left:%p right:%p colour:%s key:%p %s:%p\n",
1105
0
            prefix,
1106
0
            (void *)node, (void *)node->parent,
1107
0
            (void *)node->left, (void *)node->right,
1108
0
            node->color?"Black":"Red", node->key,
1109
0
            node->is_subtree?"tree":"data", node->data);
1110
0
    if (key_printer) {
1111
0
        wmem_print_indent(level);
1112
0
        key_printer(node->key);
1113
0
        printf("\n");
1114
0
    }
1115
0
    if (data_printer && !node->is_subtree) {
1116
0
        wmem_print_indent(level);
1117
0
        data_printer(node->data);
1118
0
        printf("\n");
1119
0
    }
1120
1121
0
    if (node->left)
1122
0
        wmem_tree_print_nodes("L-", node->left, level+1, key_printer, data_printer);
1123
0
    if (node->right)
1124
0
        wmem_tree_print_nodes("R-", node->right, level+1, key_printer, data_printer);
1125
1126
0
    if (node->is_subtree)
1127
0
        wmem_print_subtree((wmem_tree_t *)node->data, level+1, key_printer, data_printer);
1128
0
}
1129
1130
1131
static void
1132
wmem_print_subtree(wmem_tree_t *tree, uint32_t level, wmem_printer_func key_printer, wmem_printer_func data_printer)
1133
0
{
1134
0
    if (!tree)
1135
0
        return;
1136
1137
0
    wmem_print_indent(level);
1138
1139
0
    printf("WMEM tree:%p root:%p\n", (void *)tree, (void *)tree->root);
1140
0
    if (tree->root) {
1141
0
        wmem_tree_print_nodes("Root-", tree->root, level, key_printer, data_printer);
1142
0
    }
1143
0
}
1144
1145
void
1146
wmem_print_tree(wmem_tree_t *tree, wmem_printer_func key_printer, wmem_printer_func data_printer)
1147
0
{
1148
0
    wmem_print_subtree(tree, 0, key_printer, data_printer);
1149
0
}
1150
/*
1151
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1152
 *
1153
 * Local variables:
1154
 * c-basic-offset: 4
1155
 * tab-width: 8
1156
 * indent-tabs-mode: nil
1157
 * End:
1158
 *
1159
 * vi: set shiftwidth=4 tabstop=8 expandtab:
1160
 * :indentSize=4:tabSize=8:noTabs=true:
1161
 */