GCC Code Coverage Report


Directory: src/gate/
File: src/gate/strings_strbuilder.c
Date: 2026-09-21 06:26:40
Exec Total Coverage
Lines: 297 319 93.1%
Functions: 39 39 100.0%
Branches: 119 184 64.7%

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 9864 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 1998 times.
✓ Branch 1 taken 7866 times.
9864 if (newcapacity == 0)
41 {
42
2/2
✓ Branch 0 taken 158 times.
✓ Branch 1 taken 1840 times.
1998 if (src != NULL)
43 {
44 158 gate_mem_dealloc(src);
45 }
46 1998 ret = NULL;
47 }
48 else
49 {
50
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7866 times.
7866 if (newcapacity <= srclength)
51 {
52 ret = src;
53 }
54 else
55 {
56 7866 ++newcapacity;
57 7866 ret = (gate_stringbuffer_t*)gate_mem_realloc(src, sizeof(gate_stringbuffer_t) + newcapacity);
58
1/2
✓ Branch 0 taken 7866 times.
✗ Branch 1 not taken.
7866 if (ret != NULL)
59 {
60 7866 ret->data[newcapacity] = 0;
61 7866 ret->refcount = 0;
62 }
63 }
64 }
65 9864 return ret;
66 }
67
68 46 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 46 return NULL;
74 }
75
76 1990 void gate_strbuilder_create(gate_strbuilder_t* builder, gate_size_t capacity)
77 {
78
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1990 times.
1990 GATE_DEBUG_ASSERT(builder != NULL);
79 1990 builder->ptr_data = NULL;
80 1990 builder->length = 0;
81 1990 builder->capacity = 0;
82 1990 builder->resize = &gate_strbuilder_resize_heap;
83 1990 builder->buffer = NULL;
84
2/2
✓ Branch 0 taken 1798 times.
✓ Branch 1 taken 192 times.
1990 if (capacity != 0)
85 {
86 1798 builder->buffer = builder->resize(NULL, 0, capacity);
87
1/2
✓ Branch 0 taken 1798 times.
✗ Branch 1 not taken.
1798 if (builder->buffer != NULL)
88 {
89 1798 builder->ptr_data = builder->buffer->data;
90 }
91 }
92 1990 }
93 114 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 114 times.
114 GATE_DEBUG_ASSERT(builder != NULL);
96
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
114 GATE_DEBUG_ASSERT(buffer != NULL);
97
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
114 GATE_DEBUG_ASSERT(capacity > 0);
98
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
114 GATE_DEBUG_ASSERT(length_used <= capacity);
99 114 builder->ptr_data = buffer;
100 114 builder->length = length_used;
101 114 builder->capacity = capacity;
102 114 builder->resize = &gate_strbuilder_resize_disabled;
103 114 builder->buffer = NULL;
104 114 builder->ptr_data[length_used] = 0;
105 114 }
106
107
108 2123 void gate_strbuilder_release(gate_strbuilder_t* builder)
109 {
110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2123 times.
2123 GATE_DEBUG_ASSERT(builder != NULL);
111
2/2
✓ Branch 0 taken 2042 times.
✓ Branch 1 taken 81 times.
2123 if ((builder->resize != NULL))
112 {
113 2042 builder->buffer = builder->resize(builder->buffer, builder->length, 0);
114 2042 builder->capacity = 0;
115 }
116 2123 builder->ptr_data = NULL;
117 2123 builder->length = 0;
118 2123 }
119 1962 gate_size_t gate_strbuilder_length(gate_strbuilder_t const* builder)
120 {
121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1962 times.
1962 if (builder == NULL)
122 {
123 return 0;
124 }
125 else
126 {
127 1962 return builder->length;
128 }
129 }
130 1294 gate_char8_t const* gate_strbuilder_ptr(gate_strbuilder_t const* builder, gate_size_t charpos)
131 {
132
2/4
✓ Branch 0 taken 1294 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1294 times.
1294 if ((builder == NULL) || (builder->ptr_data == NULL))
133 {
134 return NULL;
135 }
136 else
137 {
138
2/2
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 1227 times.
1294 if (charpos >= builder->length)
139 {
140 67 return NULL;
141 }
142 else
143 {
144 1227 return &builder->ptr_data[charpos];
145 }
146 }
147 }
148 6070 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 6070 times.
6070 GATE_DEBUG_ASSERT(builder != NULL);
151
152
2/4
✓ Branch 0 taken 6070 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6070 times.
✗ Branch 3 not taken.
6070 if ((builder->resize != NULL) && (sz != 0))
153 {
154 gate_stringbuffer_t* newbuffer;
155 6070 newbuffer = builder->resize(builder->buffer, builder->length, sz + 1);
156
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6068 times.
6070 if (newbuffer == NULL)
157 {
158 /* allocation failed */
159 2 return 0;
160 }
161 6068 builder->buffer = newbuffer;
162 6068 builder->ptr_data = newbuffer->data;
163 6068 builder->capacity = sz;
164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6068 times.
6068 if (builder->length > builder->capacity)
165 {
166 builder->length = builder->capacity;
167 }
168 6068 return builder->capacity;
169 }
170 else
171 {
172 return 0;
173 }
174 }
175
176 6060 gate_size_t gate_strbuilder_increase(gate_strbuilder_t* builder, gate_size_t sz)
177 {
178 6060 return gate_strbuilder_resize(builder, builder->capacity + sz + 1);
179 }
180
181
182 1548627 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 1548627 times.
1548627 GATE_DEBUG_ASSERT(builder != NULL);
185
3/4
✓ Branch 0 taken 1548604 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 1548604 times.
✗ Branch 3 not taken.
1548627 if ((txtlen != 0) && (txt != NULL))
186 {
187 1548604 gate_size_t const free_chars = builder->capacity - builder->length;
188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1548604 times.
1548604 GATE_DEBUG_ASSERT(builder->capacity >= builder->length);
189
2/2
✓ Branch 0 taken 6010 times.
✓ Branch 1 taken 1542594 times.
1548604 if (txtlen >= free_chars)
190 {
191
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6010 times.
6010 if (gate_strbuilder_increase(builder, txtlen + (builder->length + 1) / 2) == 0)
192 {
193 return 0;
194 }
195 }
196 1548604 gate_mem_copy(&builder->ptr_data[builder->length], txt, txtlen);
197 1548604 builder->length += txtlen;
198 1548604 builder->ptr_data[builder->length] = 0;
199 1548604 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 1241177 gate_size_t gate_strbuilder_append_cstr(gate_strbuilder_t* builder, char const* txt)
239 {
240
1/2
✓ Branch 0 taken 1241177 times.
✗ Branch 1 not taken.
1241177 if (txt)
241 {
242 1241177 return gate_strbuilder_append_text(builder, txt, gate_str_length(txt));
243 }
244 return 0;
245 }
246
247 492 gate_size_t gate_strbuilder_append_string(gate_strbuilder_t* builder, gate_string_t const* txt)
248 {
249
1/2
✓ Branch 0 taken 492 times.
✗ Branch 1 not taken.
492 if (txt)
250 {
251 492 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 48 gate_size_t gate_strbuilder_append_int32(gate_strbuilder_t* builder, gate_int32_t num)
324 {
325 gate_char8_t buffer[16];
326 48 gate_size_t const bufferlen = sizeof(buffer) / sizeof(buffer[0]);
327 48 gate_size_t const bufferused = gate_str_print_int32(&buffer[0], bufferlen, num);
328 48 return gate_strbuilder_append_text(builder, &buffer[0], bufferused);
329 }
330 248198 gate_size_t gate_strbuilder_append_uint32(gate_strbuilder_t* builder, gate_uint32_t num)
331 {
332 gate_char8_t buffer[16];
333 248198 gate_size_t const bufferlen = sizeof(buffer) / sizeof(buffer[0]);
334 248198 gate_size_t const bufferused = gate_str_print_uint32(&buffer[0], bufferlen, num);
335 248198 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 14 gate_size_t gate_strbuilder_append_uint64(gate_strbuilder_t* builder, gate_uint64_t num)
345 {
346 gate_char8_t buffer[24];
347 14 gate_size_t const bufferlen = sizeof(buffer) / sizeof(buffer[0]);
348 14 gate_size_t const bufferused = gate_str_print_int64(&buffer[0], bufferlen, num);
349 14 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 574 static gate_size_t GATE_CALL gate_strbuilder_printer_callback(void* printer_param, gate_char8_t const* data, gate_size_t datalen)
376 {
377 574 gate_strbuilder_t* const builder = (gate_strbuilder_t*)printer_param;
378
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 574 times.
574 GATE_DEBUG_ASSERT(builder != NULL);
379 574 return gate_strbuilder_append_text(builder, data, datalen);
380 }
381
382 83 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 83 times.
83 GATE_DEBUG_ASSERT(builder != NULL);
387
388 83 va_start(vl, builder);
389
390 83 ret = gate_str_print_to(&gate_strbuilder_printer_callback, builder, vl);
391
392 83 va_end(vl);
393
394 83 return ret;
395 }
396
397 2 gate_size_t gate_strbuilder_insert(gate_strbuilder_t* builder, gate_size_t pos, char const* txt, gate_size_t txtlen)
398 {
399 2 gate_size_t ret = 0;
400
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_DEBUG_ASSERT(builder != NULL);
401
402
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (pos >= builder->length)
403 {
404 1 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 2 return ret;
419 }
420
421 3 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 3 times.
3 GATE_DEBUG_ASSERT(builder != NULL);
424
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (pos >= builder->length)
425 {
426 return 0;
427 }
428
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
3 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 3 times.
3 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 3 builder->length -= length;
442 3 builder->buffer->data[builder->length] = 0;
443
444 3 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 1070 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 1070 times.
1070 GATE_DEBUG_ASSERT(builder != NULL);
546
2/2
✓ Branch 0 taken 689 times.
✓ Branch 1 taken 381 times.
1070 if (charcount >= builder->length)
547 {
548 689 charcount = builder->length;
549 689 builder->length = 0;
550 }
551 else
552 {
553
1/2
✓ Branch 0 taken 381 times.
✗ Branch 1 not taken.
381 if (charcount > 0)
554 {
555 381 gate_mem_move(&builder->ptr_data[0], &builder->ptr_data[charcount], builder->length - charcount);
556 381 builder->length -= charcount;
557 381 builder->ptr_data[builder->length] = 0;
558 }
559 }
560 1070 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 1842 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 1842 times.
1842 GATE_DEBUG_ASSERT(builder != NULL);
605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1842 times.
1842 GATE_DEBUG_ASSERT(str != NULL);
606
607
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 1815 times.
1842 if (builder->length == 0)
608 {
609 27 gate_string_create_empty(str);
610 27 gate_strbuilder_release(builder);
611 }
612 else
613 {
614 1815 str->buffer = builder->buffer;
615 1815 str->str = builder->ptr_data;
616 1815 str->length = builder->length;
617
2/2
✓ Branch 0 taken 1805 times.
✓ Branch 1 taken 10 times.
1815 if (str->buffer != NULL)
618 {
619 1805 gate_atomic_int_init(&str->buffer->refcount, 1);
620 }
621
622 1815 builder->buffer = NULL;
623 1815 builder->ptr_data = NULL;
624 1815 builder->capacity = 0;
625 1815 builder->length = 0;
626 }
627 1842 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 4 gate_result_t gate_strbuilder_copy_constructor(void* destMem, void const* srcMem)
635 {
636 4 gate_strbuilder_t* const dst = (gate_strbuilder_t*)destMem;
637 4 gate_strbuilder_create(dst, 0);
638
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (srcMem)
639 {
640 4 gate_strbuilder_t const* const src = (gate_strbuilder_t const*)srcMem;
641 4 gate_size_t const len = gate_strbuilder_length(src);
642
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 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 4 return GATE_RESULT_OK;
652 }
653 4 void gate_strbuilder_destructor(void* dest)
654 {
655 4 gate_strbuilder_t* const dst = (gate_strbuilder_t*)dest;
656
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_DEBUG_ASSERT(dst != NULL);
657 4 gate_strbuilder_release(dst);
658 4 }
659