blob: 480768fbdebc934173025e20db07a0b1499ba2fb [file] [log] [blame]
Guido van Rossum7dab2422002-04-26 19:40:56 +00001/* enumerate object */
2
3#include "Python.h"
4
Serhiy Storchaka41baebd2017-01-19 18:48:17 +02005#include "clinic/enumobject.c.h"
6
7/*[clinic input]
8class enumerate "enumobject *" "&PyEnum_Type"
9class reversed "reversedobject *" "&PyReversed_Type"
10[clinic start generated code]*/
11/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d2dfdf1a88c88975]*/
12
Guido van Rossum7dab2422002-04-26 19:40:56 +000013typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000014 PyObject_HEAD
15 Py_ssize_t en_index; /* current index of enumeration */
16 PyObject* en_sit; /* secondary iterator of enumeration */
17 PyObject* en_result; /* result tuple */
18 PyObject* en_longindex; /* index for sequences >= PY_SSIZE_T_MAX */
Guido van Rossum7dab2422002-04-26 19:40:56 +000019} enumobject;
20
Serhiy Storchaka41baebd2017-01-19 18:48:17 +020021
22/*[clinic input]
23@classmethod
24enumerate.__new__ as enum_new
25
26 iterable: object
27 an object supporting iteration
28 start: object = 0
29
30Return an enumerate object.
31
32The enumerate object yields pairs containing a count (from start, which
33defaults to zero) and a value yielded by the iterable argument.
34
35enumerate is useful for obtaining an indexed list:
36 (0, seq[0]), (1, seq[1]), (2, seq[2]), ...
37[clinic start generated code]*/
38
Guido van Rossum7dab2422002-04-26 19:40:56 +000039static PyObject *
Serhiy Storchaka41baebd2017-01-19 18:48:17 +020040enum_new_impl(PyTypeObject *type, PyObject *iterable, PyObject *start)
41/*[clinic end generated code: output=e95e6e439f812c10 input=782e4911efcb8acf]*/
Guido van Rossum7dab2422002-04-26 19:40:56 +000042{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000043 enumobject *en;
Guido van Rossum7dab2422002-04-26 19:40:56 +000044
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000045 en = (enumobject *)type->tp_alloc(type, 0);
46 if (en == NULL)
47 return NULL;
48 if (start != NULL) {
49 start = PyNumber_Index(start);
50 if (start == NULL) {
51 Py_DECREF(en);
52 return NULL;
53 }
54 assert(PyLong_Check(start));
55 en->en_index = PyLong_AsSsize_t(start);
56 if (en->en_index == -1 && PyErr_Occurred()) {
57 PyErr_Clear();
58 en->en_index = PY_SSIZE_T_MAX;
59 en->en_longindex = start;
60 } else {
61 en->en_longindex = NULL;
62 Py_DECREF(start);
63 }
64 } else {
65 en->en_index = 0;
66 en->en_longindex = NULL;
67 }
Serhiy Storchaka41baebd2017-01-19 18:48:17 +020068 en->en_sit = PyObject_GetIter(iterable);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000069 if (en->en_sit == NULL) {
70 Py_DECREF(en);
71 return NULL;
72 }
73 en->en_result = PyTuple_Pack(2, Py_None, Py_None);
74 if (en->en_result == NULL) {
75 Py_DECREF(en);
76 return NULL;
77 }
78 return (PyObject *)en;
Guido van Rossum7dab2422002-04-26 19:40:56 +000079}
80
81static void
82enum_dealloc(enumobject *en)
83{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000084 PyObject_GC_UnTrack(en);
85 Py_XDECREF(en->en_sit);
86 Py_XDECREF(en->en_result);
87 Py_XDECREF(en->en_longindex);
88 Py_TYPE(en)->tp_free(en);
Guido van Rossum7dab2422002-04-26 19:40:56 +000089}
90
91static int
92enum_traverse(enumobject *en, visitproc visit, void *arg)
93{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000094 Py_VISIT(en->en_sit);
95 Py_VISIT(en->en_result);
96 Py_VISIT(en->en_longindex);
97 return 0;
Guido van Rossum7dab2422002-04-26 19:40:56 +000098}
99
100static PyObject *
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000101enum_next_long(enumobject *en, PyObject* next_item)
102{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000103 static PyObject *one = NULL;
104 PyObject *result = en->en_result;
105 PyObject *next_index;
106 PyObject *stepped_up;
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000107
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000108 if (en->en_longindex == NULL) {
109 en->en_longindex = PyLong_FromSsize_t(PY_SSIZE_T_MAX);
110 if (en->en_longindex == NULL)
111 return NULL;
112 }
113 if (one == NULL) {
114 one = PyLong_FromLong(1);
115 if (one == NULL)
116 return NULL;
117 }
118 next_index = en->en_longindex;
119 assert(next_index != NULL);
120 stepped_up = PyNumber_Add(next_index, one);
121 if (stepped_up == NULL)
122 return NULL;
123 en->en_longindex = stepped_up;
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000124
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000125 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 }
137 PyTuple_SET_ITEM(result, 0, next_index);
138 PyTuple_SET_ITEM(result, 1, next_item);
139 return result;
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000140}
141
142static PyObject *
Guido van Rossum7dab2422002-04-26 19:40:56 +0000143enum_next(enumobject *en)
144{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000145 PyObject *next_index;
146 PyObject *next_item;
147 PyObject *result = en->en_result;
148 PyObject *it = en->en_sit;
Guido van Rossum7dab2422002-04-26 19:40:56 +0000149
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000150 next_item = (*Py_TYPE(it)->tp_iternext)(it);
151 if (next_item == NULL)
152 return NULL;
Guido van Rossumca5ed5b2002-07-16 21:02:42 +0000153
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000154 if (en->en_index == PY_SSIZE_T_MAX)
155 return enum_next_long(en, next_item);
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000156
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000157 next_index = PyLong_FromSsize_t(en->en_index);
158 if (next_index == NULL) {
159 Py_DECREF(next_item);
160 return NULL;
161 }
162 en->en_index++;
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000163
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000164 if (result->ob_refcnt == 1) {
165 Py_INCREF(result);
166 Py_DECREF(PyTuple_GET_ITEM(result, 0));
167 Py_DECREF(PyTuple_GET_ITEM(result, 1));
168 } else {
169 result = PyTuple_New(2);
170 if (result == NULL) {
171 Py_DECREF(next_index);
172 Py_DECREF(next_item);
173 return NULL;
174 }
175 }
176 PyTuple_SET_ITEM(result, 0, next_index);
177 PyTuple_SET_ITEM(result, 1, next_item);
178 return result;
Guido van Rossum7dab2422002-04-26 19:40:56 +0000179}
180
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000181static PyObject *
182enum_reduce(enumobject *en)
183{
184 if (en->en_longindex != NULL)
185 return Py_BuildValue("O(OO)", Py_TYPE(en), en->en_sit, en->en_longindex);
186 else
187 return Py_BuildValue("O(On)", Py_TYPE(en), en->en_sit, en->en_index);
188}
189
190PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
191
192static PyMethodDef enum_methods[] = {
193 {"__reduce__", (PyCFunction)enum_reduce, METH_NOARGS, reduce_doc},
194 {NULL, NULL} /* sentinel */
195};
196
Guido van Rossum7dab2422002-04-26 19:40:56 +0000197PyTypeObject PyEnum_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000198 PyVarObject_HEAD_INIT(&PyType_Type, 0)
199 "enumerate", /* tp_name */
200 sizeof(enumobject), /* tp_basicsize */
201 0, /* tp_itemsize */
202 /* methods */
203 (destructor)enum_dealloc, /* tp_dealloc */
204 0, /* tp_print */
205 0, /* tp_getattr */
206 0, /* tp_setattr */
207 0, /* tp_reserved */
208 0, /* tp_repr */
209 0, /* tp_as_number */
210 0, /* tp_as_sequence */
211 0, /* tp_as_mapping */
212 0, /* tp_hash */
213 0, /* tp_call */
214 0, /* tp_str */
215 PyObject_GenericGetAttr, /* tp_getattro */
216 0, /* tp_setattro */
217 0, /* tp_as_buffer */
218 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Serhiy Storchaka41baebd2017-01-19 18:48:17 +0200219 Py_TPFLAGS_BASETYPE, /* tp_flags */
220 enum_new__doc__, /* tp_doc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000221 (traverseproc)enum_traverse, /* tp_traverse */
222 0, /* tp_clear */
223 0, /* tp_richcompare */
224 0, /* tp_weaklistoffset */
Serhiy Storchaka41baebd2017-01-19 18:48:17 +0200225 PyObject_SelfIter, /* tp_iter */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000226 (iternextfunc)enum_next, /* tp_iternext */
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000227 enum_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000228 0, /* tp_members */
229 0, /* tp_getset */
230 0, /* tp_base */
231 0, /* tp_dict */
232 0, /* tp_descr_get */
233 0, /* tp_descr_set */
234 0, /* tp_dictoffset */
235 0, /* tp_init */
236 PyType_GenericAlloc, /* tp_alloc */
237 enum_new, /* tp_new */
238 PyObject_GC_Del, /* tp_free */
Guido van Rossum7dab2422002-04-26 19:40:56 +0000239};
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000240
241/* Reversed Object ***************************************************************/
242
243typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000244 PyObject_HEAD
245 Py_ssize_t index;
246 PyObject* seq;
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000247} reversedobject;
248
Serhiy Storchaka41baebd2017-01-19 18:48:17 +0200249/*[clinic input]
250@classmethod
251reversed.__new__ as reversed_new
252
253 sequence as seq: object
254 /
255
256Return a reverse iterator over the values of the given sequence.
257[clinic start generated code]*/
258
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000259static PyObject *
Serhiy Storchaka41baebd2017-01-19 18:48:17 +0200260reversed_new_impl(PyTypeObject *type, PyObject *seq)
261/*[clinic end generated code: output=f7854cc1df26f570 input=aeb720361e5e3f1d]*/
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000262{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000263 Py_ssize_t n;
Serhiy Storchaka41baebd2017-01-19 18:48:17 +0200264 PyObject *reversed_meth;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000265 reversedobject *ro;
Benjamin Petersonce798522012-01-22 11:24:29 -0500266 _Py_IDENTIFIER(__reversed__);
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000267
Benjamin Petersonce798522012-01-22 11:24:29 -0500268 reversed_meth = _PyObject_LookupSpecial(seq, &PyId___reversed__);
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700269 if (reversed_meth == Py_None) {
270 Py_DECREF(reversed_meth);
271 PyErr_Format(PyExc_TypeError,
272 "'%.200s' object is not reversible",
273 Py_TYPE(seq)->tp_name);
274 return NULL;
275 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000276 if (reversed_meth != NULL) {
Victor Stinnerf17c3de2016-12-06 18:46:19 +0100277 PyObject *res = _PyObject_CallNoArg(reversed_meth);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000278 Py_DECREF(reversed_meth);
279 return res;
280 }
281 else if (PyErr_Occurred())
282 return NULL;
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000283
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000284 if (!PySequence_Check(seq)) {
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700285 PyErr_Format(PyExc_TypeError,
286 "'%.200s' object is not reversible",
287 Py_TYPE(seq)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000288 return NULL;
289 }
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000290
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000291 n = PySequence_Size(seq);
292 if (n == -1)
293 return NULL;
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000294
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000295 ro = (reversedobject *)type->tp_alloc(type, 0);
296 if (ro == NULL)
297 return NULL;
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000298
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000299 ro->index = n-1;
300 Py_INCREF(seq);
301 ro->seq = seq;
302 return (PyObject *)ro;
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000303}
304
305static void
306reversed_dealloc(reversedobject *ro)
307{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000308 PyObject_GC_UnTrack(ro);
309 Py_XDECREF(ro->seq);
310 Py_TYPE(ro)->tp_free(ro);
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000311}
312
313static int
314reversed_traverse(reversedobject *ro, visitproc visit, void *arg)
315{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000316 Py_VISIT(ro->seq);
317 return 0;
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000318}
319
320static PyObject *
321reversed_next(reversedobject *ro)
322{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000323 PyObject *item;
324 Py_ssize_t index = ro->index;
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000326 if (index >= 0) {
327 item = PySequence_GetItem(ro->seq, index);
328 if (item != NULL) {
329 ro->index--;
330 return item;
331 }
332 if (PyErr_ExceptionMatches(PyExc_IndexError) ||
333 PyErr_ExceptionMatches(PyExc_StopIteration))
334 PyErr_Clear();
335 }
336 ro->index = -1;
337 Py_CLEAR(ro->seq);
338 return NULL;
Raymond Hettinger029dba52004-02-10 09:33:39 +0000339}
340
Raymond Hettinger6b27cda2005-09-24 21:23:05 +0000341static PyObject *
Raymond Hettingeref9bf402004-03-10 10:10:42 +0000342reversed_len(reversedobject *ro)
343{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000344 Py_ssize_t position, seqsize;
Raymond Hettinger7892b1c2004-04-12 18:10:01 +0000345
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000346 if (ro->seq == NULL)
347 return PyLong_FromLong(0);
348 seqsize = PySequence_Size(ro->seq);
349 if (seqsize == -1)
350 return NULL;
351 position = ro->index + 1;
352 return PyLong_FromSsize_t((seqsize < position) ? 0 : position);
Raymond Hettingeref9bf402004-03-10 10:10:42 +0000353}
354
Armin Rigof5b3e362006-02-11 21:32:43 +0000355PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
Raymond Hettinger6b27cda2005-09-24 21:23:05 +0000356
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000357static PyObject *
358reversed_reduce(reversedobject *ro)
359{
360 if (ro->seq)
361 return Py_BuildValue("O(O)n", Py_TYPE(ro), ro->seq, ro->index);
362 else
363 return Py_BuildValue("O(())", Py_TYPE(ro));
364}
365
366static PyObject *
367reversed_setstate(reversedobject *ro, PyObject *state)
368{
369 Py_ssize_t index = PyLong_AsSsize_t(state);
370 if (index == -1 && PyErr_Occurred())
371 return NULL;
372 if (ro->seq != 0) {
373 Py_ssize_t n = PySequence_Size(ro->seq);
374 if (n < 0)
375 return NULL;
376 if (index < -1)
377 index = -1;
378 else if (index > n-1)
379 index = n-1;
380 ro->index = index;
381 }
382 Py_RETURN_NONE;
383}
384
385PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
386
Raymond Hettinger6b27cda2005-09-24 21:23:05 +0000387static PyMethodDef reversediter_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000388 {"__length_hint__", (PyCFunction)reversed_len, METH_NOARGS, length_hint_doc},
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000389 {"__reduce__", (PyCFunction)reversed_reduce, METH_NOARGS, reduce_doc},
390 {"__setstate__", (PyCFunction)reversed_setstate, METH_O, setstate_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000391 {NULL, NULL} /* sentinel */
Raymond Hettinger06353f72004-02-08 10:49:42 +0000392};
393
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000394PyTypeObject PyReversed_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000395 PyVarObject_HEAD_INIT(&PyType_Type, 0)
396 "reversed", /* tp_name */
397 sizeof(reversedobject), /* tp_basicsize */
398 0, /* tp_itemsize */
399 /* methods */
400 (destructor)reversed_dealloc, /* tp_dealloc */
401 0, /* tp_print */
402 0, /* tp_getattr */
403 0, /* tp_setattr */
404 0, /* tp_reserved */
405 0, /* tp_repr */
406 0, /* tp_as_number */
Serhiy Storchaka41baebd2017-01-19 18:48:17 +0200407 0, /* tp_as_sequence */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000408 0, /* tp_as_mapping */
409 0, /* tp_hash */
410 0, /* tp_call */
411 0, /* tp_str */
412 PyObject_GenericGetAttr, /* tp_getattro */
413 0, /* tp_setattro */
414 0, /* tp_as_buffer */
415 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Serhiy Storchaka41baebd2017-01-19 18:48:17 +0200416 Py_TPFLAGS_BASETYPE, /* tp_flags */
417 reversed_new__doc__, /* tp_doc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000418 (traverseproc)reversed_traverse,/* tp_traverse */
419 0, /* tp_clear */
420 0, /* tp_richcompare */
421 0, /* tp_weaklistoffset */
Serhiy Storchaka41baebd2017-01-19 18:48:17 +0200422 PyObject_SelfIter, /* tp_iter */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000423 (iternextfunc)reversed_next, /* tp_iternext */
Serhiy Storchaka41baebd2017-01-19 18:48:17 +0200424 reversediter_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000425 0, /* tp_members */
426 0, /* tp_getset */
427 0, /* tp_base */
428 0, /* tp_dict */
429 0, /* tp_descr_get */
430 0, /* tp_descr_set */
431 0, /* tp_dictoffset */
432 0, /* tp_init */
433 PyType_GenericAlloc, /* tp_alloc */
434 reversed_new, /* tp_new */
435 PyObject_GC_Del, /* tp_free */
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000436};