blob: 230dba294d58a17ae819bb2ac763cbc70b0cb2b4 [file] [log] [blame]
Guido van Rossum7dab2422002-04-26 19:40:56 +00001/* enumerate object */
2
3#include "Python.h"
4
5typedef struct {
6 PyObject_HEAD
7 long en_index; /* current index of enumeration */
8 PyObject* en_sit; /* secondary iterator of enumeration */
Raymond Hettingere8b0f042003-05-28 14:05:34 +00009 PyObject* en_result; /* result tuple */
Raymond Hettinger8f669372007-10-03 21:18:11 +000010 PyObject* en_longindex; /* index for sequences >= LONG_MAX */
Guido van Rossum7dab2422002-04-26 19:40:56 +000011} enumobject;
12
Guido van Rossum7dab2422002-04-26 19:40:56 +000013static PyObject *
14enum_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
15{
16 enumobject *en;
17 PyObject *seq = NULL;
Martin v. Löwis15e62742006-02-27 16:46:16 +000018 static char *kwlist[] = {"sequence", 0};
Guido van Rossum7dab2422002-04-26 19:40:56 +000019
20 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:enumerate", kwlist,
21 &seq))
22 return NULL;
23
24 en = (enumobject *)type->tp_alloc(type, 0);
25 if (en == NULL)
26 return NULL;
27 en->en_index = 0;
28 en->en_sit = PyObject_GetIter(seq);
Raymond Hettinger8f669372007-10-03 21:18:11 +000029 en->en_longindex = NULL;
Guido van Rossum7dab2422002-04-26 19:40:56 +000030 if (en->en_sit == NULL) {
31 Py_DECREF(en);
32 return NULL;
33 }
Raymond Hettinger54a831b2003-11-02 05:37:44 +000034 en->en_result = PyTuple_Pack(2, Py_None, Py_None);
Raymond Hettingere8b0f042003-05-28 14:05:34 +000035 if (en->en_result == NULL) {
Raymond Hettingere8b0f042003-05-28 14:05:34 +000036 Py_DECREF(en);
37 return NULL;
38 }
Guido van Rossum7dab2422002-04-26 19:40:56 +000039 return (PyObject *)en;
40}
41
42static void
43enum_dealloc(enumobject *en)
44{
45 PyObject_GC_UnTrack(en);
46 Py_XDECREF(en->en_sit);
Raymond Hettingere8b0f042003-05-28 14:05:34 +000047 Py_XDECREF(en->en_result);
Raymond Hettinger8f669372007-10-03 21:18:11 +000048 Py_XDECREF(en->en_longindex);
Christian Heimese93237d2007-12-19 02:37:44 +000049 Py_TYPE(en)->tp_free(en);
Guido van Rossum7dab2422002-04-26 19:40:56 +000050}
51
52static int
53enum_traverse(enumobject *en, visitproc visit, void *arg)
54{
Thomas Woutersc6e55062006-04-15 21:47:09 +000055 Py_VISIT(en->en_sit);
56 Py_VISIT(en->en_result);
Raymond Hettinger8f669372007-10-03 21:18:11 +000057 Py_VISIT(en->en_longindex);
Guido van Rossum7dab2422002-04-26 19:40:56 +000058 return 0;
59}
60
61static PyObject *
Raymond Hettinger8f669372007-10-03 21:18:11 +000062enum_next_long(enumobject *en, PyObject* next_item)
63{
64 static PyObject *one = NULL;
65 PyObject *result = en->en_result;
66 PyObject *next_index;
67 PyObject *stepped_up;
68
69 if (en->en_longindex == NULL) {
70 en->en_longindex = PyInt_FromLong(LONG_MAX);
71 if (en->en_longindex == NULL)
72 return NULL;
73 }
74 if (one == NULL) {
75 one = PyInt_FromLong(1);
76 if (one == NULL)
77 return NULL;
78 }
79 next_index = en->en_longindex;
80 assert(next_index != NULL);
81 stepped_up = PyNumber_Add(next_index, one);
82 if (stepped_up == NULL)
83 return NULL;
84 en->en_longindex = stepped_up;
85
86 if (result->ob_refcnt == 1) {
87 Py_INCREF(result);
88 Py_DECREF(PyTuple_GET_ITEM(result, 0));
89 Py_DECREF(PyTuple_GET_ITEM(result, 1));
90 } else {
91 result = PyTuple_New(2);
92 if (result == NULL) {
93 Py_DECREF(next_index);
94 Py_DECREF(next_item);
95 return NULL;
96 }
97 }
98 PyTuple_SET_ITEM(result, 0, next_index);
99 PyTuple_SET_ITEM(result, 1, next_item);
100 return result;
101}
102
103static PyObject *
Guido van Rossum7dab2422002-04-26 19:40:56 +0000104enum_next(enumobject *en)
105{
Guido van Rossum7dab2422002-04-26 19:40:56 +0000106 PyObject *next_index;
Guido van Rossumca5ed5b2002-07-16 21:02:42 +0000107 PyObject *next_item;
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000108 PyObject *result = en->en_result;
109 PyObject *it = en->en_sit;
Guido van Rossum7dab2422002-04-26 19:40:56 +0000110
Christian Heimese93237d2007-12-19 02:37:44 +0000111 next_item = (*Py_TYPE(it)->tp_iternext)(it);
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000112 if (next_item == NULL)
Guido van Rossumca5ed5b2002-07-16 21:02:42 +0000113 return NULL;
114
Raymond Hettinger8f669372007-10-03 21:18:11 +0000115 if (en->en_index == LONG_MAX)
116 return enum_next_long(en, next_item);
117
Guido van Rossumca5ed5b2002-07-16 21:02:42 +0000118 next_index = PyInt_FromLong(en->en_index);
119 if (next_index == NULL) {
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000120 Py_DECREF(next_item);
Guido van Rossum7dab2422002-04-26 19:40:56 +0000121 return NULL;
122 }
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000123 en->en_index++;
124
125 if (result->ob_refcnt == 1) {
126 Py_INCREF(result);
127 Py_DECREF(PyTuple_GET_ITEM(result, 0));
128 Py_DECREF(PyTuple_GET_ITEM(result, 1));
129 } else {
130 result = PyTuple_New(2);
131 if (result == NULL) {
132 Py_DECREF(next_index);
133 Py_DECREF(next_item);
134 return NULL;
135 }
136 }
Guido van Rossumca5ed5b2002-07-16 21:02:42 +0000137 PyTuple_SET_ITEM(result, 0, next_index);
Guido van Rossum7dab2422002-04-26 19:40:56 +0000138 PyTuple_SET_ITEM(result, 1, next_item);
139 return result;
140}
141
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000142PyDoc_STRVAR(enum_doc,
Jeremy Hyltonfbbe3472003-04-21 20:26:25 +0000143"enumerate(iterable) -> iterator for index, value of iterable\n"
144"\n"
145"Return an enumerate object. iterable must be an other object that supports\n"
146"iteration. The enumerate object yields pairs containing a count (from\n"
147"zero) and a value yielded by the iterable argument. enumerate is useful\n"
148"for obtaining an indexed list: (0, seq[0]), (1, seq[1]), (2, seq[2]), ...");
Guido van Rossum7dab2422002-04-26 19:40:56 +0000149
150PyTypeObject PyEnum_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000151 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Guido van Rossum7dab2422002-04-26 19:40:56 +0000152 "enumerate", /* tp_name */
153 sizeof(enumobject), /* tp_basicsize */
154 0, /* tp_itemsize */
155 /* methods */
156 (destructor)enum_dealloc, /* tp_dealloc */
157 0, /* tp_print */
158 0, /* tp_getattr */
159 0, /* tp_setattr */
160 0, /* tp_compare */
161 0, /* tp_repr */
162 0, /* tp_as_number */
163 0, /* tp_as_sequence */
164 0, /* tp_as_mapping */
165 0, /* tp_hash */
166 0, /* tp_call */
167 0, /* tp_str */
168 PyObject_GenericGetAttr, /* tp_getattro */
169 0, /* tp_setattro */
170 0, /* tp_as_buffer */
171 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
172 Py_TPFLAGS_BASETYPE, /* tp_flags */
173 enum_doc, /* tp_doc */
174 (traverseproc)enum_traverse, /* tp_traverse */
175 0, /* tp_clear */
176 0, /* tp_richcompare */
177 0, /* tp_weaklistoffset */
Raymond Hettinger1da1dbf2003-03-17 19:46:11 +0000178 PyObject_SelfIter, /* tp_iter */
Guido van Rossum7dab2422002-04-26 19:40:56 +0000179 (iternextfunc)enum_next, /* tp_iternext */
Guido van Rossumca5ed5b2002-07-16 21:02:42 +0000180 0, /* tp_methods */
Guido van Rossum7dab2422002-04-26 19:40:56 +0000181 0, /* tp_members */
182 0, /* tp_getset */
183 0, /* tp_base */
184 0, /* tp_dict */
185 0, /* tp_descr_get */
186 0, /* tp_descr_set */
187 0, /* tp_dictoffset */
188 0, /* tp_init */
189 PyType_GenericAlloc, /* tp_alloc */
190 enum_new, /* tp_new */
191 PyObject_GC_Del, /* tp_free */
192};
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000193
194/* Reversed Object ***************************************************************/
195
196typedef struct {
197 PyObject_HEAD
Martin v. Löwiseb079f12006-02-16 14:32:27 +0000198 Py_ssize_t index;
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000199 PyObject* seq;
200} reversedobject;
201
202static PyObject *
203reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
204{
Martin v. Löwiseb079f12006-02-16 14:32:27 +0000205 Py_ssize_t n;
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000206 PyObject *seq;
207 reversedobject *ro;
208
209 if (!PyArg_UnpackTuple(args, "reversed", 1, 1, &seq))
210 return NULL;
211
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000212 if (PyObject_HasAttrString(seq, "__reversed__"))
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000213 return PyObject_CallMethod(seq, "__reversed__", NULL);
214
215 if (!PySequence_Check(seq)) {
216 PyErr_SetString(PyExc_TypeError,
217 "argument to reversed() must be a sequence");
218 return NULL;
219 }
220
221 n = PySequence_Size(seq);
222 if (n == -1)
223 return NULL;
224
225 ro = (reversedobject *)type->tp_alloc(type, 0);
226 if (ro == NULL)
227 return NULL;
228
229 ro->index = n-1;
230 Py_INCREF(seq);
231 ro->seq = seq;
232 return (PyObject *)ro;
233}
234
235static void
236reversed_dealloc(reversedobject *ro)
237{
238 PyObject_GC_UnTrack(ro);
239 Py_XDECREF(ro->seq);
Christian Heimese93237d2007-12-19 02:37:44 +0000240 Py_TYPE(ro)->tp_free(ro);
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000241}
242
243static int
244reversed_traverse(reversedobject *ro, visitproc visit, void *arg)
245{
Thomas Woutersc6e55062006-04-15 21:47:09 +0000246 Py_VISIT(ro->seq);
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000247 return 0;
248}
249
250static PyObject *
251reversed_next(reversedobject *ro)
252{
253 PyObject *item;
Martin v. Löwis725507b2006-03-07 12:08:51 +0000254 Py_ssize_t index = ro->index;
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000255
Raymond Hettingeref9bf402004-03-10 10:10:42 +0000256 if (index >= 0) {
257 item = PySequence_GetItem(ro->seq, index);
258 if (item != NULL) {
259 ro->index--;
260 return item;
261 }
Raymond Hettinger7892b1c2004-04-12 18:10:01 +0000262 if (PyErr_ExceptionMatches(PyExc_IndexError) ||
263 PyErr_ExceptionMatches(PyExc_StopIteration))
264 PyErr_Clear();
Raymond Hettingeref9bf402004-03-10 10:10:42 +0000265 }
266 ro->index = -1;
Raymond Hettinger75ccea32004-09-01 07:02:44 +0000267 Py_CLEAR(ro->seq);
Raymond Hettingeref9bf402004-03-10 10:10:42 +0000268 return NULL;
Raymond Hettinger029dba52004-02-10 09:33:39 +0000269}
270
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000271PyDoc_STRVAR(reversed_doc,
Raymond Hettingerd2afee42004-08-25 19:42:12 +0000272"reversed(sequence) -> reverse iterator over values of the sequence\n"
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000273"\n"
274"Return a reverse iterator");
275
Raymond Hettinger6b27cda2005-09-24 21:23:05 +0000276static PyObject *
Raymond Hettingeref9bf402004-03-10 10:10:42 +0000277reversed_len(reversedobject *ro)
278{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000279 Py_ssize_t position, seqsize;
Raymond Hettinger7892b1c2004-04-12 18:10:01 +0000280
281 if (ro->seq == NULL)
Raymond Hettinger6b27cda2005-09-24 21:23:05 +0000282 return PyInt_FromLong(0);
Raymond Hettinger7892b1c2004-04-12 18:10:01 +0000283 seqsize = PySequence_Size(ro->seq);
284 if (seqsize == -1)
Raymond Hettinger6b27cda2005-09-24 21:23:05 +0000285 return NULL;
Raymond Hettinger7892b1c2004-04-12 18:10:01 +0000286 position = ro->index + 1;
Martin v. Löwiseb079f12006-02-16 14:32:27 +0000287 return PyInt_FromSsize_t((seqsize < position) ? 0 : position);
Raymond Hettingeref9bf402004-03-10 10:10:42 +0000288}
289
Armin Rigof5b3e362006-02-11 21:32:43 +0000290PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
Raymond Hettinger6b27cda2005-09-24 21:23:05 +0000291
292static PyMethodDef reversediter_methods[] = {
Armin Rigof5b3e362006-02-11 21:32:43 +0000293 {"__length_hint__", (PyCFunction)reversed_len, METH_NOARGS, length_hint_doc},
Raymond Hettinger6b27cda2005-09-24 21:23:05 +0000294 {NULL, NULL} /* sentinel */
Raymond Hettinger06353f72004-02-08 10:49:42 +0000295};
296
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000297PyTypeObject PyReversed_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000298 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000299 "reversed", /* tp_name */
300 sizeof(reversedobject), /* tp_basicsize */
301 0, /* tp_itemsize */
302 /* methods */
303 (destructor)reversed_dealloc, /* tp_dealloc */
304 0, /* tp_print */
305 0, /* tp_getattr */
306 0, /* tp_setattr */
307 0, /* tp_compare */
308 0, /* tp_repr */
309 0, /* tp_as_number */
Raymond Hettinger6b27cda2005-09-24 21:23:05 +0000310 0, /* tp_as_sequence */
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000311 0, /* tp_as_mapping */
312 0, /* tp_hash */
313 0, /* tp_call */
314 0, /* tp_str */
315 PyObject_GenericGetAttr, /* tp_getattro */
316 0, /* tp_setattro */
317 0, /* tp_as_buffer */
318 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
319 Py_TPFLAGS_BASETYPE, /* tp_flags */
320 reversed_doc, /* tp_doc */
321 (traverseproc)reversed_traverse,/* tp_traverse */
322 0, /* tp_clear */
323 0, /* tp_richcompare */
324 0, /* tp_weaklistoffset */
325 PyObject_SelfIter, /* tp_iter */
326 (iternextfunc)reversed_next, /* tp_iternext */
Raymond Hettinger6b27cda2005-09-24 21:23:05 +0000327 reversediter_methods, /* tp_methods */
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000328 0, /* tp_members */
329 0, /* tp_getset */
330 0, /* tp_base */
331 0, /* tp_dict */
332 0, /* tp_descr_get */
333 0, /* tp_descr_set */
334 0, /* tp_dictoffset */
335 0, /* tp_init */
336 PyType_GenericAlloc, /* tp_alloc */
337 reversed_new, /* tp_new */
338 PyObject_GC_Del, /* tp_free */
339};