The inefficient `Strs_init` path initializing from a Pythonic iterable of strings.
| 7274 | |
| 7275 | // The inefficient `Strs_init` path initializing from a Pythonic iterable of strings. |
| 7276 | static int Strs_init_from_iterable(Strs *self, PyObject *sequence_obj, int view) { |
| 7277 | // Get an iterator from the object |
| 7278 | PyObject *iterator = PyObject_GetIter(sequence_obj); |
| 7279 | if (!iterator) { |
| 7280 | PyErr_SetString(PyExc_TypeError, "Object is not iterable"); |
| 7281 | return -1; |
| 7282 | } |
| 7283 | |
| 7284 | if (view) { |
| 7285 | // View mode is not supported for iterators because we can't safely keep references |
| 7286 | // to all the individual string objects without significant overhead |
| 7287 | Py_DECREF(iterator); |
| 7288 | PyErr_SetString(PyExc_ValueError, "View mode (view=True) is not supported for iterators. " |
| 7289 | "Use view=False to create a copy, or convert to a list/tuple first."); |
| 7290 | return -1; |
| 7291 | } |
| 7292 | |
| 7293 | // Initialize allocator for memory management |
| 7294 | sz_memory_allocator_t allocator; |
| 7295 | sz_memory_allocator_init_default(&allocator); |
| 7296 | |
| 7297 | // Incrementally allocate a new tape to fit all of the items |
| 7298 | sz_size_t data_capacity = 4096; |
| 7299 | sz_size_t offsets_capacity = 16; |
| 7300 | sz_size_t count = 0; |
| 7301 | sz_size_t total_bytes = 0; |
| 7302 | int use_64bit = 0; // Start with 32-bit |
| 7303 | |
| 7304 | sz_ptr_t data_buffer = (sz_ptr_t)allocator.allocate(data_capacity, allocator.handle); |
| 7305 | void *offsets = allocator.allocate(offsets_capacity * sizeof(sz_u32_t), allocator.handle); // Start with 32-bit |
| 7306 | |
| 7307 | if (!data_buffer || !offsets) { |
| 7308 | if (data_buffer) allocator.free(data_buffer, data_capacity, allocator.handle); |
| 7309 | if (offsets) allocator.free(offsets, offsets_capacity * sizeof(sz_u32_t), allocator.handle); |
| 7310 | Py_DECREF(iterator); |
| 7311 | PyErr_NoMemory(); |
| 7312 | return -1; |
| 7313 | } |
| 7314 | |
| 7315 | // Set initial offset to 0 (Apache Arrow format: N+1 offsets for N strings) |
| 7316 | if (use_64bit) { ((sz_u64_t *)offsets)[0] = 0; } |
| 7317 | else { ((sz_u32_t *)offsets)[0] = 0; } |
| 7318 | |
| 7319 | // Iterate through all items |
| 7320 | PyObject *item; |
| 7321 | while ((item = PyIter_Next(iterator))) { |
| 7322 | sz_cptr_t item_start; |
| 7323 | sz_size_t item_length; |
| 7324 | if (!sz_py_export_string_like(item, &item_start, &item_length)) { |
| 7325 | Py_DECREF(item); |
| 7326 | allocator.free(data_buffer, data_capacity, allocator.handle); |
| 7327 | allocator.free(offsets, offsets_capacity * (use_64bit ? sizeof(sz_u64_t) : sizeof(sz_u32_t)), |
| 7328 | allocator.handle); |
| 7329 | Py_DECREF(iterator); |
| 7330 | PyErr_Format(PyExc_TypeError, "Item %zd is not a string-like object", count); |
| 7331 | return -1; |
| 7332 | } |
| 7333 |
no test coverage detected
searching dependent graphs…