Home | History | Annotate | Download | only in Objects
      1 /* Iterator objects */
      2 
      3 #include "Python.h"
      4 
      5 typedef struct {
      6     PyObject_HEAD
      7     long      it_index;
      8     PyObject *it_seq; /* Set to NULL when iterator is exhausted */
      9 } seqiterobject;
     10 
     11 PyObject *
     12 PySeqIter_New(PyObject *seq)
     13 {
     14     seqiterobject *it;
     15 
     16     if (!PySequence_Check(seq)) {
     17         PyErr_BadInternalCall();
     18         return NULL;
     19     }
     20     it = PyObject_GC_New(seqiterobject, &PySeqIter_Type);
     21     if (it == NULL)
     22         return NULL;
     23     it->it_index = 0;
     24     Py_INCREF(seq);
     25     it->it_seq = seq;
     26     _PyObject_GC_TRACK(it);
     27     return (PyObject *)it;
     28 }
     29 
     30 static void
     31 iter_dealloc(seqiterobject *it)
     32 {
     33     _PyObject_GC_UNTRACK(it);
     34     Py_XDECREF(it->it_seq);
     35     PyObject_GC_Del(it);
     36 }
     37 
     38 static int
     39 iter_traverse(seqiterobject *it, visitproc visit, void *arg)
     40 {
     41     Py_VISIT(it->it_seq);
     42     return 0;
     43 }
     44 
     45 static PyObject *
     46 iter_iternext(PyObject *iterator)
     47 {
     48     seqiterobject *it;
     49     PyObject *seq;
     50     PyObject *result;
     51 
     52     assert(PySeqIter_Check(iterator));
     53     it = (seqiterobject *)iterator;
     54     seq = it->it_seq;
     55     if (seq == NULL)
     56         return NULL;
     57     if (it->it_index == LONG_MAX) {
     58         PyErr_SetString(PyExc_OverflowError,
     59                         "iter index too large");
     60         return NULL;
     61     }
     62 
     63     result = PySequence_GetItem(seq, it->it_index);
     64     if (result != NULL) {
     65         it->it_index++;
     66         return result;
     67     }
     68     if (PyErr_ExceptionMatches(PyExc_IndexError) ||
     69         PyErr_ExceptionMatches(PyExc_StopIteration))
     70     {
     71         PyErr_Clear();
     72         it->it_seq = NULL;
     73         Py_DECREF(seq);
     74     }
     75     return NULL;
     76 }
     77 
     78 static PyObject *
     79 iter_len(seqiterobject *it)
     80 {
     81     Py_ssize_t seqsize, len;
     82 
     83     if (it->it_seq) {
     84         seqsize = PySequence_Size(it->it_seq);
     85         if (seqsize == -1)
     86             return NULL;
     87         len = seqsize - it->it_index;
     88         if (len >= 0)
     89             return PyInt_FromSsize_t(len);
     90     }
     91     return PyInt_FromLong(0);
     92 }
     93 
     94 PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
     95 
     96 static PyMethodDef seqiter_methods[] = {
     97     {"__length_hint__", (PyCFunction)iter_len, METH_NOARGS, length_hint_doc},
     98     {NULL,              NULL}           /* sentinel */
     99 };
    100 
    101 PyTypeObject PySeqIter_Type = {
    102     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    103     "iterator",                                 /* tp_name */
    104     sizeof(seqiterobject),                      /* tp_basicsize */
    105     0,                                          /* tp_itemsize */
    106     /* methods */
    107     (destructor)iter_dealloc,                   /* tp_dealloc */
    108     0,                                          /* tp_print */
    109     0,                                          /* tp_getattr */
    110     0,                                          /* tp_setattr */
    111     0,                                          /* tp_compare */
    112     0,                                          /* tp_repr */
    113     0,                                          /* tp_as_number */
    114     0,                                          /* tp_as_sequence */
    115     0,                                          /* tp_as_mapping */
    116     0,                                          /* tp_hash */
    117     0,                                          /* tp_call */
    118     0,                                          /* tp_str */
    119     PyObject_GenericGetAttr,                    /* tp_getattro */
    120     0,                                          /* tp_setattro */
    121     0,                                          /* tp_as_buffer */
    122     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
    123     0,                                          /* tp_doc */
    124     (traverseproc)iter_traverse,                /* tp_traverse */
    125     0,                                          /* tp_clear */
    126     0,                                          /* tp_richcompare */
    127     0,                                          /* tp_weaklistoffset */
    128     PyObject_SelfIter,                          /* tp_iter */
    129     iter_iternext,                              /* tp_iternext */
    130     seqiter_methods,                            /* tp_methods */
    131     0,                                          /* tp_members */
    132 };
    133 
    134 /* -------------------------------------- */
    135 
    136 typedef struct {
    137     PyObject_HEAD
    138     PyObject *it_callable; /* Set to NULL when iterator is exhausted */
    139     PyObject *it_sentinel; /* Set to NULL when iterator is exhausted */
    140 } calliterobject;
    141 
    142 PyObject *
    143 PyCallIter_New(PyObject *callable, PyObject *sentinel)
    144 {
    145     calliterobject *it;
    146     it = PyObject_GC_New(calliterobject, &PyCallIter_Type);
    147     if (it == NULL)
    148         return NULL;
    149     Py_INCREF(callable);
    150     it->it_callable = callable;
    151     Py_INCREF(sentinel);
    152     it->it_sentinel = sentinel;
    153     _PyObject_GC_TRACK(it);
    154     return (PyObject *)it;
    155 }
    156 static void
    157 calliter_dealloc(calliterobject *it)
    158 {
    159     _PyObject_GC_UNTRACK(it);
    160     Py_XDECREF(it->it_callable);
    161     Py_XDECREF(it->it_sentinel);
    162     PyObject_GC_Del(it);
    163 }
    164 
    165 static int
    166 calliter_traverse(calliterobject *it, visitproc visit, void *arg)
    167 {
    168     Py_VISIT(it->it_callable);
    169     Py_VISIT(it->it_sentinel);
    170     return 0;
    171 }
    172 
    173 static PyObject *
    174 calliter_iternext(calliterobject *it)
    175 {
    176     if (it->it_callable != NULL) {
    177         PyObject *args = PyTuple_New(0);
    178         PyObject *result;
    179         if (args == NULL)
    180             return NULL;
    181         result = PyObject_Call(it->it_callable, args, NULL);
    182         Py_DECREF(args);
    183         if (result != NULL) {
    184             int ok;
    185             ok = PyObject_RichCompareBool(result,
    186                                           it->it_sentinel,
    187                                           Py_EQ);
    188             if (ok == 0)
    189                 return result; /* Common case, fast path */
    190             Py_DECREF(result);
    191             if (ok > 0) {
    192                 Py_CLEAR(it->it_callable);
    193                 Py_CLEAR(it->it_sentinel);
    194             }
    195         }
    196         else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
    197             PyErr_Clear();
    198             Py_CLEAR(it->it_callable);
    199             Py_CLEAR(it->it_sentinel);
    200         }
    201     }
    202     return NULL;
    203 }
    204 
    205 PyTypeObject PyCallIter_Type = {
    206     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    207     "callable-iterator",                        /* tp_name */
    208     sizeof(calliterobject),                     /* tp_basicsize */
    209     0,                                          /* tp_itemsize */
    210     /* methods */
    211     (destructor)calliter_dealloc,               /* tp_dealloc */
    212     0,                                          /* tp_print */
    213     0,                                          /* tp_getattr */
    214     0,                                          /* tp_setattr */
    215     0,                                          /* tp_compare */
    216     0,                                          /* tp_repr */
    217     0,                                          /* tp_as_number */
    218     0,                                          /* tp_as_sequence */
    219     0,                                          /* tp_as_mapping */
    220     0,                                          /* tp_hash */
    221     0,                                          /* tp_call */
    222     0,                                          /* tp_str */
    223     PyObject_GenericGetAttr,                    /* tp_getattro */
    224     0,                                          /* tp_setattro */
    225     0,                                          /* tp_as_buffer */
    226     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
    227     0,                                          /* tp_doc */
    228     (traverseproc)calliter_traverse,            /* tp_traverse */
    229     0,                                          /* tp_clear */
    230     0,                                          /* tp_richcompare */
    231     0,                                          /* tp_weaklistoffset */
    232     PyObject_SelfIter,                          /* tp_iter */
    233     (iternextfunc)calliter_iternext,            /* tp_iternext */
    234     0,                                          /* tp_methods */
    235 };
    236