* @brief Sorts the parts of a `Strs` object. * * This accepts a `Strs` object and potentially produces a new `Strs` object of a different layout: * - `STRS_U32_TAPE_VIEW` becomes `STRS_FRAGMENTED`, and keeps a link to the old as a parent. * - `STRS_U64_TAPE_VIEW` becomes `STRS_FRAGMENTED`, and keeps a link to the old as a parent. * - `STRS_U32_TAPE` becomes `STRS_FRAGMENTED`, and keeps a
| 6213 | * - `STRS_FRAGMENTED` returns a copy of itself, with the parts sorted. |
| 6214 | */ |
| 6215 | static PyObject *Strs_sorted(Strs *self, PyObject *const *args, Py_ssize_t positional_args_count, |
| 6216 | PyObject *args_names_tuple) { |
| 6217 | PyObject *reverse_obj = NULL; // Default is not reversed |
| 6218 | |
| 6219 | // Check for positional arguments |
| 6220 | if (positional_args_count > 1) { |
| 6221 | PyErr_SetString(PyExc_TypeError, "sort() takes at most 1 positional argument"); |
| 6222 | return NULL; |
| 6223 | } |
| 6224 | else if (positional_args_count == 1) { reverse_obj = args[0]; } |
| 6225 | |
| 6226 | // Check for keyword arguments |
| 6227 | if (args_names_tuple) { |
| 6228 | Py_ssize_t args_names_count = PyTuple_GET_SIZE(args_names_tuple); |
| 6229 | for (Py_ssize_t i = 0; i < args_names_count; ++i) { |
| 6230 | PyObject *key = PyTuple_GET_ITEM(args_names_tuple, i); |
| 6231 | PyObject *value = args[positional_args_count + i]; |
| 6232 | if (PyUnicode_CompareWithASCIIString(key, "reverse") == 0 && !reverse_obj) { reverse_obj = value; } |
| 6233 | else if (PyErr_Format(PyExc_TypeError, "Got an unexpected keyword argument '%U'", key)) { return NULL; } |
| 6234 | } |
| 6235 | } |
| 6236 | |
| 6237 | sz_bool_t reverse = 0; // Default is False |
| 6238 | if (reverse_obj) { |
| 6239 | if (!PyBool_Check(reverse_obj)) { |
| 6240 | PyErr_SetString(PyExc_TypeError, "The reverse must be a boolean"); |
| 6241 | return NULL; |
| 6242 | } |
| 6243 | reverse = PyObject_IsTrue(reverse_obj); |
| 6244 | } |
| 6245 | |
| 6246 | // Determine the amount of memory needed |
| 6247 | sz_size_t substrings_count = 0; |
| 6248 | get_string_at_offset_t substring_getter = NULL; |
| 6249 | PyObject *parent_to_increment = NULL; |
| 6250 | sz_memory_allocator_t allocator; |
| 6251 | |
| 6252 | switch (self->layout) { |
| 6253 | case STRS_U32_TAPE: |
| 6254 | substring_getter = str_at_offset_u32_tape; |
| 6255 | substrings_count = self->data.u32_tape.count; |
| 6256 | parent_to_increment = (PyObject *)self; |
| 6257 | allocator = self->data.u32_tape.allocator; |
| 6258 | break; |
| 6259 | case STRS_U32_TAPE_VIEW: |
| 6260 | substring_getter = str_at_offset_u32_tape_view; |
| 6261 | substrings_count = self->data.u32_tape_view.count; |
| 6262 | parent_to_increment = (PyObject *)self; |
| 6263 | sz_memory_allocator_init_default(&allocator); |
| 6264 | break; |
| 6265 | case STRS_U64_TAPE: |
| 6266 | substring_getter = str_at_offset_u64_tape; |
| 6267 | substrings_count = self->data.u64_tape.count; |
| 6268 | parent_to_increment = (PyObject *)self; |
| 6269 | allocator = self->data.u64_tape.allocator; |
| 6270 | break; |
| 6271 | case STRS_U64_TAPE_VIEW: |
| 6272 | substring_getter = str_at_offset_u64_tape_view; |
nothing calls this directly
no test coverage detected
searching dependent graphs…