History

add hg and python

cinap_lenrek committed 15 years ago

Commit 4bb9e221 parent 987265c3706 files · +1228772 −-233Browse files

Showing the changes to sys/src/cmd/python/Objects/tupleobject.c (1 of 3706 files). Show all

Unified · Split

sys/src/cmd/python/Objects/tupleobject.c+890−0
@@ -0,0 +1,890 @@
1+
2+/* Tuple object implementation */
3+
4+#include "Python.h"
5+
6+/* Speed optimization to avoid frequent malloc/free of small tuples */
7+#ifndef MAXSAVESIZE
8+#define MAXSAVESIZE 20 /* Largest tuple to save on free list */
9+#endif
10+#ifndef MAXSAVEDTUPLES
11+#define MAXSAVEDTUPLES 2000 /* Maximum number of tuples of each size to save */
12+#endif
13+
14+#if MAXSAVESIZE > 0
15+/* Entries 1 up to MAXSAVESIZE are free lists, entry 0 is the empty
16+ tuple () of which at most one instance will be allocated.
17+*/
18+static PyTupleObject *free_tuples[MAXSAVESIZE];
19+static int num_free_tuples[MAXSAVESIZE];
20+#endif
21+#ifdef COUNT_ALLOCS
22+int fast_tuple_allocs;
23+int tuple_zero_allocs;
24+#endif
25+
26+PyObject *
27+PyTuple_New(register Py_ssize_t size)
28+{
29+ register PyTupleObject *op;
30+ Py_ssize_t i;
31+ if (size < 0) {
32+ PyErr_BadInternalCall();
33+ return NULL;
34+ }
35+#if MAXSAVESIZE > 0
36+ if (size == 0 && free_tuples[0]) {
37+ op = free_tuples[0];
38+ Py_INCREF(op);
39+#ifdef COUNT_ALLOCS
40+ tuple_zero_allocs++;
41+#endif
42+ return (PyObject *) op;
43+ }
44+ if (size < MAXSAVESIZE && (op = free_tuples[size]) != NULL) {
45+ free_tuples[size] = (PyTupleObject *) op->ob_item[0];
46+ num_free_tuples[size]--;
47+#ifdef COUNT_ALLOCS
48+ fast_tuple_allocs++;
49+#endif
50+ /* Inline PyObject_InitVar */
51+#ifdef Py_TRACE_REFS
52+ op->ob_size = size;
53+ op->ob_type = &PyTuple_Type;
54+#endif
55+ _Py_NewReference((PyObject *)op);
56+ }
57+ else
58+#endif
59+ {
60+ Py_ssize_t nbytes = size * sizeof(PyObject *);
61+ /* Check for overflow */
62+ if (nbytes / sizeof(PyObject *) != (size_t)size ||
63+ (nbytes += sizeof(PyTupleObject) - sizeof(PyObject *))
64+ <= 0)
65+ {
66+ return PyErr_NoMemory();
67+ }
68+ op = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size);
69+ if (op == NULL)
70+ return NULL;
71+ }
72+ for (i=0; i < size; i++)
73+ op->ob_item[i] = NULL;
74+#if MAXSAVESIZE > 0
75+ if (size == 0) {
76+ free_tuples[0] = op;
77+ ++num_free_tuples[0];
78+ Py_INCREF(op); /* extra INCREF so that this is never freed */
79+ }
80+#endif
81+ _PyObject_GC_TRACK(op);
82+ return (PyObject *) op;
83+}
84+
85+Py_ssize_t
86+PyTuple_Size(register PyObject *op)
87+{
88+ if (!PyTuple_Check(op)) {
89+ PyErr_BadInternalCall();
90+ return -1;
91+ }
92+ else
93+ return ((PyTupleObject *)op)->ob_size;
94+}
95+
96+PyObject *
97+PyTuple_GetItem(register PyObject *op, register Py_ssize_t i)
98+{
99+ if (!PyTuple_Check(op)) {
100+ PyErr_BadInternalCall();
101+ return NULL;
102+ }
103+ if (i < 0 || i >= ((PyTupleObject *)op) -> ob_size) {
104+ PyErr_SetString(PyExc_IndexError, "tuple index out of range");
105+ return NULL;
106+ }
107+ return ((PyTupleObject *)op) -> ob_item[i];
108+}
109+
110+int
111+PyTuple_SetItem(register PyObject *op, register Py_ssize_t i, PyObject *newitem)
112+{
113+ register PyObject *olditem;
114+ register PyObject **p;
115+ if (!PyTuple_Check(op) || op->ob_refcnt != 1) {
116+ Py_XDECREF(newitem);
117+ PyErr_BadInternalCall();
118+ return -1;
119+ }
120+ if (i < 0 || i >= ((PyTupleObject *)op) -> ob_size) {
121+ Py_XDECREF(newitem);
122+ PyErr_SetString(PyExc_IndexError,
123+ "tuple assignment index out of range");
124+ return -1;
125+ }
126+ p = ((PyTupleObject *)op) -> ob_item + i;
127+ olditem = *p;
128+ *p = newitem;
129+ Py_XDECREF(olditem);
130+ return 0;
131+}
132+
133+PyObject *
134+PyTuple_Pack(Py_ssize_t n, ...)
135+{
136+ Py_ssize_t i;
137+ PyObject *o;
138+ PyObject *result;
139+ PyObject **items;
140+ va_list vargs;
141+
142+ va_start(vargs, n);
143+ result = PyTuple_New(n);
144+ if (result == NULL)
145+ return NULL;
146+ items = ((PyTupleObject *)result)->ob_item;
147+ for (i = 0; i < n; i++) {
148+ o = va_arg(vargs, PyObject *);
149+ Py_INCREF(o);
150+ items[i] = o;
151+ }
152+ va_end(vargs);
153+ return result;
154+}
155+
156+
157+/* Methods */
158+
159+static void
160+tupledealloc(register PyTupleObject *op)
161+{
162+ register Py_ssize_t i;
163+ register Py_ssize_t len = op->ob_size;
164+ PyObject_GC_UnTrack(op);
165+ Py_TRASHCAN_SAFE_BEGIN(op)
166+ if (len > 0) {
167+ i = len;
168+ while (--i >= 0)
169+ Py_XDECREF(op->ob_item[i]);
170+#if MAXSAVESIZE > 0
171+ if (len < MAXSAVESIZE &&
172+ num_free_tuples[len] < MAXSAVEDTUPLES &&
173+ op->ob_type == &PyTuple_Type)
174+ {
175+ op->ob_item[0] = (PyObject *) free_tuples[len];
176+ num_free_tuples[len]++;
177+ free_tuples[len] = op;
178+ goto done; /* return */
179+ }
180+#endif
181+ }
182+ op->ob_type->tp_free((PyObject *)op);
183+done:
184+ Py_TRASHCAN_SAFE_END(op)
185+}
186+
187+static int
188+tupleprint(PyTupleObject *op, FILE *fp, int flags)
189+{
190+ Py_ssize_t i;
191+ fprintf(fp, "(");
192+ for (i = 0; i < op->ob_size; i++) {
193+ if (i > 0)
194+ fprintf(fp, ", ");
195+ if (PyObject_Print(op->ob_item[i], fp, 0) != 0)
196+ return -1;
197+ }
198+ if (op->ob_size == 1)
199+ fprintf(fp, ",");
200+ fprintf(fp, ")");
201+ return 0;
202+}
203+
204+static PyObject *
205+tuplerepr(PyTupleObject *v)
206+{
207+ Py_ssize_t i, n;
208+ PyObject *s, *temp;
209+ PyObject *pieces, *result = NULL;
210+
211+ n = v->ob_size;
212+ if (n == 0)
213+ return PyString_FromString("()");
214+
215+ pieces = PyTuple_New(n);
216+ if (pieces == NULL)
217+ return NULL;
218+
219+ /* Do repr() on each element. */
220+ for (i = 0; i < n; ++i) {
221+ s = PyObject_Repr(v->ob_item[i]);
222+ if (s == NULL)
223+ goto Done;
224+ PyTuple_SET_ITEM(pieces, i, s);
225+ }
226+
227+ /* Add "()" decorations to the first and last items. */
228+ assert(n > 0);
229+ s = PyString_FromString("(");
230+ if (s == NULL)
231+ goto Done;
232+ temp = PyTuple_GET_ITEM(pieces, 0);
233+ PyString_ConcatAndDel(&s, temp);
234+ PyTuple_SET_ITEM(pieces, 0, s);
235+ if (s == NULL)
236+ goto Done;
237+
238+ s = PyString_FromString(n == 1 ? ",)" : ")");
239+ if (s == NULL)
240+ goto Done;
241+ temp = PyTuple_GET_ITEM(pieces, n-1);
242+ PyString_ConcatAndDel(&temp, s);
243+ PyTuple_SET_ITEM(pieces, n-1, temp);
244+ if (temp == NULL)
245+ goto Done;
246+
247+ /* Paste them all together with ", " between. */
248+ s = PyString_FromString(", ");
249+ if (s == NULL)
250+ goto Done;
251+ result = _PyString_Join(s, pieces);
252+ Py_DECREF(s);
253+
254+Done:
255+ Py_DECREF(pieces);
256+ return result;
257+}
258+
259+/* The addend 82520, was selected from the range(0, 1000000) for
260+ generating the greatest number of prime multipliers for tuples
261+ upto length eight:
262+
263+ 1082527, 1165049, 1082531, 1165057, 1247581, 1330103, 1082533,
264+ 1330111, 1412633, 1165069, 1247599, 1495177, 1577699
265+*/
266+
267+static long
268+tuplehash(PyTupleObject *v)
269+{
270+ register long x, y;
271+ register Py_ssize_t len = v->ob_size;
272+ register PyObject **p;
273+ long mult = 1000003L;
274+ x = 0x345678L;
275+ p = v->ob_item;
276+ while (--len >= 0) {
277+ y = PyObject_Hash(*p++);
278+ if (y == -1)
279+ return -1;
280+ x = (x ^ y) * mult;
281+ /* the cast might truncate len; that doesn't change hash stability */
282+ mult += (long)(82520L + len + len);
283+ }
284+ x += 97531L;
285+ if (x == -1)
286+ x = -2;
287+ return x;
288+}
289+
290+static Py_ssize_t
291+tuplelength(PyTupleObject *a)
292+{
293+ return a->ob_size;
294+}
295+
296+static int
297+tuplecontains(PyTupleObject *a, PyObject *el)
298+{
299+ Py_ssize_t i;
300+ int cmp;
301+
302+ for (i = 0, cmp = 0 ; cmp == 0 && i < a->ob_size; ++i)
303+ cmp = PyObject_RichCompareBool(el, PyTuple_GET_ITEM(a, i),
304+ Py_EQ);
305+ return cmp;
306+}
307+
308+static PyObject *
309+tupleitem(register PyTupleObject *a, register Py_ssize_t i)
310+{
311+ if (i < 0 || i >= a->ob_size) {
312+ PyErr_SetString(PyExc_IndexError, "tuple index out of range");
313+ return NULL;
314+ }
315+ Py_INCREF(a->ob_item[i]);
316+ return a->ob_item[i];
317+}
318+
319+static PyObject *
320+tupleslice(register PyTupleObject *a, register Py_ssize_t ilow,
321+ register Py_ssize_t ihigh)
322+{
323+ register PyTupleObject *np;
324+ PyObject **src, **dest;
325+ register Py_ssize_t i;
326+ Py_ssize_t len;
327+ if (ilow < 0)
328+ ilow = 0;
329+ if (ihigh > a->ob_size)
330+ ihigh = a->ob_size;
331+ if (ihigh < ilow)
332+ ihigh = ilow;
333+ if (ilow == 0 && ihigh == a->ob_size && PyTuple_CheckExact(a)) {
334+ Py_INCREF(a);
335+ return (PyObject *)a;
336+ }
337+ len = ihigh - ilow;
338+ np = (PyTupleObject *)PyTuple_New(len);
339+ if (np == NULL)
340+ return NULL;
341+ src = a->ob_item + ilow;
342+ dest = np->ob_item;
343+ for (i = 0; i < len; i++) {
344+ PyObject *v = src[i];
345+ Py_INCREF(v);
346+ dest[i] = v;
347+ }
348+ return (PyObject *)np;
349+}
350+
351+PyObject *
352+PyTuple_GetSlice(PyObject *op, Py_ssize_t i, Py_ssize_t j)
353+{
354+ if (op == NULL || !PyTuple_Check(op)) {
355+ PyErr_BadInternalCall();
356+ return NULL;
357+ }
358+ return tupleslice((PyTupleObject *)op, i, j);
359+}
360+
361+static PyObject *
362+tupleconcat(register PyTupleObject *a, register PyObject *bb)
363+{
364+ register Py_ssize_t size;
365+ register Py_ssize_t i;
366+ PyObject **src, **dest;
367+ PyTupleObject *np;
368+ if (!PyTuple_Check(bb)) {
369+ PyErr_Format(PyExc_TypeError,
370+ "can only concatenate tuple (not \"%.200s\") to tuple",
371+ bb->ob_type->tp_name);
372+ return NULL;
373+ }
374+#define b ((PyTupleObject *)bb)
375+ size = a->ob_size + b->ob_size;
376+ if (size < 0)
377+ return PyErr_NoMemory();
378+ np = (PyTupleObject *) PyTuple_New(size);
379+ if (np == NULL) {
380+ return NULL;
381+ }
382+ src = a->ob_item;
383+ dest = np->ob_item;
384+ for (i = 0; i < a->ob_size; i++) {
385+ PyObject *v = src[i];
386+ Py_INCREF(v);
387+ dest[i] = v;
388+ }
389+ src = b->ob_item;
390+ dest = np->ob_item + a->ob_size;
391+ for (i = 0; i < b->ob_size; i++) {
392+ PyObject *v = src[i];
393+ Py_INCREF(v);
394+ dest[i] = v;
395+ }
396+ return (PyObject *)np;
397+#undef b
398+}
399+
400+static PyObject *
401+tuplerepeat(PyTupleObject *a, Py_ssize_t n)
402+{
403+ Py_ssize_t i, j;
404+ Py_ssize_t size;
405+ PyTupleObject *np;
406+ PyObject **p, **items;
407+ if (n < 0)
408+ n = 0;
409+ if (a->ob_size == 0 || n == 1) {
410+ if (PyTuple_CheckExact(a)) {
411+ /* Since tuples are immutable, we can return a shared
412+ copy in this case */
413+ Py_INCREF(a);
414+ return (PyObject *)a;
415+ }
416+ if (a->ob_size == 0)
417+ return PyTuple_New(0);
418+ }
419+ size = a->ob_size * n;
420+ if (size/a->ob_size != n)
421+ return PyErr_NoMemory();
422+ np = (PyTupleObject *) PyTuple_New(size);
423+ if (np == NULL)
424+ return NULL;
425+ p = np->ob_item;
426+ items = a->ob_item;
427+ for (i = 0; i < n; i++) {
428+ for (j = 0; j < a->ob_size; j++) {
429+ *p = items[j];
430+ Py_INCREF(*p);
431+ p++;
432+ }
433+ }
434+ return (PyObject *) np;
435+}
436+
437+static int
438+tupletraverse(PyTupleObject *o, visitproc visit, void *arg)
439+{
440+ Py_ssize_t i;
441+
442+ for (i = o->ob_size; --i >= 0; )
443+ Py_VISIT(o->ob_item[i]);
444+ return 0;
445+}
446+
447+static PyObject *
448+tuplerichcompare(PyObject *v, PyObject *w, int op)
449+{
450+ PyTupleObject *vt, *wt;
451+ Py_ssize_t i;
452+ Py_ssize_t vlen, wlen;
453+
454+ if (!PyTuple_Check(v) || !PyTuple_Check(w)) {
455+ Py_INCREF(Py_NotImplemented);
456+ return Py_NotImplemented;
457+ }
458+
459+ vt = (PyTupleObject *)v;
460+ wt = (PyTupleObject *)w;
461+
462+ vlen = vt->ob_size;
463+ wlen = wt->ob_size;
464+
465+ /* Note: the corresponding code for lists has an "early out" test
466+ * here when op is EQ or NE and the lengths differ. That pays there,
467+ * but Tim was unable to find any real code where EQ/NE tuple
468+ * compares don't have the same length, so testing for it here would
469+ * have cost without benefit.
470+ */
471+
472+ /* Search for the first index where items are different.
473+ * Note that because tuples are immutable, it's safe to reuse
474+ * vlen and wlen across the comparison calls.
475+ */
476+ for (i = 0; i < vlen && i < wlen; i++) {
477+ int k = PyObject_RichCompareBool(vt->ob_item[i],
478+ wt->ob_item[i], Py_EQ);
479+ if (k < 0)
480+ return NULL;
481+ if (!k)
482+ break;
483+ }
484+
485+ if (i >= vlen || i >= wlen) {
486+ /* No more items to compare -- compare sizes */
487+ int cmp;
488+ PyObject *res;
489+ switch (op) {
490+ case Py_LT: cmp = vlen < wlen; break;
491+ case Py_LE: cmp = vlen <= wlen; break;
492+ case Py_EQ: cmp = vlen == wlen; break;
493+ case Py_NE: cmp = vlen != wlen; break;
494+ case Py_GT: cmp = vlen > wlen; break;
495+ case Py_GE: cmp = vlen >= wlen; break;
496+ default: return NULL; /* cannot happen */
497+ }
498+ if (cmp)
499+ res = Py_True;
500+ else
501+ res = Py_False;
502+ Py_INCREF(res);
503+ return res;
504+ }
505+
506+ /* We have an item that differs -- shortcuts for EQ/NE */
507+ if (op == Py_EQ) {
508+ Py_INCREF(Py_False);
509+ return Py_False;
510+ }
511+ if (op == Py_NE) {
512+ Py_INCREF(Py_True);
513+ return Py_True;
514+ }
515+
516+ /* Compare the final item again using the proper operator */
517+ return PyObject_RichCompare(vt->ob_item[i], wt->ob_item[i], op);
518+}
519+
520+static PyObject *
521+tuple_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
522+
523+static PyObject *
524+tuple_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
525+{
526+ PyObject *arg = NULL;
527+ static char *kwlist[] = {"sequence", 0};
528+
529+ if (type != &PyTuple_Type)
530+ return tuple_subtype_new(type, args, kwds);
531+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:tuple", kwlist, &arg))
532+ return NULL;
533+
534+ if (arg == NULL)
535+ return PyTuple_New(0);
536+ else
537+ return PySequence_Tuple(arg);
538+}
539+
540+static PyObject *
541+tuple_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
542+{
543+ PyObject *tmp, *newobj, *item;
544+ Py_ssize_t i, n;
545+
546+ assert(PyType_IsSubtype(type, &PyTuple_Type));
547+ tmp = tuple_new(&PyTuple_Type, args, kwds);
548+ if (tmp == NULL)
549+ return NULL;
550+ assert(PyTuple_Check(tmp));
551+ newobj = type->tp_alloc(type, n = PyTuple_GET_SIZE(tmp));
552+ if (newobj == NULL)
553+ return NULL;
554+ for (i = 0; i < n; i++) {
555+ item = PyTuple_GET_ITEM(tmp, i);
556+ Py_INCREF(item);
557+ PyTuple_SET_ITEM(newobj, i, item);
558+ }
559+ Py_DECREF(tmp);
560+ return newobj;
561+}
562+
563+PyDoc_STRVAR(tuple_doc,
564+"tuple() -> an empty tuple\n"
565+"tuple(sequence) -> tuple initialized from sequence's items\n"
566+"\n"
567+"If the argument is a tuple, the return value is the same object.");
568+
569+static PySequenceMethods tuple_as_sequence = {
570+ (lenfunc)tuplelength, /* sq_length */
571+ (binaryfunc)tupleconcat, /* sq_concat */
572+ (ssizeargfunc)tuplerepeat, /* sq_repeat */
573+ (ssizeargfunc)tupleitem, /* sq_item */
574+ (ssizessizeargfunc)tupleslice, /* sq_slice */
575+ 0, /* sq_ass_item */
576+ 0, /* sq_ass_slice */
577+ (objobjproc)tuplecontains, /* sq_contains */
578+};
579+
580+static PyObject*
581+tuplesubscript(PyTupleObject* self, PyObject* item)
582+{
583+ if (PyIndex_Check(item)) {
584+ Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
585+ if (i == -1 && PyErr_Occurred())
586+ return NULL;
587+ if (i < 0)
588+ i += PyTuple_GET_SIZE(self);
589+ return tupleitem(self, i);
590+ }
591+ else if (PySlice_Check(item)) {
592+ Py_ssize_t start, stop, step, slicelength, cur, i;
593+ PyObject* result;
594+ PyObject* it;
595+ PyObject **src, **dest;
596+
597+ if (PySlice_GetIndicesEx((PySliceObject*)item,
598+ PyTuple_GET_SIZE(self),
599+ &start, &stop, &step, &slicelength) < 0) {
600+ return NULL;
601+ }
602+
603+ if (slicelength <= 0) {
604+ return PyTuple_New(0);
605+ }
606+ else {
607+ result = PyTuple_New(slicelength);
608+ if (!result) return NULL;
609+
610+ src = self->ob_item;
611+ dest = ((PyTupleObject *)result)->ob_item;
612+ for (cur = start, i = 0; i < slicelength;
613+ cur += step, i++) {
614+ it = src[cur];
615+ Py_INCREF(it);
616+ dest[i] = it;
617+ }
618+
619+ return result;
620+ }
621+ }
622+ else {
623+ PyErr_SetString(PyExc_TypeError,
624+ "tuple indices must be integers");
625+ return NULL;
626+ }
627+}
628+
629+static PyObject *
630+tuple_getnewargs(PyTupleObject *v)
631+{
632+ return Py_BuildValue("(N)", tupleslice(v, 0, v->ob_size));
633+
634+}
635+
636+static PyMethodDef tuple_methods[] = {
637+ {"__getnewargs__", (PyCFunction)tuple_getnewargs, METH_NOARGS},
638+ {NULL, NULL} /* sentinel */
639+};
640+
641+static PyMappingMethods tuple_as_mapping = {
642+ (lenfunc)tuplelength,
643+ (binaryfunc)tuplesubscript,
644+ 0
645+};
646+
647+static PyObject *tuple_iter(PyObject *seq);
648+
649+PyTypeObject PyTuple_Type = {
650+ PyObject_HEAD_INIT(&PyType_Type)
651+ 0,
652+ "tuple",
653+ sizeof(PyTupleObject) - sizeof(PyObject *),
654+ sizeof(PyObject *),
655+ (destructor)tupledealloc, /* tp_dealloc */
656+ (printfunc)tupleprint, /* tp_print */
657+ 0, /* tp_getattr */
658+ 0, /* tp_setattr */
659+ 0, /* tp_compare */
660+ (reprfunc)tuplerepr, /* tp_repr */
661+ 0, /* tp_as_number */
662+ &tuple_as_sequence, /* tp_as_sequence */
663+ &tuple_as_mapping, /* tp_as_mapping */
664+ (hashfunc)tuplehash, /* tp_hash */
665+ 0, /* tp_call */
666+ 0, /* tp_str */
667+ PyObject_GenericGetAttr, /* tp_getattro */
668+ 0, /* tp_setattro */
669+ 0, /* tp_as_buffer */
670+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
671+ Py_TPFLAGS_BASETYPE, /* tp_flags */
672+ tuple_doc, /* tp_doc */
673+ (traverseproc)tupletraverse, /* tp_traverse */
674+ 0, /* tp_clear */
675+ tuplerichcompare, /* tp_richcompare */
676+ 0, /* tp_weaklistoffset */
677+ tuple_iter, /* tp_iter */
678+ 0, /* tp_iternext */
679+ tuple_methods, /* tp_methods */
680+ 0, /* tp_members */
681+ 0, /* tp_getset */
682+ 0, /* tp_base */
683+ 0, /* tp_dict */
684+ 0, /* tp_descr_get */
685+ 0, /* tp_descr_set */
686+ 0, /* tp_dictoffset */
687+ 0, /* tp_init */
688+ 0, /* tp_alloc */
689+ tuple_new, /* tp_new */
690+ PyObject_GC_Del, /* tp_free */
691+};
692+
693+/* The following function breaks the notion that tuples are immutable:
694+ it changes the size of a tuple. We get away with this only if there
695+ is only one module referencing the object. You can also think of it
696+ as creating a new tuple object and destroying the old one, only more
697+ efficiently. In any case, don't use this if the tuple may already be
698+ known to some other part of the code. */
699+
700+int
701+_PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)
702+{
703+ register PyTupleObject *v;
704+ register PyTupleObject *sv;
705+ Py_ssize_t i;
706+ Py_ssize_t oldsize;
707+
708+ v = (PyTupleObject *) *pv;
709+ if (v == NULL || v->ob_type != &PyTuple_Type ||
710+ (v->ob_size != 0 && v->ob_refcnt != 1)) {
711+ *pv = 0;
712+ Py_XDECREF(v);
713+ PyErr_BadInternalCall();
714+ return -1;
715+ }
716+ oldsize = v->ob_size;
717+ if (oldsize == newsize)
718+ return 0;
719+
720+ if (oldsize == 0) {
721+ /* Empty tuples are often shared, so we should never
722+ resize them in-place even if we do own the only
723+ (current) reference */
724+ Py_DECREF(v);
725+ *pv = PyTuple_New(newsize);
726+ return *pv == NULL ? -1 : 0;
727+ }
728+
729+ /* XXX UNREF/NEWREF interface should be more symmetrical */
730+ _Py_DEC_REFTOTAL;
731+ _PyObject_GC_UNTRACK(v);
732+ _Py_ForgetReference((PyObject *) v);
733+ /* DECREF items deleted by shrinkage */
734+ for (i = newsize; i < oldsize; i++) {
735+ Py_XDECREF(v->ob_item[i]);
736+ v->ob_item[i] = NULL;
737+ }
738+ sv = PyObject_GC_Resize(PyTupleObject, v, newsize);
739+ if (sv == NULL) {
740+ *pv = NULL;
741+ PyObject_GC_Del(v);
742+ return -1;
743+ }
744+ _Py_NewReference((PyObject *) sv);
745+ /* Zero out items added by growing */
746+ if (newsize > oldsize)
747+ memset(&sv->ob_item[oldsize], 0,
748+ sizeof(*sv->ob_item) * (newsize - oldsize));
749+ *pv = (PyObject *) sv;
750+ _PyObject_GC_TRACK(sv);
751+ return 0;
752+}
753+
754+void
755+PyTuple_Fini(void)
756+{
757+#if MAXSAVESIZE > 0
758+ int i;
759+
760+ Py_XDECREF(free_tuples[0]);
761+ free_tuples[0] = NULL;
762+
763+ for (i = 1; i < MAXSAVESIZE; i++) {
764+ PyTupleObject *p, *q;
765+ p = free_tuples[i];
766+ free_tuples[i] = NULL;
767+ while (p) {
768+ q = p;
769+ p = (PyTupleObject *)(p->ob_item[0]);
770+ PyObject_GC_Del(q);
771+ }
772+ }
773+#endif
774+}
775+
776+/*********************** Tuple Iterator **************************/
777+
778+typedef struct {
779+ PyObject_HEAD
780+ long it_index;
781+ PyTupleObject *it_seq; /* Set to NULL when iterator is exhausted */
782+} tupleiterobject;
783+
784+static void
785+tupleiter_dealloc(tupleiterobject *it)
786+{
787+ _PyObject_GC_UNTRACK(it);
788+ Py_XDECREF(it->it_seq);
789+ PyObject_GC_Del(it);
790+}
791+
792+static int
793+tupleiter_traverse(tupleiterobject *it, visitproc visit, void *arg)
794+{
795+ Py_VISIT(it->it_seq);
796+ return 0;
797+}
798+
799+static PyObject *
800+tupleiter_next(tupleiterobject *it)
801+{
802+ PyTupleObject *seq;
803+ PyObject *item;
804+
805+ assert(it != NULL);
806+ seq = it->it_seq;
807+ if (seq == NULL)
808+ return NULL;
809+ assert(PyTuple_Check(seq));
810+
811+ if (it->it_index < PyTuple_GET_SIZE(seq)) {
812+ item = PyTuple_GET_ITEM(seq, it->it_index);
813+ ++it->it_index;
814+ Py_INCREF(item);
815+ return item;
816+ }
817+
818+ Py_DECREF(seq);
819+ it->it_seq = NULL;
820+ return NULL;
821+}
822+
823+static PyObject *
824+tupleiter_len(tupleiterobject *it)
825+{
826+ Py_ssize_t len = 0;
827+ if (it->it_seq)
828+ len = PyTuple_GET_SIZE(it->it_seq) - it->it_index;
829+ return PyInt_FromSsize_t(len);
830+}
831+
832+PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
833+
834+static PyMethodDef tupleiter_methods[] = {
835+ {"__length_hint__", (PyCFunction)tupleiter_len, METH_NOARGS, length_hint_doc},
836+ {NULL, NULL} /* sentinel */
837+};
838+
839+PyTypeObject PyTupleIter_Type = {
840+ PyObject_HEAD_INIT(&PyType_Type)
841+ 0, /* ob_size */
842+ "tupleiterator", /* tp_name */
843+ sizeof(tupleiterobject), /* tp_basicsize */
844+ 0, /* tp_itemsize */
845+ /* methods */
846+ (destructor)tupleiter_dealloc, /* tp_dealloc */
847+ 0, /* tp_print */
848+ 0, /* tp_getattr */
849+ 0, /* tp_setattr */
850+ 0, /* tp_compare */
851+ 0, /* tp_repr */
852+ 0, /* tp_as_number */
853+ 0, /* tp_as_sequence */
854+ 0, /* tp_as_mapping */
855+ 0, /* tp_hash */
856+ 0, /* tp_call */
857+ 0, /* tp_str */
858+ PyObject_GenericGetAttr, /* tp_getattro */
859+ 0, /* tp_setattro */
860+ 0, /* tp_as_buffer */
861+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
862+ 0, /* tp_doc */
863+ (traverseproc)tupleiter_traverse, /* tp_traverse */
864+ 0, /* tp_clear */
865+ 0, /* tp_richcompare */
866+ 0, /* tp_weaklistoffset */
867+ PyObject_SelfIter, /* tp_iter */
868+ (iternextfunc)tupleiter_next, /* tp_iternext */
869+ tupleiter_methods, /* tp_methods */
870+ 0,
871+};
872+
873+static PyObject *
874+tuple_iter(PyObject *seq)
875+{
876+ tupleiterobject *it;
877+
878+ if (!PyTuple_Check(seq)) {
879+ PyErr_BadInternalCall();
880+ return NULL;
881+ }
882+ it = PyObject_GC_New(tupleiterobject, &PyTupleIter_Type);
883+ if (it == NULL)
884+ return NULL;
885+ it->it_index = 0;
886+ Py_INCREF(seq);
887+ it->it_seq = (PyTupleObject *)seq;
888+ _PyObject_GC_TRACK(it);
889+ return (PyObject *)it;
890+}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t