summaryrefslogtreecommitdiff
path: root/Objects/tupleobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/tupleobject.c')
-rw-r--r--Objects/tupleobject.c75
1 files changed, 57 insertions, 18 deletions
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index 9e914cb634..f81559504f 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;
@@ -856,8 +866,7 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)
_Py_ForgetReference((PyObject *) v);
/* DECREF items deleted by shrinkage */
for (i = newsize; i < oldsize; i++) {
- Py_XDECREF(v->ob_item[i]);
- v->ob_item[i] = NULL;
+ Py_CLEAR(v->ob_item[i]);
}
sv = PyObject_GC_Resize(PyTupleObject, v, newsize);
if (sv == NULL) {
@@ -903,8 +912,7 @@ PyTuple_Fini(void)
#if PyTuple_MAXSAVESIZE > 0
/* empty tuples are used all over the place and applications may
* rely on the fact that an empty tuple is a singleton. */
- Py_XDECREF(free_list[0]);
- free_list[0] = NULL;
+ Py_CLEAR(free_list[0]);
(void)PyTuple_ClearFreeList();
#endif
@@ -971,8 +979,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 (index > PyTuple_GET_SIZE(it->it_seq))
+ index = PyTuple_GET_SIZE(it->it_seq); /* exhausted iterator */
+ 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 */
};