7 Py_ssize_t en_index
; /* current index of enumeration */
8 PyObject
* en_sit
; /* secondary iterator of enumeration */
9 PyObject
* en_result
; /* result tuple */
10 PyObject
* en_longindex
; /* index for sequences >= PY_SSIZE_T_MAX */
14 enum_new(PyTypeObject
*type
, PyObject
*args
, PyObject
*kwds
)
18 PyObject
*start
= NULL
;
19 static char *kwlist
[] = {"sequence", "start", 0};
21 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "O|O:enumerate", kwlist
,
25 en
= (enumobject
*)type
->tp_alloc(type
, 0);
29 start
= PyNumber_Index(start
);
34 assert(PyInt_Check(start
) || PyLong_Check(start
));
35 en
->en_index
= PyInt_AsSsize_t(start
);
36 if (en
->en_index
== -1 && PyErr_Occurred()) {
38 en
->en_index
= PY_SSIZE_T_MAX
;
39 en
->en_longindex
= start
;
41 en
->en_longindex
= NULL
;
46 en
->en_longindex
= NULL
;
48 en
->en_sit
= PyObject_GetIter(seq
);
49 if (en
->en_sit
== NULL
) {
53 en
->en_result
= PyTuple_Pack(2, Py_None
, Py_None
);
54 if (en
->en_result
== NULL
) {
58 return (PyObject
*)en
;
62 enum_dealloc(enumobject
*en
)
64 PyObject_GC_UnTrack(en
);
65 Py_XDECREF(en
->en_sit
);
66 Py_XDECREF(en
->en_result
);
67 Py_XDECREF(en
->en_longindex
);
68 Py_TYPE(en
)->tp_free(en
);
72 enum_traverse(enumobject
*en
, visitproc visit
, void *arg
)
75 Py_VISIT(en
->en_result
);
76 Py_VISIT(en
->en_longindex
);
81 enum_next_long(enumobject
*en
, PyObject
* next_item
)
83 static PyObject
*one
= NULL
;
84 PyObject
*result
= en
->en_result
;
88 if (en
->en_longindex
== NULL
) {
89 en
->en_longindex
= PyInt_FromSsize_t(PY_SSIZE_T_MAX
);
90 if (en
->en_longindex
== NULL
)
94 one
= PyInt_FromLong(1);
98 next_index
= en
->en_longindex
;
99 assert(next_index
!= NULL
);
100 stepped_up
= PyNumber_Add(next_index
, one
);
101 if (stepped_up
== NULL
)
103 en
->en_longindex
= stepped_up
;
105 if (result
->ob_refcnt
== 1) {
107 Py_DECREF(PyTuple_GET_ITEM(result
, 0));
108 Py_DECREF(PyTuple_GET_ITEM(result
, 1));
110 result
= PyTuple_New(2);
111 if (result
== NULL
) {
112 Py_DECREF(next_index
);
113 Py_DECREF(next_item
);
117 PyTuple_SET_ITEM(result
, 0, next_index
);
118 PyTuple_SET_ITEM(result
, 1, next_item
);
123 enum_next(enumobject
*en
)
125 PyObject
*next_index
;
127 PyObject
*result
= en
->en_result
;
128 PyObject
*it
= en
->en_sit
;
130 next_item
= (*Py_TYPE(it
)->tp_iternext
)(it
);
131 if (next_item
== NULL
)
134 if (en
->en_index
== PY_SSIZE_T_MAX
)
135 return enum_next_long(en
, next_item
);
137 next_index
= PyInt_FromSsize_t(en
->en_index
);
138 if (next_index
== NULL
) {
139 Py_DECREF(next_item
);
144 if (result
->ob_refcnt
== 1) {
146 Py_DECREF(PyTuple_GET_ITEM(result
, 0));
147 Py_DECREF(PyTuple_GET_ITEM(result
, 1));
149 result
= PyTuple_New(2);
150 if (result
== NULL
) {
151 Py_DECREF(next_index
);
152 Py_DECREF(next_item
);
156 PyTuple_SET_ITEM(result
, 0, next_index
);
157 PyTuple_SET_ITEM(result
, 1, next_item
);
161 PyDoc_STRVAR(enum_doc
,
162 "enumerate(iterable[, start]) -> iterator for index, value of iterable\n"
164 "Return an enumerate object. iterable must be another object that supports\n"
165 "iteration. The enumerate object yields pairs containing a count (from\n"
166 "start, which defaults to zero) and a value yielded by the iterable argument.\n"
167 "enumerate is useful for obtaining an indexed list:\n"
168 " (0, seq[0]), (1, seq[1]), (2, seq[2]), ...");
170 PyTypeObject PyEnum_Type
= {
171 PyVarObject_HEAD_INIT(&PyType_Type
, 0)
172 "enumerate", /* tp_name */
173 sizeof(enumobject
), /* tp_basicsize */
176 (destructor
)enum_dealloc
, /* tp_dealloc */
182 0, /* tp_as_number */
183 0, /* tp_as_sequence */
184 0, /* tp_as_mapping */
188 PyObject_GenericGetAttr
, /* tp_getattro */
190 0, /* tp_as_buffer */
191 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GC
|
192 Py_TPFLAGS_BASETYPE
, /* tp_flags */
193 enum_doc
, /* tp_doc */
194 (traverseproc
)enum_traverse
, /* tp_traverse */
196 0, /* tp_richcompare */
197 0, /* tp_weaklistoffset */
198 PyObject_SelfIter
, /* tp_iter */
199 (iternextfunc
)enum_next
, /* tp_iternext */
205 0, /* tp_descr_get */
206 0, /* tp_descr_set */
207 0, /* tp_dictoffset */
209 PyType_GenericAlloc
, /* tp_alloc */
210 enum_new
, /* tp_new */
211 PyObject_GC_Del
, /* tp_free */
214 /* Reversed Object ***************************************************************/
223 reversed_new(PyTypeObject
*type
, PyObject
*args
, PyObject
*kwds
)
226 PyObject
*seq
, *reversed_meth
;
227 static PyObject
*reversed_cache
= NULL
;
230 if (type
== &PyReversed_Type
&& !_PyArg_NoKeywords("reversed()", kwds
))
233 if (!PyArg_UnpackTuple(args
, "reversed", 1, 1, &seq
) )
236 if (PyInstance_Check(seq
)) {
237 reversed_meth
= PyObject_GetAttrString(seq
, "__reversed__");
238 if (reversed_meth
== NULL
) {
239 if (PyErr_ExceptionMatches(PyExc_AttributeError
))
246 reversed_meth
= _PyObject_LookupSpecial(seq
, "__reversed__",
248 if (reversed_meth
== NULL
&& PyErr_Occurred())
251 if (reversed_meth
!= NULL
) {
252 PyObject
*res
= PyObject_CallFunctionObjArgs(reversed_meth
, NULL
);
253 Py_DECREF(reversed_meth
);
257 if (!PySequence_Check(seq
)) {
258 PyErr_SetString(PyExc_TypeError
,
259 "argument to reversed() must be a sequence");
263 n
= PySequence_Size(seq
);
267 ro
= (reversedobject
*)type
->tp_alloc(type
, 0);
274 return (PyObject
*)ro
;
278 reversed_dealloc(reversedobject
*ro
)
280 PyObject_GC_UnTrack(ro
);
282 Py_TYPE(ro
)->tp_free(ro
);
286 reversed_traverse(reversedobject
*ro
, visitproc visit
, void *arg
)
293 reversed_next(reversedobject
*ro
)
296 Py_ssize_t index
= ro
->index
;
299 item
= PySequence_GetItem(ro
->seq
, index
);
304 if (PyErr_ExceptionMatches(PyExc_IndexError
) ||
305 PyErr_ExceptionMatches(PyExc_StopIteration
))
313 PyDoc_STRVAR(reversed_doc
,
314 "reversed(sequence) -> reverse iterator over values of the sequence\n"
316 "Return a reverse iterator");
319 reversed_len(reversedobject
*ro
)
321 Py_ssize_t position
, seqsize
;
324 return PyInt_FromLong(0);
325 seqsize
= PySequence_Size(ro
->seq
);
328 position
= ro
->index
+ 1;
329 return PyInt_FromSsize_t((seqsize
< position
) ? 0 : position
);
332 PyDoc_STRVAR(length_hint_doc
, "Private method returning an estimate of len(list(it)).");
334 static PyMethodDef reversediter_methods
[] = {
335 {"__length_hint__", (PyCFunction
)reversed_len
, METH_NOARGS
, length_hint_doc
},
336 {NULL
, NULL
} /* sentinel */
339 PyTypeObject PyReversed_Type
= {
340 PyVarObject_HEAD_INIT(&PyType_Type
, 0)
341 "reversed", /* tp_name */
342 sizeof(reversedobject
), /* tp_basicsize */
345 (destructor
)reversed_dealloc
, /* tp_dealloc */
351 0, /* tp_as_number */
352 0, /* tp_as_sequence */
353 0, /* tp_as_mapping */
357 PyObject_GenericGetAttr
, /* tp_getattro */
359 0, /* tp_as_buffer */
360 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GC
|
361 Py_TPFLAGS_BASETYPE
, /* tp_flags */
362 reversed_doc
, /* tp_doc */
363 (traverseproc
)reversed_traverse
,/* tp_traverse */
365 0, /* tp_richcompare */
366 0, /* tp_weaklistoffset */
367 PyObject_SelfIter
, /* tp_iter */
368 (iternextfunc
)reversed_next
, /* tp_iternext */
369 reversediter_methods
, /* tp_methods */
374 0, /* tp_descr_get */
375 0, /* tp_descr_set */
376 0, /* tp_dictoffset */
378 PyType_GenericAlloc
, /* tp_alloc */
379 reversed_new
, /* tp_new */
380 PyObject_GC_Del
, /* tp_free */