]> granicus.if.org Git - python/commitdiff
Moved special case for tuples from iterobject.c to
authorRaymond Hettinger <python@rcn.com>
Fri, 9 Aug 2002 01:30:17 +0000 (01:30 +0000)
committerRaymond Hettinger <python@rcn.com>
Fri, 9 Aug 2002 01:30:17 +0000 (01:30 +0000)
tupleobject.c. Makes the code in iterobject.c cleaner
and speeds-up the general case by not checking for
tuples everytime.   SF Patch #592065.

Objects/iterobject.c
Objects/tupleobject.c

index 447edbac503d6e56cc6565b580936e53409bf1fb..4dc225a521fabdaa9078ada81b21639977a03862 100644 (file)
@@ -55,6 +55,7 @@ iter_iternext(PyObject *iterator)
 {
        seqiterobject *it;
        PyObject *seq;
+       PyObject *result;
 
        assert(PySeqIter_Check(iterator));
        it = (seqiterobject *)iterator;
@@ -62,33 +63,19 @@ iter_iternext(PyObject *iterator)
        if (seq == NULL)
                return NULL;
 
-       if (PyTuple_CheckExact(seq)) {
-               if (it->it_index < PyTuple_GET_SIZE(seq)) {
-                       PyObject *item;
-                       item = PyTuple_GET_ITEM(seq, it->it_index);
-                       it->it_index++;
-                       Py_INCREF(item);
-                       return item;
-               }
+       result = PySequence_GetItem(seq, it->it_index);
+       if (result != NULL) {
+               it->it_index++;
+               return result;
+       }
+       if (PyErr_ExceptionMatches(PyExc_IndexError) ||
+           PyErr_ExceptionMatches(PyExc_StopIteration))
+       {
+               PyErr_Clear();
                Py_DECREF(seq);
                it->it_seq = NULL;
-               return NULL;
-       }
-       else {
-               PyObject *result = PySequence_GetItem(seq, it->it_index);
-               if (result != NULL) {
-                       it->it_index++;
-                       return result;
-               }
-               if (PyErr_ExceptionMatches(PyExc_IndexError) ||
-                   PyErr_ExceptionMatches(PyExc_StopIteration))
-               {
-                       PyErr_Clear();
-                       Py_DECREF(seq);
-                       it->it_seq = NULL;
-               }
-               return NULL;
        }
+       return NULL;
 }
 
 PyTypeObject PySeqIter_Type = {
index add9cac639c20cad91fe9b4341419a1f146fb3a7..678aeb12502310ee7310708fa09fa084b1073cc9 100644 (file)
@@ -596,6 +596,8 @@ static PyMappingMethods tuple_as_mapping = {
        0
 };
 
+static PyObject *tuple_iter(PyObject *seq);
+
 PyTypeObject PyTuple_Type = {
        PyObject_HEAD_INIT(&PyType_Type)
        0,
@@ -624,7 +626,7 @@ PyTypeObject PyTuple_Type = {
        0,                                      /* tp_clear */
        tuplerichcompare,                       /* tp_richcompare */
        0,                                      /* tp_weaklistoffset */
-       0,                                      /* tp_iter */
+       tuple_iter,                             /* tp_iter */
        0,                                      /* tp_iternext */
        0,                                      /* tp_methods */
        0,                                      /* tp_members */
@@ -722,3 +724,112 @@ PyTuple_Fini(void)
        }
 #endif
 }
+
+/*********************** Tuple Iterator **************************/
+
+typedef struct {
+       PyObject_HEAD
+       long it_index;
+       PyTupleObject *it_seq; /* Set to NULL when iterator is exhausted */
+} tupleiterobject;
+
+PyTypeObject PyTupleIter_Type;
+
+static PyObject *
+tuple_iter(PyObject *seq)
+{
+       tupleiterobject *it;
+
+       if (!PyTuple_Check(seq)) {
+               PyErr_BadInternalCall();
+               return NULL;
+       }
+       it = PyObject_GC_New(tupleiterobject, &PyTupleIter_Type);
+       if (it == NULL)
+               return NULL;
+       it->it_index = 0;
+       Py_INCREF(seq);
+       it->it_seq = (PyTupleObject *)seq;
+       _PyObject_GC_TRACK(it);
+       return (PyObject *)it;
+}
+
+static void
+tupleiter_dealloc(tupleiterobject *it)
+{
+       _PyObject_GC_UNTRACK(it);
+       Py_XDECREF(it->it_seq);
+       PyObject_GC_Del(it);
+}
+
+static int
+tupleiter_traverse(tupleiterobject *it, visitproc visit, void *arg)
+{
+       if (it->it_seq == NULL)
+               return 0;
+       return visit((PyObject *)it->it_seq, arg);
+}
+
+
+static PyObject *
+tupleiter_getiter(PyObject *it)
+{
+       Py_INCREF(it);
+       return it;
+}
+
+static PyObject *
+tupleiter_next(tupleiterobject *it)
+{
+       PyTupleObject *seq;
+       PyObject *item;
+
+       assert(it != NULL);
+       seq = it->it_seq;
+       if (seq == NULL)
+               return NULL;
+       assert(PyTuple_Check(seq));
+
+       if (it->it_index < PyTuple_GET_SIZE(seq)) {
+               item = PyTuple_GET_ITEM(seq, it->it_index);
+               ++it->it_index;
+               Py_INCREF(item);
+               return item;
+       }
+
+       Py_DECREF(seq);
+       it->it_seq = NULL;
+       return NULL;
+}
+
+PyTypeObject PyTupleIter_Type = {
+       PyObject_HEAD_INIT(&PyType_Type)
+       0,                                      /* ob_size */
+       "tupleiterator",                        /* tp_name */
+       sizeof(tupleiterobject),                /* tp_basicsize */
+       0,                                      /* tp_itemsize */
+       /* methods */
+       (destructor)tupleiter_dealloc,          /* tp_dealloc */
+       0,                                      /* tp_print */
+       0,                                      /* tp_getattr */
+       0,                                      /* tp_setattr */
+       0,                                      /* tp_compare */
+       0,                                      /* tp_repr */
+       0,                                      /* tp_as_number */
+       0,                                      /* tp_as_sequence */
+       0,                                      /* tp_as_mapping */
+       0,                                      /* tp_hash */
+       0,                                      /* tp_call */
+       0,                                      /* tp_str */
+       PyObject_GenericGetAttr,                /* tp_getattro */
+       0,                                      /* tp_setattro */
+       0,                                      /* tp_as_buffer */
+       Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
+       0,                                      /* tp_doc */
+       (traverseproc)tupleiter_traverse,       /* tp_traverse */
+       0,                                      /* tp_clear */
+       0,                                      /* tp_richcompare */
+       0,                                      /* tp_weaklistoffset */
+       (getiterfunc)tupleiter_getiter,         /* tp_iter */
+       (iternextfunc)tupleiter_next,           /* tp_iternext */
+};