* @brief Array to string conversion method, that concatenates all the strings in the array. * Will output an object that looks like `['item1', 'item2', 'item3']`, containing all * the strings. */
| 6742 | * the strings. |
| 6743 | */ |
| 6744 | static PyObject *Strs_str(Strs *self) { |
| 6745 | get_string_at_offset_t getter = str_at_offset_getter(self); |
| 6746 | if (!getter) { |
| 6747 | PyErr_SetString(PyExc_TypeError, "Unknown Strs kind"); |
| 6748 | return NULL; |
| 6749 | } |
| 6750 | |
| 6751 | // Aggregate the total length of all the slices and count the number of bytes we need to allocate: |
| 6752 | sz_size_t count = Strs_len(self); |
| 6753 | PyObject *parent_string; |
| 6754 | sz_size_t total_bytes = 2; // opening and closing square brackets |
| 6755 | for (sz_size_t i = 0; i < count; i++) { |
| 6756 | sz_cptr_t cstr_start = NULL; |
| 6757 | sz_size_t cstr_length = 0; |
| 6758 | getter(self, i, count, &parent_string, &cstr_start, &cstr_length); |
| 6759 | |
| 6760 | if (i != 0) total_bytes += 2; // For the preceding comma and space |
| 6761 | |
| 6762 | // Check if string is valid UTF-8 to determine format |
| 6763 | if (sz_utf8_valid(cstr_start, cstr_length)) { |
| 6764 | // Valid UTF-8: format as '...' with escaped quotes |
| 6765 | total_bytes += 2; // Opening and closing quotes |
| 6766 | total_bytes += cstr_length; // Base string length |
| 6767 | |
| 6768 | // Count the number of single quotes that need escaping |
| 6769 | sz_cptr_t scan_ptr = cstr_start; |
| 6770 | sz_size_t scan_length = cstr_length; |
| 6771 | while (scan_length) { |
| 6772 | char quote = '\''; |
| 6773 | sz_cptr_t next_quote = sz_find_byte(scan_ptr, scan_length, "e); |
| 6774 | if (next_quote == NULL) break; |
| 6775 | total_bytes++; // Extra byte for escaping |
| 6776 | scan_length -= next_quote - scan_ptr + 1; |
| 6777 | scan_ptr = next_quote + 1; |
| 6778 | } |
| 6779 | } |
| 6780 | else { |
| 6781 | // Invalid UTF-8: format as b'\x...' |
| 6782 | total_bytes += 3; // "b'" prefix |
| 6783 | total_bytes += cstr_length * 4; // Each byte becomes \xNN (4 chars) |
| 6784 | total_bytes += 1; // Closing quote |
| 6785 | } |
| 6786 | } |
| 6787 | |
| 6788 | // Now allocate the memory for the concatenated string |
| 6789 | sz_ptr_t const result_buffer = malloc(total_bytes); |
| 6790 | if (!result_buffer) { |
| 6791 | PyErr_SetString(PyExc_MemoryError, "Failed to allocate memory for the concatenated string"); |
| 6792 | return NULL; |
| 6793 | } |
| 6794 | |
| 6795 | // Copy the strings into the result buffer |
| 6796 | sz_ptr_t result_ptr = result_buffer; |
| 6797 | *result_ptr++ = '['; |
| 6798 | for (sz_size_t i = 0; i < count; i++) { |
| 6799 | if (i != 0) { |
| 6800 | *result_ptr++ = ','; |
| 6801 | *result_ptr++ = ' '; |
nothing calls this directly
no test coverage detected
searching dependent graphs…