diff options
Diffstat (limited to 'Modules/arraymodule.c')
-rw-r--r-- | Modules/arraymodule.c | 198 |
1 files changed, 158 insertions, 40 deletions
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 475acb4..710761e 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -22,7 +22,7 @@ struct arrayobject; /* Forward */ * functions aren't visible yet. */ struct arraydescr { - Py_UNICODE typecode; + char typecode; int itemsize; PyObject * (*getitem)(struct arrayobject *, Py_ssize_t); int (*setitem)(struct arrayobject *, Py_ssize_t, PyObject *); @@ -356,6 +356,59 @@ LL_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) return 0; } +#ifdef HAVE_LONG_LONG + +static PyObject * +q_getitem(arrayobject *ap, Py_ssize_t i) +{ + return PyLong_FromLongLong(((PY_LONG_LONG *)ap->ob_item)[i]); +} + +static int +q_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) +{ + PY_LONG_LONG x; + if (!PyArg_Parse(v, "L;array item must be integer", &x)) + return -1; + if (i >= 0) + ((PY_LONG_LONG *)ap->ob_item)[i] = x; + return 0; +} + +static PyObject * +QQ_getitem(arrayobject *ap, Py_ssize_t i) +{ + return PyLong_FromUnsignedLongLong( + ((unsigned PY_LONG_LONG *)ap->ob_item)[i]); +} + +static int +QQ_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) +{ + unsigned PY_LONG_LONG x; + if (PyLong_Check(v)) { + x = PyLong_AsUnsignedLongLong(v); + if (x == (unsigned PY_LONG_LONG) -1 && PyErr_Occurred()) + return -1; + } + else { + PY_LONG_LONG y; + if (!PyArg_Parse(v, "L;array item must be integer", &y)) + return -1; + if (y < 0) { + PyErr_SetString(PyExc_OverflowError, + "unsigned long long is less than minimum"); + return -1; + } + x = (unsigned PY_LONG_LONG)y; + } + + if (i >= 0) + ((unsigned PY_LONG_LONG *)ap->ob_item)[i] = x; + return 0; +} +#endif + static PyObject * f_getitem(arrayobject *ap, Py_ssize_t i) { @@ -406,6 +459,10 @@ static struct arraydescr descriptors[] = { {'I', sizeof(int), II_getitem, II_setitem, "I", 1, 0}, {'l', sizeof(long), l_getitem, l_setitem, "l", 1, 1}, {'L', sizeof(long), LL_getitem, LL_setitem, "L", 1, 0}, +#ifdef HAVE_LONG_LONG + {'q', sizeof(PY_LONG_LONG), q_getitem, q_setitem, "q", 1, 1}, + {'Q', sizeof(PY_LONG_LONG), QQ_getitem, QQ_setitem, "Q", 1, 0}, +#endif {'f', sizeof(float), f_getitem, f_setitem, "f", 0, 0}, {'d', sizeof(double), d_getitem, d_setitem, "d", 0, 0}, {'\0', 0, 0, 0, 0, 0, 0} /* Sentinel */ @@ -426,11 +483,11 @@ newarrayobject(PyTypeObject *type, Py_ssize_t size, struct arraydescr *descr) return NULL; } - nbytes = size * descr->itemsize; /* Check for overflow */ - if (nbytes / descr->itemsize != (size_t)size) { + if (size > PY_SSIZE_T_MAX / descr->itemsize) { return PyErr_NoMemory(); } + nbytes = size * descr->itemsize; op = (arrayobject *) type->tp_alloc(type, 0); if (op == NULL) { return NULL; @@ -514,10 +571,8 @@ array_richcompare(PyObject *v, PyObject *w, int op) Py_ssize_t i, k; PyObject *res; - if (!array_Check(v) || !array_Check(w)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } + if (!array_Check(v) || !array_Check(w)) + Py_RETURN_NOTIMPLEMENTED; va = (arrayobject *)v; wa = (arrayobject *)w; @@ -876,7 +931,6 @@ array_inplace_repeat(arrayobject *self, Py_ssize_t n) if (Py_SIZE(self) > 0) { if (n < 0) n = 0; - items = self->ob_item; if ((self->ob_descr->itemsize != 0) && (Py_SIZE(self) > PY_SSIZE_T_MAX / self->ob_descr->itemsize)) { return PyErr_NoMemory(); @@ -1191,18 +1245,23 @@ array_fromfile(arrayobject *self, PyObject *args) PyObject *f, *b, *res; Py_ssize_t itemsize = self->ob_descr->itemsize; Py_ssize_t n, nbytes; + _Py_IDENTIFIER(read); int not_enough_bytes; if (!PyArg_ParseTuple(args, "On:fromfile", &f, &n)) return NULL; - nbytes = n * itemsize; - if (nbytes < 0 || nbytes/itemsize != n) { + if (n < 0) { + PyErr_SetString(PyExc_ValueError, "negative count"); + return NULL; + } + if (n > PY_SSIZE_T_MAX / itemsize) { PyErr_NoMemory(); return NULL; } + nbytes = n * itemsize; - b = PyObject_CallMethod(f, "read", "n", nbytes); + b = _PyObject_CallMethodId(f, &PyId_read, "n", nbytes); if (b == NULL) return NULL; @@ -1259,12 +1318,14 @@ array_tofile(arrayobject *self, PyObject *f) char* ptr = self->ob_item + i*BLOCKSIZE; Py_ssize_t size = BLOCKSIZE; PyObject *bytes, *res; + _Py_IDENTIFIER(write); + if (i*BLOCKSIZE + size > nbytes) size = nbytes - i*BLOCKSIZE; bytes = PyBytes_FromStringAndSize(ptr, size); if (bytes == NULL) return NULL; - res = PyObject_CallMethod(f, "write", "O", bytes); + res = _PyObject_CallMethodId(f, &PyId_write, "O", bytes); Py_DECREF(bytes); if (res == NULL) return NULL; @@ -1456,7 +1517,7 @@ array_fromunicode(arrayobject *self, PyObject *args) { Py_UNICODE *ustr; Py_ssize_t n; - Py_UNICODE typecode; + char typecode; if (!PyArg_ParseTuple(args, "u#:fromunicode", &ustr, &n)) return NULL; @@ -1491,7 +1552,7 @@ append Unicode data to an array of some other type."); static PyObject * array_tounicode(arrayobject *self, PyObject *unused) { - Py_UNICODE typecode; + char typecode; typecode = self->ob_descr->typecode; if (typecode != 'u') { PyErr_SetString(PyExc_ValueError, @@ -1601,7 +1662,7 @@ static const struct mformatdescr { * be found. */ static enum machine_format_code -typecode_to_mformat_code(int typecode) +typecode_to_mformat_code(char typecode) { #ifdef WORDS_BIGENDIAN const int is_big_endian = 1; @@ -1671,6 +1732,16 @@ typecode_to_mformat_code(int typecode) intsize = sizeof(long); is_signed = 0; break; +#if HAVE_LONG_LONG + case 'q': + intsize = sizeof(PY_LONG_LONG); + is_signed = 1; + break; + case 'Q': + intsize = sizeof(PY_LONG_LONG); + is_signed = 0; + break; +#endif default: return UNKNOWN_FORMAT; } @@ -1701,7 +1772,7 @@ static PyObject *array_new(PyTypeObject *type, PyObject *args, PyObject *kwds); * NULL is returned to indicate a failure. */ static PyObject * -make_array(PyTypeObject *arraytype, Py_UNICODE typecode, PyObject *items) +make_array(PyTypeObject *arraytype, char typecode, PyObject *items) { PyObject *new_args; PyObject *array_obj; @@ -1710,7 +1781,7 @@ make_array(PyTypeObject *arraytype, Py_UNICODE typecode, PyObject *items) assert(arraytype != NULL); assert(items != NULL); - typecode_obj = PyUnicode_FromUnicode(&typecode, 1); + typecode_obj = PyUnicode_FromOrdinal(typecode); if (typecode_obj == NULL) return NULL; @@ -1740,17 +1811,14 @@ array_reconstructor(PyObject *self, PyObject *args) PyObject *items; PyObject *converted_items; PyObject *result; - int typecode_int; - Py_UNICODE typecode; + int typecode; enum machine_format_code mformat_code; struct arraydescr *descr; if (!PyArg_ParseTuple(args, "OCiO:array._array_reconstructor", - &arraytype, &typecode_int, &mformat_code, &items)) + &arraytype, &typecode, &mformat_code, &items)) return NULL; - typecode = (Py_UNICODE)typecode_int; - if (!PyType_Check(arraytype)) { PyErr_Format(PyExc_TypeError, "first argument must a type object, not %.200s", @@ -1764,7 +1832,7 @@ array_reconstructor(PyObject *self, PyObject *args) return NULL; } for (descr = descriptors; descr->typecode != '\0'; descr++) { - if (descr->typecode == typecode) + if ((int)descr->typecode == typecode) break; } if (descr->typecode == '\0') { @@ -1786,9 +1854,9 @@ array_reconstructor(PyObject *self, PyObject *args) } /* Fast path: No decoding has to be done. */ - if (mformat_code == typecode_to_mformat_code(typecode) || + if (mformat_code == typecode_to_mformat_code((char)typecode) || mformat_code == UNKNOWN_FORMAT) { - return make_array(arraytype, typecode, items); + return make_array(arraytype, (char)typecode, items); } /* Slow path: Decode the byte string according to the given machine @@ -1934,7 +2002,7 @@ array_reconstructor(PyObject *self, PyObject *args) return NULL; } - result = make_array(arraytype, typecode, converted_items); + result = make_array(arraytype, (char)typecode, converted_items); Py_DECREF(converted_items); return result; } @@ -1949,14 +2017,16 @@ array_reduce_ex(arrayobject *array, PyObject *value) int mformat_code; static PyObject *array_reconstructor = NULL; long protocol; + _Py_IDENTIFIER(_array_reconstructor); + _Py_IDENTIFIER(__dict__); if (array_reconstructor == NULL) { PyObject *array_module = PyImport_ImportModule("array"); if (array_module == NULL) return NULL; - array_reconstructor = PyObject_GetAttrString( + array_reconstructor = _PyObject_GetAttrId( array_module, - "_array_reconstructor"); + &PyId__array_reconstructor); Py_DECREF(array_module); if (array_reconstructor == NULL) return NULL; @@ -1971,7 +2041,7 @@ array_reduce_ex(arrayobject *array, PyObject *value) if (protocol == -1 && PyErr_Occurred()) return NULL; - dict = PyObject_GetAttrString((PyObject *)array, "__dict__"); + dict = _PyObject_GetAttrId((PyObject *)array, &PyId___dict__); if (dict == NULL) { if (!PyErr_ExceptionMatches(PyExc_AttributeError)) return NULL; @@ -2023,8 +2093,8 @@ PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); static PyObject * array_get_typecode(arrayobject *a, void *closure) { - Py_UNICODE tc = a->ob_descr->typecode; - return PyUnicode_FromUnicode(&tc, 1); + char typecode = a->ob_descr->typecode; + return PyUnicode_FromOrdinal(typecode); } static PyObject * @@ -2098,7 +2168,7 @@ static PyMethodDef array_methods[] = { static PyObject * array_repr(arrayobject *a) { - Py_UNICODE typecode; + char typecode; PyObject *s, *v = NULL; Py_ssize_t len; @@ -2303,7 +2373,7 @@ array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value) self->ob_item + (cur + 1) * itemsize, lim * itemsize); } - cur = start + slicelength * step; + cur = start + (size_t)slicelength * step; if (cur < (size_t)Py_SIZE(self)) { memmove(self->ob_item + (cur-slicelength) * itemsize, self->ob_item + cur * itemsize, @@ -2487,7 +2557,17 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) Py_DECREF(v); } else if (initial != NULL && PyUnicode_Check(initial)) { - Py_ssize_t n = PyUnicode_GET_DATA_SIZE(initial); + Py_UNICODE *ustr; + Py_ssize_t n; + + ustr = PyUnicode_AsUnicode(initial); + if (ustr == NULL) { + PyErr_NoMemory(); + Py_DECREF(a); + return NULL; + } + + n = PyUnicode_GET_DATA_SIZE(initial); if (n > 0) { arrayobject *self = (arrayobject *)a; char *item = self->ob_item; @@ -2499,7 +2579,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } self->ob_item = item; Py_SIZE(self) = n / sizeof(Py_UNICODE); - memcpy(item, PyUnicode_AS_DATA(initial), n); + memcpy(item, ustr, n); self->allocated = Py_SIZE(self); } } @@ -2520,7 +2600,11 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } } PyErr_SetString(PyExc_ValueError, +#ifdef HAVE_LONG_LONG + "bad typecode (must be b, B, u, h, H, i, I, l, L, q, Q, f or d)"); +#else "bad typecode (must be b, B, u, h, H, i, I, l, L, f or d)"); +#endif return NULL; } @@ -2543,12 +2627,18 @@ is a single character. The following type codes are defined:\n\ 'I' unsigned integer 2 \n\ 'l' signed integer 4 \n\ 'L' unsigned integer 4 \n\ + 'q' signed integer 8 (see note) \n\ + 'Q' unsigned integer 8 (see note) \n\ 'f' floating point 4 \n\ 'd' floating point 8 \n\ \n\ NOTE: The 'u' typecode corresponds to Python's unicode character. On \n\ narrow builds this is 2-bytes on wide builds this is 4-bytes.\n\ \n\ +NOTE: The 'q' and 'Q' type codes are only available if the platform \n\ +C compiler used to build Python supports 'long long', or, on Windows, \n\ +'__int64'.\n\ +\n\ The constructor is:\n\ \n\ array(typecode [, initializer]) -- create a new array\n\ @@ -2693,6 +2783,34 @@ arrayiter_traverse(arrayiterobject *it, visitproc visit, void *arg) return 0; } +static PyObject * +arrayiter_reduce(arrayiterobject *it) +{ + return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"), + it->ao, it->index); +} + +static PyObject * +arrayiter_setstate(arrayiterobject *it, PyObject *state) +{ + Py_ssize_t index = PyLong_AsSsize_t(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (index < 0) + index = 0; + it->index = index; + Py_RETURN_NONE; +} + +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); +static PyMethodDef arrayiter_methods[] = { + {"__reduce__", (PyCFunction)arrayiter_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)arrayiter_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + static PyTypeObject PyArrayIter_Type = { PyVarObject_HEAD_INIT(NULL, 0) "arrayiterator", /* tp_name */ @@ -2722,7 +2840,7 @@ static PyTypeObject PyArrayIter_Type = { 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)arrayiter_next, /* tp_iternext */ - 0, /* tp_methods */ + arrayiter_methods, /* tp_methods */ }; @@ -2752,9 +2870,9 @@ PyMODINIT_FUNC PyInit_array(void) { PyObject *m; + char buffer[Py_ARRAY_LENGTH(descriptors)], *p; PyObject *typecodes; Py_ssize_t size = 0; - register Py_UNICODE *p; struct arraydescr *descr; if (PyType_Ready(&Arraytype) < 0) @@ -2773,13 +2891,13 @@ PyInit_array(void) size++; } - typecodes = PyUnicode_FromStringAndSize(NULL, size); - p = PyUnicode_AS_UNICODE(typecodes); + p = buffer; for (descr = descriptors; descr->typecode != '\0'; descr++) { *p++ = (char)descr->typecode; } + typecodes = PyUnicode_DecodeASCII(buffer, p - buffer, NULL); - PyModule_AddObject(m, "typecodes", (PyObject *)typecodes); + PyModule_AddObject(m, "typecodes", typecodes); if (PyErr_Occurred()) { Py_DECREF(m); |