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