| 745 | } |
| 746 | |
| 747 | static sz_bool_t sz_py_replace_fragmented_allocator(Strs *strs, sz_memory_allocator_t *old_allocator, |
| 748 | sz_memory_allocator_t *allocator) { |
| 749 | struct fragmented_t *fragmented = &strs->data.fragmented; |
| 750 | sz_assert_(fragmented->spans && "Expected spans to be allocated"); |
| 751 | |
| 752 | // Calculate total size needed for consolidated tape |
| 753 | sz_size_t total_bytes = 0; |
| 754 | for (sz_size_t i = 0; i < fragmented->count; i++) total_bytes += fragmented->spans[i].length; |
| 755 | |
| 756 | // Choose 32-bit or 64-bit tape based on size |
| 757 | sz_bool_t use_64bit = total_bytes >= UINT32_MAX; |
| 758 | |
| 759 | // Skip allocation if there's no data to allocate (empty strings case) |
| 760 | if (total_bytes == 0) { |
| 761 | // Convert to empty tape layout |
| 762 | old_allocator->free(fragmented->spans, fragmented->count * sizeof(sz_string_view_t), old_allocator->handle); |
| 763 | Py_XDECREF(fragmented->parent); |
| 764 | |
| 765 | strs->layout = STRS_U32_TAPE; |
| 766 | strs->data.u32_tape.count = fragmented->count; |
| 767 | strs->data.u32_tape.data = NULL; |
| 768 | strs->data.u32_tape.offsets = NULL; |
| 769 | strs->data.u32_tape.allocator = *allocator; |
| 770 | return sz_true_k; |
| 771 | } |
| 772 | |
| 773 | // Allocate consolidated data buffer and offsets array |
| 774 | sz_ptr_t new_data = (sz_ptr_t)allocator->allocate(total_bytes, allocator->handle); |
| 775 | if (!new_data) return sz_false_k; |
| 776 | |
| 777 | if (use_64bit) { |
| 778 | sz_u64_t *new_offsets = |
| 779 | (sz_u64_t *)allocator->allocate((fragmented->count + 1) * sizeof(sz_u64_t), allocator->handle); |
| 780 | if (!new_offsets) { |
| 781 | allocator->free(new_data, total_bytes, allocator->handle); |
| 782 | return sz_false_k; |
| 783 | } |
| 784 | |
| 785 | // Copy fragmented data into consolidated buffer |
| 786 | sz_size_t current_offset = 0; |
| 787 | new_offsets[0] = 0; |
| 788 | for (sz_size_t i = 0; i < fragmented->count; i++) { |
| 789 | sz_size_t len = fragmented->spans[i].length; |
| 790 | if (len > 0) { memcpy(new_data + current_offset, fragmented->spans[i].start, len); } |
| 791 | current_offset += len; |
| 792 | new_offsets[i + 1] = current_offset; |
| 793 | } |
| 794 | |
| 795 | // Free old fragmented data and convert to 64-bit tape |
| 796 | old_allocator->free(fragmented->spans, fragmented->count * sizeof(sz_string_view_t), old_allocator->handle); |
| 797 | Py_XDECREF(fragmented->parent); |
| 798 | |
| 799 | strs->layout = STRS_U64_TAPE; |
| 800 | strs->data.u64_tape.count = fragmented->count; |
| 801 | strs->data.u64_tape.data = new_data; |
| 802 | strs->data.u64_tape.offsets = new_offsets; |
| 803 | strs->data.u64_tape.allocator = *allocator; |
| 804 | } |
no test coverage detected
searching dependent graphs…