From cfeb5437a8910e28726422a14a93a36584e32238 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Thu, 19 Nov 2020 14:36:23 +0100 Subject: [PATCH] bpo-1635741: Port _struct to multiphase initialization (GH-23398) Signed-off-by: Christian Heimes --- ...2020-11-19-12-06-43.bpo-1635741.KEfZpn.rst | 1 + Modules/_struct.c | 500 ++++++++++-------- Modules/clinic/_struct.c.h | 10 +- 3 files changed, 272 insertions(+), 239 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2020-11-19-12-06-43.bpo-1635741.KEfZpn.rst diff --git a/Misc/NEWS.d/next/C API/2020-11-19-12-06-43.bpo-1635741.KEfZpn.rst b/Misc/NEWS.d/next/C API/2020-11-19-12-06-43.bpo-1635741.KEfZpn.rst new file mode 100644 index 00000000000..fc64757e00b --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-11-19-12-06-43.bpo-1635741.KEfZpn.rst @@ -0,0 +1 @@ +Port _struct extension module to multiphase initialization (:pep:`489`) diff --git a/Modules/_struct.c b/Modules/_struct.c index 81cdbb9b817..8dfcd882a44 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -15,6 +15,7 @@ class Struct "PyStructObject *" "&PyStructType" /*[clinic end generated code: output=da39a3ee5e6b4b0d input=9b032058a83ed7c3]*/ typedef struct { + PyObject *cache; PyObject *PyStructType; PyObject *unpackiter_type; PyObject *StructError; @@ -30,16 +31,19 @@ get_struct_state(PyObject *module) static struct PyModuleDef _structmodule; -#define _structmodulestate_global get_struct_state(PyState_FindModule(&_structmodule)) +#define get_struct_state_structinst(self) \ + (get_struct_state(_PyType_GetModuleByDef(Py_TYPE(self), &_structmodule))) +#define get_struct_state_iterinst(self) \ + (get_struct_state(PyType_GetModule(Py_TYPE(self)))) /* The translation function for each format character is table driven */ typedef struct _formatdef { char format; Py_ssize_t size; Py_ssize_t alignment; - PyObject* (*unpack)(const char *, + PyObject* (*unpack)(_structmodulestate *, const char *, const struct _formatdef *); - int (*pack)(char *, PyObject *, + int (*pack)(_structmodulestate *, char *, PyObject *, const struct _formatdef *); } formatdef; @@ -61,10 +65,7 @@ typedef struct { PyObject *weakreflist; /* List of weak references */ } PyStructObject; - -#define PyStruct_Check(op) PyObject_TypeCheck(op, (PyTypeObject *)_structmodulestate_global->PyStructType) -#define PyStruct_CheckExact(op) Py_IS_TYPE(op, (PyTypeObject *)_structmodulestate_global->PyStructType) - +#define PyStruct_Check(op, state) PyObject_TypeCheck(op, (PyTypeObject *)(state)->PyStructType) /* Define various structs to figure out the alignments of types */ @@ -102,12 +103,20 @@ class cache_struct_converter(CConverter): converter = 'cache_struct_converter' c_default = "NULL" + def parse_arg(self, argname, displayname): + return """ + if (!{converter}(module, {argname}, &{paramname})) {{{{ + goto exit; + }}}} + """.format(argname=argname, paramname=self.name, + converter=self.converter) + def cleanup(self): return "Py_XDECREF(%s);\n" % self.name [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=49957cca130ffb63]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=d6746621c2fb1a7d]*/ -static int cache_struct_converter(PyObject *, PyStructObject **); +static int cache_struct_converter(PyObject *, PyObject *, PyStructObject **); #include "clinic/_struct.c.h" @@ -115,7 +124,7 @@ static int cache_struct_converter(PyObject *, PyStructObject **); PyLongObject if possible, otherwise fails. Caller should decref. */ static PyObject * -get_pylong(PyObject *v) +get_pylong(_structmodulestate *state, PyObject *v) { assert(v != NULL); if (!PyLong_Check(v)) { @@ -126,7 +135,7 @@ get_pylong(PyObject *v) return NULL; } else { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "required argument is not an integer"); return NULL; } @@ -142,11 +151,11 @@ get_pylong(PyObject *v) one */ static int -get_long(PyObject *v, long *p) +get_long(_structmodulestate *state, PyObject *v, long *p) { long x; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; assert(PyLong_Check(v)); @@ -154,7 +163,7 @@ get_long(PyObject *v, long *p) Py_DECREF(v); if (x == (long)-1 && PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "argument out of range"); return -1; } @@ -166,11 +175,11 @@ get_long(PyObject *v, long *p) /* Same, but handling unsigned long */ static int -get_ulong(PyObject *v, unsigned long *p) +get_ulong(_structmodulestate *state, PyObject *v, unsigned long *p) { unsigned long x; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; assert(PyLong_Check(v)); @@ -178,7 +187,7 @@ get_ulong(PyObject *v, unsigned long *p) Py_DECREF(v); if (x == (unsigned long)-1 && PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "argument out of range"); return -1; } @@ -189,11 +198,11 @@ get_ulong(PyObject *v, unsigned long *p) /* Same, but handling native long long. */ static int -get_longlong(PyObject *v, long long *p) +get_longlong(_structmodulestate *state, PyObject *v, long long *p) { long long x; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; assert(PyLong_Check(v)); @@ -201,7 +210,7 @@ get_longlong(PyObject *v, long long *p) Py_DECREF(v); if (x == (long long)-1 && PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "argument out of range"); return -1; } @@ -212,11 +221,11 @@ get_longlong(PyObject *v, long long *p) /* Same, but handling native unsigned long long. */ static int -get_ulonglong(PyObject *v, unsigned long long *p) +get_ulonglong(_structmodulestate *state, PyObject *v, unsigned long long *p) { unsigned long long x; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; assert(PyLong_Check(v)); @@ -224,7 +233,7 @@ get_ulonglong(PyObject *v, unsigned long long *p) Py_DECREF(v); if (x == (unsigned long long)-1 && PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "argument out of range"); return -1; } @@ -235,11 +244,11 @@ get_ulonglong(PyObject *v, unsigned long long *p) /* Same, but handling Py_ssize_t */ static int -get_ssize_t(PyObject *v, Py_ssize_t *p) +get_ssize_t(_structmodulestate *state, PyObject *v, Py_ssize_t *p) { Py_ssize_t x; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; assert(PyLong_Check(v)); @@ -247,7 +256,7 @@ get_ssize_t(PyObject *v, Py_ssize_t *p) Py_DECREF(v); if (x == (Py_ssize_t)-1 && PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "argument out of range"); return -1; } @@ -258,11 +267,11 @@ get_ssize_t(PyObject *v, Py_ssize_t *p) /* Same, but handling size_t */ static int -get_size_t(PyObject *v, size_t *p) +get_size_t(_structmodulestate *state, PyObject *v, size_t *p) { size_t x; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; assert(PyLong_Check(v)); @@ -270,7 +279,7 @@ get_size_t(PyObject *v, size_t *p) Py_DECREF(v); if (x == (size_t)-1 && PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "argument out of range"); return -1; } @@ -279,7 +288,7 @@ get_size_t(PyObject *v, size_t *p) } -#define RANGE_ERROR(x, f, flag, mask) return _range_error(f, flag) +#define RANGE_ERROR(state, x, f, flag, mask) return _range_error(state, f, flag) /* Floating point helpers */ @@ -298,13 +307,14 @@ unpack_halffloat(const char *p, /* start of 2-byte string */ } static int -pack_halffloat(char *p, /* start of 2-byte string */ +pack_halffloat(_structmodulestate *state, + 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(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "required argument is not a float"); return -1; } @@ -337,7 +347,7 @@ unpack_double(const char *p, /* start of 8-byte string */ /* Helper to format the range error exceptions */ static int -_range_error(const formatdef *f, int is_unsigned) +_range_error(_structmodulestate *state, const formatdef *f, int is_unsigned) { /* ulargest is the largest unsigned value with f->size bytes. * Note that the simpler: @@ -350,13 +360,13 @@ _range_error(const formatdef *f, int is_unsigned) const size_t ulargest = (size_t)-1 >> ((SIZEOF_SIZE_T - f->size)*8); assert(f->size >= 1 && f->size <= SIZEOF_SIZE_T); if (is_unsigned) - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "'%c' format requires 0 <= number <= %zu", f->format, ulargest); else { const Py_ssize_t largest = (Py_ssize_t)(ulargest >> 1); - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "'%c' format requires %zd <= number <= %zd", f->format, ~ largest, @@ -388,25 +398,25 @@ _range_error(const formatdef *f, int is_unsigned) does this). */ static PyObject * -nu_char(const char *p, const formatdef *f) +nu_char(_structmodulestate *state, const char *p, const formatdef *f) { return PyBytes_FromStringAndSize(p, 1); } static PyObject * -nu_byte(const char *p, const formatdef *f) +nu_byte(_structmodulestate *state, const char *p, const formatdef *f) { return PyLong_FromLong((long) *(signed char *)p); } static PyObject * -nu_ubyte(const char *p, const formatdef *f) +nu_ubyte(_structmodulestate *state, const char *p, const formatdef *f) { return PyLong_FromLong((long) *(unsigned char *)p); } static PyObject * -nu_short(const char *p, const formatdef *f) +nu_short(_structmodulestate *state, const char *p, const formatdef *f) { short x; memcpy((char *)&x, p, sizeof x); @@ -414,7 +424,7 @@ nu_short(const char *p, const formatdef *f) } static PyObject * -nu_ushort(const char *p, const formatdef *f) +nu_ushort(_structmodulestate *state, const char *p, const formatdef *f) { unsigned short x; memcpy((char *)&x, p, sizeof x); @@ -422,7 +432,7 @@ nu_ushort(const char *p, const formatdef *f) } static PyObject * -nu_int(const char *p, const formatdef *f) +nu_int(_structmodulestate *state, const char *p, const formatdef *f) { int x; memcpy((char *)&x, p, sizeof x); @@ -430,7 +440,7 @@ nu_int(const char *p, const formatdef *f) } static PyObject * -nu_uint(const char *p, const formatdef *f) +nu_uint(_structmodulestate *state, const char *p, const formatdef *f) { unsigned int x; memcpy((char *)&x, p, sizeof x); @@ -438,7 +448,7 @@ nu_uint(const char *p, const formatdef *f) } static PyObject * -nu_long(const char *p, const formatdef *f) +nu_long(_structmodulestate *state, const char *p, const formatdef *f) { long x; memcpy((char *)&x, p, sizeof x); @@ -446,7 +456,7 @@ nu_long(const char *p, const formatdef *f) } static PyObject * -nu_ulong(const char *p, const formatdef *f) +nu_ulong(_structmodulestate *state, const char *p, const formatdef *f) { unsigned long x; memcpy((char *)&x, p, sizeof x); @@ -454,7 +464,7 @@ nu_ulong(const char *p, const formatdef *f) } static PyObject * -nu_ssize_t(const char *p, const formatdef *f) +nu_ssize_t(_structmodulestate *state, const char *p, const formatdef *f) { Py_ssize_t x; memcpy((char *)&x, p, sizeof x); @@ -462,7 +472,7 @@ nu_ssize_t(const char *p, const formatdef *f) } static PyObject * -nu_size_t(const char *p, const formatdef *f) +nu_size_t(_structmodulestate *state, const char *p, const formatdef *f) { size_t x; memcpy((char *)&x, p, sizeof x); @@ -470,7 +480,7 @@ nu_size_t(const char *p, const formatdef *f) } static PyObject * -nu_longlong(const char *p, const formatdef *f) +nu_longlong(_structmodulestate *state, const char *p, const formatdef *f) { long long x; memcpy((char *)&x, p, sizeof x); @@ -478,7 +488,7 @@ nu_longlong(const char *p, const formatdef *f) } static PyObject * -nu_ulonglong(const char *p, const formatdef *f) +nu_ulonglong(_structmodulestate *state, const char *p, const formatdef *f) { unsigned long long x; memcpy((char *)&x, p, sizeof x); @@ -486,7 +496,7 @@ nu_ulonglong(const char *p, const formatdef *f) } static PyObject * -nu_bool(const char *p, const formatdef *f) +nu_bool(_structmodulestate *state, const char *p, const formatdef *f) { _Bool x; memcpy((char *)&x, p, sizeof x); @@ -495,7 +505,7 @@ nu_bool(const char *p, const formatdef *f) static PyObject * -nu_halffloat(const char *p, const formatdef *f) +nu_halffloat(_structmodulestate *state, const char *p, const formatdef *f) { #if PY_LITTLE_ENDIAN return unpack_halffloat(p, 1); @@ -505,7 +515,7 @@ nu_halffloat(const char *p, const formatdef *f) } static PyObject * -nu_float(const char *p, const formatdef *f) +nu_float(_structmodulestate *state, const char *p, const formatdef *f) { float x; memcpy((char *)&x, p, sizeof x); @@ -513,7 +523,7 @@ nu_float(const char *p, const formatdef *f) } static PyObject * -nu_double(const char *p, const formatdef *f) +nu_double(_structmodulestate *state, const char *p, const formatdef *f) { double x; memcpy((char *)&x, p, sizeof x); @@ -521,7 +531,7 @@ nu_double(const char *p, const formatdef *f) } static PyObject * -nu_void_p(const char *p, const formatdef *f) +nu_void_p(_structmodulestate *state, const char *p, const formatdef *f) { void *x; memcpy((char *)&x, p, sizeof x); @@ -529,13 +539,13 @@ nu_void_p(const char *p, const formatdef *f) } static int -np_byte(char *p, PyObject *v, const formatdef *f) +np_byte(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { long x; - if (get_long(v, &x) < 0) + if (get_long(state, v, &x) < 0) return -1; if (x < -128 || x > 127) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "byte format requires -128 <= number <= 127"); return -1; } @@ -544,13 +554,13 @@ np_byte(char *p, PyObject *v, const formatdef *f) } static int -np_ubyte(char *p, PyObject *v, const formatdef *f) +np_ubyte(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { long x; - if (get_long(v, &x) < 0) + if (get_long(state, v, &x) < 0) return -1; if (x < 0 || x > 255) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "ubyte format requires 0 <= number <= 255"); return -1; } @@ -559,10 +569,10 @@ np_ubyte(char *p, PyObject *v, const formatdef *f) } static int -np_char(char *p, PyObject *v, const formatdef *f) +np_char(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { if (!PyBytes_Check(v) || PyBytes_Size(v) != 1) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "char format requires a bytes object of length 1"); return -1; } @@ -571,14 +581,14 @@ np_char(char *p, PyObject *v, const formatdef *f) } static int -np_short(char *p, PyObject *v, const formatdef *f) +np_short(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { long x; short y; - if (get_long(v, &x) < 0) + if (get_long(state, v, &x) < 0) return -1; if (x < SHRT_MIN || x > SHRT_MAX) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "short format requires " Py_STRINGIFY(SHRT_MIN) " <= number <= " Py_STRINGIFY(SHRT_MAX)); return -1; @@ -589,14 +599,14 @@ np_short(char *p, PyObject *v, const formatdef *f) } static int -np_ushort(char *p, PyObject *v, const formatdef *f) +np_ushort(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { long x; unsigned short y; - if (get_long(v, &x) < 0) + if (get_long(state, v, &x) < 0) return -1; if (x < 0 || x > USHRT_MAX) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "ushort format requires 0 <= number <= " Py_STRINGIFY(USHRT_MAX)); return -1; @@ -607,15 +617,15 @@ np_ushort(char *p, PyObject *v, const formatdef *f) } static int -np_int(char *p, PyObject *v, const formatdef *f) +np_int(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { long x; int y; - if (get_long(v, &x) < 0) + if (get_long(state, v, &x) < 0) return -1; #if (SIZEOF_LONG > SIZEOF_INT) if ((x < ((long)INT_MIN)) || (x > ((long)INT_MAX))) - RANGE_ERROR(x, f, 0, -1); + RANGE_ERROR(state, x, f, 0, -1); #endif y = (int)x; memcpy(p, (char *)&y, sizeof y); @@ -623,76 +633,76 @@ np_int(char *p, PyObject *v, const formatdef *f) } static int -np_uint(char *p, PyObject *v, const formatdef *f) +np_uint(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { unsigned long x; unsigned int y; - if (get_ulong(v, &x) < 0) + if (get_ulong(state, v, &x) < 0) return -1; y = (unsigned int)x; #if (SIZEOF_LONG > SIZEOF_INT) if (x > ((unsigned long)UINT_MAX)) - RANGE_ERROR(y, f, 1, -1); + RANGE_ERROR(state, y, f, 1, -1); #endif memcpy(p, (char *)&y, sizeof y); return 0; } static int -np_long(char *p, PyObject *v, const formatdef *f) +np_long(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { long x; - if (get_long(v, &x) < 0) + if (get_long(state, v, &x) < 0) return -1; memcpy(p, (char *)&x, sizeof x); return 0; } static int -np_ulong(char *p, PyObject *v, const formatdef *f) +np_ulong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { unsigned long x; - if (get_ulong(v, &x) < 0) + if (get_ulong(state, v, &x) < 0) return -1; memcpy(p, (char *)&x, sizeof x); return 0; } static int -np_ssize_t(char *p, PyObject *v, const formatdef *f) +np_ssize_t(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { Py_ssize_t x; - if (get_ssize_t(v, &x) < 0) + if (get_ssize_t(state, v, &x) < 0) return -1; memcpy(p, (char *)&x, sizeof x); return 0; } static int -np_size_t(char *p, PyObject *v, const formatdef *f) +np_size_t(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { size_t x; - if (get_size_t(v, &x) < 0) + if (get_size_t(state, v, &x) < 0) return -1; memcpy(p, (char *)&x, sizeof x); return 0; } static int -np_longlong(char *p, PyObject *v, const formatdef *f) +np_longlong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { long long x; - if (get_longlong(v, &x) < 0) + if (get_longlong(state, v, &x) < 0) return -1; memcpy(p, (char *)&x, sizeof x); return 0; } static int -np_ulonglong(char *p, PyObject *v, const formatdef *f) +np_ulonglong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { unsigned long long x; - if (get_ulonglong(v, &x) < 0) + if (get_ulonglong(state, v, &x) < 0) return -1; memcpy(p, (char *)&x, sizeof x); return 0; @@ -700,7 +710,7 @@ np_ulonglong(char *p, PyObject *v, const formatdef *f) static int -np_bool(char *p, PyObject *v, const formatdef *f) +np_bool(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { int y; _Bool x; @@ -713,21 +723,21 @@ np_bool(char *p, PyObject *v, const formatdef *f) } static int -np_halffloat(char *p, PyObject *v, const formatdef *f) +np_halffloat(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { #if PY_LITTLE_ENDIAN - return pack_halffloat(p, v, 1); + return pack_halffloat(state, p, v, 1); #else - return pack_halffloat(p, v, 0); + return pack_halffloat(statem p, v, 0); #endif } static int -np_float(char *p, PyObject *v, const formatdef *f) +np_float(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { float x = (float)PyFloat_AsDouble(v); if (x == -1 && PyErr_Occurred()) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "required argument is not a float"); return -1; } @@ -736,11 +746,11 @@ np_float(char *p, PyObject *v, const formatdef *f) } static int -np_double(char *p, PyObject *v, const formatdef *f) +np_double(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { double x = PyFloat_AsDouble(v); if (x == -1 && PyErr_Occurred()) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "required argument is not a float"); return -1; } @@ -749,11 +759,11 @@ np_double(char *p, PyObject *v, const formatdef *f) } static int -np_void_p(char *p, PyObject *v, const formatdef *f) +np_void_p(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { void *x; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; assert(PyLong_Check(v)); @@ -793,7 +803,7 @@ static const formatdef native_table[] = { /* Big-endian routines. *****************************************************/ static PyObject * -bu_int(const char *p, const formatdef *f) +bu_int(_structmodulestate *state, const char *p, const formatdef *f) { long x = 0; Py_ssize_t i = f->size; @@ -808,7 +818,7 @@ bu_int(const char *p, const formatdef *f) } static PyObject * -bu_uint(const char *p, const formatdef *f) +bu_uint(_structmodulestate *state, const char *p, const formatdef *f) { unsigned long x = 0; Py_ssize_t i = f->size; @@ -820,7 +830,7 @@ bu_uint(const char *p, const formatdef *f) } static PyObject * -bu_longlong(const char *p, const formatdef *f) +bu_longlong(_structmodulestate *state, const char *p, const formatdef *f) { long long x = 0; Py_ssize_t i = f->size; @@ -835,7 +845,7 @@ bu_longlong(const char *p, const formatdef *f) } static PyObject * -bu_ulonglong(const char *p, const formatdef *f) +bu_ulonglong(_structmodulestate *state, const char *p, const formatdef *f) { unsigned long long x = 0; Py_ssize_t i = f->size; @@ -847,44 +857,44 @@ bu_ulonglong(const char *p, const formatdef *f) } static PyObject * -bu_halffloat(const char *p, const formatdef *f) +bu_halffloat(_structmodulestate *state, const char *p, const formatdef *f) { return unpack_halffloat(p, 0); } static PyObject * -bu_float(const char *p, const formatdef *f) +bu_float(_structmodulestate *state, const char *p, const formatdef *f) { return unpack_float(p, 0); } static PyObject * -bu_double(const char *p, const formatdef *f) +bu_double(_structmodulestate *state, const char *p, const formatdef *f) { return unpack_double(p, 0); } static PyObject * -bu_bool(const char *p, const formatdef *f) +bu_bool(_structmodulestate *state, const char *p, const formatdef *f) { return PyBool_FromLong(*p != 0); } static int -bp_int(char *p, PyObject *v, const formatdef *f) +bp_int(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { long x; Py_ssize_t i; unsigned char *q = (unsigned char *)p; - if (get_long(v, &x) < 0) + if (get_long(state, v, &x) < 0) return -1; i = f->size; if (i != SIZEOF_LONG) { if ((i == 2) && (x < -32768 || x > 32767)) - RANGE_ERROR(x, f, 0, 0xffffL); + RANGE_ERROR(state, x, f, 0, 0xffffL); #if (SIZEOF_LONG != 4) else if ((i == 4) && (x < -2147483648L || x > 2147483647L)) - RANGE_ERROR(x, f, 0, 0xffffffffL); + RANGE_ERROR(state, x, f, 0, 0xffffffffL); #endif } do { @@ -895,19 +905,19 @@ bp_int(char *p, PyObject *v, const formatdef *f) } static int -bp_uint(char *p, PyObject *v, const formatdef *f) +bp_uint(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { unsigned long x; Py_ssize_t i; unsigned char *q = (unsigned char *)p; - if (get_ulong(v, &x) < 0) + if (get_ulong(state, v, &x) < 0) return -1; i = f->size; if (i != SIZEOF_LONG) { unsigned long maxint = 1; maxint <<= (unsigned long)(i * 8); if (x >= maxint) - RANGE_ERROR(x, f, 1, maxint - 1); + RANGE_ERROR(state, x, f, 1, maxint - 1); } do { q[--i] = (unsigned char)(x & 0xffUL); @@ -917,10 +927,10 @@ bp_uint(char *p, PyObject *v, const formatdef *f) } static int -bp_longlong(char *p, PyObject *v, const formatdef *f) +bp_longlong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { int res; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; res = _PyLong_AsByteArray((PyLongObject *)v, @@ -933,10 +943,10 @@ bp_longlong(char *p, PyObject *v, const formatdef *f) } static int -bp_ulonglong(char *p, PyObject *v, const formatdef *f) +bp_ulonglong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { int res; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; res = _PyLong_AsByteArray((PyLongObject *)v, @@ -949,17 +959,17 @@ bp_ulonglong(char *p, PyObject *v, const formatdef *f) } static int -bp_halffloat(char *p, PyObject *v, const formatdef *f) +bp_halffloat(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { - return pack_halffloat(p, v, 0); + return pack_halffloat(state, p, v, 0); } static int -bp_float(char *p, PyObject *v, const formatdef *f) +bp_float(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { double x = PyFloat_AsDouble(v); if (x == -1 && PyErr_Occurred()) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "required argument is not a float"); return -1; } @@ -967,11 +977,11 @@ bp_float(char *p, PyObject *v, const formatdef *f) } static int -bp_double(char *p, PyObject *v, const formatdef *f) +bp_double(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { double x = PyFloat_AsDouble(v); if (x == -1 && PyErr_Occurred()) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "required argument is not a float"); return -1; } @@ -979,7 +989,7 @@ bp_double(char *p, PyObject *v, const formatdef *f) } static int -bp_bool(char *p, PyObject *v, const formatdef *f) +bp_bool(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { int y; y = PyObject_IsTrue(v); @@ -1014,7 +1024,7 @@ static formatdef bigendian_table[] = { /* Little-endian routines. *****************************************************/ static PyObject * -lu_int(const char *p, const formatdef *f) +lu_int(_structmodulestate *state, const char *p, const formatdef *f) { long x = 0; Py_ssize_t i = f->size; @@ -1029,7 +1039,7 @@ lu_int(const char *p, const formatdef *f) } static PyObject * -lu_uint(const char *p, const formatdef *f) +lu_uint(_structmodulestate *state, const char *p, const formatdef *f) { unsigned long x = 0; Py_ssize_t i = f->size; @@ -1041,7 +1051,7 @@ lu_uint(const char *p, const formatdef *f) } static PyObject * -lu_longlong(const char *p, const formatdef *f) +lu_longlong(_structmodulestate *state, const char *p, const formatdef *f) { long long x = 0; Py_ssize_t i = f->size; @@ -1056,7 +1066,7 @@ lu_longlong(const char *p, const formatdef *f) } static PyObject * -lu_ulonglong(const char *p, const formatdef *f) +lu_ulonglong(_structmodulestate *state, const char *p, const formatdef *f) { unsigned long long x = 0; Py_ssize_t i = f->size; @@ -1068,38 +1078,38 @@ lu_ulonglong(const char *p, const formatdef *f) } static PyObject * -lu_halffloat(const char *p, const formatdef *f) +lu_halffloat(_structmodulestate *state, const char *p, const formatdef *f) { return unpack_halffloat(p, 1); } static PyObject * -lu_float(const char *p, const formatdef *f) +lu_float(_structmodulestate *state, const char *p, const formatdef *f) { return unpack_float(p, 1); } static PyObject * -lu_double(const char *p, const formatdef *f) +lu_double(_structmodulestate *state, const char *p, const formatdef *f) { return unpack_double(p, 1); } static int -lp_int(char *p, PyObject *v, const formatdef *f) +lp_int(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { long x; Py_ssize_t i; unsigned char *q = (unsigned char *)p; - if (get_long(v, &x) < 0) + if (get_long(state, v, &x) < 0) return -1; i = f->size; if (i != SIZEOF_LONG) { if ((i == 2) && (x < -32768 || x > 32767)) - RANGE_ERROR(x, f, 0, 0xffffL); + RANGE_ERROR(state, x, f, 0, 0xffffL); #if (SIZEOF_LONG != 4) else if ((i == 4) && (x < -2147483648L || x > 2147483647L)) - RANGE_ERROR(x, f, 0, 0xffffffffL); + RANGE_ERROR(state, x, f, 0, 0xffffffffL); #endif } do { @@ -1110,19 +1120,19 @@ lp_int(char *p, PyObject *v, const formatdef *f) } static int -lp_uint(char *p, PyObject *v, const formatdef *f) +lp_uint(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { unsigned long x; Py_ssize_t i; unsigned char *q = (unsigned char *)p; - if (get_ulong(v, &x) < 0) + if (get_ulong(state, v, &x) < 0) return -1; i = f->size; if (i != SIZEOF_LONG) { unsigned long maxint = 1; maxint <<= (unsigned long)(i * 8); if (x >= maxint) - RANGE_ERROR(x, f, 1, maxint - 1); + RANGE_ERROR(state, x, f, 1, maxint - 1); } do { *q++ = (unsigned char)(x & 0xffUL); @@ -1132,10 +1142,10 @@ lp_uint(char *p, PyObject *v, const formatdef *f) } static int -lp_longlong(char *p, PyObject *v, const formatdef *f) +lp_longlong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { int res; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; res = _PyLong_AsByteArray((PyLongObject*)v, @@ -1148,10 +1158,10 @@ lp_longlong(char *p, PyObject *v, const formatdef *f) } static int -lp_ulonglong(char *p, PyObject *v, const formatdef *f) +lp_ulonglong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { int res; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; res = _PyLong_AsByteArray((PyLongObject*)v, @@ -1164,17 +1174,17 @@ lp_ulonglong(char *p, PyObject *v, const formatdef *f) } static int -lp_halffloat(char *p, PyObject *v, const formatdef *f) +lp_halffloat(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { - return pack_halffloat(p, v, 1); + return pack_halffloat(state, p, v, 1); } static int -lp_float(char *p, PyObject *v, const formatdef *f) +lp_float(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { double x = PyFloat_AsDouble(v); if (x == -1 && PyErr_Occurred()) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "required argument is not a float"); return -1; } @@ -1182,11 +1192,11 @@ lp_float(char *p, PyObject *v, const formatdef *f) } static int -lp_double(char *p, PyObject *v, const formatdef *f) +lp_double(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { double x = PyFloat_AsDouble(v); if (x == -1 && PyErr_Occurred()) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "required argument is not a float"); return -1; } @@ -1246,14 +1256,14 @@ whichtable(const char **pfmt) /* Get the table entry for a format code */ static const formatdef * -getentry(int c, const formatdef *f) +getentry(_structmodulestate *state, int c, const formatdef *f) { for (; f->format != '\0'; f++) { if (f->format == c) { return f; } } - PyErr_SetString(_structmodulestate_global->StructError, "bad char in struct format"); + PyErr_SetString(state->StructError, "bad char in struct format"); return NULL; } @@ -1295,9 +1305,11 @@ prepare_s(PyStructObject *self) Py_ssize_t size, len, num, itemsize; size_t ncodes; + _structmodulestate *state = get_struct_state_structinst(self); + fmt = PyBytes_AS_STRING(self->s_format); if (strlen(fmt) != (size_t)PyBytes_GET_SIZE(self->s_format)) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "embedded null character"); return -1; } @@ -1323,7 +1335,7 @@ prepare_s(PyStructObject *self) num = num*10 + (c - '0'); } if (c == '\0') { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "repeat count given without format specifier"); return -1; } @@ -1331,7 +1343,7 @@ prepare_s(PyStructObject *self) else num = 1; - e = getentry(c, f); + e = getentry(state, c, f); if (e == NULL) return -1; @@ -1384,7 +1396,7 @@ prepare_s(PyStructObject *self) else num = 1; - e = getentry(c, f); + e = getentry(state, c, f); size = align(size, c, e); if (c == 's' || c == 'p') { @@ -1413,7 +1425,7 @@ prepare_s(PyStructObject *self) return 0; overflow: - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "total struct size too long"); return -1; } @@ -1499,7 +1511,8 @@ s_dealloc(PyStructObject *s) } static PyObject * -s_unpack_internal(PyStructObject *soself, const char *startfrom) { +s_unpack_internal(PyStructObject *soself, const char *startfrom, + _structmodulestate *state) { formatcode *code; Py_ssize_t i = 0; PyObject *result = PyTuple_New(soself->s_len); @@ -1520,7 +1533,7 @@ s_unpack_internal(PyStructObject *soself, const char *startfrom) { n = code->size - 1; v = PyBytes_FromStringAndSize(res + 1, n); } else { - v = e->unpack(res, e); + v = e->unpack(state, res, e); } if (v == NULL) goto fail; @@ -1554,14 +1567,15 @@ static PyObject * Struct_unpack_impl(PyStructObject *self, Py_buffer *buffer) /*[clinic end generated code: output=873a24faf02e848a input=3113f8e7038b2f6c]*/ { + _structmodulestate *state = get_struct_state_structinst(self); assert(self->s_codes != NULL); if (buffer->len != self->s_size) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "unpack requires a buffer of %zd bytes", self->s_size); return NULL; } - return s_unpack_internal(self, buffer->buf); + return s_unpack_internal(self, buffer->buf, state); } /*[clinic input] @@ -1585,11 +1599,12 @@ Struct_unpack_from_impl(PyStructObject *self, Py_buffer *buffer, Py_ssize_t offset) /*[clinic end generated code: output=57fac875e0977316 input=cafd4851d473c894]*/ { + _structmodulestate *state = get_struct_state_structinst(self); assert(self->s_codes != NULL); if (offset < 0) { if (offset + self->s_size > 0) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "not enough data to unpack %zd bytes at offset %zd", self->s_size, offset); @@ -1597,7 +1612,7 @@ Struct_unpack_from_impl(PyStructObject *self, Py_buffer *buffer, } if (offset + buffer->len < 0) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "offset %zd out of range for %zd-byte buffer", offset, buffer->len); @@ -1607,7 +1622,7 @@ Struct_unpack_from_impl(PyStructObject *self, Py_buffer *buffer, } if ((buffer->len - offset) < self->s_size) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "unpack_from requires a buffer of at least %zu bytes for " "unpacking %zd bytes at offset %zd " "(actual buffer size is %zd)", @@ -1617,7 +1632,7 @@ Struct_unpack_from_impl(PyStructObject *self, Py_buffer *buffer, buffer->len); return NULL; } - return s_unpack_internal(self, (char*)buffer->buf + offset); + return s_unpack_internal(self, (char*)buffer->buf + offset, state); } @@ -1671,6 +1686,7 @@ static PyMethodDef unpackiter_methods[] = { static PyObject * unpackiter_iternext(unpackiterobject *self) { + _structmodulestate *state = get_struct_state_iterinst(self); PyObject *result; if (self->so == NULL) return NULL; @@ -1682,7 +1698,8 @@ unpackiter_iternext(unpackiterobject *self) } assert(self->index + self->so->s_size <= self->buf.len); result = s_unpack_internal(self->so, - (char*) self->buf.buf + self->index); + (char*) self->buf.buf + self->index, + state); self->index += self->so->s_size; return result; } @@ -1729,17 +1746,18 @@ static PyObject * Struct_iter_unpack(PyStructObject *self, PyObject *buffer) /*[clinic end generated code: output=172d83d0cd15dbab input=6d65b3f3107dbc99]*/ { + _structmodulestate *state = get_struct_state_structinst(self); unpackiterobject *iter; assert(self->s_codes != NULL); if (self->s_size == 0) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "cannot iteratively unpack with a struct of length 0"); return NULL; } - iter = (unpackiterobject *) PyType_GenericAlloc((PyTypeObject *)_structmodulestate_global->unpackiter_type, 0); + iter = (unpackiterobject *) PyType_GenericAlloc((PyTypeObject *)state->unpackiter_type, 0); if (iter == NULL) return NULL; @@ -1748,7 +1766,7 @@ Struct_iter_unpack(PyStructObject *self, PyObject *buffer) return NULL; } if (iter->buf.len % self->s_size != 0) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "iterative unpacking requires a buffer of " "a multiple of %zd bytes", self->s_size); @@ -1773,7 +1791,8 @@ Struct_iter_unpack(PyStructObject *self, PyObject *buffer) * */ static int -s_pack_internal(PyStructObject *soself, PyObject *const *args, int offset, char* buf) +s_pack_internal(PyStructObject *soself, PyObject *const *args, int offset, + char* buf, _structmodulestate *state) { formatcode *code; /* XXX(nnorwitz): why does i need to be a local? can we use @@ -1794,7 +1813,7 @@ s_pack_internal(PyStructObject *soself, PyObject *const *args, int offset, char* const void *p; isstring = PyBytes_Check(v); if (!isstring && !PyByteArray_Check(v)) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "argument for 's' must be a bytes object"); return -1; } @@ -1816,7 +1835,7 @@ s_pack_internal(PyStructObject *soself, PyObject *const *args, int offset, char* const void *p; isstring = PyBytes_Check(v); if (!isstring && !PyByteArray_Check(v)) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "argument for 'p' must be a bytes object"); return -1; } @@ -1836,9 +1855,9 @@ s_pack_internal(PyStructObject *soself, PyObject *const *args, int offset, char* n = 255; *res = Py_SAFE_DOWNCAST(n, Py_ssize_t, unsigned char); } else { - if (e->pack(res, v, e) < 0) { + if (e->pack(state, res, v, e) < 0) { if (PyLong_Check(v) && PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "int too large to convert"); return -1; } @@ -1864,14 +1883,15 @@ s_pack(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { char *buf; PyStructObject *soself; + _structmodulestate *state = get_struct_state_structinst(self); /* Validate arguments. */ soself = (PyStructObject *)self; - assert(PyStruct_Check(self)); + assert(PyStruct_Check(self, state)); assert(soself->s_codes != NULL); if (nargs != soself->s_len) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "pack expected %zd items for packing (got %zd)", soself->s_len, nargs); return NULL; } @@ -1886,7 +1906,7 @@ s_pack(PyObject *self, PyObject *const *args, Py_ssize_t nargs) } /* Call the guts */ - if ( s_pack_internal(soself, args, 0, buf) != 0 ) { + if ( s_pack_internal(soself, args, 0, buf, state) != 0 ) { _PyBytesWriter_Dealloc(&writer); return NULL; } @@ -1908,23 +1928,24 @@ s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs) PyStructObject *soself; Py_buffer buffer; Py_ssize_t offset; + _structmodulestate *state = get_struct_state_structinst(self); /* Validate arguments. +1 is for the first arg as buffer. */ soself = (PyStructObject *)self; - assert(PyStruct_Check(self)); + assert(PyStruct_Check(self, state)); assert(soself->s_codes != NULL); if (nargs != (soself->s_len + 2)) { if (nargs == 0) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "pack_into expected buffer argument"); } else if (nargs == 1) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "pack_into expected offset argument"); } else { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "pack_into expected %zd items for packing (got %zd)", soself->s_len, (nargs - 2)); } @@ -1947,7 +1968,7 @@ s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs) if (offset < 0) { /* Check that negative offset is low enough to fit data */ if (offset + soself->s_size > 0) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "no space to pack %zd bytes at offset %zd", soself->s_size, offset); @@ -1957,7 +1978,7 @@ s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs) /* Check that negative offset is not crossing buffer boundary */ if (offset + buffer.len < 0) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "offset %zd out of range for %zd-byte buffer", offset, buffer.len); @@ -1973,7 +1994,7 @@ s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs) assert(offset >= 0); assert(soself->s_size >= 0); - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "pack_into requires a buffer of at least %zu bytes for " "packing %zd bytes at offset %zd " "(actual buffer size is %zd)", @@ -1986,7 +2007,7 @@ s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs) } /* Call the guts */ - if (s_pack_internal(soself, args, 2, (char*)buffer.buf + offset) != 0) { + if (s_pack_internal(soself, args, 2, (char*)buffer.buf + offset, state) != 0) { PyBuffer_Release(&buffer); return NULL; } @@ -2080,12 +2101,12 @@ static PyType_Spec PyStructType_spec = { /* ---- Standalone functions ---- */ #define MAXCACHE 100 -static PyObject *cache = NULL; static int -cache_struct_converter(PyObject *fmt, PyStructObject **ptr) +cache_struct_converter(PyObject *module, PyObject *fmt, PyStructObject **ptr) { PyObject * s_object; + _structmodulestate *state = get_struct_state(module); if (fmt == NULL) { Py_DECREF(*ptr); @@ -2093,13 +2114,13 @@ cache_struct_converter(PyObject *fmt, PyStructObject **ptr) return 1; } - if (cache == NULL) { - cache = PyDict_New(); - if (cache == NULL) + if (state->cache == NULL) { + state->cache = PyDict_New(); + if (state->cache == NULL) return 0; } - s_object = PyDict_GetItemWithError(cache, fmt); + s_object = PyDict_GetItemWithError(state->cache, fmt); if (s_object != NULL) { Py_INCREF(s_object); *ptr = (PyStructObject *)s_object; @@ -2109,12 +2130,12 @@ cache_struct_converter(PyObject *fmt, PyStructObject **ptr) return 0; } - s_object = PyObject_CallOneArg(_structmodulestate_global->PyStructType, fmt); + s_object = PyObject_CallOneArg(state->PyStructType, fmt); if (s_object != NULL) { - if (PyDict_GET_SIZE(cache) >= MAXCACHE) - PyDict_Clear(cache); + if (PyDict_GET_SIZE(state->cache) >= MAXCACHE) + PyDict_Clear(state->cache); /* Attempt to cache the result */ - if (PyDict_SetItem(cache, fmt, s_object) == -1) + if (PyDict_SetItem(state->cache, fmt, s_object) == -1) PyErr_Clear(); *ptr = (PyStructObject *)s_object; return Py_CLEANUP_SUPPORTED; @@ -2132,7 +2153,7 @@ static PyObject * _clearcache_impl(PyObject *module) /*[clinic end generated code: output=ce4fb8a7bf7cb523 input=463eaae04bab3211]*/ { - Py_CLEAR(cache); + Py_CLEAR(get_struct_state(module)->cache); Py_RETURN_NONE; } @@ -2160,7 +2181,7 @@ Return a bytes object containing the values v1, v2, ... packed according\n\ to the format string. See help(struct) for more on format strings."); static PyObject * -pack(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +pack(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *s_object = NULL; PyObject *format, *result; @@ -2171,7 +2192,7 @@ pack(PyObject *self, PyObject *const *args, Py_ssize_t nargs) } format = args[0]; - if (!cache_struct_converter(format, (PyStructObject **)&s_object)) { + if (!cache_struct_converter(module, format, (PyStructObject **)&s_object)) { return NULL; } result = s_pack(s_object, args + 1, nargs - 1); @@ -2188,7 +2209,7 @@ that the offset is a required argument. See help(struct) for more\n\ on format strings."); static PyObject * -pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +pack_into(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *s_object = NULL; PyObject *format, *result; @@ -2199,7 +2220,7 @@ pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs) } format = args[0]; - if (!cache_struct_converter(format, (PyStructObject **)&s_object)) { + if (!cache_struct_converter(module, format, (PyStructObject **)&s_object)) { return NULL; } result = s_pack_into(s_object, args + 1, nargs - 1); @@ -2322,8 +2343,9 @@ The variable struct.error is an exception raised on errors.\n"); static int _structmodule_traverse(PyObject *module, visitproc visit, void *arg) { - _structmodulestate *state = (_structmodulestate *)PyModule_GetState(module); + _structmodulestate *state = get_struct_state(module); if (state) { + Py_VISIT(state->cache); Py_VISIT(state->PyStructType); Py_VISIT(state->unpackiter_type); Py_VISIT(state->StructError); @@ -2334,8 +2356,9 @@ _structmodule_traverse(PyObject *module, visitproc visit, void *arg) static int _structmodule_clear(PyObject *module) { - _structmodulestate *state = (_structmodulestate *)PyModule_GetState(module); + _structmodulestate *state = get_struct_state(module); if (state) { + Py_CLEAR(state->cache); Py_CLEAR(state->PyStructType); Py_CLEAR(state->unpackiter_type); Py_CLEAR(state->StructError); @@ -2349,40 +2372,25 @@ _structmodule_free(void *module) _structmodule_clear((PyObject *)module); } -static struct PyModuleDef _structmodule = { - PyModuleDef_HEAD_INIT, - "_struct", - module_doc, - sizeof(_structmodulestate), - module_functions, - NULL, - _structmodule_traverse, - _structmodule_clear, - _structmodule_free, -}; - -PyMODINIT_FUNC -PyInit__struct(void) +static int +_structmodule_exec(PyObject *m) { - PyObject *m; + _structmodulestate *state = get_struct_state(m); - m = PyModule_Create(&_structmodule); - if (m == NULL) - return NULL; - - PyObject *PyStructType = PyType_FromSpec(&PyStructType_spec); - if (PyStructType == NULL) { - return NULL; + state->PyStructType = PyType_FromModuleAndSpec( + m, &PyStructType_spec, NULL); + if (state->PyStructType == NULL) { + return -1; } - Py_INCREF(PyStructType); - PyModule_AddObject(m, "Struct", PyStructType); - get_struct_state(m)->PyStructType = PyStructType; - - PyObject *unpackiter_type = PyType_FromSpec(&unpackiter_type_spec); - if (unpackiter_type == NULL) { - return NULL; + if (PyModule_AddType(m, (PyTypeObject *)state->PyStructType) < 0) { + return -1; + } + + state->unpackiter_type = PyType_FromModuleAndSpec( + m, &unpackiter_type_spec, NULL); + if (state->unpackiter_type == NULL) { + return -1; } - get_struct_state(m)->unpackiter_type = unpackiter_type; /* Check endian and swap in faster functions */ { @@ -2427,12 +2435,36 @@ PyInit__struct(void) } /* Add some symbolic constants to the module */ - PyObject *StructError = PyErr_NewException("struct.error", NULL, NULL); - if (StructError == NULL) - return NULL; - Py_INCREF(StructError); - PyModule_AddObject(m, "error", StructError); - get_struct_state(m)->StructError = StructError; + state->StructError = PyErr_NewException("struct.error", NULL, NULL); + if (state->StructError == NULL) { + return -1; + } + if (PyModule_AddObjectRef(m, "error", state->StructError) < 0) { + return -1; + } - return m; + return 0; +} + +static PyModuleDef_Slot _structmodule_slots[] = { + {Py_mod_exec, _structmodule_exec}, + {0, NULL} +}; + +static struct PyModuleDef _structmodule = { + PyModuleDef_HEAD_INIT, + .m_name = "_struct", + .m_doc = module_doc, + .m_size = sizeof(_structmodulestate), + .m_methods = module_functions, + .m_slots = _structmodule_slots, + .m_traverse = _structmodule_traverse, + .m_clear = _structmodule_clear, + .m_free = _structmodule_free, +}; + +PyMODINIT_FUNC +PyInit__struct(void) +{ + return PyModuleDef_Init(&_structmodule); } diff --git a/Modules/clinic/_struct.c.h b/Modules/clinic/_struct.c.h index 1cfaef3b713..b0c1eb4587a 100644 --- a/Modules/clinic/_struct.c.h +++ b/Modules/clinic/_struct.c.h @@ -199,7 +199,7 @@ calcsize(PyObject *module, PyObject *arg) PyStructObject *s_object = NULL; Py_ssize_t _return_value; - if (!cache_struct_converter(arg, &s_object)) { + if (!cache_struct_converter(module, arg, &s_object)) { goto exit; } _return_value = calcsize_impl(module, s_object); @@ -241,7 +241,7 @@ unpack(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("unpack", nargs, 2, 2)) { goto exit; } - if (!cache_struct_converter(args[0], &s_object)) { + if (!cache_struct_converter(module, args[0], &s_object)) { goto exit; } if (PyObject_GetBuffer(args[1], &buffer, PyBUF_SIMPLE) != 0) { @@ -297,7 +297,7 @@ unpack_from(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!args) { goto exit; } - if (!cache_struct_converter(args[0], &s_object)) { + if (!cache_struct_converter(module, args[0], &s_object)) { goto exit; } if (PyObject_GetBuffer(args[1], &buffer, PyBUF_SIMPLE) != 0) { @@ -364,7 +364,7 @@ iter_unpack(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("iter_unpack", nargs, 2, 2)) { goto exit; } - if (!cache_struct_converter(args[0], &s_object)) { + if (!cache_struct_converter(module, args[0], &s_object)) { goto exit; } buffer = args[1]; @@ -376,4 +376,4 @@ exit: return return_value; } -/*[clinic end generated code: output=8089792d8ed0c1be input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a3d3cd900091cb1c input=a9049054013a1b77]*/