Coverage Report

Created: 2025-12-27 06:52

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
219
{
38
219
    wmem_multimap_t *multimap;
39
40
219
    multimap = wmem_new(allocator, wmem_multimap_t);
41
42
219
    multimap->map = wmem_map_new(allocator, hash_func, eql_func);
43
219
    multimap->metadata_allocator = allocator;
44
219
    multimap->data_allocator = allocator;
45
46
219
    return multimap;
47
219
}
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
56
{
78
56
    wmem_multimap_t *multimap;
79
80
56
    multimap = wmem_new(metadata_scope, wmem_multimap_t);
81
82
56
    multimap->map = wmem_map_new_autoreset(metadata_scope, data_scope, hash_func, eql_func);
83
56
    multimap->metadata_allocator = metadata_scope;
84
56
    multimap->data_allocator = data_scope;
85
86
56
    multimap->metadata_scope_cb_id = wmem_register_callback(metadata_scope, wmem_multimap_destroy_cb, multimap);
87
56
    multimap->data_scope_cb_id  = wmem_register_callback(data_scope, wmem_multimap_reset_cb, multimap);
88
89
56
    return multimap;
90
56
}
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
0
    wmem_map_foreach(map->map, count_nodes, &count);
111
0
    return count;
112
0
}
113
114
unsigned
115
wmem_multimap_count(const wmem_multimap_t *map, const void *key)
116
0
{
117
0
    wmem_tree_t *tree;
118
119
0
    if ((tree = wmem_map_lookup(map->map, key)) == NULL) {
120
0
        return 0;
121
0
    }
122
0
    return wmem_tree_count(tree);
123
0
}
124
125
bool
126
wmem_multimap_insert32(wmem_multimap_t *map, const void *key, uint32_t frame_num, void *value)
127
696
{
128
696
    wmem_tree_t *tree;
129
696
    bool ret = true;
130
131
696
    if ((tree = wmem_map_lookup(map->map, key)) == NULL) {
132
288
        tree = wmem_tree_new(map->data_allocator);
133
288
        wmem_map_insert(map->map, key, tree);
134
288
        ret = false;
135
288
    }
136
696
    wmem_tree_insert32(tree, frame_num, value);
137
138
696
    return ret;
139
696
}
140
141
void *
142
wmem_multimap_lookup32(const wmem_multimap_t *map, const void *key, uint32_t frame_num)
143
145
{
144
145
    wmem_tree_t *tree;
145
146
145
    if ((tree = wmem_map_lookup(map->map, key)) == NULL) {
147
121
        return NULL;
148
121
    }
149
24
    return wmem_tree_lookup32(tree, frame_num);
150
145
}
151
152
void *
153
wmem_multimap_lookup32_le(const wmem_multimap_t *map, const void *key, uint32_t frame_num)
154
311
{
155
311
    wmem_tree_t *tree;
156
157
311
    if ((tree = wmem_map_lookup(map->map, key)) == NULL) {
158
86
        return NULL;
159
86
    }
160
225
    return wmem_tree_lookup32_le(tree, frame_num);
161
311
}
162
163
void *
164
wmem_multimap_remove32(wmem_multimap_t *map, const void *key, const uint32_t frame_num)
165
0
{
166
0
    wmem_tree_t *tree;
167
168
0
    if ((tree = wmem_map_lookup(map->map, key)) == NULL) {
169
0
        return NULL;
170
0
    }
171
0
    return wmem_tree_remove32(tree, frame_num);
172
0
}
173
174
/*
175
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
176
 *
177
 * Local variables:
178
 * c-basic-offset: 4
179
 * tab-width: 8
180
 * indent-tabs-mode: nil
181
 * End:
182
 *
183
 * vi: set shiftwidth=4 tabstop=8 expandtab:
184
 * :indentSize=4:tabSize=8:noTabs=true:
185
 */