LCOV - code coverage report
Current view: top level - Objects - iterobject.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 62 87 71.3 %
Date: 2017-04-19 Functions: 7 9 77.8 %

          Line data    Source code
       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        3455 : PySeqIter_New(PyObject *seq)
      13             : {
      14             :     seqiterobject *it;
      15             : 
      16        3455 :     if (!PySequence_Check(seq)) {
      17           0 :         PyErr_BadInternalCall();
      18           0 :         return NULL;
      19             :     }
      20        3455 :     it = PyObject_GC_New(seqiterobject, &PySeqIter_Type);
      21        3455 :     if (it == NULL)
      22           0 :         return NULL;
      23        3455 :     it->it_index = 0;
      24        3455 :     Py_INCREF(seq);
      25        3455 :     it->it_seq = seq;
      26        3455 :     _PyObject_GC_TRACK(it);
      27        3455 :     return (PyObject *)it;
      28             : }
      29             : 
      30             : static void
      31        3455 : iter_dealloc(seqiterobject *it)
      32             : {
      33        3455 :     _PyObject_GC_UNTRACK(it);
      34        3455 :     Py_XDECREF(it->it_seq);
      35        3455 :     PyObject_GC_Del(it);
      36        3455 : }
      37             : 
      38             : static int
      39           0 : iter_traverse(seqiterobject *it, visitproc visit, void *arg)
      40             : {
      41           0 :     Py_VISIT(it->it_seq);
      42           0 :     return 0;
      43             : }
      44             : 
      45             : static PyObject *
      46       11981 : iter_iternext(PyObject *iterator)
      47             : {
      48             :     seqiterobject *it;
      49             :     PyObject *seq;
      50             :     PyObject *result;
      51             : 
      52             :     assert(PySeqIter_Check(iterator));
      53       11981 :     it = (seqiterobject *)iterator;
      54       11981 :     seq = it->it_seq;
      55       11981 :     if (seq == NULL)
      56           0 :         return NULL;
      57       11981 :     if (it->it_index == LONG_MAX) {
      58           0 :         PyErr_SetString(PyExc_OverflowError,
      59             :                         "iter index too large");
      60           0 :         return NULL;
      61             :     }
      62             : 
      63       11981 :     result = PySequence_GetItem(seq, it->it_index);
      64       11981 :     if (result != NULL) {
      65        8526 :         it->it_index++;
      66        8526 :         return result;
      67             :     }
      68        3455 :     if (PyErr_ExceptionMatches(PyExc_IndexError) ||
      69           0 :         PyErr_ExceptionMatches(PyExc_StopIteration))
      70             :     {
      71        3455 :         PyErr_Clear();
      72        3455 :         it->it_seq = NULL;
      73        3455 :         Py_DECREF(seq);
      74             :     }
      75        3455 :     return NULL;
      76             : }
      77             : 
      78             : static PyObject *
      79           0 : iter_len(seqiterobject *it)
      80             : {
      81             :     Py_ssize_t seqsize, len;
      82             : 
      83           0 :     if (it->it_seq) {
      84           0 :         seqsize = PySequence_Size(it->it_seq);
      85           0 :         if (seqsize == -1)
      86           0 :             return NULL;
      87           0 :         len = seqsize - it->it_index;
      88           0 :         if (len >= 0)
      89           0 :             return PyInt_FromSsize_t(len);
      90             :     }
      91           0 :     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         753 : PyCallIter_New(PyObject *callable, PyObject *sentinel)
     144             : {
     145             :     calliterobject *it;
     146         753 :     it = PyObject_GC_New(calliterobject, &PyCallIter_Type);
     147         753 :     if (it == NULL)
     148           0 :         return NULL;
     149         753 :     Py_INCREF(callable);
     150         753 :     it->it_callable = callable;
     151         753 :     Py_INCREF(sentinel);
     152         753 :     it->it_sentinel = sentinel;
     153         753 :     _PyObject_GC_TRACK(it);
     154         753 :     return (PyObject *)it;
     155             : }
     156             : static void
     157         753 : calliter_dealloc(calliterobject *it)
     158             : {
     159         753 :     _PyObject_GC_UNTRACK(it);
     160         753 :     Py_XDECREF(it->it_callable);
     161         753 :     Py_XDECREF(it->it_sentinel);
     162         753 :     PyObject_GC_Del(it);
     163         753 : }
     164             : 
     165             : static int
     166           6 : calliter_traverse(calliterobject *it, visitproc visit, void *arg)
     167             : {
     168           6 :     Py_VISIT(it->it_callable);
     169           6 :     Py_VISIT(it->it_sentinel);
     170           6 :     return 0;
     171             : }
     172             : 
     173             : static PyObject *
     174        3165 : calliter_iternext(calliterobject *it)
     175             : {
     176        3165 :     if (it->it_callable != NULL) {
     177        3165 :         PyObject *args = PyTuple_New(0);
     178             :         PyObject *result;
     179        3165 :         if (args == NULL)
     180           0 :             return NULL;
     181        3165 :         result = PyObject_Call(it->it_callable, args, NULL);
     182        3165 :         Py_DECREF(args);
     183        3165 :         if (result != NULL) {
     184             :             int ok;
     185        3165 :             ok = PyObject_RichCompareBool(result,
     186             :                                           it->it_sentinel,
     187             :                                           Py_EQ);
     188        3165 :             if (ok == 0)
     189        2760 :                 return result; /* Common case, fast path */
     190         405 :             Py_DECREF(result);
     191         405 :             if (ok > 0) {
     192         405 :                 Py_CLEAR(it->it_callable);
     193         405 :                 Py_CLEAR(it->it_sentinel);
     194             :             }
     195             :         }
     196           0 :         else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
     197           0 :             PyErr_Clear();
     198           0 :             Py_CLEAR(it->it_callable);
     199           0 :             Py_CLEAR(it->it_sentinel);
     200             :         }
     201             :     }
     202         405 :     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             : };

Generated by: LCOV version 1.10