1 /* wmem_array.c
2 * Wireshark Memory Manager Array
3 * Copyright 2013, 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 "config.h"
13
14 #include <string.h>
15 #include <stdlib.h>
16 #include <glib.h>
17
18 #include "wmem_core.h"
19 #include "wmem_array.h"
20
21 /* Holds a wmem-allocated array.
22 * elem_len is the size of each element
23 * elem_count is the number of used elements
24 * alloc_count is the length (in elems) of the raw buffer pointed to by buf,
25 * regardless of how many elems are used (the contents)
26 */
27 struct _wmem_array_t {
28 wmem_allocator_t *allocator;
29
30 guint8 *buf;
31
32 gsize elem_size;
33
34 guint elem_count;
35 guint alloc_count;
36
37 gboolean null_terminated;
38 };
39
40 wmem_array_t *
wmem_array_sized_new(wmem_allocator_t * allocator,gsize elem_size,guint alloc_count)41 wmem_array_sized_new(wmem_allocator_t *allocator, gsize elem_size,
42 guint alloc_count)
43 {
44 wmem_array_t *array;
45
46 array = wmem_new(allocator, wmem_array_t);
47
48 array->allocator = allocator;
49 array->elem_size = elem_size;
50 array->elem_count = 0;
51 array->alloc_count = alloc_count ? alloc_count : 1;
52 array->null_terminated = FALSE;
53
54 array->buf = (guint8 *)wmem_alloc(array->allocator,
55 array->elem_size * array->alloc_count);
56
57 return array;
58 }
59
60 wmem_array_t *
wmem_array_new(wmem_allocator_t * allocator,const gsize elem_size)61 wmem_array_new(wmem_allocator_t *allocator, const gsize elem_size)
62 {
63 wmem_array_t *array;
64
65 array = wmem_array_sized_new(allocator, elem_size, 1);
66
67 return array;
68 }
69
70 void
wmem_array_grow(wmem_array_t * array,const guint to_add)71 wmem_array_grow(wmem_array_t *array, const guint to_add)
72 {
73 guint new_alloc_count, new_count;
74
75 new_alloc_count = array->alloc_count;
76 new_count = array->elem_count + to_add;
77
78 while (new_alloc_count < new_count) {
79 new_alloc_count *= 2;
80 }
81
82 if (new_alloc_count == array->alloc_count) {
83 return;
84 }
85
86 array->buf = (guint8 *)wmem_realloc(array->allocator, array->buf,
87 new_alloc_count * array->elem_size);
88
89 array->alloc_count = new_alloc_count;
90 }
91
92 static void
wmem_array_write_null_terminator(wmem_array_t * array)93 wmem_array_write_null_terminator(wmem_array_t *array)
94 {
95 if (array->null_terminated) {
96 wmem_array_grow(array, 1);
97 memset(&array->buf[array->elem_count * array->elem_size], 0x0, array->elem_size);
98 }
99 }
100
101 void
wmem_array_set_null_terminator(wmem_array_t * array)102 wmem_array_set_null_terminator(wmem_array_t *array)
103 {
104 array->null_terminated = TRUE;
105 wmem_array_write_null_terminator(array);
106 }
107
108 void
wmem_array_bzero(wmem_array_t * array)109 wmem_array_bzero(wmem_array_t *array)
110 {
111 memset(array->buf, 0x0, array->elem_size * array->elem_count);
112 }
113
114 void
wmem_array_append(wmem_array_t * array,const void * in,guint count)115 wmem_array_append(wmem_array_t *array, const void *in, guint count)
116 {
117 wmem_array_grow(array, count);
118
119 memcpy(&array->buf[array->elem_count * array->elem_size], in,
120 count * array->elem_size);
121
122 array->elem_count += count;
123
124 wmem_array_write_null_terminator(array);
125 }
126
127 void *
wmem_array_index(wmem_array_t * array,guint array_index)128 wmem_array_index(wmem_array_t *array, guint array_index)
129 {
130 g_assert(array_index < array->elem_count);
131 return &array->buf[array_index * array->elem_size];
132 }
133
134 int
wmem_array_try_index(wmem_array_t * array,guint array_index,void * val)135 wmem_array_try_index(wmem_array_t *array, guint array_index, void *val)
136 {
137 if (array_index >= array->elem_count)
138 return -1;
139 memcpy(val, &array->buf[array_index * array->elem_size], array->elem_size);
140 return 0;
141 }
142
143 void
wmem_array_sort(wmem_array_t * array,int (* compar)(const void *,const void *))144 wmem_array_sort(wmem_array_t *array, int (*compar)(const void*,const void*))
145 {
146 qsort(array->buf, array->elem_count, array->elem_size, compar);
147 }
148
149 void *
wmem_array_get_raw(wmem_array_t * array)150 wmem_array_get_raw(wmem_array_t *array)
151 {
152 return array->buf;
153 }
154
155 guint
wmem_array_get_count(wmem_array_t * array)156 wmem_array_get_count(wmem_array_t *array)
157 {
158 return array->elem_count;
159 }
160
161 void
wmem_destroy_array(wmem_array_t * array)162 wmem_destroy_array(wmem_array_t *array)
163 {
164 wmem_free(array->allocator, array->buf);
165 wmem_free(array->allocator, array);
166 }
167
168 /*
169 * Editor modelines - https://www.wireshark.org/tools/modelines.html
170 *
171 * Local variables:
172 * c-basic-offset: 4
173 * tab-width: 8
174 * indent-tabs-mode: nil
175 * End:
176 *
177 * vi: set shiftwidth=4 tabstop=8 expandtab:
178 * :indentSize=4:tabSize=8:noTabs=true:
179 */
180