| #ifndef BYTESWRITER_EXTRA_OPS_H |
| #define BYTESWRITER_EXTRA_OPS_H |
| |
| #ifdef MYPYC_EXPERIMENTAL |
| |
| #include <stdbool.h> |
| #include <stdint.h> |
| #include <Python.h> |
| |
| #include "mypyc_util.h" |
| #include "strings/librt_strings.h" |
| #include "strings/librt_strings_common.h" |
| |
| // BytesWriter: Length and capacity |
| |
| static inline CPyTagged |
| CPyBytesWriter_Len(PyObject *obj) { |
| return (CPyTagged)((BytesWriterObject *)obj)->len << 1; |
| } |
| |
| static inline bool |
| CPyBytesWriter_EnsureSize(BytesWriterObject *data, Py_ssize_t n) { |
| if (likely(data->capacity - data->len >= n)) { |
| return true; |
| } else { |
| return LibRTStrings_ByteWriter_grow_buffer_internal(data, n); |
| } |
| } |
| |
| // BytesWriter: Basic write operations |
| |
| static inline char |
| CPyBytesWriter_Append(PyObject *obj, uint8_t value) { |
| BytesWriterObject *self = (BytesWriterObject *)obj; |
| // Store length in a local variable to enable additional optimizations |
| Py_ssize_t len = self->len; |
| if (!CPyBytesWriter_EnsureSize(self, 1)) |
| return CPY_NONE_ERROR; |
| self->buf[len] = value; |
| self->len = len + 1; |
| return CPY_NONE; |
| } |
| |
| char CPyBytesWriter_Write(PyObject *obj, PyObject *value); |
| |
| // BytesWriter: Indexing operations |
| |
| // If index is negative, convert to non-negative index (no range checking) |
| static inline int64_t CPyBytesWriter_AdjustIndex(PyObject *obj, int64_t index) { |
| if (index < 0) { |
| return index + ((BytesWriterObject *)obj)->len; |
| } |
| return index; |
| } |
| |
| static inline bool CPyBytesWriter_RangeCheck(PyObject *obj, int64_t index) { |
| return index >= 0 && index < ((BytesWriterObject *)obj)->len; |
| } |
| |
| static inline uint8_t CPyBytesWriter_GetItem(PyObject *obj, int64_t index) { |
| return (((BytesWriterObject *)obj)->buf)[index]; |
| } |
| |
| static inline void CPyBytesWriter_SetItem(PyObject *obj, int64_t index, uint8_t x) { |
| (((BytesWriterObject *)obj)->buf)[index] = x; |
| } |
| |
| // BytesWriter: Write integer operations (little-endian) |
| |
| static inline char |
| CPyBytesWriter_WriteI16LE(PyObject *obj, int16_t value) { |
| BytesWriterObject *self = (BytesWriterObject *)obj; |
| if (!CPyBytesWriter_EnsureSize(self, 2)) |
| return CPY_NONE_ERROR; |
| BytesWriter_WriteI16LEUnsafe(self, value); |
| return CPY_NONE; |
| } |
| |
| static inline char |
| CPyBytesWriter_WriteI16BE(PyObject *obj, int16_t value) { |
| BytesWriterObject *self = (BytesWriterObject *)obj; |
| if (!CPyBytesWriter_EnsureSize(self, 2)) |
| return CPY_NONE_ERROR; |
| BytesWriter_WriteI16BEUnsafe(self, value); |
| return CPY_NONE; |
| } |
| |
| static inline char |
| CPyBytesWriter_WriteI32LE(PyObject *obj, int32_t value) { |
| BytesWriterObject *self = (BytesWriterObject *)obj; |
| if (!CPyBytesWriter_EnsureSize(self, 4)) |
| return CPY_NONE_ERROR; |
| BytesWriter_WriteI32LEUnsafe(self, value); |
| return CPY_NONE; |
| } |
| |
| static inline char |
| CPyBytesWriter_WriteI32BE(PyObject *obj, int32_t value) { |
| BytesWriterObject *self = (BytesWriterObject *)obj; |
| if (!CPyBytesWriter_EnsureSize(self, 4)) |
| return CPY_NONE_ERROR; |
| BytesWriter_WriteI32BEUnsafe(self, value); |
| return CPY_NONE; |
| } |
| |
| static inline char |
| CPyBytesWriter_WriteI64LE(PyObject *obj, int64_t value) { |
| BytesWriterObject *self = (BytesWriterObject *)obj; |
| if (!CPyBytesWriter_EnsureSize(self, 8)) |
| return CPY_NONE_ERROR; |
| BytesWriter_WriteI64LEUnsafe(self, value); |
| return CPY_NONE; |
| } |
| |
| static inline char |
| CPyBytesWriter_WriteI64BE(PyObject *obj, int64_t value) { |
| BytesWriterObject *self = (BytesWriterObject *)obj; |
| if (!CPyBytesWriter_EnsureSize(self, 8)) |
| return CPY_NONE_ERROR; |
| BytesWriter_WriteI64BEUnsafe(self, value); |
| return CPY_NONE; |
| } |
| |
| // BytesWriter: Write float operations |
| |
| static inline char |
| CPyBytesWriter_WriteF32LE(PyObject *obj, double value) { |
| BytesWriterObject *self = (BytesWriterObject *)obj; |
| if (!CPyBytesWriter_EnsureSize(self, 4)) |
| return CPY_NONE_ERROR; |
| BytesWriter_WriteF32LEUnsafe(self, (float)value); |
| return CPY_NONE; |
| } |
| |
| static inline char |
| CPyBytesWriter_WriteF32BE(PyObject *obj, double value) { |
| BytesWriterObject *self = (BytesWriterObject *)obj; |
| if (!CPyBytesWriter_EnsureSize(self, 4)) |
| return CPY_NONE_ERROR; |
| BytesWriter_WriteF32BEUnsafe(self, (float)value); |
| return CPY_NONE; |
| } |
| |
| static inline char |
| CPyBytesWriter_WriteF64LE(PyObject *obj, double value) { |
| BytesWriterObject *self = (BytesWriterObject *)obj; |
| if (!CPyBytesWriter_EnsureSize(self, 8)) |
| return CPY_NONE_ERROR; |
| BytesWriter_WriteF64LEUnsafe(self, value); |
| return CPY_NONE; |
| } |
| |
| static inline char |
| CPyBytesWriter_WriteF64BE(PyObject *obj, double value) { |
| BytesWriterObject *self = (BytesWriterObject *)obj; |
| if (!CPyBytesWriter_EnsureSize(self, 8)) |
| return CPY_NONE_ERROR; |
| BytesWriter_WriteF64BEUnsafe(self, value); |
| return CPY_NONE; |
| } |
| |
| // Bytes: Read integer operations |
| |
| // Helper function for bytes read error handling (negative index or out of range) |
| void CPyBytes_ReadError(int64_t index, Py_ssize_t size); |
| |
| static inline int16_t |
| CPyBytes_ReadI16LE(PyObject *bytes_obj, int64_t index) { |
| // bytes_obj type is enforced by mypyc |
| Py_ssize_t size = PyBytes_GET_SIZE(bytes_obj); |
| if (unlikely(index < 0 || index > size - 2)) { |
| CPyBytes_ReadError(index, size); |
| return CPY_LL_INT_ERROR; |
| } |
| const unsigned char *data = (const unsigned char *)PyBytes_AS_STRING(bytes_obj); |
| return CPyBytes_ReadI16LEUnsafe(data + index); |
| } |
| |
| static inline int16_t |
| CPyBytes_ReadI16BE(PyObject *bytes_obj, int64_t index) { |
| // bytes_obj type is enforced by mypyc |
| Py_ssize_t size = PyBytes_GET_SIZE(bytes_obj); |
| if (unlikely(index < 0 || index > size - 2)) { |
| CPyBytes_ReadError(index, size); |
| return CPY_LL_INT_ERROR; |
| } |
| const unsigned char *data = (const unsigned char *)PyBytes_AS_STRING(bytes_obj); |
| return CPyBytes_ReadI16BEUnsafe(data + index); |
| } |
| |
| static inline int32_t |
| CPyBytes_ReadI32BE(PyObject *bytes_obj, int64_t index) { |
| // bytes_obj type is enforced by mypyc |
| Py_ssize_t size = PyBytes_GET_SIZE(bytes_obj); |
| if (unlikely(index < 0 || index > size - 4)) { |
| CPyBytes_ReadError(index, size); |
| return CPY_LL_INT_ERROR; |
| } |
| const unsigned char *data = (const unsigned char *)PyBytes_AS_STRING(bytes_obj); |
| return CPyBytes_ReadI32BEUnsafe(data + index); |
| } |
| |
| static inline int32_t |
| CPyBytes_ReadI32LE(PyObject *bytes_obj, int64_t index) { |
| // bytes_obj type is enforced by mypyc |
| Py_ssize_t size = PyBytes_GET_SIZE(bytes_obj); |
| if (unlikely(index < 0 || index > size - 4)) { |
| CPyBytes_ReadError(index, size); |
| return CPY_LL_INT_ERROR; |
| } |
| const unsigned char *data = (const unsigned char *)PyBytes_AS_STRING(bytes_obj); |
| return CPyBytes_ReadI32LEUnsafe(data + index); |
| } |
| |
| static inline int64_t |
| CPyBytes_ReadI64LE(PyObject *bytes_obj, int64_t index) { |
| // bytes_obj type is enforced by mypyc |
| Py_ssize_t size = PyBytes_GET_SIZE(bytes_obj); |
| if (unlikely(index < 0 || index > size - 8)) { |
| CPyBytes_ReadError(index, size); |
| return CPY_LL_INT_ERROR; |
| } |
| const unsigned char *data = (const unsigned char *)PyBytes_AS_STRING(bytes_obj); |
| return CPyBytes_ReadI64LEUnsafe(data + index); |
| } |
| |
| static inline int64_t |
| CPyBytes_ReadI64BE(PyObject *bytes_obj, int64_t index) { |
| // bytes_obj type is enforced by mypyc |
| Py_ssize_t size = PyBytes_GET_SIZE(bytes_obj); |
| if (unlikely(index < 0 || index > size - 8)) { |
| CPyBytes_ReadError(index, size); |
| return CPY_LL_INT_ERROR; |
| } |
| const unsigned char *data = (const unsigned char *)PyBytes_AS_STRING(bytes_obj); |
| return CPyBytes_ReadI64BEUnsafe(data + index); |
| } |
| |
| // Bytes: Read float operations |
| |
| static inline double |
| CPyBytes_ReadF32LE(PyObject *bytes_obj, int64_t index) { |
| // bytes_obj type is enforced by mypyc |
| Py_ssize_t size = PyBytes_GET_SIZE(bytes_obj); |
| if (unlikely(index < 0 || index > size - 4)) { |
| CPyBytes_ReadError(index, size); |
| return CPY_FLOAT_ERROR; |
| } |
| const unsigned char *data = (const unsigned char *)PyBytes_AS_STRING(bytes_obj); |
| return (double)CPyBytes_ReadF32LEUnsafe(data + index); |
| } |
| |
| static inline double |
| CPyBytes_ReadF32BE(PyObject *bytes_obj, int64_t index) { |
| // bytes_obj type is enforced by mypyc |
| Py_ssize_t size = PyBytes_GET_SIZE(bytes_obj); |
| if (unlikely(index < 0 || index > size - 4)) { |
| CPyBytes_ReadError(index, size); |
| return CPY_FLOAT_ERROR; |
| } |
| const unsigned char *data = (const unsigned char *)PyBytes_AS_STRING(bytes_obj); |
| return (double)CPyBytes_ReadF32BEUnsafe(data + index); |
| } |
| |
| static inline double |
| CPyBytes_ReadF64LE(PyObject *bytes_obj, int64_t index) { |
| // bytes_obj type is enforced by mypyc |
| Py_ssize_t size = PyBytes_GET_SIZE(bytes_obj); |
| if (unlikely(index < 0 || index > size - 8)) { |
| CPyBytes_ReadError(index, size); |
| return CPY_FLOAT_ERROR; |
| } |
| const unsigned char *data = (const unsigned char *)PyBytes_AS_STRING(bytes_obj); |
| return CPyBytes_ReadF64LEUnsafe(data + index); |
| } |
| |
| static inline double |
| CPyBytes_ReadF64BE(PyObject *bytes_obj, int64_t index) { |
| // bytes_obj type is enforced by mypyc |
| Py_ssize_t size = PyBytes_GET_SIZE(bytes_obj); |
| if (unlikely(index < 0 || index > size - 8)) { |
| CPyBytes_ReadError(index, size); |
| return CPY_FLOAT_ERROR; |
| } |
| const unsigned char *data = (const unsigned char *)PyBytes_AS_STRING(bytes_obj); |
| return CPyBytes_ReadF64BEUnsafe(data + index); |
| } |
| |
| #endif // MYPYC_EXPERIMENTAL |
| |
| #endif |