summaryrefslogtreecommitdiffstats
path: root/Objects/tupleobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/tupleobject.c')
-rw-r--r--Objects/tupleobject.c74
1 files changed, 58 insertions, 16 deletions
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index b345460..9c843fa 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;
@@ -315,11 +327,12 @@ error:
static Py_hash_t
tuplehash(PyTupleObject *v)
{
- register Py_hash_t x, y;
+ register Py_uhash_t x;
+ register Py_hash_t y;
register Py_ssize_t len = Py_SIZE(v);
register PyObject **p;
- Py_hash_t mult = _PyHASH_MULTIPLIER;
- x = 0x345678L;
+ Py_uhash_t mult = _PyHASH_MULTIPLIER;
+ x = 0x345678;
p = v->ob_item;
while (--len >= 0) {
y = PyObject_Hash(*p++);
@@ -330,7 +343,7 @@ tuplehash(PyTupleObject *v)
mult += (Py_hash_t)(82520L + len + len);
}
x += 97531L;
- if (x == -1)
+ if (x == (Py_uhash_t)-1)
x = -2;
return x;
}
@@ -464,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;
@@ -546,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;
@@ -970,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 */
};