Skip to content
Prev Previous commit
Next Next commit
Establish global state and add types to it
  • Loading branch information
Erlend E. Aasland committed Nov 3, 2020
commit 3f7876667db0cb463d366b6517275c5590ac7964
79 changes: 45 additions & 34 deletions Modules/arraymodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,27 @@ typedef struct arrayobject {
Py_ssize_t ob_exports; /* Number of exported buffers */
} arrayobject;

static PyTypeObject *Arraytype = NULL;

typedef struct {
PyObject_HEAD
Py_ssize_t index;
arrayobject *ao;
PyObject* (*getitem)(struct arrayobject *, Py_ssize_t);
} arrayiterobject;

static PyTypeObject *PyArrayIter_Type = NULL;
typedef struct {
PyTypeObject *Arraytype;
PyTypeObject *PyArrayIter_Type;
} array_state;

static array_state global_array_state;

static array_state *
get_array_state()
{
return &global_array_state;
}

#define PyArrayIter_Check(op) PyObject_TypeCheck(op, PyArrayIter_Type)
#define PyArrayIter_Check(op) PyObject_TypeCheck(op, get_array_state()->PyArrayIter_Type)

enum machine_format_code {
UNKNOWN_FORMAT = -1,
Expand Down Expand Up @@ -106,8 +115,8 @@ enum machine_format_code {
*/
#include "clinic/arraymodule.c.h"

#define array_Check(op) PyObject_TypeCheck(op, Arraytype)
#define array_CheckExact(op) Py_IS_TYPE(op, Arraytype)
#define array_Check(op) PyObject_TypeCheck(op, get_array_state()->Arraytype)
#define array_CheckExact(op) Py_IS_TYPE(op, get_array_state()->Arraytype)

static int
array_resize(arrayobject *self, Py_ssize_t newsize)
Expand Down Expand Up @@ -802,7 +811,7 @@ array_slice(arrayobject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
ihigh = ilow;
else if (ihigh > Py_SIZE(a))
ihigh = Py_SIZE(a);
np = (arrayobject *) newarrayobject(Arraytype, ihigh - ilow, a->ob_descr);
np = (arrayobject *) newarrayobject(get_array_state()->Arraytype, ihigh - ilow, a->ob_descr);
if (np == NULL)
return NULL;
if (ihigh > ilow) {
Expand Down Expand Up @@ -862,7 +871,7 @@ array_concat(arrayobject *a, PyObject *bb)
return PyErr_NoMemory();
}
size = Py_SIZE(a) + Py_SIZE(b);
np = (arrayobject *) newarrayobject(Arraytype, size, a->ob_descr);
np = (arrayobject *) newarrayobject(get_array_state()->Arraytype, size, a->ob_descr);
if (np == NULL) {
return NULL;
}
Expand All @@ -889,7 +898,7 @@ array_repeat(arrayobject *a, Py_ssize_t n)
return PyErr_NoMemory();
}
size = Py_SIZE(a) * n;
np = (arrayobject *) newarrayobject(Arraytype, size, a->ob_descr);
np = (arrayobject *) newarrayobject(get_array_state()->Arraytype, size, a->ob_descr);
if (np == NULL)
return NULL;
if (size == 0)
Expand Down Expand Up @@ -1942,10 +1951,10 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype,
Py_TYPE(arraytype)->tp_name);
return NULL;
}
if (!PyType_IsSubtype(arraytype, Arraytype)) {
if (!PyType_IsSubtype(arraytype, get_array_state()->Arraytype)) {
PyErr_Format(PyExc_TypeError,
"%.200s is not a subtype of %.200s",
arraytype->tp_name, Arraytype->tp_name);
arraytype->tp_name, get_array_state()->Arraytype->tp_name);
return NULL;
}
for (descr = descriptors; descr->typecode != '\0'; descr++) {
Expand Down Expand Up @@ -2314,10 +2323,10 @@ array_subscr(arrayobject* self, PyObject* item)
step);

if (slicelength <= 0) {
return newarrayobject(Arraytype, 0, self->ob_descr);
return newarrayobject(get_array_state()->Arraytype, 0, self->ob_descr);
}
else if (step == 1) {
PyObject *result = newarrayobject(Arraytype,
PyObject *result = newarrayobject(get_array_state()->Arraytype,
slicelength, self->ob_descr);
if (result == NULL)
return NULL;
Expand All @@ -2327,7 +2336,7 @@ array_subscr(arrayobject* self, PyObject* item)
return result;
}
else {
result = newarrayobject(Arraytype, slicelength, self->ob_descr);
result = newarrayobject(get_array_state()->Arraytype, slicelength, self->ob_descr);
if (!result) return NULL;

ar = (arrayobject*)result;
Expand Down Expand Up @@ -2563,7 +2572,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
PyObject *initial = NULL, *it = NULL;
const struct arraydescr *descr;

if (type == Arraytype && !_PyArg_NoKeywords("array.array", kwds))
if (type == get_array_state()->Arraytype && !_PyArg_NoKeywords("array.array", kwds))
return NULL;

if (!PyArg_ParseTuple(args, "C|O:array", &c, &initial))
Expand Down Expand Up @@ -2808,7 +2817,7 @@ static PyType_Spec array_spec = {
/*********************** Array Iterator **************************/

/*[clinic input]
class array.arrayiterator "arrayiterobject *" "PyArrayIter_Type"
class array.arrayiterator "arrayiterobject *" "get_array_state()->PyArrayIter_Type"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=5aefd2d74d8c8e30]*/

Expand All @@ -2822,7 +2831,7 @@ array_iter(arrayobject *ao)
return NULL;
}

it = PyObject_GC_New(arrayiterobject, PyArrayIter_Type);
it = PyObject_GC_New(arrayiterobject, get_array_state()->PyArrayIter_Type);
if (it == NULL)
return NULL;

Expand Down Expand Up @@ -2949,48 +2958,50 @@ static PyMethodDef a_methods[] = {
static int
array_modexec(PyObject *m)
{
array_state *state = get_array_state();
char buffer[Py_ARRAY_LENGTH(descriptors)], *p;
PyObject *typecodes;
const struct arraydescr *descr;

Arraytype = (PyTypeObject *)PyType_FromModuleAndSpec(m, &array_spec, NULL);
if (Arraytype == NULL)
state->Arraytype = (PyTypeObject *)PyType_FromModuleAndSpec(m, &array_spec, NULL);
if (state->Arraytype == NULL)
return -1;
PyArrayIter_Type = (PyTypeObject *)PyType_FromModuleAndSpec(m,
&arrayiter_spec,
NULL);
if (PyArrayIter_Type == NULL)
state->PyArrayIter_Type = (PyTypeObject *)PyType_FromModuleAndSpec(m,
&arrayiter_spec,
NULL);
if (state->PyArrayIter_Type == NULL)
return -1;
Py_SET_TYPE(PyArrayIter_Type, &PyType_Type);
Py_SET_TYPE(state->PyArrayIter_Type, &PyType_Type);

Py_INCREF((PyObject *)Arraytype);
if (PyModule_AddObject(m, "ArrayType", (PyObject *)Arraytype) < 0) {
Py_DECREF((PyObject *)Arraytype);
Py_INCREF((PyObject *)state->Arraytype);
if (PyModule_AddObject(m, "ArrayType", (PyObject *)state->Arraytype) < 0) {
Py_DECREF((PyObject *)state->Arraytype);
return -1;
}

PyObject *abc_mod = PyImport_ImportModule("collections.abc");
if (!abc_mod) {
Py_DECREF((PyObject *)Arraytype);
Py_DECREF((PyObject *)state->Arraytype);
return -1;
}
PyObject *mutablesequence = PyObject_GetAttrString(abc_mod, "MutableSequence");
Py_DECREF(abc_mod);
if (!mutablesequence) {
Py_DECREF((PyObject *)Arraytype);
Py_DECREF((PyObject *)state->Arraytype);
return -1;
}
PyObject *res = PyObject_CallMethod(mutablesequence, "register", "O", (PyObject *)Arraytype);
PyObject *res = PyObject_CallMethod(mutablesequence, "register", "O",
(PyObject *)state->Arraytype);
Py_DECREF(mutablesequence);
if (!res) {
Py_DECREF((PyObject *)Arraytype);
Py_DECREF((PyObject *)state->Arraytype);
return -1;
}
Py_DECREF(res);

Py_INCREF((PyObject *)Arraytype);
if (PyModule_AddObject(m, "array", (PyObject *)Arraytype) < 0) {
Py_DECREF((PyObject *)Arraytype);
Py_INCREF((PyObject *)state->Arraytype);
if (PyModule_AddObject(m, "array", (PyObject *)state->Arraytype) < 0) {
Py_DECREF((PyObject *)state->Arraytype);
return -1;
}

Expand Down