Coverage Report

Created: 2026-11-12 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/wsutil/wmem/wmem_multimap.c
Line
Count
Source
1
/* wmem_multimap.c
2
 * Wireshark Memory Manager Hash Multimap
3
 * Copyright 2021, John Thacker <johnthacker@gmail.com>
4
 * Copyright 2014, 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
#include "config.h"
13
14
#include <glib.h>
15
16
#include "wmem_core.h"
17
#include "wmem_list.h"
18
#include "wmem_map.h"
19
#include "wmem_multimap.h"
20
#include "wmem_tree.h"
21
#include "wmem_user_cb.h"
22
23
struct _wmem_multimap_t {
24
25
    wmem_map_t *map;
26
27
    unsigned   metadata_scope_cb_id;
28
    unsigned   data_scope_cb_id;
29
30
    wmem_allocator_t *metadata_allocator;
31
    wmem_allocator_t *data_allocator;
32
};
33
34
wmem_multimap_t *
35
wmem_multimap_new(wmem_allocator_t *allocator,
36
        GHashFunc hash_func, GEqualFunc eql_func)
37
175
{
38
175
    wmem_multimap_t *multimap;
39
40
175
    multimap = wmem_new(allocator, wmem_multimap_t);
41
42
175
    multimap->map = wmem_map_new(allocator, hash_func, eql_func);
43
175
    multimap->metadata_allocator = allocator;
44
175
    multimap->data_allocator = allocator;
45
46
175
    return multimap;
47
175
}
48
49
static bool
50
wmem_multimap_reset_cb(wmem_allocator_t *allocator _U_, wmem_cb_event_t event,
51
        void *user_data)
52
0
{
53
0
    wmem_multimap_t *multimap = (wmem_multimap_t*)user_data;
54
55
0
    if (event == WMEM_CB_DESTROY_EVENT) {
56
0
        wmem_unregister_callback(multimap->metadata_allocator, multimap->metadata_scope_cb_id);
57
0
        wmem_free(multimap->metadata_allocator, multimap);
58
0
    }
59
60
0
    return true;
61
0
}
62
63
static bool
64
wmem_multimap_destroy_cb(wmem_allocator_t *allocator _U_, wmem_cb_event_t event _U_,
65
        void *user_data)
66
0
{
67
0
    wmem_multimap_t *multimap = (wmem_multimap_t*)user_data;
68
69
0
    wmem_unregister_callback(multimap->data_allocator, multimap->data_scope_cb_id);
70
71
0
    return false;
72
0
}
73
74
wmem_multimap_t *
75
wmem_multimap_new_autoreset(wmem_allocator_t *metadata_scope, wmem_allocator_t *data_scope,
76
        GHashFunc hash_func, GEqualFunc eql_func)
77
96
{
78
96
    wmem_multimap_t *multimap;
79
80
96
    multimap = wmem_new(metadata_scope, wmem_multimap_t);
81
82
96
    multimap->map = wmem_map_new_autoreset(metadata_scope, data_scope, hash_func, eql_func);
83
96
    multimap->metadata_allocator = metadata_scope;
84
96
    multimap->data_allocator = data_scope;
85
86
96
    multimap->metadata_scope_cb_id = wmem_register_callback(metadata_scope, wmem_multimap_destroy_cb, multimap);
87
96
    multimap->data_scope_cb_id  = wmem_register_callback(data_scope, wmem_multimap_reset_cb, multimap);
88
89
96
    return multimap;
90
96
}
91
92
wmem_list_t*
93
wmem_multimap_get_keys(wmem_allocator_t *list_allocator, const wmem_multimap_t *map)
94
0
{
95
0
    return wmem_map_get_keys(list_allocator, map->map);
96
0
}
97
98
static void
99
count_nodes(void * key _U_, void * value, void * user_data)
100
0
{
101
0
    unsigned* count = (unsigned*)user_data;
102
0
    (*count) += wmem_tree_count(value);
103
0
}
104
105
unsigned
106
wmem_multimap_size(const wmem_multimap_t *map)
107
0
{
108
0
    unsigned count = 0;
109
110
    /* Make sure we have map and a multimap */
111
0
    if (map == NULL || map->map == NULL) {
112
0
        return 0;
113
0
    }
114
115
0
    wmem_map_foreach(map->map, count_nodes, &count);
116
0
    return count;
117
0
}
118
119
unsigned
120
wmem_multimap_count(const wmem_multimap_t *map, const void *key)
121
0
{
122
0
    wmem_tree_t *tree;
123
124
    /* Make sure we have map and a multimap */
125
0
    if (map == NULL || map->map == NULL) {
126
0
        return 0;
127
0
    }
128
129
0
    if ((tree = wmem_map_lookup(map->map, key)) == NULL) {
130
0
        return 0;
131
0
    }
132
0
    return wmem_tree_count(tree);
133
0
}
134
135
bool
136
wmem_multimap_insert32(wmem_multimap_t *map, const void *key, uint32_t frame_num, void *value)
137
615
{
138
615
    wmem_tree_t *tree;
139
615
    bool ret = true;
140
141
615
    if ((tree = wmem_map_lookup(map->map, key)) == NULL) {
142
257
        tree = wmem_tree_new(map->data_allocator);
143
257
        wmem_map_insert(map->map, key, tree);
144
257
        ret = false;
145
257
    }
146
615
    wmem_tree_insert32(tree, frame_num, value);
147
148
615
    return ret;
149
615
}
150
151
void *
152
wmem_multimap_lookup32(const wmem_multimap_t *map, const void *key, uint32_t frame_num)
153
109
{
154
109
    wmem_tree_t *tree;
155
156
    /* Make sure we have map and a multimap */
157
109
    if (map == NULL || map->map == NULL) {
158
0
        return NULL;
159
0
    }
160
161
109
    if ((tree = wmem_map_lookup(map->map, key)) == NULL) {
162
86
        return NULL;
163
86
    }
164
23
    return wmem_tree_lookup32(tree, frame_num);
165
109
}
166
167
void *
168
wmem_multimap_lookup32_le(const wmem_multimap_t *map, const void *key, uint32_t frame_num)
169
697
{
170
697
    wmem_tree_t *tree;
171
172
    /* Make sure we have map and a multimap */
173
697
    if (map == NULL || map->map == NULL) {
174
0
        return NULL;
175
0
    }
176
177
697
    if ((tree = wmem_map_lookup(map->map, key)) == NULL) {
178
513
        return NULL;
179
513
    }
180
184
    return wmem_tree_lookup32_le(tree, frame_num);
181
697
}
182
183
void *
184
wmem_multimap_lookup32_le_full(const wmem_multimap_t *map, const void *key, uint32_t frame_num, uint32_t *orig_frame_num)
185
0
{
186
0
    wmem_tree_t *tree;
187
188
    /* Make sure we have map and a multimap */
189
0
    if (map == NULL || map->map == NULL) {
190
0
        return NULL;
191
0
    }
192
193
0
    if ((tree = wmem_map_lookup(map->map, key)) == NULL) {
194
0
        return NULL;
195
0
    }
196
0
    return wmem_tree_lookup32_le_full(tree, frame_num, orig_frame_num);
197
0
}
198
199
void *
200
wmem_multimap_remove32(wmem_multimap_t *map, const void *key, const uint32_t frame_num)
201
0
{
202
0
    wmem_tree_t *tree;
203
204
    /* Make sure we have map and a multimap */
205
0
    if (map == NULL || map->map == NULL) {
206
0
        return NULL;
207
0
    }
208
209
0
    if ((tree = wmem_map_lookup(map->map, key)) == NULL) {
210
0
        return NULL;
211
0
    }
212
0
    return wmem_tree_remove32(tree, frame_num);
213
0
}
214
215
/*
216
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
217
 *
218
 * Local variables:
219
 * c-basic-offset: 4
220
 * tab-width: 8
221
 * indent-tabs-mode: nil
222
 * End:
223
 *
224
 * vi: set shiftwidth=4 tabstop=8 expandtab:
225
 * :indentSize=4:tabSize=8:noTabs=true:
226
 */