summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Heimes <christian@python.org>2020-11-19 13:36:23 (GMT)
committerGitHub <noreply@github.com>2020-11-19 13:36:23 (GMT)
commitcfeb5437a8910e28726422a14a93a36584e32238 (patch)
treea5ddb6495bf59bbd2d787b715dedaa8faac915cb
parent3390347aa036404453213d589fe1e35902e55fd4 (diff)
downloadcpython-cfeb5437a8910e28726422a14a93a36584e32238.zip
cpython-cfeb5437a8910e28726422a14a93a36584e32238.tar.gz
cpython-cfeb5437a8910e28726422a14a93a36584e32238.tar.bz2
bpo-1635741: Port _struct to multiphase initialization (GH-23398)
Signed-off-by: Christian Heimes <christian@python.org>
-rw-r--r--Misc/NEWS.d/next/C API/2020-11-19-12-06-43.bpo-1635741.KEfZpn.rst1
-rw-r--r--Modules/_struct.c498
-rw-r--r--Modules/clinic/_struct.c.h10
3 files changed, 271 insertions, 238 deletions
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 0000000..fc64757
--- /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 81cdbb9..8dfcd88 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;
+ }
+ if (PyModule_AddType(m, (PyTypeObject *)state->PyStructType) < 0) {
+ 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;
+ 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 0;
+}
- return m;
+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 1cfaef3..b0c1eb4 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]*/