* @brief Helper function to replace the memory allocator in a `Strs` object. * This reallocates existing string data using the new allocator. * * This may change the layout of the `Strs` layout: * - `STRS_U32_TAPE_VIEW` becomes `STRS_U32_TAPE`. * - `STRS_U64_TAPE_VIEW` becomes `STRS_U64_TAPE`. * - `STRS_U32_TAPE` remains, if the allocator is different. * - `STRS_U64_TAPE` re
| 851 | * - `STRS_FRAGMENTED` becomes a `STRS_U32_TAPE` or `STRS_U64_TAPE` depending on the content size. |
| 852 | */ |
| 853 | SZ_DYNAMIC sz_bool_t sz_py_replace_strings_allocator(PyObject *object, sz_memory_allocator_t *allocator) { |
| 854 | if (!object || !allocator) return sz_false_k; |
| 855 | if (!PyObject_TypeCheck(object, &StrsType)) return sz_false_k; |
| 856 | |
| 857 | Strs *strs = (Strs *)object; |
| 858 | |
| 859 | // Get the current allocator based on layout |
| 860 | sz_memory_allocator_t old_allocator; |
| 861 | switch (strs->layout) { |
| 862 | case STRS_U32_TAPE: old_allocator = strs->data.u32_tape.allocator; break; |
| 863 | case STRS_U64_TAPE: old_allocator = strs->data.u64_tape.allocator; break; |
| 864 | case STRS_FRAGMENTED: old_allocator = strs->data.fragmented.allocator; break; |
| 865 | case STRS_U32_TAPE_VIEW: |
| 866 | case STRS_U64_TAPE_VIEW: |
| 867 | // Traverse parent chain until we find an allocator |
| 868 | { |
| 869 | Strs *up = strs; |
| 870 | while (up && (up->layout == STRS_U32_TAPE_VIEW || up->layout == STRS_U64_TAPE_VIEW)) { |
| 871 | PyObject *parent = |
| 872 | (up->layout == STRS_U32_TAPE_VIEW) ? up->data.u32_tape_view.parent : up->data.u64_tape_view.parent; |
| 873 | if (!parent || !PyObject_TypeCheck(parent, &StrsType)) break; |
| 874 | up = (Strs *)parent; |
| 875 | } |
| 876 | |
| 877 | // Extract allocator from the owning layout we found |
| 878 | if (up && up->layout == STRS_U32_TAPE) { old_allocator = up->data.u32_tape.allocator; } |
| 879 | else if (up && up->layout == STRS_U64_TAPE) { old_allocator = up->data.u64_tape.allocator; } |
| 880 | else if (up && up->layout == STRS_FRAGMENTED) { old_allocator = up->data.fragmented.allocator; } |
| 881 | else { sz_memory_allocator_init_default(&old_allocator); } // Final fallback |
| 882 | } |
| 883 | break; |
| 884 | default: sz_memory_allocator_init_default(&old_allocator); break; |
| 885 | } |
| 886 | |
| 887 | // Check if the allocators are the same - no need to reallocate |
| 888 | if (sz_memory_allocator_equal(&old_allocator, allocator)) return sz_true_k; |
| 889 | |
| 890 | // Handle different Strs layouts using dedicated functions |
| 891 | switch (strs->layout) { |
| 892 | case STRS_U32_TAPE: return sz_py_replace_u32_tape_allocator(strs, &old_allocator, allocator); |
| 893 | case STRS_U64_TAPE: return sz_py_replace_u64_tape_allocator(strs, &old_allocator, allocator); |
| 894 | case STRS_U32_TAPE_VIEW: return sz_py_replace_u32_tape_view_allocator(strs, allocator); |
| 895 | case STRS_U64_TAPE_VIEW: return sz_py_replace_u64_tape_view_allocator(strs, allocator); |
| 896 | case STRS_FRAGMENTED: return sz_py_replace_fragmented_allocator(strs, &old_allocator, allocator); |
| 897 | } |
| 898 | |
| 899 | return sz_false_k; // Should never reach here |
| 900 | } |
| 901 | |
| 902 | /** |
| 903 | * @brief Helper function to wrap the current exception with a custom prefix message. |
no test coverage detected
searching dependent graphs…