4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
6 * SPDX-License-Identifier: GPL-2.0-or-later
15 #define SMALL_BUFFER_SIZE (2 * 1024) /* Everyone still uses 1500 byte frames, right? */
16 static GPtrArray *small_buffers = NULL; /* Guaranteed to be at least SMALL_BUFFER_SIZE */
17 /* XXX - Add medium and large buffers? */
19 /* Initializes a buffer with a certain amount of allocated space */
21 ws_buffer_init(Buffer* buffer, gsize space)
24 if (G_UNLIKELY(!small_buffers)) small_buffers = g_ptr_array_sized_new(1024);
26 if (space <= SMALL_BUFFER_SIZE) {
27 if (small_buffers->len > 0) {
28 buffer->data = (guint8*) g_ptr_array_remove_index(small_buffers, small_buffers->len - 1);
30 buffer->data = (guint8*)g_malloc(SMALL_BUFFER_SIZE);
32 buffer->allocated = SMALL_BUFFER_SIZE;
34 buffer->data = (guint8*)g_malloc(space);
35 buffer->allocated = space;
38 buffer->first_free = 0;
41 /* Frees the memory used by a buffer */
43 ws_buffer_free(Buffer* buffer)
46 if (buffer->allocated == SMALL_BUFFER_SIZE) {
47 g_ptr_array_add(small_buffers, buffer->data);
54 /* Assures that there are 'space' bytes at the end of the used space
55 so that another routine can copy directly into the buffer space. After
56 doing that, the routine will also want to run
57 ws_buffer_increase_length(). */
59 ws_buffer_assure_space(Buffer* buffer, gsize space)
62 gsize available_at_end = buffer->allocated - buffer->first_free;
64 gboolean space_at_beginning;
66 /* If we've got the space already, good! */
67 if (space <= available_at_end) {
71 /* Maybe we don't have the space available at the end, but we would
72 if we moved the used space back to the beginning of the
73 allocation. The buffer could have become fragmented through lots
74 of calls to ws_buffer_remove_start(). I'm using buffer->start as the
75 same as 'available_at_start' in this comparison. */
77 /* or maybe there's just no more room. */
79 space_at_beginning = buffer->start >= space;
80 if (space_at_beginning || buffer->start > 0) {
81 space_used = buffer->first_free - buffer->start;
82 /* this memory copy better be safe for overlapping memory regions! */
83 memmove(buffer->data, buffer->data + buffer->start, space_used);
85 buffer->first_free = space_used;
87 /*if (buffer->start >= space) {*/
88 if (space_at_beginning) {
92 /* We'll allocate more space */
93 buffer->allocated += space + 1024;
94 buffer->data = (guint8*)g_realloc(buffer->data, buffer->allocated);
98 ws_buffer_append(Buffer* buffer, guint8 *from, gsize bytes)
101 ws_buffer_assure_space(buffer, bytes);
102 memcpy(buffer->data + buffer->first_free, from, bytes);
103 buffer->first_free += bytes;
107 ws_buffer_remove_start(Buffer* buffer, gsize bytes)
110 if (buffer->start + bytes > buffer->first_free) {
111 g_error("ws_buffer_remove_start trying to remove %" G_GINT64_MODIFIER "u bytes. s=%" G_GINT64_MODIFIER "u ff=%" G_GINT64_MODIFIER "u!\n",
112 (guint64)bytes, (guint64)buffer->start,
113 (guint64)buffer->first_free);
114 /** g_error() does an abort() and thus never returns **/
116 buffer->start += bytes;
118 if (buffer->start == buffer->first_free) {
120 buffer->first_free = 0;
125 #ifndef SOME_FUNCTIONS_ARE_DEFINES
127 ws_buffer_clean(Buffer* buffer)
130 ws_buffer_remove_start(buffer, ws_buffer_length(buffer));
134 #ifndef SOME_FUNCTIONS_ARE_DEFINES
136 ws_buffer_increase_length(Buffer* buffer, gsize bytes)
139 buffer->first_free += bytes;
143 #ifndef SOME_FUNCTIONS_ARE_DEFINES
145 ws_buffer_length(Buffer* buffer)
148 return buffer->first_free - buffer->start;
152 #ifndef SOME_FUNCTIONS_ARE_DEFINES
154 ws_buffer_start_ptr(Buffer* buffer)
157 return buffer->data + buffer->start;
161 #ifndef SOME_FUNCTIONS_ARE_DEFINES
163 ws_buffer_end_ptr(Buffer* buffer)
166 return buffer->data + buffer->first_free;
170 #ifndef SOME_FUNCTIONS_ARE_DEFINES
172 ws_buffer_append_buffer(Buffer* buffer, Buffer* src_buffer)
175 ws_buffer_append(buffer, ws_buffer_start_ptr(src_buffer), ws_buffer_length(src_buffer));
180 ws_buffer_cleanup(void)
183 g_ptr_array_set_free_func(small_buffers, g_free);
184 g_ptr_array_free(small_buffers, TRUE);
185 small_buffers = NULL;
190 * Editor modelines - http://www.wireshark.org/tools/modelines.html
195 * indent-tabs-mode: t
198 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
199 * :indentSize=8:tabSize=8:noTabs=false: