diff options
Diffstat (limited to 'Modules/_struct.c')
| -rw-r--r-- | Modules/_struct.c | 129 |
1 files changed, 80 insertions, 49 deletions
diff --git a/Modules/_struct.c b/Modules/_struct.c index f965541..ba60ba6 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -71,10 +71,8 @@ typedef struct { char c; size_t x; } st_size_t; /* We can't support q and Q in native mode unless the compiler does; in std mode, they're 8 bytes on all platforms. */ -#ifdef HAVE_LONG_LONG typedef struct { char c; PY_LONG_LONG x; } s_long_long; #define LONG_LONG_ALIGN (sizeof(s_long_long) - sizeof(PY_LONG_LONG)) -#endif #ifdef HAVE_C99_BOOL #define BOOL_TYPE _Bool @@ -164,8 +162,6 @@ get_ulong(PyObject *v, unsigned long *p) return 0; } -#ifdef HAVE_LONG_LONG - /* Same, but handling native long long. */ static int @@ -212,8 +208,6 @@ get_ulonglong(PyObject *v, unsigned PY_LONG_LONG *p) return 0; } -#endif - /* Same, but handling Py_ssize_t */ static int @@ -267,6 +261,33 @@ get_size_t(PyObject *v, size_t *p) /* Floating point helpers */ static PyObject * +unpack_halffloat(const char *p, /* start of 2-byte string */ + int le) /* true for little-endian, false for big-endian */ +{ + double x; + + x = _PyFloat_Unpack2((unsigned char *)p, le); + if (x == -1.0 && PyErr_Occurred()) { + return NULL; + } + return PyFloat_FromDouble(x); +} + +static int +pack_halffloat(char *p, /* start of 2-byte string */ + PyObject *v, /* value to pack */ + int le) /* true for little-endian, false for big-endian */ +{ + double x = PyFloat_AsDouble(v); + if (x == -1.0 && PyErr_Occurred()) { + PyErr_SetString(StructError, + "required argument is not a float"); + return -1; + } + return _PyFloat_Pack2(x, (unsigned char *)p, le); +} + +static PyObject * unpack_float(const char *p, /* start of 4-byte string */ int le) /* true for little-endian, false for big-endian */ { @@ -436,8 +457,6 @@ nu_size_t(const char *p, const formatdef *f) /* Native mode doesn't support q or Q unless the platform C supports long long (or, on Windows, __int64). */ -#ifdef HAVE_LONG_LONG - static PyObject * nu_longlong(const char *p, const formatdef *f) { @@ -458,8 +477,6 @@ nu_ulonglong(const char *p, const formatdef *f) return PyLong_FromUnsignedLongLong(x); } -#endif - static PyObject * nu_bool(const char *p, const formatdef *f) { @@ -470,6 +487,16 @@ nu_bool(const char *p, const formatdef *f) static PyObject * +nu_halffloat(const char *p, const formatdef *f) +{ +#if PY_LITTLE_ENDIAN + return unpack_halffloat(p, 1); +#else + return unpack_halffloat(p, 0); +#endif +} + +static PyObject * nu_float(const char *p, const formatdef *f) { float x; @@ -643,8 +670,6 @@ np_size_t(char *p, PyObject *v, const formatdef *f) return 0; } -#ifdef HAVE_LONG_LONG - static int np_longlong(char *p, PyObject *v, const formatdef *f) { @@ -664,7 +689,6 @@ np_ulonglong(char *p, PyObject *v, const formatdef *f) memcpy(p, (char *)&x, sizeof x); return 0; } -#endif static int @@ -681,6 +705,16 @@ np_bool(char *p, PyObject *v, const formatdef *f) } static int +np_halffloat(char *p, PyObject *v, const formatdef *f) +{ +#if PY_LITTLE_ENDIAN + return pack_halffloat(p, v, 1); +#else + return pack_halffloat(p, v, 0); +#endif +} + +static int np_float(char *p, PyObject *v, const formatdef *f) { float x = (float)PyFloat_AsDouble(v); @@ -723,7 +757,7 @@ np_void_p(char *p, PyObject *v, const formatdef *f) return 0; } -static formatdef native_table[] = { +static const formatdef native_table[] = { {'x', sizeof(char), 0, NULL}, {'b', sizeof(char), 0, nu_byte, np_byte}, {'B', sizeof(char), 0, nu_ubyte, np_ubyte}, @@ -738,11 +772,10 @@ static formatdef native_table[] = { {'L', sizeof(long), LONG_ALIGN, nu_ulong, np_ulong}, {'n', sizeof(size_t), SIZE_T_ALIGN, nu_ssize_t, np_ssize_t}, {'N', sizeof(size_t), SIZE_T_ALIGN, nu_size_t, np_size_t}, -#ifdef HAVE_LONG_LONG {'q', sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_longlong, np_longlong}, {'Q', sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_ulonglong,np_ulonglong}, -#endif {'?', sizeof(BOOL_TYPE), BOOL_ALIGN, nu_bool, np_bool}, + {'e', sizeof(short), SHORT_ALIGN, nu_halffloat, np_halffloat}, {'f', sizeof(float), FLOAT_ALIGN, nu_float, np_float}, {'d', sizeof(double), DOUBLE_ALIGN, nu_double, np_double}, {'P', sizeof(void *), VOID_P_ALIGN, nu_void_p, np_void_p}, @@ -783,7 +816,6 @@ bu_uint(const char *p, const formatdef *f) static PyObject * bu_longlong(const char *p, const formatdef *f) { -#ifdef HAVE_LONG_LONG PY_LONG_LONG x = 0; Py_ssize_t i = f->size; const unsigned char *bytes = (const unsigned char *)p; @@ -796,18 +828,11 @@ bu_longlong(const char *p, const formatdef *f) if (x >= LONG_MIN && x <= LONG_MAX) return PyLong_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long)); return PyLong_FromLongLong(x); -#else - return _PyLong_FromByteArray((const unsigned char *)p, - 8, - 0, /* little-endian */ - 1 /* signed */); -#endif } static PyObject * bu_ulonglong(const char *p, const formatdef *f) { -#ifdef HAVE_LONG_LONG unsigned PY_LONG_LONG x = 0; Py_ssize_t i = f->size; const unsigned char *bytes = (const unsigned char *)p; @@ -817,12 +842,12 @@ bu_ulonglong(const char *p, const formatdef *f) if (x <= LONG_MAX) return PyLong_FromLong(Py_SAFE_DOWNCAST(x, unsigned PY_LONG_LONG, long)); return PyLong_FromUnsignedLongLong(x); -#else - return _PyLong_FromByteArray((const unsigned char *)p, - 8, - 0, /* little-endian */ - 0 /* signed */); -#endif +} + +static PyObject * +bu_halffloat(const char *p, const formatdef *f) +{ + return unpack_halffloat(p, 0); } static PyObject * @@ -922,6 +947,12 @@ bp_ulonglong(char *p, PyObject *v, const formatdef *f) } static int +bp_halffloat(char *p, PyObject *v, const formatdef *f) +{ + return pack_halffloat(p, v, 0); +} + +static int bp_float(char *p, PyObject *v, const formatdef *f) { double x = PyFloat_AsDouble(v); @@ -972,6 +1003,7 @@ static formatdef bigendian_table[] = { {'q', 8, 0, bu_longlong, bp_longlong}, {'Q', 8, 0, bu_ulonglong, bp_ulonglong}, {'?', 1, 0, bu_bool, bp_bool}, + {'e', 2, 0, bu_halffloat, bp_halffloat}, {'f', 4, 0, bu_float, bp_float}, {'d', 8, 0, bu_double, bp_double}, {0} @@ -1011,7 +1043,6 @@ lu_uint(const char *p, const formatdef *f) static PyObject * lu_longlong(const char *p, const formatdef *f) { -#ifdef HAVE_LONG_LONG PY_LONG_LONG x = 0; Py_ssize_t i = f->size; const unsigned char *bytes = (const unsigned char *)p; @@ -1024,18 +1055,11 @@ lu_longlong(const char *p, const formatdef *f) if (x >= LONG_MIN && x <= LONG_MAX) return PyLong_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long)); return PyLong_FromLongLong(x); -#else - return _PyLong_FromByteArray((const unsigned char *)p, - 8, - 1, /* little-endian */ - 1 /* signed */); -#endif } static PyObject * lu_ulonglong(const char *p, const formatdef *f) { -#ifdef HAVE_LONG_LONG unsigned PY_LONG_LONG x = 0; Py_ssize_t i = f->size; const unsigned char *bytes = (const unsigned char *)p; @@ -1045,12 +1069,12 @@ lu_ulonglong(const char *p, const formatdef *f) if (x <= LONG_MAX) return PyLong_FromLong(Py_SAFE_DOWNCAST(x, unsigned PY_LONG_LONG, long)); return PyLong_FromUnsignedLongLong(x); -#else - return _PyLong_FromByteArray((const unsigned char *)p, - 8, - 1, /* little-endian */ - 0 /* signed */); -#endif +} + +static PyObject * +lu_halffloat(const char *p, const formatdef *f) +{ + return unpack_halffloat(p, 1); } static PyObject * @@ -1142,6 +1166,12 @@ lp_ulonglong(char *p, PyObject *v, const formatdef *f) } static int +lp_halffloat(char *p, PyObject *v, const formatdef *f) +{ + return pack_halffloat(p, v, 1); +} + +static int lp_float(char *p, PyObject *v, const formatdef *f) { double x = PyFloat_AsDouble(v); @@ -1182,6 +1212,7 @@ static formatdef lilendian_table[] = { {'Q', 8, 0, lu_ulonglong, lp_ulonglong}, {'?', 1, 0, bu_bool, bp_bool}, /* Std rep not endian dep, but potentially different from native rep -- reuse bx_bool funcs. */ + {'e', 2, 0, lu_halffloat, lp_halffloat}, {'f', 4, 0, lu_float, lp_float}, {'d', 8, 0, lu_double, lp_double}, {0} @@ -1189,7 +1220,7 @@ static formatdef lilendian_table[] = { static const formatdef * -whichtable(char **pfmt) +whichtable(const char **pfmt) { const char *fmt = (*pfmt)++; /* May be backed out of later */ switch (*fmt) { @@ -1268,7 +1299,7 @@ prepare_s(PyStructObject *self) fmt = PyBytes_AS_STRING(self->s_format); - f = whichtable((char **)&fmt); + f = whichtable(&fmt); s = fmt; size = 0; @@ -1456,7 +1487,7 @@ s_dealloc(PyStructObject *s) } static PyObject * -s_unpack_internal(PyStructObject *soself, char *startfrom) { +s_unpack_internal(PyStructObject *soself, const char *startfrom) { formatcode *code; Py_ssize_t i = 0; PyObject *result = PyTuple_New(soself->s_len); @@ -2239,7 +2270,7 @@ these can be preceded by a decimal repeat count:\n\ x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;\n\ ?: _Bool (requires C99; if not available, char is used instead)\n\ h:short; H:unsigned short; i:int; I:unsigned int;\n\ - l:long; L:unsigned long; f:float; d:double.\n\ + l:long; L:unsigned long; f:float; d:double; e:half-float.\n\ Special cases (preceding decimal count indicates length):\n\ s:string (array of char); p: pascal string (with count byte).\n\ Special cases (only available in native format):\n\ @@ -2279,7 +2310,7 @@ PyInit__struct(void) /* Check endian and swap in faster functions */ { - formatdef *native = native_table; + const formatdef *native = native_table; formatdef *other, *ptr; #if PY_LITTLE_ENDIAN other = lilendian_table; |
