This source file includes following definitions.
- sb_init
- sb_ensure_more_bytes
- sb_append
- sb_appendvf
- sb_appendf
- sb_free
- sb_dupfree
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <config.h>
20
21
22 #include "string-buffer.h"
23
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 void
30 sb_init (struct string_buffer *buffer)
31 {
32 buffer->data = buffer->space;
33 buffer->length = 0;
34 buffer->allocated = sizeof (buffer->space);
35 buffer->error = false;
36 }
37
38
39
40
41 static int
42 sb_ensure_more_bytes (struct string_buffer *buffer, size_t increment)
43 {
44 size_t incremented_length = buffer->length + increment;
45 if (incremented_length < increment)
46
47 return -1;
48
49 if (buffer->allocated < incremented_length)
50 {
51 size_t new_allocated = 2 * buffer->allocated;
52 if (new_allocated < buffer->allocated)
53
54 return -1;
55 if (new_allocated < incremented_length)
56 new_allocated = incremented_length;
57
58 char *new_data;
59 if (buffer->data == buffer->space)
60 {
61 new_data = (char *) malloc (new_allocated);
62 if (new_data == NULL)
63
64 return -1;
65 memcpy (new_data, buffer->data, buffer->length);
66 }
67 else
68 {
69 new_data = (char *) realloc (buffer->data, new_allocated);
70 if (new_data == NULL)
71
72 return -1;
73 }
74 buffer->data = new_data;
75 buffer->allocated = new_allocated;
76 }
77 return 0;
78 }
79
80 int
81 sb_append (struct string_buffer *buffer, const char *str)
82 {
83 size_t len = strlen (str);
84 if (sb_ensure_more_bytes (buffer, len) < 0)
85 {
86 buffer->error = true;
87 return -1;
88 }
89 memcpy (buffer->data + buffer->length, str, len);
90 buffer->length += len;
91 return 0;
92 }
93
94 int
95 sb_appendvf (struct string_buffer *buffer, const char *formatstring,
96 va_list list)
97 {
98 va_list list_copy;
99
100
101
102 size_t room = buffer->allocated - buffer->length;
103 if (room < 64)
104 {
105 if (sb_ensure_more_bytes (buffer, 64) < 0)
106 {
107 buffer->error = true;
108 return -1;
109 }
110 room = buffer->allocated - buffer->length;
111 }
112
113 va_copy (list_copy, list);
114
115
116 int ret = vsnprintf (buffer->data + buffer->length, room, formatstring, list);
117 if (ret < 0)
118 {
119
120 buffer->error = true;
121 ret = -1;
122 }
123 else
124 {
125 if ((size_t) ret <= room)
126 {
127
128 buffer->length += (size_t) ret;
129 ret = 0;
130 }
131 else
132 {
133
134
135 if (sb_ensure_more_bytes (buffer, (size_t) ret) < 0)
136 {
137 buffer->error = true;
138 ret = -1;
139 }
140 else
141 {
142
143 room = buffer->allocated - buffer->length;
144 ret = vsnprintf (buffer->data + buffer->length, room,
145 formatstring, list_copy);
146 if (ret < 0)
147 {
148
149 buffer->error = true;
150 ret = -1;
151 }
152 else
153 {
154 if ((size_t) ret <= room)
155 {
156
157 buffer->length += (size_t) ret;
158 ret = 0;
159 }
160 else
161
162
163 abort ();
164 }
165 }
166 }
167 }
168
169 va_end (list_copy);
170 return ret;
171 }
172
173 int
174 sb_appendf (struct string_buffer *buffer, const char *formatstring, ...)
175 {
176 va_list args;
177
178
179
180 size_t room = buffer->allocated - buffer->length;
181 if (room < 64)
182 {
183 if (sb_ensure_more_bytes (buffer, 64) < 0)
184 {
185 buffer->error = true;
186 return -1;
187 }
188 room = buffer->allocated - buffer->length;
189 }
190
191 va_start (args, formatstring);
192
193
194 int ret = vsnprintf (buffer->data + buffer->length, room, formatstring, args);
195 if (ret < 0)
196 {
197
198 buffer->error = true;
199 ret = -1;
200 }
201 else
202 {
203 if ((size_t) ret <= room)
204 {
205
206 buffer->length += (size_t) ret;
207 ret = 0;
208 }
209 else
210 {
211
212
213 if (sb_ensure_more_bytes (buffer, (size_t) ret) < 0)
214 {
215 buffer->error = true;
216 ret = -1;
217 }
218 else
219 {
220
221 room = buffer->allocated - buffer->length;
222 va_end (args);
223 va_start (args, formatstring);
224 ret = vsnprintf (buffer->data + buffer->length, room,
225 formatstring, args);
226 if (ret < 0)
227 {
228
229 buffer->error = true;
230 ret = -1;
231 }
232 else
233 {
234 if ((size_t) ret <= room)
235 {
236
237 buffer->length += (size_t) ret;
238 ret = 0;
239 }
240 else
241
242
243 abort ();
244 }
245 }
246 }
247 }
248
249 va_end (args);
250 return ret;
251 }
252
253 void
254 sb_free (struct string_buffer *buffer)
255 {
256 if (buffer->data != buffer->space)
257 free (buffer->data);
258 }
259
260
261
262 char *
263 sb_dupfree (struct string_buffer *buffer)
264 {
265 if (buffer->error)
266 goto fail;
267
268 if (sb_ensure_more_bytes (buffer, 1) < 0)
269 goto fail;
270 buffer->data[buffer->length] = '\0';
271 buffer->length++;
272
273 if (buffer->data == buffer->space)
274 {
275 char *copy = (char *) malloc (buffer->length);
276 if (copy == NULL)
277 goto fail;
278 memcpy (copy, buffer->data, buffer->length);
279 return copy;
280 }
281 else
282 {
283
284 char *contents = buffer->data;
285 if (buffer->length < buffer->allocated)
286 {
287 contents = realloc (contents, buffer->length);
288 if (contents == NULL)
289 goto fail;
290 }
291 return contents;
292 }
293
294 fail:
295 sb_free (buffer);
296 return NULL;
297 }