| 395 | } |
| 396 | |
| 397 | SZ_PUBLIC sz_ptr_t sz_string_expand( // |
| 398 | sz_string_t *string, sz_size_t offset, sz_size_t added_length, sz_memory_allocator_t *allocator) { |
| 399 | |
| 400 | sz_assert_(string && allocator && "String and allocator can't be SZ_NULL."); |
| 401 | |
| 402 | sz_ptr_t string_start; |
| 403 | sz_size_t string_length; |
| 404 | sz_size_t string_space; |
| 405 | sz_bool_t string_is_external; |
| 406 | sz_string_unpack(string, &string_start, &string_length, &string_space, &string_is_external); |
| 407 | |
| 408 | // The user intended to extend the string. |
| 409 | offset = sz_min_of_two(offset, string_length); |
| 410 | |
| 411 | // Guard against integer overflow in size calculation. |
| 412 | if (added_length > SZ_SSIZE_MAX - string_length - 1) return SZ_NULL_CHAR; |
| 413 | |
| 414 | // If we are lucky, no memory allocations will be needed. |
| 415 | if (string_length + added_length < string_space) { |
| 416 | sz_move(string_start + offset + added_length, string_start + offset, string_length - offset); |
| 417 | string_start[string_length + added_length] = 0; |
| 418 | // Even if the string is on the stack, the `+=` won't affect the tail of the string. |
| 419 | string->external.length += added_length; |
| 420 | } |
| 421 | // If we are not lucky, we need to allocate more memory. |
| 422 | else { |
| 423 | sz_size_t next_planned_size = sz_max_of_two(SZ_CACHE_LINE_WIDTH, string_space * (sz_size_t)2); |
| 424 | sz_size_t min_needed_space = sz_size_bit_ceil(offset + string_length + added_length + 1); |
| 425 | sz_size_t new_space = sz_max_of_two(min_needed_space, next_planned_size); |
| 426 | string_start = sz_string_reserve(string, new_space - 1, allocator); |
| 427 | if (!string_start) return SZ_NULL_CHAR; |
| 428 | |
| 429 | // Copy into the new buffer. |
| 430 | sz_move(string_start + offset + added_length, string_start + offset, string_length - offset); |
| 431 | string_start[string_length + added_length] = 0; |
| 432 | string->external.length = string_length + added_length; |
| 433 | } |
| 434 | |
| 435 | return string_start; |
| 436 | } |
| 437 | |
| 438 | SZ_PUBLIC sz_size_t sz_string_erase(sz_string_t *string, sz_size_t offset, sz_size_t length) { |
| 439 |
no test coverage detected
searching dependent graphs…