This commit was manufactured by cvs2svn to create tag 'r222'.
[python/dscho.git] / Objects / iterobject.c
blob8f8d70bfe2ec060e45a7a23aeaf2f6431bec424e
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 return (PyObject *)it;
23 static void
24 iter_dealloc(seqiterobject *it)
26 Py_DECREF(it->it_seq);
27 PyObject_DEL(it);
30 static int
31 iter_traverse(seqiterobject *it, visitproc visit, void *arg)
33 return visit(it->it_seq, arg);
36 static PyObject *
37 iter_next(seqiterobject *it)
39 PyObject *seq = it->it_seq;
40 PyObject *result = PySequence_GetItem(seq, it->it_index++);
42 if (result == NULL && PyErr_ExceptionMatches(PyExc_IndexError))
43 PyErr_SetObject(PyExc_StopIteration, Py_None);
44 return result;
47 static PyObject *
48 iter_getiter(PyObject *it)
50 Py_INCREF(it);
51 return it;
54 static PyObject *
55 iter_iternext(PyObject *iterator)
57 seqiterobject *it;
58 PyObject *seq;
60 assert(PySeqIter_Check(iterator));
61 it = (seqiterobject *)iterator;
62 seq = it->it_seq;
64 if (PyList_Check(seq)) {
65 PyObject *item;
66 if (it->it_index >= PyList_GET_SIZE(seq)) {
67 return NULL;
69 item = PyList_GET_ITEM(seq, it->it_index);
70 it->it_index++;
71 Py_INCREF(item);
72 return item;
74 else {
75 PyObject *result = PySequence_GetItem(seq, it->it_index++);
76 if (result != NULL) {
77 return result;
79 if (PyErr_ExceptionMatches(PyExc_IndexError) ||
80 PyErr_ExceptionMatches(PyExc_StopIteration)) {
81 PyErr_Clear();
82 return NULL;
84 else {
85 return NULL;
90 static PyMethodDef iter_methods[] = {
91 {"next", (PyCFunction)iter_next, METH_NOARGS,
92 "it.next() -- get the next value, or raise StopIteration"},
93 {NULL, NULL} /* sentinel */
96 PyTypeObject PySeqIter_Type = {
97 PyObject_HEAD_INIT(&PyType_Type)
98 0, /* ob_size */
99 "iterator", /* tp_name */
100 sizeof(seqiterobject), /* tp_basicsize */
101 0, /* tp_itemsize */
102 /* methods */
103 (destructor)iter_dealloc, /* tp_dealloc */
104 0, /* tp_print */
105 0, /* tp_getattr */
106 0, /* tp_setattr */
107 0, /* tp_compare */
108 0, /* tp_repr */
109 0, /* tp_as_number */
110 0, /* tp_as_sequence */
111 0, /* tp_as_mapping */
112 0, /* tp_hash */
113 0, /* tp_call */
114 0, /* tp_str */
115 PyObject_GenericGetAttr, /* tp_getattro */
116 0, /* tp_setattro */
117 0, /* tp_as_buffer */
118 Py_TPFLAGS_DEFAULT, /* tp_flags */
119 0, /* tp_doc */
120 (traverseproc)iter_traverse, /* tp_traverse */
121 0, /* tp_clear */
122 0, /* tp_richcompare */
123 0, /* tp_weaklistoffset */
124 (getiterfunc)iter_getiter, /* tp_iter */
125 (iternextfunc)iter_iternext, /* tp_iternext */
126 iter_methods, /* tp_methods */
127 0, /* tp_members */
128 0, /* tp_getset */
129 0, /* tp_base */
130 0, /* tp_dict */
131 0, /* tp_descr_get */
132 0, /* tp_descr_set */
135 /* -------------------------------------- */
137 typedef struct {
138 PyObject_HEAD
139 PyObject *it_callable;
140 PyObject *it_sentinel;
141 } calliterobject;
143 PyObject *
144 PyCallIter_New(PyObject *callable, PyObject *sentinel)
146 calliterobject *it;
147 it = PyObject_NEW(calliterobject, &PyCallIter_Type);
148 if (it == NULL)
149 return NULL;
150 Py_INCREF(callable);
151 it->it_callable = callable;
152 Py_INCREF(sentinel);
153 it->it_sentinel = sentinel;
154 return (PyObject *)it;
156 static void
157 calliter_dealloc(calliterobject *it)
159 Py_DECREF(it->it_callable);
160 Py_DECREF(it->it_sentinel);
161 PyObject_DEL(it);
164 static int
165 calliter_traverse(calliterobject *it, visitproc visit, void *arg)
167 int err;
168 if ((err = visit(it->it_callable, arg)))
169 return err;
170 if ((err = visit(it->it_sentinel, arg)))
171 return err;
172 return 0;
175 static PyObject *
176 calliter_next(calliterobject *it, PyObject *args)
178 PyObject *result = PyObject_CallObject(it->it_callable, NULL);
179 if (result != NULL) {
180 if (PyObject_RichCompareBool(result, it->it_sentinel, Py_EQ)) {
181 PyErr_SetObject(PyExc_StopIteration, Py_None);
182 Py_DECREF(result);
183 result = NULL;
186 return result;
189 static PyMethodDef calliter_methods[] = {
190 {"next", (PyCFunction)calliter_next, METH_VARARGS,
191 "it.next() -- get the next value, or raise StopIteration"},
192 {NULL, NULL} /* sentinel */
195 static PyObject *
196 calliter_iternext(calliterobject *it)
198 PyObject *result = PyObject_CallObject(it->it_callable, NULL);
199 if (result != NULL) {
200 if (PyObject_RichCompareBool(result, it->it_sentinel, Py_EQ)) {
201 Py_DECREF(result);
202 result = NULL;
205 else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
206 PyErr_Clear();
208 return result;
211 PyTypeObject PyCallIter_Type = {
212 PyObject_HEAD_INIT(&PyType_Type)
213 0, /* ob_size */
214 "callable-iterator", /* tp_name */
215 sizeof(calliterobject), /* tp_basicsize */
216 0, /* tp_itemsize */
217 /* methods */
218 (destructor)calliter_dealloc, /* tp_dealloc */
219 0, /* tp_print */
220 0, /* tp_getattr */
221 0, /* tp_setattr */
222 0, /* tp_compare */
223 0, /* tp_repr */
224 0, /* tp_as_number */
225 0, /* tp_as_sequence */
226 0, /* tp_as_mapping */
227 0, /* tp_hash */
228 0, /* tp_call */
229 0, /* tp_str */
230 PyObject_GenericGetAttr, /* tp_getattro */
231 0, /* tp_setattro */
232 0, /* tp_as_buffer */
233 Py_TPFLAGS_DEFAULT, /* tp_flags */
234 0, /* tp_doc */
235 (traverseproc)calliter_traverse, /* tp_traverse */
236 0, /* tp_clear */
237 0, /* tp_richcompare */
238 0, /* tp_weaklistoffset */
239 (getiterfunc)iter_getiter, /* tp_iter */
240 (iternextfunc)calliter_iternext, /* tp_iternext */
241 calliter_methods, /* tp_methods */
242 0, /* tp_members */
243 0, /* tp_getset */
244 0, /* tp_base */
245 0, /* tp_dict */
246 0, /* tp_descr_get */
247 0, /* tp_descr_set */