| 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 |