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 
     58     result = PySequence_GetItem(seq, it->it_index);
     59     if (result != NULL) {
     60         it->it_index++;
     61         return result;
     62     }
     63     if (PyErr_ExceptionMatches(PyExc_IndexError) ||
     64         PyErr_ExceptionMatches(PyExc_StopIteration))
     65     {
     66         PyErr_Clear();
     67         Py_DECREF(seq);
     68         it->it_seq = NULL;
     69     }
     70     return NULL;
     71 }
     72 
     73 static PyObject *
     74 iter_len(seqiterobject *it)
     75 {
     76     Py_ssize_t seqsize, len;
     77 
     78     if (it->it_seq) {
     79         seqsize = PySequence_Size(it->it_seq);
     80         if (seqsize == -1)
     81             return NULL;
     82         len = seqsize - it->it_index;
     83         if (len >= 0)
     84             return PyInt_FromSsize_t(len);
     85     }
     86     return PyInt_FromLong(0);
     87 }
     88 
     89 PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
     90 
     91 static PyMethodDef seqiter_methods[] = {
     92     {"__length_hint__", (PyCFunction)iter_len, METH_NOARGS, length_hint_doc},
     93     {NULL,              NULL}           /* sentinel */
     94 };
     95 
     96 PyTypeObject PySeqIter_Type = {
     97     PyVarObject_HEAD_INIT(&PyType_Type, 0)
     98     "iterator",                                 /* tp_name */
     99     sizeof(seqiterobject),                      /* tp_basicsize */
    100     0,                                          /* tp_itemsize */
    101     /* methods */
    102     (destructor)iter_dealloc,                   /* tp_dealloc */
    103     0,                                          /* tp_print */
    104     0,                                          /* tp_getattr */
    105     0,                                          /* tp_setattr */
    106     0,                                          /* tp_compare */
    107     0,                                          /* tp_repr */
    108     0,                                          /* tp_as_number */
    109     0,                                          /* tp_as_sequence */
    110     0,                                          /* tp_as_mapping */
    111     0,                                          /* tp_hash */
    112     0,                                          /* tp_call */
    113     0,                                          /* tp_str */
    114     PyObject_GenericGetAttr,                    /* tp_getattro */
    115     0,                                          /* tp_setattro */
    116     0,                                          /* tp_as_buffer */
    117     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
    118     0,                                          /* tp_doc */
    119     (traverseproc)iter_traverse,                /* tp_traverse */
    120     0,                                          /* tp_clear */
    121     0,                                          /* tp_richcompare */
    122     0,                                          /* tp_weaklistoffset */
    123     PyObject_SelfIter,                          /* tp_iter */
    124     iter_iternext,                              /* tp_iternext */
    125     seqiter_methods,                            /* tp_methods */
    126     0,                                          /* tp_members */
    127 };
    128 
    129 /* -------------------------------------- */
    130 
    131 typedef struct {
    132     PyObject_HEAD
    133     PyObject *it_callable; /* Set to NULL when iterator is exhausted */
    134     PyObject *it_sentinel; /* Set to NULL when iterator is exhausted */
    135 } calliterobject;
    136 
    137 PyObject *
    138 PyCallIter_New(PyObject *callable, PyObject *sentinel)
    139 {
    140     calliterobject *it;
    141     it = PyObject_GC_New(calliterobject, &PyCallIter_Type);
    142     if (it == NULL)
    143         return NULL;
    144     Py_INCREF(callable);
    145     it->it_callable = callable;
    146     Py_INCREF(sentinel);
    147     it->it_sentinel = sentinel;
    148     _PyObject_GC_TRACK(it);
    149     return (PyObject *)it;
    150 }
    151 static void
    152 calliter_dealloc(calliterobject *it)
    153 {
    154     _PyObject_GC_UNTRACK(it);
    155     Py_XDECREF(it->it_callable);
    156     Py_XDECREF(it->it_sentinel);
    157     PyObject_GC_Del(it);
    158 }
    159 
    160 static int
    161 calliter_traverse(calliterobject *it, visitproc visit, void *arg)
    162 {
    163     Py_VISIT(it->it_callable);
    164     Py_VISIT(it->it_sentinel);
    165     return 0;
    166 }
    167 
    168 static PyObject *
    169 calliter_iternext(calliterobject *it)
    170 {
    171     if (it->it_callable != NULL) {
    172         PyObject *args = PyTuple_New(0);
    173         PyObject *result;
    174         if (args == NULL)
    175             return NULL;
    176         result = PyObject_Call(it->it_callable, args, NULL);
    177         Py_DECREF(args);
    178         if (result != NULL) {
    179             int ok;
    180             ok = PyObject_RichCompareBool(result,
    181                                           it->it_sentinel,
    182                                           Py_EQ);
    183             if (ok == 0)
    184                 return result; /* Common case, fast path */
    185             Py_DECREF(result);
    186             if (ok > 0) {
    187                 Py_CLEAR(it->it_callable);
    188                 Py_CLEAR(it->it_sentinel);
    189             }
    190         }
    191         else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
    192             PyErr_Clear();
    193             Py_CLEAR(it->it_callable);
    194             Py_CLEAR(it->it_sentinel);
    195         }
    196     }
    197     return NULL;
    198 }
    199 
    200 PyTypeObject PyCallIter_Type = {
    201     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    202     "callable-iterator",                        /* tp_name */
    203     sizeof(calliterobject),                     /* tp_basicsize */
    204     0,                                          /* tp_itemsize */
    205     /* methods */
    206     (destructor)calliter_dealloc,               /* tp_dealloc */
    207     0,                                          /* tp_print */
    208     0,                                          /* tp_getattr */
    209     0,                                          /* tp_setattr */
    210     0,                                          /* tp_compare */
    211     0,                                          /* tp_repr */
    212     0,                                          /* tp_as_number */
    213     0,                                          /* tp_as_sequence */
    214     0,                                          /* tp_as_mapping */
    215     0,                                          /* tp_hash */
    216     0,                                          /* tp_call */
    217     0,                                          /* tp_str */
    218     PyObject_GenericGetAttr,                    /* tp_getattro */
    219     0,                                          /* tp_setattro */
    220     0,                                          /* tp_as_buffer */
    221     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
    222     0,                                          /* tp_doc */
    223     (traverseproc)calliter_traverse,            /* tp_traverse */
    224     0,                                          /* tp_clear */
    225     0,                                          /* tp_richcompare */
    226     0,                                          /* tp_weaklistoffset */
    227     PyObject_SelfIter,                          /* tp_iter */
    228     (iternextfunc)calliter_iternext,            /* tp_iternext */
    229     0,                                          /* tp_methods */
    230 };
    231