/src/wireshark/wsutil/wmem/wmem_list.c
Line | Count | Source |
1 | | /* wmem_list.c |
2 | | * Wireshark Memory Manager Doubly-Linked List |
3 | | * Copyright 2012, Evan Huus <eapache@gmail.com> |
4 | | * |
5 | | * Wireshark - Network traffic analyzer |
6 | | * By Gerald Combs <gerald@wireshark.org> |
7 | | * Copyright 1998 Gerald Combs |
8 | | * |
9 | | * SPDX-License-Identifier: GPL-2.0-or-later |
10 | | */ |
11 | | |
12 | | #include <string.h> |
13 | | #include <glib.h> |
14 | | |
15 | | #include "wmem_core.h" |
16 | | #include "wmem_list.h" |
17 | | |
18 | | struct _wmem_list_frame_t { |
19 | | struct _wmem_list_frame_t *next, *prev; |
20 | | void *data; |
21 | | }; |
22 | | |
23 | | struct _wmem_list_t { |
24 | | unsigned count; |
25 | | wmem_list_frame_t *head, *tail; |
26 | | wmem_allocator_t *allocator; |
27 | | }; |
28 | | |
29 | | unsigned |
30 | | wmem_list_count(const wmem_list_t *list) |
31 | 7.92M | { |
32 | 7.92M | return list->count; |
33 | 7.92M | } |
34 | | |
35 | | wmem_list_frame_t * |
36 | | wmem_list_head(const wmem_list_t *list) |
37 | 397k | { |
38 | 397k | return list->head; |
39 | 397k | } |
40 | | |
41 | | wmem_list_frame_t * |
42 | | wmem_list_tail(const wmem_list_t *list) |
43 | 691k | { |
44 | 691k | return list->tail; |
45 | 691k | } |
46 | | |
47 | | wmem_list_frame_t * |
48 | | wmem_list_frame_next(const wmem_list_frame_t *frame) |
49 | 499k | { |
50 | 499k | return frame->next; |
51 | 499k | } |
52 | | |
53 | | wmem_list_frame_t * |
54 | | wmem_list_frame_prev(const wmem_list_frame_t *frame) |
55 | 290k | { |
56 | 290k | return frame->prev; |
57 | 290k | } |
58 | | |
59 | | void * |
60 | | wmem_list_frame_data(const wmem_list_frame_t *frame) |
61 | 1.30M | { |
62 | 1.30M | return frame->data; |
63 | 1.30M | } |
64 | | |
65 | | void |
66 | | wmem_list_remove(wmem_list_t *list, void *data) |
67 | 134k | { |
68 | 134k | wmem_list_frame_t *frame; |
69 | | |
70 | 134k | frame = list->head; |
71 | | |
72 | 134k | while (frame && frame->data != data) { |
73 | 0 | frame = frame->next; |
74 | 0 | } |
75 | | |
76 | 134k | if (frame == NULL) { |
77 | 0 | return; |
78 | 0 | } |
79 | | |
80 | 134k | wmem_list_remove_frame(list, frame); |
81 | 134k | } |
82 | | |
83 | | void |
84 | | wmem_list_remove_frame(wmem_list_t *list, wmem_list_frame_t *frame) |
85 | 673k | { |
86 | 673k | if (frame->prev) { |
87 | 538k | frame->prev->next = frame->next; |
88 | 538k | } |
89 | 134k | else { |
90 | 134k | list->head = frame->next; |
91 | 134k | } |
92 | | |
93 | 673k | if (frame->next) { |
94 | 98.6k | frame->next->prev = frame->prev; |
95 | 98.6k | } |
96 | 574k | else { |
97 | 574k | list->tail = frame->prev; |
98 | 574k | } |
99 | | |
100 | 673k | list->count--; |
101 | 673k | wmem_free(list->allocator, frame); |
102 | 673k | } |
103 | | |
104 | | wmem_list_frame_t * |
105 | | wmem_list_find(const wmem_list_t *list, const void *data) |
106 | 10.5k | { |
107 | 10.5k | wmem_list_frame_t *cur; |
108 | | |
109 | 69.8k | for (cur = list->head; cur; cur = cur->next) { |
110 | 59.2k | if(cur->data == data) |
111 | 0 | return cur; |
112 | 59.2k | } |
113 | | |
114 | 10.5k | return NULL; |
115 | 10.5k | } |
116 | | |
117 | | wmem_list_frame_t * |
118 | | wmem_list_find_custom(const wmem_list_t *list, const void *data, GCompareFunc compare_func) |
119 | 10.6k | { |
120 | 10.6k | wmem_list_frame_t *cur; |
121 | | |
122 | 170k | for (cur = list->head; cur != NULL; cur = cur->next) { |
123 | 164k | if (compare_func(cur->data, data) == 0) { |
124 | 4.49k | return cur; |
125 | 4.49k | } |
126 | 164k | } |
127 | | |
128 | 6.16k | return NULL; |
129 | 10.6k | } |
130 | | |
131 | | void |
132 | | wmem_list_prepend(wmem_list_t *list, void *data) |
133 | 234k | { |
134 | 234k | wmem_list_frame_t *new_frame; |
135 | | |
136 | 234k | new_frame = wmem_new(list->allocator, wmem_list_frame_t); |
137 | | |
138 | 234k | new_frame->data = data; |
139 | 234k | new_frame->next = list->head; |
140 | 234k | new_frame->prev = NULL; |
141 | | |
142 | 234k | if (list->head) { |
143 | 113k | list->head->prev = new_frame; |
144 | 113k | } |
145 | 121k | else { |
146 | 121k | list->tail = new_frame; |
147 | 121k | } |
148 | | |
149 | 234k | list->head = new_frame; |
150 | 234k | list->count++; |
151 | 234k | } |
152 | | |
153 | | void |
154 | | wmem_list_append(wmem_list_t *list, void *data) |
155 | 2.02M | { |
156 | 2.02M | wmem_list_frame_t *new_frame; |
157 | | |
158 | 2.02M | new_frame = wmem_new(list->allocator, wmem_list_frame_t); |
159 | 2.02M | new_frame->data = data; |
160 | 2.02M | new_frame->next = NULL; |
161 | 2.02M | new_frame->prev = list->tail; |
162 | | |
163 | 2.02M | if (list->tail) { |
164 | 1.77M | list->tail->next = new_frame; |
165 | 1.77M | } |
166 | 255k | else { |
167 | 255k | list->head = new_frame; |
168 | 255k | } |
169 | | |
170 | 2.02M | list->tail = new_frame; |
171 | 2.02M | list->count++; |
172 | 2.02M | } |
173 | | |
174 | | void |
175 | | wmem_list_insert_sorted(wmem_list_t *list, void* data, GCompareFunc func) |
176 | 9.82k | { |
177 | 9.82k | wmem_list_frame_t *new_frame; |
178 | 9.82k | wmem_list_frame_t *cur; |
179 | 9.82k | wmem_list_frame_t *prev; |
180 | | |
181 | 9.82k | new_frame = wmem_new(list->allocator, wmem_list_frame_t); |
182 | 9.82k | new_frame->data = data; |
183 | 9.82k | new_frame->next = NULL; |
184 | 9.82k | new_frame->prev = NULL; |
185 | | |
186 | 9.82k | list->count++; |
187 | | |
188 | 9.82k | if (!list->head) { |
189 | 2.15k | list->head = new_frame; |
190 | 2.15k | list->tail = new_frame; |
191 | 2.15k | return; |
192 | 2.15k | } |
193 | | |
194 | 7.66k | cur = list->head; |
195 | | |
196 | 7.66k | if (func(cur->data, data) >= 0) { |
197 | 1.69k | cur->prev = new_frame; |
198 | 1.69k | new_frame->next = cur; |
199 | 1.69k | list->head = new_frame; |
200 | 1.69k | return; |
201 | 1.69k | } |
202 | | |
203 | 343k | do { |
204 | 343k | prev = cur; |
205 | 343k | cur = cur->next; |
206 | 343k | } while (cur && func(cur->data, data) <= 0); |
207 | | |
208 | 5.96k | if (!cur) { |
209 | 1.34k | prev->next = new_frame; |
210 | 1.34k | new_frame->prev = prev; |
211 | 1.34k | list->tail = new_frame; |
212 | 1.34k | return; |
213 | 1.34k | } |
214 | | |
215 | 4.61k | new_frame->prev = prev; |
216 | 4.61k | new_frame->next = cur; |
217 | 4.61k | new_frame->prev->next = new_frame; |
218 | 4.61k | new_frame->next->prev = new_frame; |
219 | 4.61k | } |
220 | | |
221 | | void |
222 | | wmem_list_append_sorted(wmem_list_t *list, void* data, GCompareFunc func) |
223 | 0 | { |
224 | 0 | wmem_list_frame_t *new_frame; |
225 | 0 | wmem_list_frame_t *cur; |
226 | 0 | wmem_list_frame_t *next; |
227 | |
|
228 | 0 | new_frame = wmem_new(list->allocator, wmem_list_frame_t); |
229 | 0 | new_frame->data = data; |
230 | 0 | new_frame->next = NULL; |
231 | 0 | new_frame->prev = NULL; |
232 | |
|
233 | 0 | list->count++; |
234 | |
|
235 | 0 | if (!list->head) { |
236 | 0 | list->head = new_frame; |
237 | 0 | list->tail = new_frame; |
238 | 0 | return; |
239 | 0 | } |
240 | | |
241 | 0 | cur = list->tail; |
242 | | |
243 | | /* best case scenario: append */ |
244 | 0 | if (func(cur->data, data) <= 0) { |
245 | 0 | cur->next = new_frame; |
246 | 0 | new_frame->prev = cur; |
247 | 0 | list->tail = new_frame; |
248 | 0 | return; |
249 | 0 | } |
250 | | |
251 | 0 | do { |
252 | 0 | next = cur; |
253 | 0 | cur = cur->prev; |
254 | 0 | } while (cur && func(cur->data, data) >= 0); |
255 | | |
256 | | /* worst case scenario: prepend */ |
257 | 0 | if (!cur) { |
258 | 0 | next->prev = new_frame; |
259 | 0 | new_frame->next = next; |
260 | 0 | list->head = new_frame; |
261 | 0 | return; |
262 | 0 | } |
263 | | |
264 | | /* ordinary case: insert */ |
265 | 0 | new_frame->next = next; |
266 | 0 | new_frame->prev = cur; |
267 | 0 | new_frame->prev->next = new_frame; |
268 | 0 | new_frame->next->prev = new_frame; |
269 | 0 | } |
270 | | |
271 | | wmem_list_t * |
272 | | wmem_list_new(wmem_allocator_t *allocator) |
273 | 1.44M | { |
274 | 1.44M | wmem_list_t *list; |
275 | | |
276 | 1.44M | list = wmem_new(allocator, wmem_list_t); |
277 | | |
278 | 1.44M | list->count = 0; |
279 | 1.44M | list->head = NULL; |
280 | 1.44M | list->tail = NULL; |
281 | 1.44M | list->allocator = allocator; |
282 | | |
283 | 1.44M | return list; |
284 | 1.44M | } |
285 | | |
286 | | void |
287 | | wmem_destroy_list(wmem_list_t *list) |
288 | 362k | { |
289 | 362k | wmem_list_frame_t *cur, *next; |
290 | | |
291 | 362k | cur = list->head; |
292 | | |
293 | 385k | while (cur) { |
294 | 23.5k | next = cur->next; |
295 | 23.5k | wmem_free(list->allocator, cur); |
296 | 23.5k | cur = next; |
297 | 23.5k | } |
298 | | |
299 | 362k | wmem_free(list->allocator, list); |
300 | 362k | } |
301 | | |
302 | | void |
303 | | wmem_list_foreach(const wmem_list_t *list, GFunc foreach_func, void * user_data) |
304 | 501k | { |
305 | 501k | wmem_list_frame_t *cur; |
306 | | |
307 | 501k | cur = list->head; |
308 | | |
309 | 569k | while (cur) { |
310 | 68.2k | foreach_func(cur->data, user_data); |
311 | 68.2k | cur = cur->next; |
312 | 68.2k | } |
313 | 501k | } |
314 | | |
315 | | /* |
316 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
317 | | * |
318 | | * Local variables: |
319 | | * c-basic-offset: 4 |
320 | | * tab-width: 8 |
321 | | * indent-tabs-mode: nil |
322 | | * End: |
323 | | * |
324 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
325 | | * :indentSize=4:tabSize=8:noTabs=true: |
326 | | */ |