Coverage Report

Created: 2026-05-14 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/wsutil/wmem/wmem_interval_tree.c
Line
Count
Source
1
/* wmem_interval_tree.c
2
 * Implements an augmented interval tree
3
 * Based on the red-black tree implementation in epan/wmem.*
4
 * Copyright 2015, Matthieu coudron <matthieu.coudron@lip6.fr>
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 <inttypes.h>
16
#include <string.h>
17
#include <inttypes.h>
18
#include <stdio.h>
19
#include <glib.h>
20
21
#include "wmem-int.h"
22
#include "wmem_core.h"
23
#include "wmem_tree-int.h"
24
#include "wmem_strutl.h"
25
#include "wmem_interval_tree.h"
26
#include "wmem_user_cb.h"
27
28
static void
29
print_range(const void *value)
30
0
{
31
0
    const wmem_range_t *range = (const wmem_range_t *)value;
32
0
    if(!value) {
33
0
        return;
34
0
    }
35
0
    printf("Range: low=%" PRIu64 " high=%" PRIu64 " max_edge=%" PRIu64 "\n", range->low, range->high, range->max_edge);
36
0
}
37
38
/**
39
 * In an augmented interval tree, each node saves the maximum edge of its child subtrees
40
 * This function compares the children max_edge with the current max_edge
41
 * and propagates any change to the parent nodes.
42
 */
43
static void
44
update_max_edge(wmem_tree_node_t *node)
45
1.30k
{
46
1.30k
    wmem_range_t *range;
47
1.30k
    const wmem_range_t *range_l;
48
1.30k
    const wmem_range_t *range_r;
49
1.30k
    uint64_t maxEdge = 0;
50
51
1.30k
    if(!node) {
52
540
        return ;
53
540
    }
54
55
765
    range = (wmem_range_t *)node->key;
56
57
765
    range_l = (node->left) ? (const wmem_range_t *) (node->left->key) : NULL;
58
765
    range_r = (node->right) ? (const wmem_range_t *) (node->right->key) : NULL;
59
60
765
    maxEdge = range->high;
61
62
765
    if(range_r) {
63
79
        maxEdge = MAX(maxEdge, range_r->max_edge) ;
64
79
    }
65
765
    if(range_l) {
66
90
        maxEdge = MAX(maxEdge, range_l->max_edge) ;
67
90
    }
68
69
    /* update the parent nodes only if a change happened (optimization) */
70
765
    if(range->max_edge != maxEdge) {
71
641
        range->max_edge = maxEdge;
72
641
        update_max_edge(node->parent);
73
641
    }
74
765
}
75
76
bool
77
wmem_itree_range_overlap(const wmem_range_t *r1, const wmem_range_t *r2)
78
55.7k
{
79
55.7k
    return (r1->low <= r2->high && r2->low <= r1->high);
80
55.7k
}
81
82
83
/* after a rotation, some of the children nodes might (dis)appear, thus we need
84
 * to refresh children max_edge. Changes will propagate to parents */
85
29
static void update_edges_after_rotation(wmem_tree_node_t *node) {
86
29
    if(node->left)  update_max_edge(node->left);
87
29
    if(node->right)  update_max_edge(node->right);
88
29
}
89
90
wmem_itree_t *
91
wmem_itree_new(wmem_allocator_t *allocator)
92
1.07k
{
93
1.07k
    wmem_itree_t *tree      = wmem_tree_new(allocator);
94
1.07k
    tree->post_rotation_cb  = &update_edges_after_rotation;
95
1.07k
    return tree;
96
1.07k
}
97
98
bool
99
wmem_itree_is_empty(wmem_itree_t *tree)
100
0
{
101
0
    return wmem_tree_is_empty(tree);
102
0
}
103
104
static int
105
wmem_tree_compare_ranges(const wmem_range_t *ra, const wmem_range_t *rb)
106
242
{
107
242
    if( ra->low == rb->low) {
108
51
        return 0;
109
51
    }
110
191
    else if(ra->low < rb->low) {
111
100
        return -1;
112
100
    }
113
91
    else {
114
91
        return 1;
115
91
    }
116
242
}
117
118
119
void
120
wmem_itree_insert(wmem_itree_t *tree, const uint64_t low, const uint64_t high, void *data)
121
648
{
122
648
    wmem_tree_node_t *node;
123
648
    wmem_range_t *range = (wmem_range_t *)wmem_new(tree->data_allocator, wmem_range_t);
124
125
648
    ws_assert(low <= high);
126
648
    range->low = low;
127
648
    range->high = high;
128
648
    range->max_edge = 0;
129
130
648
    node = wmem_tree_insert_node(tree, range, data, (compare_func)wmem_tree_compare_ranges);
131
132
    /* in absence of rotation, we still need to update max_edge */
133
648
    update_max_edge(node);
134
648
}
135
136
137
static void
138
wmem_itree_find_intervals_in_subtree(wmem_tree_node_t *node, wmem_range_t requested, wmem_list_t *results)
139
162k
{
140
162k
    const wmem_range_t* current;
141
142
162k
    if(!node) {
143
103k
        return;
144
103k
    }
145
58.9k
    current = (wmem_range_t*)node->key;
146
147
    /* there is no child that can possibly match */
148
58.9k
    if(requested.low > current->max_edge) {
149
3.22k
        return;
150
3.22k
    }
151
152
55.7k
    if(wmem_itree_range_overlap(current, &requested)) {
153
37.8k
        wmem_list_prepend(results, node->data);
154
37.8k
    }
155
156
55.7k
    wmem_itree_find_intervals_in_subtree(node->left, requested, results);
157
55.7k
    wmem_itree_find_intervals_in_subtree(node->right, requested, results);
158
55.7k
}
159
160
wmem_list_t *
161
wmem_itree_find_intervals(wmem_itree_t *tree, wmem_allocator_t *allocator, uint64_t low, uint64_t high)
162
50.6k
{
163
50.6k
    wmem_list_t *results = NULL;
164
50.6k
    wmem_range_t requested = { low, high, 0 };
165
50.6k
    results = wmem_list_new(allocator);
166
167
50.6k
    wmem_itree_find_intervals_in_subtree(tree->root, requested, results);
168
50.6k
    return results;
169
50.6k
}
170
171
172
void
173
wmem_print_itree(wmem_tree_t *tree)
174
0
{
175
    wmem_print_tree(tree, &print_range, NULL);
176
0
}
177
178
/*
179
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
180
 *
181
 * Local variables:
182
 * c-basic-offset: 4
183
 * tab-width: 8
184
 * indent-tabs-mode: nil
185
 * End:
186
 *
187
 * vi: set shiftwidth=4 tabstop=8 expandtab:
188
 * :indentSize=4:tabSize=8:noTabs=true:
189
 */