TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags
[wireshark-sm.git] / wsutil / buffer.c
blobcdb16a83d934dbdcc362b09a217c9e91472756d2
1 /* buffer.c
3 * Wiretap Library
4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8 #include "config.h"
9 #define WS_LOG_DOMAIN LOG_DOMAIN_WSUTIL
10 #include "buffer.h"
12 #include <stdlib.h>
13 #include <string.h>
15 #include <wsutil/ws_assert.h>
16 #include <wsutil/wslog.h>
18 #define SMALL_BUFFER_SIZE (2 * 1024) /* Everyone still uses 1500 byte frames, right? */
19 static GPtrArray *small_buffers; /* Guaranteed to be at least SMALL_BUFFER_SIZE */
20 /* XXX - Add medium and large buffers? */
22 /* Initializes a buffer with a certain amount of allocated space */
23 void
24 ws_buffer_init(Buffer* buffer, size_t space)
26 ws_assert(buffer);
27 if (G_UNLIKELY(!small_buffers)) small_buffers = g_ptr_array_sized_new(1024);
29 if (space <= SMALL_BUFFER_SIZE) {
30 if (small_buffers->len > 0) {
31 buffer->data = (uint8_t*) g_ptr_array_remove_index(small_buffers, small_buffers->len - 1);
32 ws_assert(buffer->data);
33 } else {
34 buffer->data = (uint8_t*)g_malloc(SMALL_BUFFER_SIZE);
36 buffer->allocated = SMALL_BUFFER_SIZE;
37 } else {
38 buffer->data = (uint8_t*)g_malloc(space);
39 buffer->allocated = space;
41 buffer->start = 0;
42 buffer->first_free = 0;
45 /* Frees the memory used by a buffer */
46 void
47 ws_buffer_free(Buffer* buffer)
49 ws_assert(buffer);
50 if (buffer->allocated == SMALL_BUFFER_SIZE) {
51 ws_assert(buffer->data);
52 g_ptr_array_add(small_buffers, buffer->data);
53 } else {
54 g_free(buffer->data);
56 buffer->allocated = 0;
57 buffer->data = NULL;
60 /* Assures that there are 'space' bytes at the end of the used space
61 so that another routine can copy directly into the buffer space. After
62 doing that, the routine will also want to run
63 ws_buffer_increase_length(). */
64 void
65 ws_buffer_assure_space(Buffer* buffer, size_t space)
67 ws_assert(buffer);
68 size_t available_at_end = buffer->allocated - buffer->first_free;
69 size_t space_used;
70 bool space_at_beginning;
72 /* If we've got the space already, good! */
73 if (space <= available_at_end) {
74 return;
77 /* Maybe we don't have the space available at the end, but we would
78 if we moved the used space back to the beginning of the
79 allocation. The buffer could have become fragmented through lots
80 of calls to ws_buffer_remove_start(). I'm using buffer->start as the
81 same as 'available_at_start' in this comparison. */
83 /* or maybe there's just no more room. */
85 space_at_beginning = buffer->start >= space;
86 if (space_at_beginning || buffer->start > 0) {
87 space_used = buffer->first_free - buffer->start;
88 /* this memory copy better be safe for overlapping memory regions! */
89 memmove(buffer->data, buffer->data + buffer->start, space_used);
90 buffer->start = 0;
91 buffer->first_free = space_used;
93 /*if (buffer->start >= space) {*/
94 if (space_at_beginning) {
95 return;
98 /* We'll allocate more space */
99 buffer->allocated += space + 1024;
100 buffer->data = (uint8_t*)g_realloc(buffer->data, buffer->allocated);
103 void
104 ws_buffer_append(Buffer* buffer, uint8_t *from, size_t bytes)
106 ws_assert(buffer);
107 ws_buffer_assure_space(buffer, bytes);
108 memcpy(buffer->data + buffer->first_free, from, bytes);
109 buffer->first_free += bytes;
112 void
113 ws_buffer_remove_start(Buffer* buffer, size_t bytes)
115 ws_assert(buffer);
116 if (buffer->start + bytes > buffer->first_free) {
117 ws_error("ws_buffer_remove_start trying to remove %" PRIu64 " bytes. s=%" PRIu64 " ff=%" PRIu64 "!\n",
118 (uint64_t)bytes, (uint64_t)buffer->start,
119 (uint64_t)buffer->first_free);
120 /** ws_error() does an abort() and thus never returns **/
122 buffer->start += bytes;
124 if (buffer->start == buffer->first_free) {
125 buffer->start = 0;
126 buffer->first_free = 0;
131 #ifndef SOME_FUNCTIONS_ARE_DEFINES
132 void
133 ws_buffer_clean(Buffer* buffer)
135 ws_assert(buffer);
136 ws_buffer_remove_start(buffer, ws_buffer_length(buffer));
138 #endif
140 #ifndef SOME_FUNCTIONS_ARE_DEFINES
141 void
142 ws_buffer_increase_length(Buffer* buffer, size_t bytes)
144 ws_assert(buffer);
145 buffer->first_free += bytes;
147 #endif
149 #ifndef SOME_FUNCTIONS_ARE_DEFINES
150 size_t
151 ws_buffer_length(Buffer* buffer)
153 ws_assert(buffer);
154 return buffer->first_free - buffer->start;
156 #endif
158 #ifndef SOME_FUNCTIONS_ARE_DEFINES
159 uint8_t *
160 ws_buffer_start_ptr(Buffer* buffer)
162 ws_assert(buffer);
163 return buffer->data + buffer->start;
165 #endif
167 #ifndef SOME_FUNCTIONS_ARE_DEFINES
168 uint8_t *
169 ws_buffer_end_ptr(Buffer* buffer)
171 ws_assert(buffer);
172 return buffer->data + buffer->first_free;
174 #endif
176 #ifndef SOME_FUNCTIONS_ARE_DEFINES
177 void
178 ws_buffer_append_buffer(Buffer* buffer, Buffer* src_buffer)
180 ws_assert(buffer);
181 ws_buffer_append(buffer, ws_buffer_start_ptr(src_buffer), ws_buffer_length(src_buffer));
183 #endif
185 void
186 ws_buffer_cleanup(void)
188 if (small_buffers) {
189 g_ptr_array_set_free_func(small_buffers, g_free);
190 g_ptr_array_free(small_buffers, true);
191 small_buffers = NULL;
196 * Editor modelines - https://www.wireshark.org/tools/modelines.html
198 * Local variables:
199 * c-basic-offset: 8
200 * tab-width: 8
201 * indent-tabs-mode: t
202 * End:
204 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
205 * :indentSize=8:tabSize=8:noTabs=false: