| 436 | } |
| 437 | |
| 438 | SZ_PUBLIC sz_size_t sz_string_erase(sz_string_t *string, sz_size_t offset, sz_size_t length) { |
| 439 | |
| 440 | sz_assert_(string && "String can't be SZ_NULL."); |
| 441 | |
| 442 | sz_ptr_t string_start; |
| 443 | sz_size_t string_length; |
| 444 | sz_size_t string_space; |
| 445 | sz_bool_t string_is_external; |
| 446 | sz_string_unpack(string, &string_start, &string_length, &string_space, &string_is_external); |
| 447 | |
| 448 | // Normalize the offset, it can't be larger than the length. |
| 449 | offset = sz_min_of_two(offset, string_length); |
| 450 | |
| 451 | // We shouldn't normalize the length, to avoid overflowing on `offset + length >= string_length`, |
| 452 | // if receiving `length == SZ_SIZE_MAX`. After following expression the `length` will contain |
| 453 | // exactly the delta between original and final length of this `string`. |
| 454 | length = sz_min_of_two(length, string_length - offset); |
| 455 | |
| 456 | // There are 2 common cases, that wouldn't even require a `memmove`: |
| 457 | // 1. Erasing the entire contents of the string. |
| 458 | // In that case `length` argument will be equal or greater than `length` member. |
| 459 | // 2. Removing the tail of the string with something like `string.pop_back()` in C++. |
| 460 | // |
| 461 | // In both of those, regardless of the location of the string - stack or heap, |
| 462 | // the erasing is as easy as setting the length to the offset. |
| 463 | // In every other case, we must `memmove` the tail of the string to the left. |
| 464 | if (offset + length < string_length) |
| 465 | sz_move(string_start + offset, string_start + offset + length, string_length - offset - length); |
| 466 | |
| 467 | // The `string->external.length = offset` assignment would discard last characters |
| 468 | // of the on-the-stack string, but inplace subtraction would work. |
| 469 | string->external.length -= length; |
| 470 | string_start[string_length - length] = 0; |
| 471 | return length; |
| 472 | } |
| 473 | |
| 474 | SZ_PUBLIC void sz_string_free(sz_string_t *string, sz_memory_allocator_t *allocator) { |
| 475 | if (!sz_string_is_on_stack(string)) |
no test coverage detected
searching dependent graphs…