GCC Code Coverage Report


Directory: src/gate/
File: src/gate/strings_strbuilder.c
Date: 2026-08-06 22:46:24
Exec Total Coverage
Lines: 296 319 92.8%
Functions: 39 39 100.0%
Branches: 115 184 62.5%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright (c) 2018-2026, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/strings.h"
30 #include "gate/results.h"
31 #include "gate/debugging.h"
32
33 /********************************
34 * StringBuilder implementation *
35 ********************************/
36
37 5968 static gate_stringbuffer_t* gate_strbuilder_resize_heap(gate_stringbuffer_t* src, gate_size_t srclength, gate_size_t newcapacity)
38 {
39 gate_stringbuffer_t* ret;
40
2/2
✓ Branch 0 taken 1261 times.
✓ Branch 1 taken 4707 times.
5968 if (newcapacity == 0)
41 {
42
2/2
✓ Branch 0 taken 142 times.
✓ Branch 1 taken 1119 times.
1261 if (src != NULL)
43 {
44 142 gate_mem_dealloc(src);
45 }
46 1261 ret = NULL;
47 }
48 else
49 {
50
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4707 times.
4707 if (newcapacity <= srclength)
51 {
52 ret = src;
53 }
54 else
55 {
56 4707 ++newcapacity;
57 4707 ret = (gate_stringbuffer_t*)gate_mem_realloc(src, sizeof(gate_stringbuffer_t) + newcapacity);
58
1/2
✓ Branch 0 taken 4707 times.
✗ Branch 1 not taken.
4707 if (ret != NULL)
59 {
60 4707 ret->data[newcapacity] = 0;
61 4707 ret->refcount = 0;
62 }
63 }
64 }
65 5968 return ret;
66 }
67
68 42 static gate_stringbuffer_t* gate_strbuilder_resize_disabled(gate_stringbuffer_t* src, gate_size_t srclength, gate_size_t newcapacity)
69 {
70 (void)src;
71 (void)srclength;
72 (void)newcapacity;
73 42 return NULL;
74 }
75
76 1258 void gate_strbuilder_create(gate_strbuilder_t* builder, gate_size_t capacity)
77 {
78
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1258 times.
1258 GATE_DEBUG_ASSERT(builder != NULL);
79 1258 builder->ptr_data = NULL;
80 1258 builder->length = 0;
81 1258 builder->capacity = 0;
82 1258 builder->resize = &gate_strbuilder_resize_heap;
83 1258 builder->buffer = NULL;
84
2/2
✓ Branch 0 taken 1109 times.
✓ Branch 1 taken 149 times.
1258 if (capacity != 0)
85 {
86 1109 builder->buffer = builder->resize(NULL, 0, capacity);
87
1/2
✓ Branch 0 taken 1109 times.
✗ Branch 1 not taken.
1109 if (builder->buffer != NULL)
88 {
89 1109 builder->ptr_data = builder->buffer->data;
90 }
91 }
92 1258 }
93 98 void gate_strbuilder_create_static(gate_strbuilder_t* builder, char* buffer, gate_size_t capacity, gate_size_t length_used)
94 {
95
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 GATE_DEBUG_ASSERT(builder != NULL);
96
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 GATE_DEBUG_ASSERT(buffer != NULL);
97
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 GATE_DEBUG_ASSERT(capacity > 0);
98
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 GATE_DEBUG_ASSERT(length_used <= capacity);
99 98 builder->ptr_data = buffer;
100 98 builder->length = length_used;
101 98 builder->capacity = capacity;
102 98 builder->resize = &gate_strbuilder_resize_disabled;
103 98 builder->buffer = NULL;
104 98 builder->ptr_data[length_used] = 0;
105 98 }
106
107
108 1327 void gate_strbuilder_release(gate_strbuilder_t* builder)
109 {
110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1327 times.
1327 GATE_DEBUG_ASSERT(builder != NULL);
111
2/2
✓ Branch 0 taken 1301 times.
✓ Branch 1 taken 26 times.
1327 if ((builder->resize != NULL))
112 {
113 1301 builder->buffer = builder->resize(builder->buffer, builder->length, 0);
114 1301 builder->capacity = 0;
115 }
116 1327 builder->ptr_data = NULL;
117 1327 builder->length = 0;
118 1327 }
119 1830 gate_size_t gate_strbuilder_length(gate_strbuilder_t const* builder)
120 {
121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1830 times.
1830 if (builder == NULL)
122 {
123 return 0;
124 }
125 else
126 {
127 1830 return builder->length;
128 }
129 }
130 1254 gate_char8_t const* gate_strbuilder_ptr(gate_strbuilder_t const* builder, gate_size_t charpos)
131 {
132
2/4
✓ Branch 0 taken 1254 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1254 times.
1254 if ((builder == NULL) || (builder->ptr_data == NULL))
133 {
134 return NULL;
135 }
136 else
137 {
138
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 1190 times.
1254 if (charpos >= builder->length)
139 {
140 64 return NULL;
141 }
142 else
143 {
144 1190 return &builder->ptr_data[charpos];
145 }
146 }
147 }
148 3600 gate_size_t gate_strbuilder_resize(gate_strbuilder_t* builder, gate_size_t sz)
149 {
150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3600 times.
3600 GATE_DEBUG_ASSERT(builder != NULL);
151
152
2/4
✓ Branch 0 taken 3600 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3600 times.
✗ Branch 3 not taken.
3600 if ((builder->resize != NULL) && (sz != 0))
153 {
154 gate_stringbuffer_t* newbuffer;
155 3600 newbuffer = builder->resize(builder->buffer, builder->length, sz + 1);
156
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3598 times.
3600 if (newbuffer == NULL)
157 {
158 /* allocation failed */
159 2 return 0;
160 }
161 3598 builder->buffer = newbuffer;
162 3598 builder->ptr_data = newbuffer->data;
163 3598 builder->capacity = sz;
164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3598 times.
3598 if (builder->length > builder->capacity)
165 {
166 builder->length = builder->capacity;
167 }
168 3598 return builder->capacity;
169 }
170 else
171 {
172 return 0;
173 }
174 }
175
176 3590 gate_size_t gate_strbuilder_increase(gate_strbuilder_t* builder, gate_size_t sz)
177 {
178 3590 return gate_strbuilder_resize(builder, builder->capacity + sz + 1);
179 }
180
181
182 1511277 gate_size_t gate_strbuilder_append_text(gate_strbuilder_t* builder, gate_char8_t const* txt, gate_size_t txtlen)
183 {
184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1511277 times.
1511277 GATE_DEBUG_ASSERT(builder != NULL);
185
3/4
✓ Branch 0 taken 1511254 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 1511254 times.
✗ Branch 3 not taken.
1511277 if ((txtlen != 0) && (txt != NULL))
186 {
187 1511254 gate_size_t const free_chars = builder->capacity - builder->length;
188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1511254 times.
1511254 GATE_DEBUG_ASSERT(builder->capacity >= builder->length);
189
2/2
✓ Branch 0 taken 3540 times.
✓ Branch 1 taken 1507714 times.
1511254 if (txtlen >= free_chars)
190 {
191
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3540 times.
3540 if (gate_strbuilder_increase(builder, txtlen + (builder->length + 1) / 2) == 0)
192 {
193 return 0;
194 }
195 }
196 1511254 gate_mem_copy(&builder->ptr_data[builder->length], txt, txtlen);
197 1511254 builder->length += txtlen;
198 1511254 builder->ptr_data[builder->length] = 0;
199 1511254 return txtlen;
200 }
201 else
202 {
203 23 return 0;
204 }
205 }
206 302 gate_size_t gate_strbuilder_append_chars(gate_strbuilder_t* builder, gate_size_t char_count, char chr)
207 {
208
2/2
✓ Branch 0 taken 287 times.
✓ Branch 1 taken 15 times.
302 if (char_count != 0)
209 {
210 gate_size_t cnt;
211 char* ptr;
212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 287 times.
287 GATE_DEBUG_ASSERT(builder != NULL);
213
214
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 239 times.
287 if (char_count >= builder->capacity - builder->length)
215 {
216
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 48 times.
48 if (gate_strbuilder_increase(builder, char_count + builder->length / 2) == 0)
217 {
218 return 0;
219 }
220 }
221 287 ptr = &builder->ptr_data[builder->length];
222 287 cnt = char_count;
223
2/2
✓ Branch 0 taken 391 times.
✓ Branch 1 taken 287 times.
678 while (cnt-- != 0)
224 {
225 391 *ptr = chr;
226 391 ++ptr;
227 }
228 287 builder->length += char_count;
229 287 builder->ptr_data[builder->length] = 0;
230 287 return char_count;
231 }
232 else
233 {
234 15 return 0;
235 }
236 }
237
238 1236418 gate_size_t gate_strbuilder_append_cstr(gate_strbuilder_t* builder, char const* txt)
239 {
240
1/2
✓ Branch 0 taken 1236418 times.
✗ Branch 1 not taken.
1236418 if (txt)
241 {
242 1236418 return gate_strbuilder_append_text(builder, txt, gate_str_length(txt));
243 }
244 return 0;
245 }
246
247 427 gate_size_t gate_strbuilder_append_string(gate_strbuilder_t* builder, gate_string_t const* txt)
248 {
249
1/2
✓ Branch 0 taken 427 times.
✗ Branch 1 not taken.
427 if (txt)
250 {
251 427 return gate_strbuilder_append_text(builder, txt->str, txt->length);
252 }
253 return 0;
254 }
255
256 1 gate_size_t gate_strbuilder_append_text16(gate_strbuilder_t* builder, gate_char16_t const* txt, gate_size_t txtlen)
257 {
258 1 gate_size_t ret = 0;
259
260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(builder != NULL);
261 1 gate_strbuilder_increase(builder, txtlen);
262
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 while (txtlen != 0)
263 {
264 gate_size_t len_decoded;
265 gate_size_t len_encoded;
266 gate_char32_t chr;
267 gate_char8_t utf8[16];
268
269 1 len_decoded = gate_char_read_utf16(txt, txtlen, &chr);
270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (len_decoded == 0)
271 {
272 break;
273 }
274 1 txt += len_decoded;
275 1 txtlen -= len_decoded;
276 1 len_encoded = gate_char_write_utf8(chr, utf8, sizeof(utf8));
277 1 gate_strbuilder_append_text(builder, utf8, len_encoded);
278 1 ret += len_encoded;
279 }
280 1 return ret;
281 }
282 1 gate_size_t gate_strbuilder_append_text32(gate_strbuilder_t* builder, gate_char32_t const* txt, gate_size_t txtlen)
283 {
284 1 gate_size_t ret = 0;
285
286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(builder != NULL);
287 1 gate_strbuilder_increase(builder, txtlen);
288
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 while (txtlen != 0)
289 {
290 gate_char32_t chr;
291 gate_size_t len_decoded, len_encoded;
292 gate_char8_t utf8[16];
293
294 1 len_decoded = gate_char_read_utf32(txt, txtlen, &chr);
295
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (len_decoded == 0)
296 {
297 break;
298 }
299 1 txt += len_decoded;
300 1 txtlen -= len_decoded;
301 1 len_encoded = gate_char_write_utf8(chr, utf8, sizeof(utf8));
302 1 gate_strbuilder_append_text(builder, utf8, len_encoded);
303 1 ret += len_encoded;
304 }
305 1 return ret;
306 }
307
308
309 2 gate_size_t gate_strbuilder_append_int16(gate_strbuilder_t* builder, gate_int16_t num)
310 {
311 gate_char8_t buffer[12];
312 2 gate_size_t const bufferlen = sizeof(buffer) / sizeof(buffer[0]);
313 2 gate_size_t const bufferused = gate_str_print_int16(&buffer[0], bufferlen, num);
314 2 return gate_strbuilder_append_text(builder, &buffer[0], bufferused);
315 }
316 25 gate_size_t gate_strbuilder_append_uint16(gate_strbuilder_t* builder, gate_uint16_t num)
317 {
318 gate_char8_t buffer[12];
319 25 gate_size_t const bufferlen = sizeof(buffer) / sizeof(buffer[0]);
320 25 gate_size_t const bufferused = gate_str_print_uint16(&buffer[0], bufferlen, num);
321 25 return gate_strbuilder_append_text(builder, &buffer[0], bufferused);
322 }
323 36 gate_size_t gate_strbuilder_append_int32(gate_strbuilder_t* builder, gate_int32_t num)
324 {
325 gate_char8_t buffer[16];
326 36 gate_size_t const bufferlen = sizeof(buffer) / sizeof(buffer[0]);
327 36 gate_size_t const bufferused = gate_str_print_int32(&buffer[0], bufferlen, num);
328 36 return gate_strbuilder_append_text(builder, &buffer[0], bufferused);
329 }
330 247248 gate_size_t gate_strbuilder_append_uint32(gate_strbuilder_t* builder, gate_uint32_t num)
331 {
332 gate_char8_t buffer[16];
333 247248 gate_size_t const bufferlen = sizeof(buffer) / sizeof(buffer[0]);
334 247248 gate_size_t const bufferused = gate_str_print_uint32(&buffer[0], bufferlen, num);
335 247248 return gate_strbuilder_append_text(builder, &buffer[0], bufferused);
336 }
337 54 gate_size_t gate_strbuilder_append_int64(gate_strbuilder_t* builder, gate_int64_t num)
338 {
339 gate_char8_t buffer[24];
340 54 gate_size_t const bufferlen = sizeof(buffer) / sizeof(buffer[0]);
341 54 gate_size_t const bufferused = gate_str_print_int64(&buffer[0], bufferlen, num);
342 54 return gate_strbuilder_append_text(builder, &buffer[0], bufferused);
343 }
344 12 gate_size_t gate_strbuilder_append_uint64(gate_strbuilder_t* builder, gate_uint64_t num)
345 {
346 gate_char8_t buffer[24];
347 12 gate_size_t const bufferlen = sizeof(buffer) / sizeof(buffer[0]);
348 12 gate_size_t const bufferused = gate_str_print_int64(&buffer[0], bufferlen, num);
349 12 return gate_strbuilder_append_text(builder, &buffer[0], bufferused);
350 }
351 30 gate_size_t gate_strbuilder_append_real(gate_strbuilder_t* builder, gate_real64_t num, unsigned intlen, unsigned decimallen, unsigned grouplen)
352 {
353 gate_char8_t buffer[64];
354 30 gate_size_t const bufferlen = sizeof(buffer) / sizeof(buffer[0]);
355 30 gate_size_t const bufferused = gate_str_print_real(&buffer[0], bufferlen, num, intlen, decimallen, grouplen);
356 30 return gate_strbuilder_append_text(builder, &buffer[0], bufferused);
357 }
358 6 gate_size_t gate_strbuilder_append_hex(gate_strbuilder_t* builder, gate_uint8_t const* bytes, gate_size_t byte_count, gate_bool_t uppercase)
359 {
360 6 gate_size_t ret = 0;
361
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 while (byte_count-- != 0)
362 {
363 gate_char8_t chr[4];
364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 GATE_DEBUG_ASSERT(builder != NULL);
365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 GATE_DEBUG_ASSERT(bytes != NULL);
366 6 chr[0] = gate_str_print_hex_nibble((gate_uint8_t)((*bytes >> 4) & 0x0f), uppercase);
367 6 chr[1] = gate_str_print_hex_nibble((gate_uint8_t)((*bytes) & 0x0f), uppercase);
368 6 ret += gate_strbuilder_append_text(builder, chr, 2);
369 6 ++bytes;
370 }
371 6 return ret;
372 }
373
374
375 546 static gate_size_t GATE_CALL gate_strbuilder_printer_callback(void* printer_param, gate_char8_t const* data, gate_size_t datalen)
376 {
377 546 gate_strbuilder_t* const builder = (gate_strbuilder_t*)printer_param;
378
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 546 times.
546 GATE_DEBUG_ASSERT(builder != NULL);
379 546 return gate_strbuilder_append_text(builder, data, datalen);
380 }
381
382 79 gate_size_t gate_strbuilder_append(gate_strbuilder_t* builder, ...)
383 {
384 gate_size_t ret;
385 va_list vl;
386
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 GATE_DEBUG_ASSERT(builder != NULL);
387
388 79 va_start(vl, builder);
389
390 79 ret = gate_str_print_to(&gate_strbuilder_printer_callback, builder, vl);
391
392 79 va_end(vl);
393
394 79 return ret;
395 }
396
397 1 gate_size_t gate_strbuilder_insert(gate_strbuilder_t* builder, gate_size_t pos, char const* txt, gate_size_t txtlen)
398 {
399 1 gate_size_t ret = 0;
400
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(builder != NULL);
401
402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pos >= builder->length)
403 {
404 ret = gate_strbuilder_append_text(builder, txt, txtlen);
405 }
406
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 else if ((txt != NULL) && (txtlen > 0))
407 {
408 1 ret = gate_strbuilder_resize(builder, builder->length + txtlen + 2);
409
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ret != 0)
410 {
411 1 gate_mem_move(&builder->buffer->data[pos + txtlen], &builder->buffer->data[pos], builder->length - pos);
412 1 gate_mem_copy(&builder->buffer->data[pos], txt, txtlen);
413 1 builder->length += txtlen;
414 1 builder->buffer->data[builder->length] = 0;
415 1 ret = txtlen;
416 }
417 }
418 1 return ret;
419 }
420
421 1 gate_size_t gate_strbuilder_remove(gate_strbuilder_t* builder, gate_size_t pos, gate_size_t length)
422 {
423
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(builder != NULL);
424
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pos >= builder->length)
425 {
426 return 0;
427 }
428
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if ((length == GATE_STR_NPOS) || (pos + length > builder->length) )
429 {
430 1 length = builder->length - pos;
431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (length == 0)
432 {
433 return 0;
434 }
435 }
436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pos + length < builder->length)
437 {
438 gate_mem_move(&builder->buffer->data[pos], &builder->buffer->data[pos + length], builder->length - pos - length);
439 }
440
441 1 builder->length -= length;
442 1 builder->buffer->data[builder->length] = 0;
443
444 1 return length;
445 }
446
447 34 gate_size_t gate_strbuilder_replace(gate_strbuilder_t* builder, gate_size_t pos, gate_size_t len, char const* txt, gate_size_t txtlen)
448 {
449 34 gate_size_t ret = 0; /* default result: no replacement applied */
450 gate_size_t diff;
451 gate_size_t movelen;
452 do
453 {
454
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 GATE_DEBUG_ASSERT(builder != NULL);
455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if (pos + len > builder->length)
456 {
457 /* out of bounds */
458 break;
459 }
460
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 24 times.
34 if (txtlen > len)
461 {
462 /* replacement requires string expansion */
463 10 diff = txtlen - len;
464
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 if (builder->length + diff + 1 > builder->capacity)
465 {
466
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (0 == gate_strbuilder_resize(builder, builder->length + diff + 1))
467 {
468 /* allocation failed */
469 break;
470 }
471 }
472 10 movelen = builder->length - (pos + len);
473
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
10 if (movelen > 0)
474 {
475 7 gate_mem_move(&builder->ptr_data[pos + txtlen], &builder->ptr_data[pos + len], movelen);
476 }
477 10 gate_mem_copy(&builder->ptr_data[pos], txt, txtlen);
478 10 builder->length += diff;
479 10 builder->ptr_data[builder->length] = 0;
480 }
481 else
482 {
483 /* inline replacement */
484
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 1 times.
24 if (txtlen > 0)
485 {
486 23 gate_mem_copy(&builder->ptr_data[pos], txt, txtlen);
487 }
488
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 if (len > txtlen)
489 {
490 /* discard characters */
491 20 diff = len - txtlen;
492 20 movelen = builder->length - (pos + len);
493
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 8 times.
20 if (movelen > 0)
494 {
495 12 gate_mem_move(&builder->ptr_data[pos + txtlen], &builder->ptr_data[pos + len], movelen);
496 }
497 20 builder->length -= diff;
498 20 builder->ptr_data[builder->length] = 0;
499 }
500 }
501 34 ret = 1; /* one replacement applied */
502 } while (0);
503 34 return ret;
504
505 }
506
507 1 gate_size_t gate_strbuilder_replace_str(gate_strbuilder_t* builder, char const* find, gate_size_t find_len, char const* replace_with, gate_size_t replace_with_len, gate_size_t start_pos, gate_size_t max_replace)
508 {
509 1 gate_size_t replaced_count = 0;
510
511
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 while (max_replace-- > 0)
512 {
513 gate_size_t find_pos;
514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_DEBUG_ASSERT(builder != NULL);
515 4 find_pos = gate_strbuilder_str_pos(builder, find, find_len, start_pos);
516
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (find_pos == GATE_STR_NPOS)
517 {
518 /* nothing more found */
519 1 break;
520 }
521
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (0 == gate_strbuilder_replace(builder, find_pos, find_len, replace_with, replace_with_len))
522 {
523 /* native replace operation failed */
524 break;
525 }
526 3 start_pos = find_pos;
527 3 ++replaced_count;
528 }
529 1 return replaced_count;
530 }
531
532 1 gate_size_t gate_strbuilder_replace_string(gate_strbuilder_t* builder, gate_string_t const* find, gate_string_t const* replace_with, gate_size_t start_pos, gate_size_t max_replace)
533 {
534
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(builder != NULL);
535 3 return gate_strbuilder_replace_str(builder,
536 1 gate_string_ptr(find, 0), gate_string_length(find),
537 1 gate_string_ptr(replace_with, 0), gate_string_length(replace_with),
538 start_pos, max_replace);
539 }
540
541
542
543 1026 gate_size_t gate_strbuilder_discard(gate_strbuilder_t* builder, gate_size_t charcount)
544 {
545
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1026 times.
1026 GATE_DEBUG_ASSERT(builder != NULL);
546
2/2
✓ Branch 0 taken 654 times.
✓ Branch 1 taken 372 times.
1026 if (charcount >= builder->length)
547 {
548 654 charcount = builder->length;
549 654 builder->length = 0;
550 }
551 else
552 {
553
1/2
✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
372 if (charcount > 0)
554 {
555 372 gate_mem_move(&builder->ptr_data[0], &builder->ptr_data[charcount], builder->length - charcount);
556 372 builder->length -= charcount;
557 372 builder->ptr_data[builder->length] = 0;
558 }
559 }
560 1026 return charcount;
561 }
562
563 1 gate_size_t gate_strbuilder_discard_back(gate_strbuilder_t* builder, gate_size_t charcount)
564 {
565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(builder != NULL);
566
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (charcount > builder->length)
567 {
568 charcount = builder->length;
569 }
570
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (charcount > 0)
571 {
572 1 builder->length -= charcount;
573 1 builder->ptr_data[builder->length] = 0;
574 }
575 1 return charcount;
576 }
577
578 532 gate_size_t gate_strbuilder_str_pos(gate_strbuilder_t const* builder, gate_char8_t const* str, gate_size_t strlength, gate_size_t start_at)
579 {
580
3/6
✓ Branch 0 taken 532 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 532 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 532 times.
532 if (!builder || !str || (strlength == 0))
581 {
582 return GATE_STR_NPOS;
583 }
584 532 return gate_str_pos(builder->ptr_data, builder->length, str, strlength, start_at);
585 }
586
587 1 gate_size_t gate_strbuilder_pos(gate_strbuilder_t const* builder, gate_string_t const* token, gate_size_t start_at)
588 {
589
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 if (!builder || (gate_string_length(token) == 0))
590 {
591 return GATE_STR_NPOS;
592 }
593 1 return gate_str_pos(builder->ptr_data, builder->length, token->str, token->length, start_at);
594 }
595 1 gate_size_t gate_strbuilder_char_pos(gate_strbuilder_t const* builder, gate_char8_t chr, gate_size_t start_at)
596 {
597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(builder != NULL);
598 1 return gate_str_char_pos(builder->ptr_data, builder->length, chr, start_at);
599 }
600
601
602 1132 gate_string_t* gate_strbuilder_to_string(gate_strbuilder_t* builder, gate_string_t* str)
603 {
604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1132 times.
1132 GATE_DEBUG_ASSERT(builder != NULL);
605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1132 times.
1132 GATE_DEBUG_ASSERT(str != NULL);
606
607
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 1112 times.
1132 if (builder->length == 0)
608 {
609 20 gate_string_create_empty(str);
610 20 gate_strbuilder_release(builder);
611 }
612 else
613 {
614 1112 str->buffer = builder->buffer;
615 1112 str->str = builder->ptr_data;
616 1112 str->length = builder->length;
617
2/2
✓ Branch 0 taken 1104 times.
✓ Branch 1 taken 8 times.
1112 if (str->buffer != NULL)
618 {
619 1104 gate_atomic_int_init(&str->buffer->refcount, 1);
620 }
621
622 1112 builder->buffer = NULL;
623 1112 builder->ptr_data = NULL;
624 1112 builder->capacity = 0;
625 1112 builder->length = 0;
626 }
627 1132 return str;
628 }
629 5 gate_string_t* gate_strbuilder_copy_to_string(gate_strbuilder_t const* builder, gate_string_t* str)
630 {
631
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 GATE_DEBUG_ASSERT(builder != NULL);
632 5 return gate_string_create(str, &builder->ptr_data[0], builder->length);
633 }
634 1 gate_result_t gate_strbuilder_copy_constructor(void* destMem, void const* srcMem)
635 {
636 1 gate_strbuilder_t* const dst = (gate_strbuilder_t*)destMem;
637 1 gate_strbuilder_create(dst, 0);
638
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (srcMem)
639 {
640 1 gate_strbuilder_t const* const src = (gate_strbuilder_t const*)srcMem;
641 1 gate_size_t const len = gate_strbuilder_length(src);
642
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (len > 0)
643 {
644
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (0 == gate_strbuilder_append_text(dst, gate_strbuilder_ptr(src, 0), len))
645 {
646 gate_strbuilder_release(dst);
647 return GATE_RESULT_OUTOFMEMORY;
648 }
649 }
650 }
651 1 return GATE_RESULT_OK;
652 }
653 1 void gate_strbuilder_destructor(void* dest)
654 {
655 1 gate_strbuilder_t* const dst = (gate_strbuilder_t*)dest;
656
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(dst != NULL);
657 1 gate_strbuilder_release(dst);
658 1 }
659