+++ /dev/null
-\r
-/* Tuple object implementation */\r
-\r
-#include "Python.h"\r
-\r
-/* Speed optimization to avoid frequent malloc/free of small tuples */\r
-#ifndef PyTuple_MAXSAVESIZE\r
-#define PyTuple_MAXSAVESIZE 20 /* Largest tuple to save on free list */\r
-#endif\r
-#ifndef PyTuple_MAXFREELIST\r
-#define PyTuple_MAXFREELIST 2000 /* Maximum number of tuples of each size to save */\r
-#endif\r
-\r
-#if PyTuple_MAXSAVESIZE > 0\r
-/* Entries 1 up to PyTuple_MAXSAVESIZE are free lists, entry 0 is the empty\r
- tuple () of which at most one instance will be allocated.\r
-*/\r
-static PyTupleObject *free_list[PyTuple_MAXSAVESIZE];\r
-static int numfree[PyTuple_MAXSAVESIZE];\r
-#endif\r
-#ifdef COUNT_ALLOCS\r
-Py_ssize_t fast_tuple_allocs;\r
-Py_ssize_t tuple_zero_allocs;\r
-#endif\r
-\r
-/* Debug statistic to count GC tracking of tuples.\r
- Please note that tuples are only untracked when considered by the GC, and\r
- many of them will be dead before. Therefore, a tracking rate close to 100%\r
- does not necessarily prove that the heuristic is inefficient.\r
-*/\r
-#ifdef SHOW_TRACK_COUNT\r
-static Py_ssize_t count_untracked = 0;\r
-static Py_ssize_t count_tracked = 0;\r
-\r
-static void\r
-show_track(void)\r
-{\r
- fprintf(stderr, "Tuples created: %" PY_FORMAT_SIZE_T "d\n",\r
- count_tracked + count_untracked);\r
- fprintf(stderr, "Tuples tracked by the GC: %" PY_FORMAT_SIZE_T\r
- "d\n", count_tracked);\r
- fprintf(stderr, "%.2f%% tuple tracking rate\n\n",\r
- (100.0*count_tracked/(count_untracked+count_tracked)));\r
-}\r
-#endif\r
-\r
-\r
-PyObject *\r
-PyTuple_New(register Py_ssize_t size)\r
-{\r
- register PyTupleObject *op;\r
- Py_ssize_t i;\r
- if (size < 0) {\r
- PyErr_BadInternalCall();\r
- return NULL;\r
- }\r
-#if PyTuple_MAXSAVESIZE > 0\r
- if (size == 0 && free_list[0]) {\r
- op = free_list[0];\r
- Py_INCREF(op);\r
-#ifdef COUNT_ALLOCS\r
- tuple_zero_allocs++;\r
-#endif\r
- return (PyObject *) op;\r
- }\r
- if (size < PyTuple_MAXSAVESIZE && (op = free_list[size]) != NULL) {\r
- free_list[size] = (PyTupleObject *) op->ob_item[0];\r
- numfree[size]--;\r
-#ifdef COUNT_ALLOCS\r
- fast_tuple_allocs++;\r
-#endif\r
- /* Inline PyObject_InitVar */\r
-#ifdef Py_TRACE_REFS\r
- Py_SIZE(op) = size;\r
- Py_TYPE(op) = &PyTuple_Type;\r
-#endif\r
- _Py_NewReference((PyObject *)op);\r
- }\r
- else\r
-#endif\r
- {\r
- Py_ssize_t nbytes = size * sizeof(PyObject *);\r
- /* Check for overflow */\r
- if (nbytes / sizeof(PyObject *) != (size_t)size ||\r
- (nbytes > PY_SSIZE_T_MAX - sizeof(PyTupleObject) - sizeof(PyObject *)))\r
- {\r
- return PyErr_NoMemory();\r
- }\r
-\r
- op = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size);\r
- if (op == NULL)\r
- return NULL;\r
- }\r
- for (i=0; i < size; i++)\r
- op->ob_item[i] = NULL;\r
-#if PyTuple_MAXSAVESIZE > 0\r
- if (size == 0) {\r
- free_list[0] = op;\r
- ++numfree[0];\r
- Py_INCREF(op); /* extra INCREF so that this is never freed */\r
- }\r
-#endif\r
-#ifdef SHOW_TRACK_COUNT\r
- count_tracked++;\r
-#endif\r
- _PyObject_GC_TRACK(op);\r
- return (PyObject *) op;\r
-}\r
-\r
-Py_ssize_t\r
-PyTuple_Size(register PyObject *op)\r
-{\r
- if (!PyTuple_Check(op)) {\r
- PyErr_BadInternalCall();\r
- return -1;\r
- }\r
- else\r
- return Py_SIZE(op);\r
-}\r
-\r
-PyObject *\r
-PyTuple_GetItem(register PyObject *op, register Py_ssize_t i)\r
-{\r
- if (!PyTuple_Check(op)) {\r
- PyErr_BadInternalCall();\r
- return NULL;\r
- }\r
- if (i < 0 || i >= Py_SIZE(op)) {\r
- PyErr_SetString(PyExc_IndexError, "tuple index out of range");\r
- return NULL;\r
- }\r
- return ((PyTupleObject *)op) -> ob_item[i];\r
-}\r
-\r
-int\r
-PyTuple_SetItem(register PyObject *op, register Py_ssize_t i, PyObject *newitem)\r
-{\r
- register PyObject *olditem;\r
- register PyObject **p;\r
- if (!PyTuple_Check(op) || op->ob_refcnt != 1) {\r
- Py_XDECREF(newitem);\r
- PyErr_BadInternalCall();\r
- return -1;\r
- }\r
- if (i < 0 || i >= Py_SIZE(op)) {\r
- Py_XDECREF(newitem);\r
- PyErr_SetString(PyExc_IndexError,\r
- "tuple assignment index out of range");\r
- return -1;\r
- }\r
- p = ((PyTupleObject *)op) -> ob_item + i;\r
- olditem = *p;\r
- *p = newitem;\r
- Py_XDECREF(olditem);\r
- return 0;\r
-}\r
-\r
-void\r
-_PyTuple_MaybeUntrack(PyObject *op)\r
-{\r
- PyTupleObject *t;\r
- Py_ssize_t i, n;\r
-\r
- if (!PyTuple_CheckExact(op) || !_PyObject_GC_IS_TRACKED(op))\r
- return;\r
- t = (PyTupleObject *) op;\r
- n = Py_SIZE(t);\r
- for (i = 0; i < n; i++) {\r
- PyObject *elt = PyTuple_GET_ITEM(t, i);\r
- /* Tuple with NULL elements aren't\r
- fully constructed, don't untrack\r
- them yet. */\r
- if (!elt ||\r
- _PyObject_GC_MAY_BE_TRACKED(elt))\r
- return;\r
- }\r
-#ifdef SHOW_TRACK_COUNT\r
- count_tracked--;\r
- count_untracked++;\r
-#endif\r
- _PyObject_GC_UNTRACK(op);\r
-}\r
-\r
-PyObject *\r
-PyTuple_Pack(Py_ssize_t n, ...)\r
-{\r
- Py_ssize_t i;\r
- PyObject *o;\r
- PyObject *result;\r
- PyObject **items;\r
- va_list vargs;\r
-\r
- va_start(vargs, n);\r
- result = PyTuple_New(n);\r
- if (result == NULL) {\r
- va_end(vargs);\r
- return NULL;\r
- }\r
- items = ((PyTupleObject *)result)->ob_item;\r
- for (i = 0; i < n; i++) {\r
- o = va_arg(vargs, PyObject *);\r
- Py_INCREF(o);\r
- items[i] = o;\r
- }\r
- va_end(vargs);\r
- return result;\r
-}\r
-\r
-\r
-/* Methods */\r
-\r
-static void\r
-tupledealloc(register PyTupleObject *op)\r
-{\r
- register Py_ssize_t i;\r
- register Py_ssize_t len = Py_SIZE(op);\r
- PyObject_GC_UnTrack(op);\r
- Py_TRASHCAN_SAFE_BEGIN(op)\r
- if (len > 0) {\r
- i = len;\r
- while (--i >= 0)\r
- Py_XDECREF(op->ob_item[i]);\r
-#if PyTuple_MAXSAVESIZE > 0\r
- if (len < PyTuple_MAXSAVESIZE &&\r
- numfree[len] < PyTuple_MAXFREELIST &&\r
- Py_TYPE(op) == &PyTuple_Type)\r
- {\r
- op->ob_item[0] = (PyObject *) free_list[len];\r
- numfree[len]++;\r
- free_list[len] = op;\r
- goto done; /* return */\r
- }\r
-#endif\r
- }\r
- Py_TYPE(op)->tp_free((PyObject *)op);\r
-done:\r
- Py_TRASHCAN_SAFE_END(op)\r
-}\r
-\r
-static int\r
-tupleprint(PyTupleObject *op, FILE *fp, int flags)\r
-{\r
- Py_ssize_t i;\r
- Py_BEGIN_ALLOW_THREADS\r
- fprintf(fp, "(");\r
- Py_END_ALLOW_THREADS\r
- for (i = 0; i < Py_SIZE(op); i++) {\r
- if (i > 0) {\r
- Py_BEGIN_ALLOW_THREADS\r
- fprintf(fp, ", ");\r
- Py_END_ALLOW_THREADS\r
- }\r
- if (PyObject_Print(op->ob_item[i], fp, 0) != 0)\r
- return -1;\r
- }\r
- i = Py_SIZE(op);\r
- Py_BEGIN_ALLOW_THREADS\r
- if (i == 1)\r
- fprintf(fp, ",");\r
- fprintf(fp, ")");\r
- Py_END_ALLOW_THREADS\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-tuplerepr(PyTupleObject *v)\r
-{\r
- Py_ssize_t i, n;\r
- PyObject *s, *temp;\r
- PyObject *pieces, *result = NULL;\r
-\r
- n = Py_SIZE(v);\r
- if (n == 0)\r
- return PyString_FromString("()");\r
-\r
- /* While not mutable, it is still possible to end up with a cycle in a\r
- tuple through an object that stores itself within a tuple (and thus\r
- infinitely asks for the repr of itself). This should only be\r
- possible within a type. */\r
- i = Py_ReprEnter((PyObject *)v);\r
- if (i != 0) {\r
- return i > 0 ? PyString_FromString("(...)") : NULL;\r
- }\r
-\r
- pieces = PyTuple_New(n);\r
- if (pieces == NULL)\r
- return NULL;\r
-\r
- /* Do repr() on each element. */\r
- for (i = 0; i < n; ++i) {\r
- if (Py_EnterRecursiveCall(" while getting the repr of a tuple"))\r
- goto Done;\r
- s = PyObject_Repr(v->ob_item[i]);\r
- Py_LeaveRecursiveCall();\r
- if (s == NULL)\r
- goto Done;\r
- PyTuple_SET_ITEM(pieces, i, s);\r
- }\r
-\r
- /* Add "()" decorations to the first and last items. */\r
- assert(n > 0);\r
- s = PyString_FromString("(");\r
- if (s == NULL)\r
- goto Done;\r
- temp = PyTuple_GET_ITEM(pieces, 0);\r
- PyString_ConcatAndDel(&s, temp);\r
- PyTuple_SET_ITEM(pieces, 0, s);\r
- if (s == NULL)\r
- goto Done;\r
-\r
- s = PyString_FromString(n == 1 ? ",)" : ")");\r
- if (s == NULL)\r
- goto Done;\r
- temp = PyTuple_GET_ITEM(pieces, n-1);\r
- PyString_ConcatAndDel(&temp, s);\r
- PyTuple_SET_ITEM(pieces, n-1, temp);\r
- if (temp == NULL)\r
- goto Done;\r
-\r
- /* Paste them all together with ", " between. */\r
- s = PyString_FromString(", ");\r
- if (s == NULL)\r
- goto Done;\r
- result = _PyString_Join(s, pieces);\r
- Py_DECREF(s);\r
-\r
-Done:\r
- Py_DECREF(pieces);\r
- Py_ReprLeave((PyObject *)v);\r
- return result;\r
-}\r
-\r
-/* The addend 82520, was selected from the range(0, 1000000) for\r
- generating the greatest number of prime multipliers for tuples\r
- upto length eight:\r
-\r
- 1082527, 1165049, 1082531, 1165057, 1247581, 1330103, 1082533,\r
- 1330111, 1412633, 1165069, 1247599, 1495177, 1577699\r
-*/\r
-\r
-static long\r
-tuplehash(PyTupleObject *v)\r
-{\r
- register long x, y;\r
- register Py_ssize_t len = Py_SIZE(v);\r
- register PyObject **p;\r
- long mult = 1000003L;\r
- x = 0x345678L;\r
- p = v->ob_item;\r
- while (--len >= 0) {\r
- y = PyObject_Hash(*p++);\r
- if (y == -1)\r
- return -1;\r
- x = (x ^ y) * mult;\r
- /* the cast might truncate len; that doesn't change hash stability */\r
- mult += (long)(82520L + len + len);\r
- }\r
- x += 97531L;\r
- if (x == -1)\r
- x = -2;\r
- return x;\r
-}\r
-\r
-static Py_ssize_t\r
-tuplelength(PyTupleObject *a)\r
-{\r
- return Py_SIZE(a);\r
-}\r
-\r
-static int\r
-tuplecontains(PyTupleObject *a, PyObject *el)\r
-{\r
- Py_ssize_t i;\r
- int cmp;\r
-\r
- for (i = 0, cmp = 0 ; cmp == 0 && i < Py_SIZE(a); ++i)\r
- cmp = PyObject_RichCompareBool(el, PyTuple_GET_ITEM(a, i),\r
- Py_EQ);\r
- return cmp;\r
-}\r
-\r
-static PyObject *\r
-tupleitem(register PyTupleObject *a, register Py_ssize_t i)\r
-{\r
- if (i < 0 || i >= Py_SIZE(a)) {\r
- PyErr_SetString(PyExc_IndexError, "tuple index out of range");\r
- return NULL;\r
- }\r
- Py_INCREF(a->ob_item[i]);\r
- return a->ob_item[i];\r
-}\r
-\r
-static PyObject *\r
-tupleslice(register PyTupleObject *a, register Py_ssize_t ilow,\r
- register Py_ssize_t ihigh)\r
-{\r
- register PyTupleObject *np;\r
- PyObject **src, **dest;\r
- register Py_ssize_t i;\r
- Py_ssize_t len;\r
- if (ilow < 0)\r
- ilow = 0;\r
- if (ihigh > Py_SIZE(a))\r
- ihigh = Py_SIZE(a);\r
- if (ihigh < ilow)\r
- ihigh = ilow;\r
- if (ilow == 0 && ihigh == Py_SIZE(a) && PyTuple_CheckExact(a)) {\r
- Py_INCREF(a);\r
- return (PyObject *)a;\r
- }\r
- len = ihigh - ilow;\r
- np = (PyTupleObject *)PyTuple_New(len);\r
- if (np == NULL)\r
- return NULL;\r
- src = a->ob_item + ilow;\r
- dest = np->ob_item;\r
- for (i = 0; i < len; i++) {\r
- PyObject *v = src[i];\r
- Py_INCREF(v);\r
- dest[i] = v;\r
- }\r
- return (PyObject *)np;\r
-}\r
-\r
-PyObject *\r
-PyTuple_GetSlice(PyObject *op, Py_ssize_t i, Py_ssize_t j)\r
-{\r
- if (op == NULL || !PyTuple_Check(op)) {\r
- PyErr_BadInternalCall();\r
- return NULL;\r
- }\r
- return tupleslice((PyTupleObject *)op, i, j);\r
-}\r
-\r
-static PyObject *\r
-tupleconcat(register PyTupleObject *a, register PyObject *bb)\r
-{\r
- register Py_ssize_t size;\r
- register Py_ssize_t i;\r
- PyObject **src, **dest;\r
- PyTupleObject *np;\r
- if (!PyTuple_Check(bb)) {\r
- PyErr_Format(PyExc_TypeError,\r
- "can only concatenate tuple (not \"%.200s\") to tuple",\r
- Py_TYPE(bb)->tp_name);\r
- return NULL;\r
- }\r
-#define b ((PyTupleObject *)bb)\r
- size = Py_SIZE(a) + Py_SIZE(b);\r
- if (size < 0)\r
- return PyErr_NoMemory();\r
- np = (PyTupleObject *) PyTuple_New(size);\r
- if (np == NULL) {\r
- return NULL;\r
- }\r
- src = a->ob_item;\r
- dest = np->ob_item;\r
- for (i = 0; i < Py_SIZE(a); i++) {\r
- PyObject *v = src[i];\r
- Py_INCREF(v);\r
- dest[i] = v;\r
- }\r
- src = b->ob_item;\r
- dest = np->ob_item + Py_SIZE(a);\r
- for (i = 0; i < Py_SIZE(b); i++) {\r
- PyObject *v = src[i];\r
- Py_INCREF(v);\r
- dest[i] = v;\r
- }\r
- return (PyObject *)np;\r
-#undef b\r
-}\r
-\r
-static PyObject *\r
-tuplerepeat(PyTupleObject *a, Py_ssize_t n)\r
-{\r
- Py_ssize_t i, j;\r
- Py_ssize_t size;\r
- PyTupleObject *np;\r
- PyObject **p, **items;\r
- if (n < 0)\r
- n = 0;\r
- if (Py_SIZE(a) == 0 || n == 1) {\r
- if (PyTuple_CheckExact(a)) {\r
- /* Since tuples are immutable, we can return a shared\r
- copy in this case */\r
- Py_INCREF(a);\r
- return (PyObject *)a;\r
- }\r
- if (Py_SIZE(a) == 0)\r
- return PyTuple_New(0);\r
- }\r
- size = Py_SIZE(a) * n;\r
- if (size/Py_SIZE(a) != n)\r
- return PyErr_NoMemory();\r
- np = (PyTupleObject *) PyTuple_New(size);\r
- if (np == NULL)\r
- return NULL;\r
- p = np->ob_item;\r
- items = a->ob_item;\r
- for (i = 0; i < n; i++) {\r
- for (j = 0; j < Py_SIZE(a); j++) {\r
- *p = items[j];\r
- Py_INCREF(*p);\r
- p++;\r
- }\r
- }\r
- return (PyObject *) np;\r
-}\r
-\r
-static PyObject *\r
-tupleindex(PyTupleObject *self, PyObject *args)\r
-{\r
- Py_ssize_t i, start=0, stop=Py_SIZE(self);\r
- PyObject *v;\r
-\r
- if (!PyArg_ParseTuple(args, "O|O&O&:index", &v,\r
- _PyEval_SliceIndex, &start,\r
- _PyEval_SliceIndex, &stop))\r
- return NULL;\r
- if (start < 0) {\r
- start += Py_SIZE(self);\r
- if (start < 0)\r
- start = 0;\r
- }\r
- if (stop < 0) {\r
- stop += Py_SIZE(self);\r
- if (stop < 0)\r
- stop = 0;\r
- }\r
- for (i = start; i < stop && i < Py_SIZE(self); i++) {\r
- int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ);\r
- if (cmp > 0)\r
- return PyInt_FromSsize_t(i);\r
- else if (cmp < 0)\r
- return NULL;\r
- }\r
- PyErr_SetString(PyExc_ValueError, "tuple.index(x): x not in tuple");\r
- return NULL;\r
-}\r
-\r
-static PyObject *\r
-tuplecount(PyTupleObject *self, PyObject *v)\r
-{\r
- Py_ssize_t count = 0;\r
- Py_ssize_t i;\r
-\r
- for (i = 0; i < Py_SIZE(self); i++) {\r
- int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ);\r
- if (cmp > 0)\r
- count++;\r
- else if (cmp < 0)\r
- return NULL;\r
- }\r
- return PyInt_FromSsize_t(count);\r
-}\r
-\r
-static int\r
-tupletraverse(PyTupleObject *o, visitproc visit, void *arg)\r
-{\r
- Py_ssize_t i;\r
-\r
- for (i = Py_SIZE(o); --i >= 0; )\r
- Py_VISIT(o->ob_item[i]);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-tuplerichcompare(PyObject *v, PyObject *w, int op)\r
-{\r
- PyTupleObject *vt, *wt;\r
- Py_ssize_t i;\r
- Py_ssize_t vlen, wlen;\r
-\r
- if (!PyTuple_Check(v) || !PyTuple_Check(w)) {\r
- Py_INCREF(Py_NotImplemented);\r
- return Py_NotImplemented;\r
- }\r
-\r
- vt = (PyTupleObject *)v;\r
- wt = (PyTupleObject *)w;\r
-\r
- vlen = Py_SIZE(vt);\r
- wlen = Py_SIZE(wt);\r
-\r
- /* Note: the corresponding code for lists has an "early out" test\r
- * here when op is EQ or NE and the lengths differ. That pays there,\r
- * but Tim was unable to find any real code where EQ/NE tuple\r
- * compares don't have the same length, so testing for it here would\r
- * have cost without benefit.\r
- */\r
-\r
- /* Search for the first index where items are different.\r
- * Note that because tuples are immutable, it's safe to reuse\r
- * vlen and wlen across the comparison calls.\r
- */\r
- for (i = 0; i < vlen && i < wlen; i++) {\r
- int k = PyObject_RichCompareBool(vt->ob_item[i],\r
- wt->ob_item[i], Py_EQ);\r
- if (k < 0)\r
- return NULL;\r
- if (!k)\r
- break;\r
- }\r
-\r
- if (i >= vlen || i >= wlen) {\r
- /* No more items to compare -- compare sizes */\r
- int cmp;\r
- PyObject *res;\r
- switch (op) {\r
- case Py_LT: cmp = vlen < wlen; break;\r
- case Py_LE: cmp = vlen <= wlen; break;\r
- case Py_EQ: cmp = vlen == wlen; break;\r
- case Py_NE: cmp = vlen != wlen; break;\r
- case Py_GT: cmp = vlen > wlen; break;\r
- case Py_GE: cmp = vlen >= wlen; break;\r
- default: return NULL; /* cannot happen */\r
- }\r
- if (cmp)\r
- res = Py_True;\r
- else\r
- res = Py_False;\r
- Py_INCREF(res);\r
- return res;\r
- }\r
-\r
- /* We have an item that differs -- shortcuts for EQ/NE */\r
- if (op == Py_EQ) {\r
- Py_INCREF(Py_False);\r
- return Py_False;\r
- }\r
- if (op == Py_NE) {\r
- Py_INCREF(Py_True);\r
- return Py_True;\r
- }\r
-\r
- /* Compare the final item again using the proper operator */\r
- return PyObject_RichCompare(vt->ob_item[i], wt->ob_item[i], op);\r
-}\r
-\r
-static PyObject *\r
-tuple_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);\r
-\r
-static PyObject *\r
-tuple_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- PyObject *arg = NULL;\r
- static char *kwlist[] = {"sequence", 0};\r
-\r
- if (type != &PyTuple_Type)\r
- return tuple_subtype_new(type, args, kwds);\r
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:tuple", kwlist, &arg))\r
- return NULL;\r
-\r
- if (arg == NULL)\r
- return PyTuple_New(0);\r
- else\r
- return PySequence_Tuple(arg);\r
-}\r
-\r
-static PyObject *\r
-tuple_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- PyObject *tmp, *newobj, *item;\r
- Py_ssize_t i, n;\r
-\r
- assert(PyType_IsSubtype(type, &PyTuple_Type));\r
- tmp = tuple_new(&PyTuple_Type, args, kwds);\r
- if (tmp == NULL)\r
- return NULL;\r
- assert(PyTuple_Check(tmp));\r
- newobj = type->tp_alloc(type, n = PyTuple_GET_SIZE(tmp));\r
- if (newobj == NULL)\r
- return NULL;\r
- for (i = 0; i < n; i++) {\r
- item = PyTuple_GET_ITEM(tmp, i);\r
- Py_INCREF(item);\r
- PyTuple_SET_ITEM(newobj, i, item);\r
- }\r
- Py_DECREF(tmp);\r
- return newobj;\r
-}\r
-\r
-PyDoc_STRVAR(tuple_doc,\r
-"tuple() -> empty tuple\n\\r
-tuple(iterable) -> tuple initialized from iterable's items\n\\r
-\n\\r
-If the argument is a tuple, the return value is the same object.");\r
-\r
-static PySequenceMethods tuple_as_sequence = {\r
- (lenfunc)tuplelength, /* sq_length */\r
- (binaryfunc)tupleconcat, /* sq_concat */\r
- (ssizeargfunc)tuplerepeat, /* sq_repeat */\r
- (ssizeargfunc)tupleitem, /* sq_item */\r
- (ssizessizeargfunc)tupleslice, /* sq_slice */\r
- 0, /* sq_ass_item */\r
- 0, /* sq_ass_slice */\r
- (objobjproc)tuplecontains, /* sq_contains */\r
-};\r
-\r
-static PyObject*\r
-tuplesubscript(PyTupleObject* self, PyObject* item)\r
-{\r
- if (PyIndex_Check(item)) {\r
- Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);\r
- if (i == -1 && PyErr_Occurred())\r
- return NULL;\r
- if (i < 0)\r
- i += PyTuple_GET_SIZE(self);\r
- return tupleitem(self, i);\r
- }\r
- else if (PySlice_Check(item)) {\r
- Py_ssize_t start, stop, step, slicelength, cur, i;\r
- PyObject* result;\r
- PyObject* it;\r
- PyObject **src, **dest;\r
-\r
- if (PySlice_GetIndicesEx((PySliceObject*)item,\r
- PyTuple_GET_SIZE(self),\r
- &start, &stop, &step, &slicelength) < 0) {\r
- return NULL;\r
- }\r
-\r
- if (slicelength <= 0) {\r
- return PyTuple_New(0);\r
- }\r
- else if (start == 0 && step == 1 &&\r
- slicelength == PyTuple_GET_SIZE(self) &&\r
- PyTuple_CheckExact(self)) {\r
- Py_INCREF(self);\r
- return (PyObject *)self;\r
- }\r
- else {\r
- result = PyTuple_New(slicelength);\r
- if (!result) return NULL;\r
-\r
- src = self->ob_item;\r
- dest = ((PyTupleObject *)result)->ob_item;\r
- for (cur = start, i = 0; i < slicelength;\r
- cur += step, i++) {\r
- it = src[cur];\r
- Py_INCREF(it);\r
- dest[i] = it;\r
- }\r
-\r
- return result;\r
- }\r
- }\r
- else {\r
- PyErr_Format(PyExc_TypeError,\r
- "tuple indices must be integers, not %.200s",\r
- Py_TYPE(item)->tp_name);\r
- return NULL;\r
- }\r
-}\r
-\r
-static PyObject *\r
-tuple_getnewargs(PyTupleObject *v)\r
-{\r
- return Py_BuildValue("(N)", tupleslice(v, 0, Py_SIZE(v)));\r
-\r
-}\r
-\r
-PyDoc_STRVAR(index_doc,\r
-"T.index(value, [start, [stop]]) -> integer -- return first index of value.\n"\r
-"Raises ValueError if the value is not present."\r
-);\r
-PyDoc_STRVAR(count_doc,\r
-"T.count(value) -> integer -- return number of occurrences of value");\r
-\r
-static PyMethodDef tuple_methods[] = {\r
- {"__getnewargs__", (PyCFunction)tuple_getnewargs, METH_NOARGS},\r
- {"index", (PyCFunction)tupleindex, METH_VARARGS, index_doc},\r
- {"count", (PyCFunction)tuplecount, METH_O, count_doc},\r
- {NULL, NULL} /* sentinel */\r
-};\r
-\r
-static PyMappingMethods tuple_as_mapping = {\r
- (lenfunc)tuplelength,\r
- (binaryfunc)tuplesubscript,\r
- 0\r
-};\r
-\r
-static PyObject *tuple_iter(PyObject *seq);\r
-\r
-PyTypeObject PyTuple_Type = {\r
- PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
- "tuple",\r
- sizeof(PyTupleObject) - sizeof(PyObject *),\r
- sizeof(PyObject *),\r
- (destructor)tupledealloc, /* tp_dealloc */\r
- (printfunc)tupleprint, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- (reprfunc)tuplerepr, /* tp_repr */\r
- 0, /* tp_as_number */\r
- &tuple_as_sequence, /* tp_as_sequence */\r
- &tuple_as_mapping, /* tp_as_mapping */\r
- (hashfunc)tuplehash, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TUPLE_SUBCLASS, /* tp_flags */\r
- tuple_doc, /* tp_doc */\r
- (traverseproc)tupletraverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- tuplerichcompare, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- tuple_iter, /* tp_iter */\r
- 0, /* tp_iternext */\r
- tuple_methods, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- tuple_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-/* The following function breaks the notion that tuples are immutable:\r
- it changes the size of a tuple. We get away with this only if there\r
- is only one module referencing the object. You can also think of it\r
- as creating a new tuple object and destroying the old one, only more\r
- efficiently. In any case, don't use this if the tuple may already be\r
- known to some other part of the code. */\r
-\r
-int\r
-_PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)\r
-{\r
- register PyTupleObject *v;\r
- register PyTupleObject *sv;\r
- Py_ssize_t i;\r
- Py_ssize_t oldsize;\r
-\r
- v = (PyTupleObject *) *pv;\r
- if (v == NULL || Py_TYPE(v) != &PyTuple_Type ||\r
- (Py_SIZE(v) != 0 && Py_REFCNT(v) != 1)) {\r
- *pv = 0;\r
- Py_XDECREF(v);\r
- PyErr_BadInternalCall();\r
- return -1;\r
- }\r
- oldsize = Py_SIZE(v);\r
- if (oldsize == newsize)\r
- return 0;\r
-\r
- if (oldsize == 0) {\r
- /* Empty tuples are often shared, so we should never\r
- resize them in-place even if we do own the only\r
- (current) reference */\r
- Py_DECREF(v);\r
- *pv = PyTuple_New(newsize);\r
- return *pv == NULL ? -1 : 0;\r
- }\r
-\r
- /* XXX UNREF/NEWREF interface should be more symmetrical */\r
- _Py_DEC_REFTOTAL;\r
- if (_PyObject_GC_IS_TRACKED(v))\r
- _PyObject_GC_UNTRACK(v);\r
- _Py_ForgetReference((PyObject *) v);\r
- /* DECREF items deleted by shrinkage */\r
- for (i = newsize; i < oldsize; i++) {\r
- Py_CLEAR(v->ob_item[i]);\r
- }\r
- sv = PyObject_GC_Resize(PyTupleObject, v, newsize);\r
- if (sv == NULL) {\r
- *pv = NULL;\r
- PyObject_GC_Del(v);\r
- return -1;\r
- }\r
- _Py_NewReference((PyObject *) sv);\r
- /* Zero out items added by growing */\r
- if (newsize > oldsize)\r
- memset(&sv->ob_item[oldsize], 0,\r
- sizeof(*sv->ob_item) * (newsize - oldsize));\r
- *pv = (PyObject *) sv;\r
- _PyObject_GC_TRACK(sv);\r
- return 0;\r
-}\r
-\r
-int\r
-PyTuple_ClearFreeList(void)\r
-{\r
- int freelist_size = 0;\r
-#if PyTuple_MAXSAVESIZE > 0\r
- int i;\r
- for (i = 1; i < PyTuple_MAXSAVESIZE; i++) {\r
- PyTupleObject *p, *q;\r
- p = free_list[i];\r
- freelist_size += numfree[i];\r
- free_list[i] = NULL;\r
- numfree[i] = 0;\r
- while (p) {\r
- q = p;\r
- p = (PyTupleObject *)(p->ob_item[0]);\r
- PyObject_GC_Del(q);\r
- }\r
- }\r
-#endif\r
- return freelist_size;\r
-}\r
-\r
-void\r
-PyTuple_Fini(void)\r
-{\r
-#if PyTuple_MAXSAVESIZE > 0\r
- /* empty tuples are used all over the place and applications may\r
- * rely on the fact that an empty tuple is a singleton. */\r
- Py_CLEAR(free_list[0]);\r
-\r
- (void)PyTuple_ClearFreeList();\r
-#endif\r
-#ifdef SHOW_TRACK_COUNT\r
- show_track();\r
-#endif\r
-}\r
-\r
-/*********************** Tuple Iterator **************************/\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- long it_index;\r
- PyTupleObject *it_seq; /* Set to NULL when iterator is exhausted */\r
-} tupleiterobject;\r
-\r
-static void\r
-tupleiter_dealloc(tupleiterobject *it)\r
-{\r
- _PyObject_GC_UNTRACK(it);\r
- Py_XDECREF(it->it_seq);\r
- PyObject_GC_Del(it);\r
-}\r
-\r
-static int\r
-tupleiter_traverse(tupleiterobject *it, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(it->it_seq);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-tupleiter_next(tupleiterobject *it)\r
-{\r
- PyTupleObject *seq;\r
- PyObject *item;\r
-\r
- assert(it != NULL);\r
- seq = it->it_seq;\r
- if (seq == NULL)\r
- return NULL;\r
- assert(PyTuple_Check(seq));\r
-\r
- if (it->it_index < PyTuple_GET_SIZE(seq)) {\r
- item = PyTuple_GET_ITEM(seq, it->it_index);\r
- ++it->it_index;\r
- Py_INCREF(item);\r
- return item;\r
- }\r
-\r
- Py_DECREF(seq);\r
- it->it_seq = NULL;\r
- return NULL;\r
-}\r
-\r
-static PyObject *\r
-tupleiter_len(tupleiterobject *it)\r
-{\r
- Py_ssize_t len = 0;\r
- if (it->it_seq)\r
- len = PyTuple_GET_SIZE(it->it_seq) - it->it_index;\r
- return PyInt_FromSsize_t(len);\r
-}\r
-\r
-PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");\r
-\r
-static PyMethodDef tupleiter_methods[] = {\r
- {"__length_hint__", (PyCFunction)tupleiter_len, METH_NOARGS, length_hint_doc},\r
- {NULL, NULL} /* sentinel */\r
-};\r
-\r
-PyTypeObject PyTupleIter_Type = {\r
- PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
- "tupleiterator", /* tp_name */\r
- sizeof(tupleiterobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)tupleiter_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */\r
- 0, /* tp_doc */\r
- (traverseproc)tupleiter_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)tupleiter_next, /* tp_iternext */\r
- tupleiter_methods, /* tp_methods */\r
- 0,\r
-};\r
-\r
-static PyObject *\r
-tuple_iter(PyObject *seq)\r
-{\r
- tupleiterobject *it;\r
-\r
- if (!PyTuple_Check(seq)) {\r
- PyErr_BadInternalCall();\r
- return NULL;\r
- }\r
- it = PyObject_GC_New(tupleiterobject, &PyTupleIter_Type);\r
- if (it == NULL)\r
- return NULL;\r
- it->it_index = 0;\r
- Py_INCREF(seq);\r
- it->it_seq = (PyTupleObject *)seq;\r
- _PyObject_GC_TRACK(it);\r
- return (PyObject *)it;\r
-}\r