The less efficient `Strs_init` path initializing from a Pythonic tuple of strings.
| 6994 | |
| 6995 | // The less efficient `Strs_init` path initializing from a Pythonic tuple of strings. |
| 6996 | static int Strs_init_from_tuple(Strs *self, PyObject *sequence_obj, int view) { |
| 6997 | Py_ssize_t count = PyTuple_GET_SIZE(sequence_obj); |
| 6998 | |
| 6999 | // Empty tuple, create empty Strs |
| 7000 | if (count == 0) { |
| 7001 | self->layout = STRS_FRAGMENTED; |
| 7002 | self->data.fragmented.count = 0; |
| 7003 | self->data.fragmented.spans = NULL; |
| 7004 | self->data.fragmented.parent = NULL; |
| 7005 | sz_memory_allocator_init_default(&self->data.fragmented.allocator); |
| 7006 | return 0; |
| 7007 | } |
| 7008 | |
| 7009 | // Zero-copy mode for Python sequences - use reordered layout for memory-scattered strings |
| 7010 | if (view) { |
| 7011 | // Initialize allocator for memory management |
| 7012 | sz_memory_allocator_t allocator; |
| 7013 | sz_memory_allocator_init_default(&allocator); |
| 7014 | |
| 7015 | sz_string_view_t *parts = |
| 7016 | (sz_string_view_t *)allocator.allocate(count * sizeof(sz_string_view_t), allocator.handle); |
| 7017 | if (!parts) { |
| 7018 | PyErr_NoMemory(); |
| 7019 | return -1; |
| 7020 | } |
| 7021 | |
| 7022 | // Create views directly to Python string objects |
| 7023 | for (sz_size_t i = 0; i < (sz_size_t)count; i++) { |
| 7024 | PyObject *item = PyTuple_GET_ITEM(sequence_obj, i); |
| 7025 | sz_cptr_t item_start; |
| 7026 | sz_size_t item_length; |
| 7027 | if (!sz_py_export_string_like(item, &item_start, &item_length)) { |
| 7028 | allocator.free(parts, count * sizeof(sz_string_view_t), allocator.handle); |
| 7029 | PyErr_Format(PyExc_TypeError, "Item %zd is not a string-like object", i); |
| 7030 | return -1; |
| 7031 | } |
| 7032 | parts[i].start = item_start; |
| 7033 | parts[i].length = item_length; |
| 7034 | } |
| 7035 | |
| 7036 | self->layout = STRS_FRAGMENTED; |
| 7037 | self->data.fragmented.count = count; |
| 7038 | self->data.fragmented.spans = parts; |
| 7039 | self->data.fragmented.allocator = allocator; |
| 7040 | self->data.fragmented.parent = sequence_obj; // Keep sequence alive |
| 7041 | Py_INCREF(sequence_obj); |
| 7042 | } |
| 7043 | // Allocate a new tape to fit all of the items |
| 7044 | else { |
| 7045 | // Estimate the overall size of strings in bytes |
| 7046 | sz_size_t total_bytes = 0; |
| 7047 | for (Py_ssize_t i = 0; i < count; i++) { |
| 7048 | PyObject *item = PyTuple_GET_ITEM(sequence_obj, i); |
| 7049 | sz_cptr_t item_start; |
| 7050 | sz_size_t item_length; |
| 7051 | if (!sz_py_export_string_like(item, &item_start, &item_length)) { |
| 7052 | PyErr_Format(PyExc_TypeError, "Item %zd is not a string-like object", i); |
| 7053 | return -1; |
no test coverage detected
searching dependent graphs…