This commit was manufactured by cvs2svn to create tag
[python/dscho.git] / Objects / iterobject.c
blob5783d2085bc07d038d6e28f1b685a275a3e9d330
1 /* Iterator objects */
3 #include "Python.h"
5 typedef struct {
6 PyObject_HEAD
7 long it_index;
8 PyObject *it_seq;
9 } seqiterobject;
11 PyObject *
12 PySeqIter_New(PyObject *seq)
14 seqiterobject *it;
15 it = PyObject_NEW(seqiterobject, &PySeqIter_Type);
16 if (it == NULL)
17 return NULL;
18 it->it_index = 0;
19 Py_INCREF(seq);
20 it->it_seq = seq;
21 PyObject_GC_Init(it);
22 return (PyObject *)it;
24 static void
25 iter_dealloc(seqiterobject *it)
27 PyObject_GC_Fini(it);
28 Py_DECREF(it->it_seq);
29 it = (seqiterobject *) PyObject_AS_GC(it);
30 PyObject_DEL(it);
33 static int
34 iter_traverse(seqiterobject *it, visitproc visit, void *arg)
36 return visit(it->it_seq, arg);
39 static PyObject *
40 iter_next(seqiterobject *it)
42 PyObject *seq = it->it_seq;
43 PyObject *result = PySequence_GetItem(seq, it->it_index++);
45 if (result == NULL && PyErr_ExceptionMatches(PyExc_IndexError))
46 PyErr_SetObject(PyExc_StopIteration, Py_None);
47 return result;
50 static PyObject *
51 iter_getiter(PyObject *it)
53 Py_INCREF(it);
54 return it;
57 static PyObject *
58 iter_iternext(PyObject *iterator)
60 seqiterobject *it;
61 PyObject *seq;
63 assert(PySeqIter_Check(iterator));
64 it = (seqiterobject *)iterator;
65 seq = it->it_seq;
67 if (PyList_Check(seq)) {
68 PyObject *item;
69 if (it->it_index >= PyList_GET_SIZE(seq)) {
70 return NULL;
72 item = PyList_GET_ITEM(seq, it->it_index);
73 it->it_index++;
74 Py_INCREF(item);
75 return item;
77 else {
78 PyObject *result = PySequence_GetItem(seq, it->it_index++);
79 if (result != NULL) {
80 return result;
82 if (PyErr_ExceptionMatches(PyExc_IndexError) ||
83 PyErr_ExceptionMatches(PyExc_StopIteration)) {
84 PyErr_Clear();
85 return NULL;
87 else {
88 return NULL;
93 static PyMethodDef iter_methods[] = {
94 {"next", (PyCFunction)iter_next, METH_NOARGS,
95 "it.next() -- get the next value, or raise StopIteration"},
96 {NULL, NULL} /* sentinel */
99 PyTypeObject PySeqIter_Type = {
100 PyObject_HEAD_INIT(&PyType_Type)
101 0, /* ob_size */
102 "iterator", /* tp_name */
103 sizeof(seqiterobject) + PyGC_HEAD_SIZE, /* tp_basicsize */
104 0, /* tp_itemsize */
105 /* methods */
106 (destructor)iter_dealloc, /* tp_dealloc */
107 0, /* tp_print */
108 0, /* tp_getattr */
109 0, /* tp_setattr */
110 0, /* tp_compare */
111 0, /* tp_repr */
112 0, /* tp_as_number */
113 0, /* tp_as_sequence */
114 0, /* tp_as_mapping */
115 0, /* tp_hash */
116 0, /* tp_call */
117 0, /* tp_str */
118 PyObject_GenericGetAttr, /* tp_getattro */
119 0, /* tp_setattro */
120 0, /* tp_as_buffer */
121 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
122 0, /* tp_doc */
123 (traverseproc)iter_traverse, /* tp_traverse */
124 0, /* tp_clear */
125 0, /* tp_richcompare */
126 0, /* tp_weaklistoffset */
127 (getiterfunc)iter_getiter, /* tp_iter */
128 (iternextfunc)iter_iternext, /* tp_iternext */
129 iter_methods, /* tp_methods */
130 0, /* tp_members */
131 0, /* tp_getset */
132 0, /* tp_base */
133 0, /* tp_dict */
134 0, /* tp_descr_get */
135 0, /* tp_descr_set */
138 /* -------------------------------------- */
140 typedef struct {
141 PyObject_HEAD
142 PyObject *it_callable;
143 PyObject *it_sentinel;
144 } calliterobject;
146 PyObject *
147 PyCallIter_New(PyObject *callable, PyObject *sentinel)
149 calliterobject *it;
150 it = PyObject_NEW(calliterobject, &PyCallIter_Type);
151 if (it == NULL)
152 return NULL;
153 Py_INCREF(callable);
154 it->it_callable = callable;
155 Py_INCREF(sentinel);
156 it->it_sentinel = sentinel;
157 PyObject_GC_Init(it);
158 return (PyObject *)it;
160 static void
161 calliter_dealloc(calliterobject *it)
163 PyObject_GC_Fini(it);
164 Py_DECREF(it->it_callable);
165 Py_DECREF(it->it_sentinel);
166 it = (calliterobject *) PyObject_AS_GC(it);
167 PyObject_DEL(it);
170 static int
171 calliter_traverse(calliterobject *it, visitproc visit, void *arg)
173 int err;
174 if ((err = visit(it->it_callable, arg)))
175 return err;
176 if ((err = visit(it->it_sentinel, arg)))
177 return err;
178 return 0;
181 static PyObject *
182 calliter_next(calliterobject *it, PyObject *args)
184 PyObject *result = PyObject_CallObject(it->it_callable, NULL);
185 if (result != NULL) {
186 if (PyObject_RichCompareBool(result, it->it_sentinel, Py_EQ)) {
187 PyErr_SetObject(PyExc_StopIteration, Py_None);
188 Py_DECREF(result);
189 result = NULL;
192 return result;
195 static PyMethodDef calliter_methods[] = {
196 {"next", (PyCFunction)calliter_next, METH_VARARGS,
197 "it.next() -- get the next value, or raise StopIteration"},
198 {NULL, NULL} /* sentinel */
201 static PyObject *
202 calliter_iternext(calliterobject *it)
204 PyObject *result = PyObject_CallObject(it->it_callable, NULL);
205 if (result != NULL) {
206 if (PyObject_RichCompareBool(result, it->it_sentinel, Py_EQ)) {
207 Py_DECREF(result);
208 result = NULL;
211 else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
212 PyErr_Clear();
214 return result;
217 PyTypeObject PyCallIter_Type = {
218 PyObject_HEAD_INIT(&PyType_Type)
219 0, /* ob_size */
220 "callable-iterator", /* tp_name */
221 sizeof(calliterobject) + PyGC_HEAD_SIZE,/* tp_basicsize */
222 0, /* tp_itemsize */
223 /* methods */
224 (destructor)calliter_dealloc, /* tp_dealloc */
225 0, /* tp_print */
226 0, /* tp_getattr */
227 0, /* tp_setattr */
228 0, /* tp_compare */
229 0, /* tp_repr */
230 0, /* tp_as_number */
231 0, /* tp_as_sequence */
232 0, /* tp_as_mapping */
233 0, /* tp_hash */
234 0, /* tp_call */
235 0, /* tp_str */
236 PyObject_GenericGetAttr, /* tp_getattro */
237 0, /* tp_setattro */
238 0, /* tp_as_buffer */
239 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
240 0, /* tp_doc */
241 (traverseproc)calliter_traverse, /* tp_traverse */
242 0, /* tp_clear */
243 0, /* tp_richcompare */
244 0, /* tp_weaklistoffset */
245 (getiterfunc)iter_getiter, /* tp_iter */
246 (iternextfunc)calliter_iternext, /* tp_iternext */
247 calliter_methods, /* tp_methods */
248 0, /* tp_members */
249 0, /* tp_getset */
250 0, /* tp_base */
251 0, /* tp_dict */
252 0, /* tp_descr_get */
253 0, /* tp_descr_set */