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