LCOV - code coverage report
Current view: top level - Objects - enumobject.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 59 155 38.1 %
Date: 2017-04-19 Functions: 5 10 50.0 %

          Line data    Source code
       1             : /* enumerate object */
       2             : 
       3             : #include "Python.h"
       4             : 
       5             : typedef struct {
       6             :     PyObject_HEAD
       7             :     Py_ssize_t en_index;           /* current index of enumeration */
       8             :     PyObject* en_sit;          /* secondary iterator of enumeration */
       9             :     PyObject* en_result;           /* result tuple  */
      10             :     PyObject* en_longindex;        /* index for sequences >= PY_SSIZE_T_MAX */
      11             : } enumobject;
      12             : 
      13             : static PyObject *
      14        1224 : enum_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
      15             : {
      16             :     enumobject *en;
      17        1224 :     PyObject *seq = NULL;
      18        1224 :     PyObject *start = NULL;
      19             :     static char *kwlist[] = {"sequence", "start", 0};
      20             : 
      21        1224 :     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:enumerate", kwlist,
      22             :                                      &seq, &start))
      23           0 :         return NULL;
      24             : 
      25        1224 :     en = (enumobject *)type->tp_alloc(type, 0);
      26        1224 :     if (en == NULL)
      27           0 :         return NULL;
      28        1224 :     if (start != NULL) {
      29           9 :         start = PyNumber_Index(start);
      30           9 :         if (start == NULL) {
      31           0 :             Py_DECREF(en);
      32           0 :             return NULL;
      33             :         }
      34             :         assert(PyInt_Check(start) || PyLong_Check(start));
      35           9 :         en->en_index = PyInt_AsSsize_t(start);
      36           9 :         if (en->en_index == -1 && PyErr_Occurred()) {
      37           0 :             PyErr_Clear();
      38           0 :             en->en_index = PY_SSIZE_T_MAX;
      39           0 :             en->en_longindex = start;
      40             :         } else {
      41           9 :             en->en_longindex = NULL;
      42           9 :             Py_DECREF(start);
      43             :         }
      44             :     } else {
      45        1215 :         en->en_index = 0;
      46        1215 :         en->en_longindex = NULL;
      47             :     }
      48        1224 :     en->en_sit = PyObject_GetIter(seq);
      49        1224 :     if (en->en_sit == NULL) {
      50           0 :         Py_DECREF(en);
      51           0 :         return NULL;
      52             :     }
      53        1224 :     en->en_result = PyTuple_Pack(2, Py_None, Py_None);
      54        1224 :     if (en->en_result == NULL) {
      55           0 :         Py_DECREF(en);
      56           0 :         return NULL;
      57             :     }
      58        1224 :     return (PyObject *)en;
      59             : }
      60             : 
      61             : static void
      62        1224 : enum_dealloc(enumobject *en)
      63             : {
      64        1224 :     PyObject_GC_UnTrack(en);
      65        1224 :     Py_XDECREF(en->en_sit);
      66        1224 :     Py_XDECREF(en->en_result);
      67        1224 :     Py_XDECREF(en->en_longindex);
      68        1224 :     Py_TYPE(en)->tp_free(en);
      69        1224 : }
      70             : 
      71             : static int
      72           6 : enum_traverse(enumobject *en, visitproc visit, void *arg)
      73             : {
      74           6 :     Py_VISIT(en->en_sit);
      75           6 :     Py_VISIT(en->en_result);
      76           6 :     Py_VISIT(en->en_longindex);
      77           6 :     return 0;
      78             : }
      79             : 
      80             : static PyObject *
      81           0 : enum_next_long(enumobject *en, PyObject* next_item)
      82             : {
      83             :     static PyObject *one = NULL;
      84           0 :     PyObject *result = en->en_result;
      85             :     PyObject *next_index;
      86             :     PyObject *stepped_up;
      87             : 
      88           0 :     if (en->en_longindex == NULL) {
      89           0 :         en->en_longindex = PyInt_FromSsize_t(PY_SSIZE_T_MAX);
      90           0 :         if (en->en_longindex == NULL)
      91           0 :             return NULL;
      92             :     }
      93           0 :     if (one == NULL) {
      94           0 :         one = PyInt_FromLong(1);
      95           0 :         if (one == NULL)
      96           0 :             return NULL;
      97             :     }
      98           0 :     next_index = en->en_longindex;
      99             :     assert(next_index != NULL);
     100           0 :     stepped_up = PyNumber_Add(next_index, one);
     101           0 :     if (stepped_up == NULL)
     102           0 :         return NULL;
     103           0 :     en->en_longindex = stepped_up;
     104             : 
     105           0 :     if (result->ob_refcnt == 1) {
     106           0 :         Py_INCREF(result);
     107           0 :         Py_DECREF(PyTuple_GET_ITEM(result, 0));
     108           0 :         Py_DECREF(PyTuple_GET_ITEM(result, 1));
     109             :     } else {
     110           0 :         result = PyTuple_New(2);
     111           0 :         if (result == NULL) {
     112           0 :             Py_DECREF(next_index);
     113           0 :             Py_DECREF(next_item);
     114           0 :             return NULL;
     115             :         }
     116             :     }
     117           0 :     PyTuple_SET_ITEM(result, 0, next_index);
     118           0 :     PyTuple_SET_ITEM(result, 1, next_item);
     119           0 :     return result;
     120             : }
     121             : 
     122             : static PyObject *
     123        4482 : enum_next(enumobject *en)
     124             : {
     125             :     PyObject *next_index;
     126             :     PyObject *next_item;
     127        4482 :     PyObject *result = en->en_result;
     128        4482 :     PyObject *it = en->en_sit;
     129             : 
     130        4482 :     next_item = (*Py_TYPE(it)->tp_iternext)(it);
     131        4482 :     if (next_item == NULL)
     132        1224 :         return NULL;
     133             : 
     134        3258 :     if (en->en_index == PY_SSIZE_T_MAX)
     135           0 :         return enum_next_long(en, next_item);
     136             : 
     137        3258 :     next_index = PyInt_FromSsize_t(en->en_index);
     138        3258 :     if (next_index == NULL) {
     139           0 :         Py_DECREF(next_item);
     140           0 :         return NULL;
     141             :     }
     142        3258 :     en->en_index++;
     143             : 
     144        3258 :     if (result->ob_refcnt == 1) {
     145        3258 :         Py_INCREF(result);
     146        3258 :         Py_DECREF(PyTuple_GET_ITEM(result, 0));
     147        3258 :         Py_DECREF(PyTuple_GET_ITEM(result, 1));
     148             :     } else {
     149           0 :         result = PyTuple_New(2);
     150           0 :         if (result == NULL) {
     151           0 :             Py_DECREF(next_index);
     152           0 :             Py_DECREF(next_item);
     153           0 :             return NULL;
     154             :         }
     155             :     }
     156        3258 :     PyTuple_SET_ITEM(result, 0, next_index);
     157        3258 :     PyTuple_SET_ITEM(result, 1, next_item);
     158        3258 :     return result;
     159             : }
     160             : 
     161             : PyDoc_STRVAR(enum_doc,
     162             : "enumerate(iterable[, start]) -> iterator for index, value of iterable\n"
     163             : "\n"
     164             : "Return an enumerate object.  iterable must be another object that supports\n"
     165             : "iteration.  The enumerate object yields pairs containing a count (from\n"
     166             : "start, which defaults to zero) and a value yielded by the iterable argument.\n"
     167             : "enumerate is useful for obtaining an indexed list:\n"
     168             : "    (0, seq[0]), (1, seq[1]), (2, seq[2]), ...");
     169             : 
     170             : PyTypeObject PyEnum_Type = {
     171             :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
     172             :     "enumerate",                    /* tp_name */
     173             :     sizeof(enumobject),             /* tp_basicsize */
     174             :     0,                              /* tp_itemsize */
     175             :     /* methods */
     176             :     (destructor)enum_dealloc,       /* tp_dealloc */
     177             :     0,                              /* tp_print */
     178             :     0,                              /* tp_getattr */
     179             :     0,                              /* tp_setattr */
     180             :     0,                              /* tp_compare */
     181             :     0,                              /* tp_repr */
     182             :     0,                              /* tp_as_number */
     183             :     0,                              /* tp_as_sequence */
     184             :     0,                              /* tp_as_mapping */
     185             :     0,                              /* tp_hash */
     186             :     0,                              /* tp_call */
     187             :     0,                              /* tp_str */
     188             :     PyObject_GenericGetAttr,        /* tp_getattro */
     189             :     0,                              /* tp_setattro */
     190             :     0,                              /* tp_as_buffer */
     191             :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
     192             :         Py_TPFLAGS_BASETYPE,    /* tp_flags */
     193             :     enum_doc,                       /* tp_doc */
     194             :     (traverseproc)enum_traverse,    /* tp_traverse */
     195             :     0,                              /* tp_clear */
     196             :     0,                              /* tp_richcompare */
     197             :     0,                              /* tp_weaklistoffset */
     198             :     PyObject_SelfIter,                  /* tp_iter */
     199             :     (iternextfunc)enum_next,        /* tp_iternext */
     200             :     0,                              /* tp_methods */
     201             :     0,                              /* tp_members */
     202             :     0,                              /* tp_getset */
     203             :     0,                              /* tp_base */
     204             :     0,                              /* tp_dict */
     205             :     0,                              /* tp_descr_get */
     206             :     0,                              /* tp_descr_set */
     207             :     0,                              /* tp_dictoffset */
     208             :     0,                              /* tp_init */
     209             :     PyType_GenericAlloc,            /* tp_alloc */
     210             :     enum_new,                       /* tp_new */
     211             :     PyObject_GC_Del,                /* tp_free */
     212             : };
     213             : 
     214             : /* Reversed Object ***************************************************************/
     215             : 
     216             : typedef struct {
     217             :     PyObject_HEAD
     218             :     Py_ssize_t      index;
     219             :     PyObject* seq;
     220             : } reversedobject;
     221             : 
     222             : static PyObject *
     223           3 : reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     224             : {
     225             :     Py_ssize_t n;
     226             :     PyObject *seq, *reversed_meth;
     227             :     static PyObject *reversed_cache = NULL;
     228             :     reversedobject *ro;
     229             : 
     230           3 :     if (type == &PyReversed_Type && !_PyArg_NoKeywords("reversed()", kwds))
     231           0 :         return NULL;
     232             : 
     233           3 :     if (!PyArg_UnpackTuple(args, "reversed", 1, 1, &seq) )
     234           0 :         return NULL;
     235             : 
     236           3 :     if (PyInstance_Check(seq)) {
     237           0 :         reversed_meth = PyObject_GetAttrString(seq, "__reversed__");
     238           0 :         if (reversed_meth == NULL) {
     239           0 :             if (PyErr_ExceptionMatches(PyExc_AttributeError))
     240           0 :                 PyErr_Clear();
     241             :             else
     242           0 :                 return NULL;
     243             :         }
     244             :     }
     245             :     else {
     246           3 :         reversed_meth = _PyObject_LookupSpecial(seq, "__reversed__",
     247             :                                                 &reversed_cache);
     248           3 :         if (reversed_meth == NULL && PyErr_Occurred())
     249           0 :             return NULL;
     250             :     }
     251           3 :     if (reversed_meth != NULL) {
     252           3 :         PyObject *res = PyObject_CallFunctionObjArgs(reversed_meth, NULL);
     253           3 :         Py_DECREF(reversed_meth);
     254           3 :         return res;
     255             :     }
     256             : 
     257           0 :     if (!PySequence_Check(seq)) {
     258           0 :         PyErr_SetString(PyExc_TypeError,
     259             :                         "argument to reversed() must be a sequence");
     260           0 :         return NULL;
     261             :     }
     262             : 
     263           0 :     n = PySequence_Size(seq);
     264           0 :     if (n == -1)
     265           0 :         return NULL;
     266             : 
     267           0 :     ro = (reversedobject *)type->tp_alloc(type, 0);
     268           0 :     if (ro == NULL)
     269           0 :         return NULL;
     270             : 
     271           0 :     ro->index = n-1;
     272           0 :     Py_INCREF(seq);
     273           0 :     ro->seq = seq;
     274           0 :     return (PyObject *)ro;
     275             : }
     276             : 
     277             : static void
     278           0 : reversed_dealloc(reversedobject *ro)
     279             : {
     280           0 :     PyObject_GC_UnTrack(ro);
     281           0 :     Py_XDECREF(ro->seq);
     282           0 :     Py_TYPE(ro)->tp_free(ro);
     283           0 : }
     284             : 
     285             : static int
     286           0 : reversed_traverse(reversedobject *ro, visitproc visit, void *arg)
     287             : {
     288           0 :     Py_VISIT(ro->seq);
     289           0 :     return 0;
     290             : }
     291             : 
     292             : static PyObject *
     293           0 : reversed_next(reversedobject *ro)
     294             : {
     295             :     PyObject *item;
     296           0 :     Py_ssize_t index = ro->index;
     297             : 
     298           0 :     if (index >= 0) {
     299           0 :         item = PySequence_GetItem(ro->seq, index);
     300           0 :         if (item != NULL) {
     301           0 :             ro->index--;
     302           0 :             return item;
     303             :         }
     304           0 :         if (PyErr_ExceptionMatches(PyExc_IndexError) ||
     305           0 :             PyErr_ExceptionMatches(PyExc_StopIteration))
     306           0 :             PyErr_Clear();
     307             :     }
     308           0 :     ro->index = -1;
     309           0 :     Py_CLEAR(ro->seq);
     310           0 :     return NULL;
     311             : }
     312             : 
     313             : PyDoc_STRVAR(reversed_doc,
     314             : "reversed(sequence) -> reverse iterator over values of the sequence\n"
     315             : "\n"
     316             : "Return a reverse iterator");
     317             : 
     318             : static PyObject *
     319           0 : reversed_len(reversedobject *ro)
     320             : {
     321             :     Py_ssize_t position, seqsize;
     322             : 
     323           0 :     if (ro->seq == NULL)
     324           0 :         return PyInt_FromLong(0);
     325           0 :     seqsize = PySequence_Size(ro->seq);
     326           0 :     if (seqsize == -1)
     327           0 :         return NULL;
     328           0 :     position = ro->index + 1;
     329           0 :     return PyInt_FromSsize_t((seqsize < position)  ?  0  :  position);
     330             : }
     331             : 
     332             : PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
     333             : 
     334             : static PyMethodDef reversediter_methods[] = {
     335             :     {"__length_hint__", (PyCFunction)reversed_len, METH_NOARGS, length_hint_doc},
     336             :     {NULL,              NULL}           /* sentinel */
     337             : };
     338             : 
     339             : PyTypeObject PyReversed_Type = {
     340             :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
     341             :     "reversed",                     /* tp_name */
     342             :     sizeof(reversedobject),         /* tp_basicsize */
     343             :     0,                              /* tp_itemsize */
     344             :     /* methods */
     345             :     (destructor)reversed_dealloc,   /* tp_dealloc */
     346             :     0,                              /* tp_print */
     347             :     0,                              /* tp_getattr */
     348             :     0,                              /* tp_setattr */
     349             :     0,                              /* tp_compare */
     350             :     0,                              /* tp_repr */
     351             :     0,                              /* tp_as_number */
     352             :     0,                                  /* tp_as_sequence */
     353             :     0,                              /* tp_as_mapping */
     354             :     0,                              /* tp_hash */
     355             :     0,                              /* tp_call */
     356             :     0,                              /* tp_str */
     357             :     PyObject_GenericGetAttr,        /* tp_getattro */
     358             :     0,                              /* tp_setattro */
     359             :     0,                              /* tp_as_buffer */
     360             :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
     361             :         Py_TPFLAGS_BASETYPE,    /* tp_flags */
     362             :     reversed_doc,                   /* tp_doc */
     363             :     (traverseproc)reversed_traverse,/* tp_traverse */
     364             :     0,                              /* tp_clear */
     365             :     0,                              /* tp_richcompare */
     366             :     0,                              /* tp_weaklistoffset */
     367             :     PyObject_SelfIter,                  /* tp_iter */
     368             :     (iternextfunc)reversed_next,    /* tp_iternext */
     369             :     reversediter_methods,               /* tp_methods */
     370             :     0,                              /* tp_members */
     371             :     0,                              /* tp_getset */
     372             :     0,                              /* tp_base */
     373             :     0,                              /* tp_dict */
     374             :     0,                              /* tp_descr_get */
     375             :     0,                              /* tp_descr_set */
     376             :     0,                              /* tp_dictoffset */
     377             :     0,                              /* tp_init */
     378             :     PyType_GenericAlloc,            /* tp_alloc */
     379             :     reversed_new,                   /* tp_new */
     380             :     PyObject_GC_Del,                /* tp_free */
     381             : };

Generated by: LCOV version 1.10