HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / wmem / wmem_strbuf.c
blob00062b61421ac5d5dfe60c8566655f6c07f699e8
1 /* wmem_strbuf.c
2 * Wireshark Memory Manager String Buffer
3 * Copyright 2012, Evan Huus <eapache@gmail.com>
5 * $Id$
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.
26 #include "config.h"
28 #include <string.h>
29 #include <glib.h>
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
39 * nulls.
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;
49 gchar *str;
51 gsize len;
52 gsize alloc_len;
53 gsize max_len;
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)
61 wmem_strbuf_t *
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;
72 strbuf->len = 0;
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';
79 return strbuf;
82 wmem_strbuf_t *
83 wmem_strbuf_new(wmem_allocator_t *allocator, const gchar *str)
85 wmem_strbuf_t *strbuf;
86 gsize len, alloc_len;
88 len = str ? strlen(str) : 0;
89 alloc_len = DEFAULT_MINIMUM_LEN;
91 /* +1 for the null-terminator */
92 while (alloc_len < (len + 1)) {
93 alloc_len *= 2;
96 strbuf = wmem_strbuf_sized_new(allocator, alloc_len, 0);
98 if (str && len > 0) {
99 strcpy(strbuf->str, str);
100 strbuf->len = len;
103 return strbuf;
106 static void
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)) {
116 new_alloc_len *= 2;
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) {
125 return;
128 strbuf->str = (gchar *)wmem_realloc(strbuf->allocator, strbuf->str, new_alloc_len);
130 strbuf->alloc_len = new_alloc_len;
133 void
134 wmem_strbuf_append(wmem_strbuf_t *strbuf, const gchar *str)
136 gsize append_len;
138 if (!str || str[0] == '\0') {
139 return;
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);
151 static void
152 wmem_strbuf_append_vprintf(wmem_strbuf_t *strbuf, const gchar *fmt, va_list ap)
154 va_list ap2;
155 gsize append_len;
157 G_VA_COPY(ap2, 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),
167 fmt, ap2);
169 va_end(ap2);
171 strbuf->len = MIN(strbuf->len + append_len, strbuf->alloc_len - 1);
174 void
175 wmem_strbuf_append_printf(wmem_strbuf_t *strbuf, const gchar *format, ...)
177 va_list ap;
179 va_start(ap, format);
180 wmem_strbuf_append_vprintf(strbuf, format, ap);
181 va_end(ap);
184 void
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;
192 strbuf->len++;
193 strbuf->str[strbuf->len] = '\0';
197 void
198 wmem_strbuf_append_unichar(wmem_strbuf_t *strbuf, const gunichar c)
200 gchar buf[6];
201 gsize charlen;
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';
214 void
215 wmem_strbuf_truncate(wmem_strbuf_t *strbuf, const gsize len)
217 if (len >= strbuf->len) {
218 return;
221 strbuf->str[len] = '\0';
222 strbuf->len = len;
225 const gchar *
226 wmem_strbuf_get_str(wmem_strbuf_t *strbuf)
228 return strbuf->str;
231 gsize
232 wmem_strbuf_get_len(wmem_strbuf_t *strbuf)
234 return strbuf->len;
238 * Editor modelines - http://www.wireshark.org/tools/modelines.html
240 * Local variables:
241 * c-basic-offset: 4
242 * tab-width: 8
243 * indent-tabs-mode: nil
244 * End:
246 * vi: set shiftwidth=4 tabstop=8 expandtab:
247 * :indentSize=4:tabSize=8:noTabs=true: