diff options
Diffstat (limited to 'Objects/tupleobject.c')
-rw-r--r-- | Objects/tupleobject.c | 69 |
1 files changed, 55 insertions, 14 deletions
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 9e914cb..ec3f91b 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -45,6 +45,22 @@ show_track(void) } #endif +/* Print summary info about the state of the optimized allocator */ +void +_PyTuple_DebugMallocStats(FILE *out) +{ +#if PyTuple_MAXSAVESIZE > 0 + int i; + char buf[128]; + for (i = 1; i < PyTuple_MAXSAVESIZE; i++) { + PyOS_snprintf(buf, sizeof(buf), + "free %d-sized PyTupleObject", i); + _PyDebugAllocatorStats(out, + buf, + numfree[i], _PyObject_VAR_SIZE(&PyTuple_Type, i)); + } +#endif +} PyObject * PyTuple_New(register Py_ssize_t size) @@ -80,15 +96,11 @@ PyTuple_New(register Py_ssize_t size) else #endif { - Py_ssize_t nbytes = size * sizeof(PyObject *); /* Check for overflow */ - if (nbytes / sizeof(PyObject *) != (size_t)size || - (nbytes > PY_SSIZE_T_MAX - sizeof(PyTupleObject) - sizeof(PyObject *))) - { + if (size > (PY_SSIZE_T_MAX - sizeof(PyTupleObject) - + sizeof(PyObject *)) / sizeof(PyObject *)) { return PyErr_NoMemory(); } - nbytes += sizeof(PyTupleObject) - sizeof(PyObject *); - op = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size); if (op == NULL) return NULL; @@ -328,10 +340,10 @@ tuplehash(PyTupleObject *v) return -1; x = (x ^ y) * mult; /* the cast might truncate len; that doesn't change hash stability */ - mult += (Py_uhash_t)(82520UL + len + len); + mult += (Py_hash_t)(82520UL + len + len); } x += 97531UL; - if (x == -1) + if (x == (Py_uhash_t)-1) x = -2; return x; } @@ -465,9 +477,9 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n) if (Py_SIZE(a) == 0) return PyTuple_New(0); } - size = Py_SIZE(a) * n; - if (size/Py_SIZE(a) != n) + if (n > PY_SSIZE_T_MAX / Py_SIZE(a)) return PyErr_NoMemory(); + size = Py_SIZE(a) * n; np = (PyTupleObject *) PyTuple_New(size); if (np == NULL) return NULL; @@ -547,10 +559,8 @@ tuplerichcompare(PyObject *v, PyObject *w, int op) Py_ssize_t i; Py_ssize_t vlen, wlen; - if (!PyTuple_Check(v) || !PyTuple_Check(w)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } + if (!PyTuple_Check(v) || !PyTuple_Check(w)) + Py_RETURN_NOTIMPLEMENTED; vt = (PyTupleObject *)v; wt = (PyTupleObject *)w; @@ -971,8 +981,39 @@ tupleiter_len(tupleiterobject *it) PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject * +tupleiter_reduce(tupleiterobject *it) +{ + if (it->it_seq) + return Py_BuildValue("N(O)l", _PyObject_GetBuiltin("iter"), + it->it_seq, it->it_index); + else + return Py_BuildValue("N(())", _PyObject_GetBuiltin("iter")); +} + +static PyObject * +tupleiter_setstate(tupleiterobject *it, PyObject *state) +{ + long index = PyLong_AsLong(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (it->it_seq != NULL) { + if (index < 0) + index = 0; + else if (it->it_seq != NULL && index > PyTuple_GET_SIZE(it->it_seq)) + index = PyTuple_GET_SIZE(it->it_seq); + it->it_index = index; + } + Py_RETURN_NONE; +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); + static PyMethodDef tupleiter_methods[] = { {"__length_hint__", (PyCFunction)tupleiter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)tupleiter_reduce, METH_NOARGS, reduce_doc}, + {"__setstate__", (PyCFunction)tupleiter_setstate, METH_O, setstate_doc}, {NULL, NULL} /* sentinel */ }; |