cdef int32_t days = PyObject_CallFunctionObjArgs(
date_toordinal, <PyObject *>obj, NULL)
days -= PG_DATE_EPOCH_DAYS
- cdef int32_t *buf = <int32_t *>CDumper.ensure_size(
- rv, offset, sizeof(int32_t))
- buf[0] = endian.htobe32(days)
- return sizeof(int32_t)
+ cdef uint32_t bedays = endian.htobe32(days)
+ cdef uint32_t *buf = <uint32_t *>CDumper.ensure_size(rv, offset, sizeof(bedays))
+ memcpy(buf, &bedays, sizeof(bedays))
+ return sizeof(bedays)
cdef class _BaseTimeDumper(CDumper):
oid = oids.TIME_OID
cdef Py_ssize_t cdump(self, obj, bytearray rv, Py_ssize_t offset) except -1:
- cdef int64_t micros = cdt.time_microsecond(obj) + 1000000 * (
+ cdef int64_t us = cdt.time_microsecond(obj) + 1000000 * (
cdt.time_second(obj)
+ 60 * (cdt.time_minute(obj) + 60 * <int64_t>cdt.time_hour(obj))
)
+ cdef uint64_t beus = endian.htobe64(us)
- cdef int64_t *buf = <int64_t *>CDumper.ensure_size(
- rv, offset, sizeof(int64_t))
- buf[0] = endian.htobe64(micros)
- return sizeof(int64_t)
+ cdef char *buf = CDumper.ensure_size(rv, offset, sizeof(beus))
+ memcpy(buf, &beus, sizeof(beus))
+ return sizeof(beus)
cpdef upgrade(self, obj, format):
if not obj.tzinfo:
oid = oids.TIMETZ_OID
cdef Py_ssize_t cdump(self, obj, bytearray rv, Py_ssize_t offset) except -1:
- cdef int64_t micros = cdt.time_microsecond(obj) + 1_000_000 * (
+ cdef int64_t us = cdt.time_microsecond(obj) + 1_000_000 * (
cdt.time_second(obj)
+ 60 * (cdt.time_minute(obj) + 60 * <int64_t>cdt.time_hour(obj))
)
+ cdef uint64_t beus = endian.htobe64(us)
off = self._get_offset(obj)
cdef int32_t offsec = int(PyObject_CallFunctionObjArgs(
timedelta_total_seconds, <PyObject *>off, NULL))
+ cdef uint32_t beoff = endian.htobe32(-offsec)
- cdef char *buf = CDumper.ensure_size(
- rv, offset, sizeof(int64_t) + sizeof(int32_t))
- (<int64_t *>buf)[0] = endian.htobe64(micros)
- (<int32_t *>(buf + sizeof(int64_t)))[0] = endian.htobe32(-offsec)
-
- return sizeof(int64_t) + sizeof(int32_t)
+ cdef char *buf = CDumper.ensure_size(rv, offset, sizeof(beus) + sizeof(beoff))
+ memcpy(buf, &beus, sizeof(beus))
+ memcpy(buf + sizeof(beus), &beoff, sizeof(beoff))
+ return sizeof(beus) + sizeof(beoff)
cdef class _BaseDatetimeDumper(CDumper):
cdef Py_ssize_t cdump(self, obj, bytearray rv, Py_ssize_t offset) except -1:
delta = obj - pg_datetimetz_epoch
- cdef int64_t micros = cdt.timedelta_microseconds(delta) + 1_000_000 * (
+ cdef int64_t us = cdt.timedelta_microseconds(delta) + 1_000_000 * (
86_400 * <int64_t>cdt.timedelta_days(delta)
+ <int64_t>cdt.timedelta_seconds(delta))
+ cdef uint64_t beus = endian.htobe64(us)
- cdef char *buf = CDumper.ensure_size(rv, offset, sizeof(int64_t))
- (<int64_t *>buf)[0] = endian.htobe64(micros)
- return sizeof(int64_t)
+ cdef char *buf = CDumper.ensure_size(rv, offset, sizeof(beus))
+ memcpy(buf, &beus, sizeof(beus))
+ return sizeof(beus)
cpdef upgrade(self, obj, format):
if obj.tzinfo:
cdef Py_ssize_t cdump(self, obj, bytearray rv, Py_ssize_t offset) except -1:
delta = obj - pg_datetime_epoch
- cdef int64_t micros = cdt.timedelta_microseconds(delta) + 1_000_000 * (
+ cdef int64_t us = cdt.timedelta_microseconds(delta) + 1_000_000 * (
86_400 * <int64_t>cdt.timedelta_days(delta)
+ <int64_t>cdt.timedelta_seconds(delta))
+ cdef uint64_t beus = endian.htobe64(us)
- cdef char *buf = CDumper.ensure_size(rv, offset, sizeof(int64_t))
- (<int64_t *>buf)[0] = endian.htobe64(micros)
- return sizeof(int64_t)
+ cdef char *buf = CDumper.ensure_size(rv, offset, sizeof(beus))
+ memcpy(buf, &beus, sizeof(beus))
+ return sizeof(beus)
@cython.final
oid = oids.INTERVAL_OID
cdef Py_ssize_t cdump(self, obj, bytearray rv, Py_ssize_t offset) except -1:
- cdef int64_t micros = (
+ cdef int64_t us = (
1_000_000 * <int64_t>cdt.timedelta_seconds(obj)
+ cdt.timedelta_microseconds(obj))
+ cdef uint64_t beus = endian.htobe64(us)
+
cdef int32_t days = cdt.timedelta_days(obj)
+ cdef uint32_t bedays = endian.htobe32(days)
+ # The third item is months
cdef char *buf = CDumper.ensure_size(
- rv, offset, sizeof(int64_t) + sizeof(int32_t) + sizeof(int32_t))
- (<int64_t *>buf)[0] = endian.htobe64(micros)
- (<int32_t *>(buf + sizeof(int64_t)))[0] = endian.htobe32(days)
- (<int32_t *>(buf + sizeof(int64_t) + sizeof(int32_t)))[0] = 0
+ rv, offset, sizeof(beus) + sizeof(bedays) + sizeof(int32_t))
+ memcpy(buf, &beus, sizeof(beus))
+ memcpy(buf + sizeof(beus), &bedays, sizeof(bedays))
+ memset(buf + sizeof(beus) + sizeof(bedays), 0, sizeof(int32_t))
- return sizeof(int64_t) + sizeof(int32_t) + sizeof(int32_t)
+ return sizeof(beus) + sizeof(bedays) + sizeof(int32_t)
@cython.final
format = PQ_BINARY
cdef object cload(self, const char *data, size_t length):
- cdef int days = endian.be32toh((<uint32_t *>data)[0])
+ cdef uint32_t bedata
+ memcpy(&bedata, data, sizeof(bedata))
+ cdef int days = endian.be32toh(bedata)
cdef object pydays = days + PG_DATE_EPOCH_DAYS
try:
return PyObject_CallFunctionObjArgs(
format = PQ_BINARY
cdef object cload(self, const char *data, size_t length):
- cdef int64_t val = endian.be64toh((<uint64_t *>data)[0])
+ cdef uint64_t bedata
+ memcpy(&bedata, data, sizeof(bedata))
+ cdef int64_t val = endian.be64toh(bedata)
cdef int h, m, s, us
with cython.cdivision(True):
format = PQ_BINARY
cdef object cload(self, const char *data, size_t length):
- cdef int64_t val = endian.be64toh((<uint64_t *>data)[0])
- cdef int32_t off = endian.be32toh((<uint32_t *>(data + sizeof(int64_t)))[0])
+ cdef uint64_t beval
+ memcpy(&beval, data, sizeof(beval))
+ cdef int64_t val = endian.be64toh(beval)
+
+ cdef uint32_t beoff
+ memcpy(&beoff, data + sizeof(beval), sizeof(beoff))
+ cdef int32_t off = endian.be32toh(beoff)
+
cdef int h, m, s, us
with cython.cdivision(True):
format = PQ_BINARY
cdef object cload(self, const char *data, size_t length):
- cdef int64_t val = endian.be64toh((<uint64_t *>data)[0])
+ cdef uint64_t beval
+ memcpy(&beval, data, sizeof(beval))
+ cdef int64_t val = endian.be64toh(beval)
cdef int64_t micros, secs, days
# Work only with positive values as the cdivision behaves differently
format = PQ_BINARY
cdef object cload(self, const char *data, size_t length):
- cdef int64_t val = endian.be64toh((<uint64_t *>data)[0])
+ cdef uint64_t bedata
+ memcpy(&bedata, data, sizeof(bedata))
+ cdef int64_t val = endian.be64toh(bedata)
cdef int64_t micros, secs, days
# Work only with positive values as the cdivision behaves differently
format = PQ_BINARY
cdef object cload(self, const char *data, size_t length):
- cdef int64_t val = endian.be64toh((<uint64_t *>data)[0])
- cdef int32_t days = endian.be32toh(
- (<uint32_t *>(data + sizeof(int64_t)))[0])
- cdef int32_t months = endian.be32toh(
- (<uint32_t *>(data + sizeof(int64_t) + sizeof(int32_t)))[0])
+ cdef int32_t bedata[4]
+ memcpy(&bedata, data, sizeof(bedata))
+ cdef int64_t val = endian.be64toh((<uint64_t *>bedata)[0])
+ cdef int32_t days = endian.be32toh(bedata[2])
+ cdef int32_t months = endian.be32toh(bedata[3])
cdef int years
with cython.cdivision(True):
cimport cython
from libc.stdint cimport *
-from libc.string cimport memcpy, strlen
+from libc.string cimport memcpy, memset, strlen
from cpython.mem cimport PyMem_Free
from cpython.dict cimport PyDict_GetItem, PyDict_SetItem
from cpython.long cimport (
format = PQ_BINARY
cdef object cload(self, const char *data, size_t length):
- return PyLong_FromLong(<int16_t>endian.be16toh((<uint16_t *>data)[0]))
+ cdef int16_t bedata
+ memcpy(&bedata, data, sizeof(bedata))
+ return PyLong_FromLong(<int16_t>endian.be16toh(bedata))
@cython.final
format = PQ_BINARY
cdef object cload(self, const char *data, size_t length):
- return PyLong_FromLong(<int32_t>endian.be32toh((<uint32_t *>data)[0]))
+ cdef int32_t bedata
+ memcpy(&bedata, data, sizeof(bedata))
+ return PyLong_FromLong(<int32_t>endian.be32toh(bedata))
@cython.final
format = PQ_BINARY
cdef object cload(self, const char *data, size_t length):
- return PyLong_FromLongLong(<int64_t>endian.be64toh((<uint64_t *>data)[0]))
+ cdef int64_t bedata
+ memcpy(&bedata, data, sizeof(bedata))
+ return PyLong_FromLongLong(<int64_t>endian.be64toh(bedata))
@cython.final
format = PQ_BINARY
cdef object cload(self, const char *data, size_t length):
- return PyLong_FromUnsignedLong(endian.be32toh((<uint32_t *>data)[0]))
+ cdef uint32_t bedata
+ memcpy(&bedata, data, sizeof(bedata))
+ return PyLong_FromUnsignedLong(endian.be32toh(bedata))
cdef class _FloatDumper(CDumper):
cdef Py_ssize_t cdump(self, obj, bytearray rv, Py_ssize_t offset) except -1:
cdef double d = PyFloat_AsDouble(obj)
- cdef uint64_t *intptr = <uint64_t *>&d
+ cdef uint64_t beval = endian.htobe64((<uint64_t *>&d)[0])
cdef uint64_t *buf = <uint64_t *>CDumper.ensure_size(
- rv, offset, sizeof(uint64_t))
- buf[0] = endian.htobe64(intptr[0])
- return sizeof(uint64_t)
+ rv, offset, sizeof(beval))
+ memcpy(buf, &beval, sizeof(beval))
+ return sizeof(beval)
@cython.final
cdef Py_ssize_t cdump(self, obj, bytearray rv, Py_ssize_t offset) except -1:
cdef float f = <float>PyFloat_AsDouble(obj)
- cdef uint32_t *intptr = <uint32_t *>&f
+ cdef uint32_t beval = endian.htobe32((<uint32_t *>&f)[0])
cdef uint32_t *buf = <uint32_t *>CDumper.ensure_size(
- rv, offset, sizeof(uint32_t))
- buf[0] = endian.htobe32(intptr[0])
- return sizeof(uint32_t)
+ rv, offset, sizeof(beval))
+ memcpy(buf, &beval, sizeof(beval))
+ return sizeof(beval)
@cython.final
format = PQ_BINARY
cdef object cload(self, const char *data, size_t length):
- cdef uint32_t asint = endian.be32toh((<uint32_t *>data)[0])
+ cdef uint32_t bedata
+ memcpy(&bedata, data, sizeof(bedata))
+ cdef uint32_t asint = endian.be32toh(bedata)
# avoid warning:
# dereferencing type-punned pointer will break strict-aliasing rules
cdef char *swp = <char *>&asint
format = PQ_BINARY
cdef object cload(self, const char *data, size_t length):
- cdef uint64_t asint = endian.be64toh((<uint64_t *>data)[0])
+ cdef uint64_t bedata
+ memcpy(&bedata, data, sizeof(bedata))
+ cdef uint64_t asint = endian.be64toh(bedata)
cdef char *swp = <char *>&asint
return PyFloat_FromDouble((<double *>swp)[0])
cdef object cload(self, const char *data, size_t length):
- cdef uint16_t *data16 = <uint16_t *>data
- cdef uint16_t ndigits = endian.be16toh(data16[0])
- cdef int16_t weight = <int16_t>endian.be16toh(data16[1])
- cdef uint16_t sign = endian.be16toh(data16[2])
- cdef uint16_t dscale = endian.be16toh(data16[3])
+ cdef uint16_t behead[4]
+ memcpy(&behead, data, sizeof(behead))
+ cdef uint16_t ndigits = endian.be16toh(behead[0])
+ cdef int16_t weight = <int16_t>endian.be16toh(behead[1])
+ cdef uint16_t sign = endian.be16toh(behead[2])
+ cdef uint16_t dscale = endian.be16toh(behead[3])
+
cdef int shift
cdef int i
cdef PyObject *pctx
cdef object key
+ cdef char *digitptr
+ cdef uint16_t bedigit
if sign == NUMERIC_POS or sign == NUMERIC_NEG:
if length != (4 + ndigits) * sizeof(uint16_t):
raise e.DataError("bad ndigits in numeric binary representation")
val = 0
+ digitptr = data + sizeof(behead)
for i in range(ndigits):
+ memcpy(&bedigit, digitptr, sizeof(bedigit))
+ digitptr += sizeof(bedigit)
val *= 10_000
- val += endian.be16toh(data16[i + 4])
+ val += endian.be16toh(bedigit)
shift = dscale - (ndigits - weight - 1) * DEC_DIGITS
cdef int sign = t[0]
cdef tuple digits = t[1]
cdef uint16_t *buf
+ cdef uint16_t behead[4]
cdef Py_ssize_t length
cdef object pyexp = t[2]
cdef const char *bexp
+
if not isinstance(pyexp, int):
# Handle inf, nan
- length = 4 * sizeof(uint16_t)
- buf = <uint16_t *>CDumper.ensure_size(rv, offset, length)
- buf[0] = 0
- buf[1] = 0
- buf[3] = 0
+ buf = <uint16_t *>CDumper.ensure_size(rv, offset, sizeof(behead))
+ behead[0] = 0
+ behead[1] = 0
+ behead[3] = 0
bexp = PyUnicode_AsUTF8(pyexp)
if bexp[0] == b'n' or bexp[0] == b'N':
- buf[2] = endian.htobe16(NUMERIC_NAN)
+ behead[2] = endian.htobe16(NUMERIC_NAN)
elif bexp[0] == b'F':
if sign:
- buf[2] = endian.htobe16(NUMERIC_NINF)
+ behead[2] = endian.htobe16(NUMERIC_NINF)
else:
- buf[2] = endian.htobe16(NUMERIC_PINF)
+ behead[2] = endian.htobe16(NUMERIC_PINF)
else:
raise e.DataError(f"unexpected decimal exponent: {pyexp}")
- return length
+ memcpy(buf, behead, sizeof(behead))
+ return sizeof(behead)
cdef int exp = pyexp
cdef uint16_t ndigits = <uint16_t>len(digits)
ndigits += exp % DEC_DIGITS
if nzdigits == 0:
- length = 4 * sizeof(uint16_t)
- buf = <uint16_t *>CDumper.ensure_size(rv, offset, length)
- buf[0] = 0 # ndigits
- buf[1] = 0 # weight
- buf[2] = endian.htobe16(NUMERIC_POS) # sign
- buf[3] = endian.htobe16(dscale)
- return length
+ buf = <uint16_t *>CDumper.ensure_size(rv, offset, sizeof(behead))
+ behead[0] = 0 # ndigits
+ behead[1] = 0 # weight
+ behead[2] = endian.htobe16(NUMERIC_POS) # sign
+ behead[3] = endian.htobe16(dscale)
+ memcpy(buf, behead, sizeof(behead))
+ return sizeof(behead)
# Equivalent of 0-padding left to align the py digits to the pg digits
# but without changing the digits tuple.
cdef int tmp = nzdigits + wi
cdef int pgdigits = tmp // DEC_DIGITS + (tmp % DEC_DIGITS and 1)
- length = (pgdigits + 4) * sizeof(uint16_t)
+ length = sizeof(behead) + pgdigits * sizeof(uint16_t)
buf = <uint16_t*>CDumper.ensure_size(rv, offset, length)
- buf[0] = endian.htobe16(pgdigits)
- buf[1] = endian.htobe16(<int16_t>((ndigits + exp) // DEC_DIGITS - 1))
- buf[2] = endian.htobe16(NUMERIC_NEG) if sign else endian.htobe16(NUMERIC_POS)
- buf[3] = endian.htobe16(dscale)
-
- cdef uint16_t pgdigit = 0
- cdef int bi = 4
+ behead[0] = endian.htobe16(pgdigits)
+ behead[1] = endian.htobe16(<int16_t>((ndigits + exp) // DEC_DIGITS - 1))
+ behead[2] = endian.htobe16(NUMERIC_NEG) if sign else endian.htobe16(NUMERIC_POS)
+ behead[3] = endian.htobe16(dscale)
+ memcpy(buf, behead, sizeof(behead))
+ buf += 4
+
+ cdef uint16_t pgdigit = 0, bedigit
for i in range(nzdigits):
pgdigit += pydigit_weights[wi] * <int>(digits[i])
wi += 1
if wi >= DEC_DIGITS:
- buf[bi] = endian.htobe16(pgdigit)
+ bedigit = endian.htobe16(pgdigit)
+ memcpy(buf, &bedigit, sizeof(bedigit))
+ buf += 1
pgdigit = wi = 0
- bi += 1
if pgdigit:
- buf[bi] = endian.htobe16(pgdigit)
+ bedigit = endian.htobe16(pgdigit)
+ memcpy(buf, &bedigit, sizeof(bedigit))
return length
cdef Py_ssize_t dump_int_to_int2_binary(
obj, bytearray rv, Py_ssize_t offset
) except -1:
- cdef int16_t *buf = <int16_t *>CDumper.ensure_size(
- rv, offset, sizeof(int16_t))
cdef int16_t val = <int16_t>PyLong_AsLongLong(obj)
- # swap bytes if needed
- cdef uint16_t *ptvar = <uint16_t *>(&val)
- buf[0] = endian.htobe16(ptvar[0])
- return sizeof(int16_t)
+ cdef int16_t *buf = <int16_t *>CDumper.ensure_size(rv, offset, sizeof(obj))
+ cdef uint16_t beval = endian.htobe16(val) # swap bytes if needed
+ memcpy(buf, &beval, sizeof(beval))
+ return sizeof(val)
cdef Py_ssize_t dump_int_to_int4_binary(
obj, bytearray rv, Py_ssize_t offset
) except -1:
- cdef int32_t *buf = <int32_t *>CDumper.ensure_size(
- rv, offset, sizeof(int32_t))
cdef int32_t val = <int32_t>PyLong_AsLongLong(obj)
- # swap bytes if needed
- cdef uint32_t *ptvar = <uint32_t *>(&val)
- buf[0] = endian.htobe32(ptvar[0])
- return sizeof(int32_t)
+ cdef int32_t *buf = <int32_t *>CDumper.ensure_size(rv, offset, sizeof(val))
+ cdef uint32_t beval = endian.htobe32(val) # swap bytes if needed
+ memcpy(buf, &beval, sizeof(beval))
+ return sizeof(val)
cdef Py_ssize_t dump_int_to_int8_binary(
obj, bytearray rv, Py_ssize_t offset
) except -1:
- cdef int64_t *buf = <int64_t *>CDumper.ensure_size(
- rv, offset, sizeof(int64_t))
cdef int64_t val = PyLong_AsLongLong(obj)
- # swap bytes if needed
- cdef uint64_t *ptvar = <uint64_t *>(&val)
- buf[0] = endian.htobe64(ptvar[0])
- return sizeof(int64_t)
+ cdef int64_t *buf = <int64_t *>CDumper.ensure_size(rv, offset, sizeof(val))
+ cdef uint64_t beval = endian.htobe64(val) # swap bytes if needed
+ memcpy(buf, &beval, sizeof(beval))
+ return sizeof(val)
cdef Py_ssize_t dump_int_to_numeric_binary(obj, bytearray rv, Py_ssize_t offset) except -1:
cdef Py_ssize_t length = sizeof(uint16_t) * (ndigits + 4)
cdef uint16_t *buf
buf = <uint16_t *><void *>CDumper.ensure_size(rv, offset, length)
- buf[0] = endian.htobe16(ndigits)
- buf[1] = endian.htobe16(ndigits - 1) # weight
- buf[2] = endian.htobe16(sign)
- buf[3] = 0 # dscale
+
+ cdef uint16_t behead[4]
+ behead[0] = endian.htobe16(ndigits)
+ behead[1] = endian.htobe16(ndigits - 1) # weight
+ behead[2] = endian.htobe16(sign)
+ behead[3] = 0 # dscale
+ memcpy(buf, behead, sizeof(behead))
cdef int i = 4 + ndigits - 1
- cdef uint16_t rem
+ cdef uint16_t rem, berem
while obj:
rem = obj % 10000
obj //= 10000
- buf[i] = endian.htobe16(rem)
+ berem = endian.htobe16(rem)
+ memcpy(buf + i, &berem, sizeof(berem))
i -= 1
while i > 3:
- buf[i] = 0
+ memset(buf + i, 0, sizeof(buf[0]))
i -= 1
return length