Skip to content

Commit 2204237

Browse files
author
rhettinger
committed
Moved special case for tuples from iterobject.c to
tupleobject.c. Makes the code in iterobject.c cleaner and speeds-up the general case by not checking for tuples everytime. SF Patch #592065. git-svn-id: http://svn.python.org/projects/python/trunk@28088 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent 18026e1 commit 2204237

2 files changed

Lines changed: 123 additions & 25 deletions

File tree

Objects/iterobject.c

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -55,40 +55,27 @@ iter_iternext(PyObject *iterator)
5555
{
5656
seqiterobject *it;
5757
PyObject *seq;
58+
PyObject *result;
5859

5960
assert(PySeqIter_Check(iterator));
6061
it = (seqiterobject *)iterator;
6162
seq = it->it_seq;
6263
if (seq == NULL)
6364
return NULL;
6465

65-
if (PyTuple_CheckExact(seq)) {
66-
if (it->it_index < PyTuple_GET_SIZE(seq)) {
67-
PyObject *item;
68-
item = PyTuple_GET_ITEM(seq, it->it_index);
69-
it->it_index++;
70-
Py_INCREF(item);
71-
return item;
72-
}
66+
result = PySequence_GetItem(seq, it->it_index);
67+
if (result != NULL) {
68+
it->it_index++;
69+
return result;
70+
}
71+
if (PyErr_ExceptionMatches(PyExc_IndexError) ||
72+
PyErr_ExceptionMatches(PyExc_StopIteration))
73+
{
74+
PyErr_Clear();
7375
Py_DECREF(seq);
7476
it->it_seq = NULL;
75-
return NULL;
76-
}
77-
else {
78-
PyObject *result = PySequence_GetItem(seq, it->it_index);
79-
if (result != NULL) {
80-
it->it_index++;
81-
return result;
82-
}
83-
if (PyErr_ExceptionMatches(PyExc_IndexError) ||
84-
PyErr_ExceptionMatches(PyExc_StopIteration))
85-
{
86-
PyErr_Clear();
87-
Py_DECREF(seq);
88-
it->it_seq = NULL;
89-
}
90-
return NULL;
9177
}
78+
return NULL;
9279
}
9380

9481
PyTypeObject PySeqIter_Type = {

Objects/tupleobject.c

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,8 @@ static PyMappingMethods tuple_as_mapping = {
596596
0
597597
};
598598

599+
static PyObject *tuple_iter(PyObject *seq);
600+
599601
PyTypeObject PyTuple_Type = {
600602
PyObject_HEAD_INIT(&PyType_Type)
601603
0,
@@ -624,7 +626,7 @@ PyTypeObject PyTuple_Type = {
624626
0, /* tp_clear */
625627
tuplerichcompare, /* tp_richcompare */
626628
0, /* tp_weaklistoffset */
627-
0, /* tp_iter */
629+
tuple_iter, /* tp_iter */
628630
0, /* tp_iternext */
629631
0, /* tp_methods */
630632
0, /* tp_members */
@@ -722,3 +724,112 @@ PyTuple_Fini(void)
722724
}
723725
#endif
724726
}
727+
728+
/*********************** Tuple Iterator **************************/
729+
730+
typedef struct {
731+
PyObject_HEAD
732+
long it_index;
733+
PyTupleObject *it_seq; /* Set to NULL when iterator is exhausted */
734+
} tupleiterobject;
735+
736+
PyTypeObject PyTupleIter_Type;
737+
738+
static PyObject *
739+
tuple_iter(PyObject *seq)
740+
{
741+
tupleiterobject *it;
742+
743+
if (!PyTuple_Check(seq)) {
744+
PyErr_BadInternalCall();
745+
return NULL;
746+
}
747+
it = PyObject_GC_New(tupleiterobject, &PyTupleIter_Type);
748+
if (it == NULL)
749+
return NULL;
750+
it->it_index = 0;
751+
Py_INCREF(seq);
752+
it->it_seq = (PyTupleObject *)seq;
753+
_PyObject_GC_TRACK(it);
754+
return (PyObject *)it;
755+
}
756+
757+
static void
758+
tupleiter_dealloc(tupleiterobject *it)
759+
{
760+
_PyObject_GC_UNTRACK(it);
761+
Py_XDECREF(it->it_seq);
762+
PyObject_GC_Del(it);
763+
}
764+
765+
static int
766+
tupleiter_traverse(tupleiterobject *it, visitproc visit, void *arg)
767+
{
768+
if (it->it_seq == NULL)
769+
return 0;
770+
return visit((PyObject *)it->it_seq, arg);
771+
}
772+
773+
774+
static PyObject *
775+
tupleiter_getiter(PyObject *it)
776+
{
777+
Py_INCREF(it);
778+
return it;
779+
}
780+
781+
static PyObject *
782+
tupleiter_next(tupleiterobject *it)
783+
{
784+
PyTupleObject *seq;
785+
PyObject *item;
786+
787+
assert(it != NULL);
788+
seq = it->it_seq;
789+
if (seq == NULL)
790+
return NULL;
791+
assert(PyTuple_Check(seq));
792+
793+
if (it->it_index < PyTuple_GET_SIZE(seq)) {
794+
item = PyTuple_GET_ITEM(seq, it->it_index);
795+
++it->it_index;
796+
Py_INCREF(item);
797+
return item;
798+
}
799+
800+
Py_DECREF(seq);
801+
it->it_seq = NULL;
802+
return NULL;
803+
}
804+
805+
PyTypeObject PyTupleIter_Type = {
806+
PyObject_HEAD_INIT(&PyType_Type)
807+
0, /* ob_size */
808+
"tupleiterator", /* tp_name */
809+
sizeof(tupleiterobject), /* tp_basicsize */
810+
0, /* tp_itemsize */
811+
/* methods */
812+
(destructor)tupleiter_dealloc, /* tp_dealloc */
813+
0, /* tp_print */
814+
0, /* tp_getattr */
815+
0, /* tp_setattr */
816+
0, /* tp_compare */
817+
0, /* tp_repr */
818+
0, /* tp_as_number */
819+
0, /* tp_as_sequence */
820+
0, /* tp_as_mapping */
821+
0, /* tp_hash */
822+
0, /* tp_call */
823+
0, /* tp_str */
824+
PyObject_GenericGetAttr, /* tp_getattro */
825+
0, /* tp_setattro */
826+
0, /* tp_as_buffer */
827+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
828+
0, /* tp_doc */
829+
(traverseproc)tupleiter_traverse, /* tp_traverse */
830+
0, /* tp_clear */
831+
0, /* tp_richcompare */
832+
0, /* tp_weaklistoffset */
833+
(getiterfunc)tupleiter_getiter, /* tp_iter */
834+
(iternextfunc)tupleiter_next, /* tp_iternext */
835+
};

0 commit comments

Comments
 (0)