blob: 9cb4765d1acbdaade63a359acdf840ec7df42caa [file]
#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