4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
6 * SPDX-License-Identifier: GPL-2.0-or-later
9 #define WS_LOG_DOMAIN LOG_DOMAIN_WSUTIL
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 */
24 ws_buffer_init(Buffer
* buffer
, size_t space
)
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
);
34 buffer
->data
= (uint8_t*)g_malloc(SMALL_BUFFER_SIZE
);
36 buffer
->allocated
= SMALL_BUFFER_SIZE
;
38 buffer
->data
= (uint8_t*)g_malloc(space
);
39 buffer
->allocated
= space
;
42 buffer
->first_free
= 0;
45 /* Frees the memory used by a buffer */
47 ws_buffer_free(Buffer
* buffer
)
50 if (buffer
->allocated
== SMALL_BUFFER_SIZE
) {
51 ws_assert(buffer
->data
);
52 g_ptr_array_add(small_buffers
, buffer
->data
);
56 buffer
->allocated
= 0;
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(). */
65 ws_buffer_assure_space(Buffer
* buffer
, size_t space
)
68 size_t available_at_end
= buffer
->allocated
- buffer
->first_free
;
70 bool space_at_beginning
;
72 /* If we've got the space already, good! */
73 if (space
<= available_at_end
) {
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
);
91 buffer
->first_free
= space_used
;
93 /*if (buffer->start >= space) {*/
94 if (space_at_beginning
) {
98 /* We'll allocate more space */
99 buffer
->allocated
+= space
+ 1024;
100 buffer
->data
= (uint8_t*)g_realloc(buffer
->data
, buffer
->allocated
);
104 ws_buffer_append(Buffer
* buffer
, uint8_t *from
, size_t bytes
)
107 ws_buffer_assure_space(buffer
, bytes
);
108 memcpy(buffer
->data
+ buffer
->first_free
, from
, bytes
);
109 buffer
->first_free
+= bytes
;
113 ws_buffer_remove_start(Buffer
* buffer
, size_t bytes
)
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
) {
126 buffer
->first_free
= 0;
131 #ifndef SOME_FUNCTIONS_ARE_DEFINES
133 ws_buffer_clean(Buffer
* buffer
)
136 ws_buffer_remove_start(buffer
, ws_buffer_length(buffer
));
140 #ifndef SOME_FUNCTIONS_ARE_DEFINES
142 ws_buffer_increase_length(Buffer
* buffer
, size_t bytes
)
145 buffer
->first_free
+= bytes
;
149 #ifndef SOME_FUNCTIONS_ARE_DEFINES
151 ws_buffer_length(Buffer
* buffer
)
154 return buffer
->first_free
- buffer
->start
;
158 #ifndef SOME_FUNCTIONS_ARE_DEFINES
160 ws_buffer_start_ptr(Buffer
* buffer
)
163 return buffer
->data
+ buffer
->start
;
167 #ifndef SOME_FUNCTIONS_ARE_DEFINES
169 ws_buffer_end_ptr(Buffer
* buffer
)
172 return buffer
->data
+ buffer
->first_free
;
176 #ifndef SOME_FUNCTIONS_ARE_DEFINES
178 ws_buffer_append_buffer(Buffer
* buffer
, Buffer
* src_buffer
)
181 ws_buffer_append(buffer
, ws_buffer_start_ptr(src_buffer
), ws_buffer_length(src_buffer
));
186 ws_buffer_cleanup(void)
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
201 * indent-tabs-mode: t
204 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
205 * :indentSize=8:tabSize=8:noTabs=false: