From 6c05292a8462532da323053f66c132f495d029f7 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sun, 10 May 2020 22:30:36 +1200 Subject: [PATCH] Added proper binary integer decoding in cython --- psycopg3/types/endian.pxd | 22 ++++++++++++++++++++++ psycopg3/types/numeric.pyx | 23 +++++++---------------- 2 files changed, 29 insertions(+), 16 deletions(-) create mode 100644 psycopg3/types/endian.pxd diff --git a/psycopg3/types/endian.pxd b/psycopg3/types/endian.pxd new file mode 100644 index 000000000..cf7592dc2 --- /dev/null +++ b/psycopg3/types/endian.pxd @@ -0,0 +1,22 @@ +# convert values between host and big-/little-endian byte order +# http://man7.org/linux/man-pages/man3/endian.3.html + +from libc.stdint cimport uint16_t, uint32_t, uint64_t + + +cdef extern from "" nogil: + + cdef uint16_t htobe16(uint16_t host_16bits) + cdef uint16_t htole16(uint16_t host_16bits) + cdef uint16_t be16toh(uint16_t big_endian_16bits) + cdef uint16_t le16toh(uint16_t little_endian_16bits) + + cdef uint32_t htobe32(uint32_t host_32bits) + cdef uint32_t htole32(uint32_t host_32bits) + cdef uint32_t be32toh(uint32_t big_endian_32bits) + cdef uint32_t le32toh(uint32_t little_endian_32bits) + + cdef uint64_t htobe64(uint64_t host_64bits) + cdef uint64_t htole64(uint64_t host_64bits) + cdef uint64_t be64toh(uint64_t big_endian_64bits) + cdef uint64_t le64toh(uint64_t little_endian_64bits) diff --git a/psycopg3/types/numeric.pyx b/psycopg3/types/numeric.pyx index 10a1ff8ba..7faa564fd 100644 --- a/psycopg3/types/numeric.pyx +++ b/psycopg3/types/numeric.pyx @@ -1,3 +1,6 @@ +from libc.stdint cimport * +from psycopg3.types.endian cimport be16toh, be32toh, be64toh + from cpython.long cimport ( PyLong_FromLong, PyLong_FromLongLong, PyLong_FromUnsignedLong) @@ -6,31 +9,19 @@ cdef object load_int_text(const char *data, size_t length, void *context): return int(data) cdef object load_int2_binary(const char *data, size_t length, void *context): - return PyLong_FromLong(unpack_int16(data, 2)) + return PyLong_FromLong(be16toh((data)[0])) cdef object load_int4_binary(const char *data, size_t length, void *context): - return PyLong_FromLong(unpack_int32(data, 4)) + return PyLong_FromLong(be32toh((data)[0])) cdef object load_int8_binary(const char *data, size_t length, void *context): - return PyLong_FromLongLong(unpack_int64(data, 8)) + return PyLong_FromLongLong(be64toh((data)[0])) cdef object load_oid_binary(const char *data, size_t length, void *context): - return PyLong_FromUnsignedLong(unpack_uint32(data, 4)) + return PyLong_FromUnsignedLong(be32toh((data)[0])) cdef object load_bool_binary(const char *data, size_t length, void *context): if data[0]: return True else: return False - -cdef long unpack_int16(const char *data, size_t length): - return 0 - -cdef long unpack_int32(const char *data, size_t length): - return 0 - -cdef long unpack_uint32(const char *data, size_t length): - return 0 - -cdef long long unpack_int64(const char *data, size_t length): - return 0 -- 2.47.2