* @brief Helper function to export a Python string-like object into a `sz_string_view_t`. * On failure, sets a Python exception and returns 0. */
| 442 | * On failure, sets a Python exception and returns 0. |
| 443 | */ |
| 444 | SZ_DYNAMIC sz_bool_t sz_py_export_string_like(PyObject *object, sz_cptr_t *start, sz_size_t *length) { |
| 445 | if (PyUnicode_Check(object)) { |
| 446 | // Handle Python `str` object |
| 447 | Py_ssize_t signed_length; |
| 448 | *start = PyUnicode_AsUTF8AndSize(object, &signed_length); |
| 449 | *length = (sz_size_t)signed_length; |
| 450 | return 1; |
| 451 | } |
| 452 | else if (PyBytes_Check(object)) { |
| 453 | // Handle Python `bytes` object |
| 454 | // https://docs.python.org/3/c-api/bytes.html |
| 455 | Py_ssize_t signed_length; |
| 456 | if (PyBytes_AsStringAndSize(object, (sz_ptr_t *)start, &signed_length) == -1) { |
| 457 | PyErr_SetString(PyExc_ValueError, "Couldn't access `bytes` buffer internals"); |
| 458 | return 0; |
| 459 | } |
| 460 | *length = (sz_size_t)signed_length; |
| 461 | return 1; |
| 462 | } |
| 463 | else if (PyByteArray_Check(object)) { |
| 464 | // Handle Python mutable `bytearray` object |
| 465 | // https://docs.python.org/3/c-api/bytearray.html |
| 466 | *start = PyByteArray_AS_STRING(object); |
| 467 | *length = PyByteArray_GET_SIZE(object); |
| 468 | return 1; |
| 469 | } |
| 470 | else if (PyObject_TypeCheck(object, &StrType)) { |
| 471 | Str *str = (Str *)object; |
| 472 | *start = str->memory.start; |
| 473 | *length = str->memory.length; |
| 474 | return 1; |
| 475 | } |
| 476 | else if (PyObject_TypeCheck(object, &FileType)) { |
| 477 | File *file = (File *)object; |
| 478 | *start = file->memory.start; |
| 479 | *length = file->memory.length; |
| 480 | return 1; |
| 481 | } |
| 482 | else if (PyMemoryView_Check(object)) { |
| 483 | // Handle Python `memoryview` object |
| 484 | // https://docs.python.org/3/c-api/memoryview.html |
| 485 | // https://docs.python.org/3/c-api/buffer.html#c.Py_buffer |
| 486 | Py_buffer *view = PyMemoryView_GET_BUFFER(object); |
| 487 | // Make sure we are dealing with single-byte integral representations |
| 488 | if (view->itemsize != 1) { |
| 489 | PyErr_SetString(PyExc_ValueError, "Only single-byte integral types are supported"); |
| 490 | return 0; |
| 491 | } |
| 492 | // Let's make sure the data is contiguous. |
| 493 | // This can be a bit trickier for high-dimensional arrays, but CPython has a built-in function for that. |
| 494 | // The flag 'C' stands for C-style-contiguous, which means that the last dimension is contiguous. |
| 495 | // The flag 'F' stands for Fortran-style-contiguous, which means that the first dimension is contiguous. |
| 496 | // The flag 'A' stands for any-contiguous, which only means there are no gaps between elements. |
| 497 | // For byte-level processing that's all we need. |
| 498 | if (!PyBuffer_IsContiguous(view, 'A')) { |
| 499 | PyErr_SetString(PyExc_ValueError, "The array must be contiguous"); |
| 500 | return 0; |
| 501 | } |
no outgoing calls
no test coverage detected
searching dependent graphs…