2 * Wireshark Memory Manager String Buffer
3 * Copyright 2012, Evan Huus <eapache@gmail.com>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include "wmem_core.h"
32 #include "wmem_strbuf.h"
34 #define DEFAULT_MINIMUM_LEN 16
36 /* Holds a wmem-allocated string-buffer.
37 * len is the length of the string (not counting the null-terminator) and
38 * should be the same as strlen(str) unless the string contains embedded
40 * alloc_len is the length of the raw buffer pointed to by str, regardless of
41 * what string is actually being stored (i.e. the buffer contents)
42 * max_len is the maximum permitted alloc_len (NOT the maximum permitted len,
43 * which must be one shorter than alloc_len to permit null-termination).
44 * When max_len is 0 (the default), no maximum is enforced.
46 struct _wmem_strbuf_t
{
47 wmem_allocator_t
*allocator
;
56 /* _ROOM accounts for the null-terminator, _RAW_ROOM does not.
57 * Some functions need one, some functions need the other. */
58 #define WMEM_STRBUF_ROOM(S) ((S)->alloc_len - (S)->len - 1)
59 #define WMEM_STRBUF_RAW_ROOM(S) ((S)->alloc_len - (S)->len)
62 wmem_strbuf_sized_new(wmem_allocator_t
*allocator
,
63 gsize alloc_len
, gsize max_len
)
65 wmem_strbuf_t
*strbuf
;
67 g_assert((max_len
== 0) || (alloc_len
<= max_len
));
69 strbuf
= wmem_new(allocator
, wmem_strbuf_t
);
71 strbuf
->allocator
= allocator
;
73 strbuf
->alloc_len
= alloc_len
? alloc_len
: DEFAULT_MINIMUM_LEN
;
74 strbuf
->max_len
= max_len
;
76 strbuf
->str
= (gchar
*)wmem_alloc(strbuf
->allocator
, strbuf
->alloc_len
);
77 strbuf
->str
[0] = '\0';
83 wmem_strbuf_new(wmem_allocator_t
*allocator
, const gchar
*str
)
85 wmem_strbuf_t
*strbuf
;
88 len
= str
? strlen(str
) : 0;
89 alloc_len
= DEFAULT_MINIMUM_LEN
;
91 /* +1 for the null-terminator */
92 while (alloc_len
< (len
+ 1)) {
96 strbuf
= wmem_strbuf_sized_new(allocator
, alloc_len
, 0);
99 strcpy(strbuf
->str
, str
);
107 wmem_strbuf_grow(wmem_strbuf_t
*strbuf
, const gsize to_add
)
109 gsize new_alloc_len
, new_len
;
111 new_alloc_len
= strbuf
->alloc_len
;
112 new_len
= strbuf
->len
+ to_add
;
114 /* +1 for the null-terminator */
115 while (new_alloc_len
< (new_len
+ 1)) {
119 /* max length only enforced if not 0 */
120 if (strbuf
->max_len
&& new_alloc_len
> strbuf
->max_len
) {
121 new_alloc_len
= strbuf
->max_len
;
124 if (new_alloc_len
== strbuf
->alloc_len
) {
128 strbuf
->str
= (gchar
*)wmem_realloc(strbuf
->allocator
, strbuf
->str
, new_alloc_len
);
130 strbuf
->alloc_len
= new_alloc_len
;
134 wmem_strbuf_append(wmem_strbuf_t
*strbuf
, const gchar
*str
)
138 if (!str
|| str
[0] == '\0') {
142 append_len
= strlen(str
);
144 wmem_strbuf_grow(strbuf
, append_len
);
146 g_strlcpy(&strbuf
->str
[strbuf
->len
], str
, WMEM_STRBUF_RAW_ROOM(strbuf
));
148 strbuf
->len
= MIN(strbuf
->len
+ append_len
, strbuf
->alloc_len
- 1);
152 wmem_strbuf_append_vprintf(wmem_strbuf_t
*strbuf
, const gchar
*fmt
, va_list ap
)
159 append_len
= g_printf_string_upper_bound(fmt
, ap
);
161 /* -1 because g_printf_string_upper_bound counts the null-terminator, but
162 * wmem_strbuf_grow does not */
163 wmem_strbuf_grow(strbuf
, append_len
- 1);
165 append_len
= g_vsnprintf(&strbuf
->str
[strbuf
->len
],
166 (gulong
) WMEM_STRBUF_RAW_ROOM(strbuf
),
171 strbuf
->len
= MIN(strbuf
->len
+ append_len
, strbuf
->alloc_len
- 1);
175 wmem_strbuf_append_printf(wmem_strbuf_t
*strbuf
, const gchar
*format
, ...)
179 va_start(ap
, format
);
180 wmem_strbuf_append_vprintf(strbuf
, format
, ap
);
185 wmem_strbuf_append_c(wmem_strbuf_t
*strbuf
, const gchar c
)
187 wmem_strbuf_grow(strbuf
, 1);
189 /* one for the char, one for the null-terminator */
190 if (WMEM_STRBUF_ROOM(strbuf
) >= 1) {
191 strbuf
->str
[strbuf
->len
] = c
;
193 strbuf
->str
[strbuf
->len
] = '\0';
198 wmem_strbuf_append_unichar(wmem_strbuf_t
*strbuf
, const gunichar c
)
203 charlen
= g_unichar_to_utf8(c
, buf
);
205 wmem_strbuf_grow(strbuf
, charlen
);
207 if (WMEM_STRBUF_ROOM(strbuf
) >= charlen
) {
208 memcpy(&strbuf
->str
[strbuf
->len
], buf
, charlen
);
209 strbuf
->len
+= charlen
;
210 strbuf
->str
[strbuf
->len
] = '\0';
215 wmem_strbuf_truncate(wmem_strbuf_t
*strbuf
, const gsize len
)
217 if (len
>= strbuf
->len
) {
221 strbuf
->str
[len
] = '\0';
226 wmem_strbuf_get_str(wmem_strbuf_t
*strbuf
)
232 wmem_strbuf_get_len(wmem_strbuf_t
*strbuf
)
238 * Editor modelines - http://www.wireshark.org/tools/modelines.html
243 * indent-tabs-mode: nil
246 * vi: set shiftwidth=4 tabstop=8 expandtab:
247 * :indentSize=4:tabSize=8:noTabs=true: