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) -> 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 "zero) and a value yielded by the iterable argument. enumerate is useful\n"
167 "for obtaining an indexed list: (0, seq[0]), (1, seq[1]), (2, seq[2]), ...");
169 PyTypeObject PyEnum_Type
= {
170 PyVarObject_HEAD_INIT(&PyType_Type
, 0)
171 "enumerate", /* tp_name */
172 sizeof(enumobject
), /* tp_basicsize */
175 (destructor
)enum_dealloc
, /* tp_dealloc */
181 0, /* tp_as_number */
182 0, /* tp_as_sequence */
183 0, /* tp_as_mapping */
187 PyObject_GenericGetAttr
, /* tp_getattro */
189 0, /* tp_as_buffer */
190 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GC
|
191 Py_TPFLAGS_BASETYPE
, /* tp_flags */
192 enum_doc
, /* tp_doc */
193 (traverseproc
)enum_traverse
, /* tp_traverse */
195 0, /* tp_richcompare */
196 0, /* tp_weaklistoffset */
197 PyObject_SelfIter
, /* tp_iter */
198 (iternextfunc
)enum_next
, /* tp_iternext */
204 0, /* tp_descr_get */
205 0, /* tp_descr_set */
206 0, /* tp_dictoffset */
208 PyType_GenericAlloc
, /* tp_alloc */
209 enum_new
, /* tp_new */
210 PyObject_GC_Del
, /* tp_free */
213 /* Reversed Object ***************************************************************/
222 reversed_new(PyTypeObject
*type
, PyObject
*args
, PyObject
*kwds
)
225 PyObject
*seq
, *reversed_meth
;
226 static PyObject
*reversed_cache
= NULL
;
229 if (type
== &PyReversed_Type
&& !_PyArg_NoKeywords("reversed()", kwds
))
232 if (!PyArg_UnpackTuple(args
, "reversed", 1, 1, &seq
) )
235 if (PyInstance_Check(seq
)) {
236 reversed_meth
= PyObject_GetAttrString(seq
, "__reversed__");
237 if (reversed_meth
== NULL
) {
238 if (PyErr_ExceptionMatches(PyExc_AttributeError
))
245 reversed_meth
= _PyObject_LookupSpecial(seq
, "__reversed__",
247 if (reversed_meth
== NULL
&& PyErr_Occurred())
250 if (reversed_meth
!= NULL
) {
251 PyObject
*res
= PyObject_CallFunctionObjArgs(reversed_meth
, NULL
);
252 Py_DECREF(reversed_meth
);
256 if (!PySequence_Check(seq
)) {
257 PyErr_SetString(PyExc_TypeError
,
258 "argument to reversed() must be a sequence");
262 n
= PySequence_Size(seq
);
266 ro
= (reversedobject
*)type
->tp_alloc(type
, 0);
273 return (PyObject
*)ro
;
277 reversed_dealloc(reversedobject
*ro
)
279 PyObject_GC_UnTrack(ro
);
281 Py_TYPE(ro
)->tp_free(ro
);
285 reversed_traverse(reversedobject
*ro
, visitproc visit
, void *arg
)
292 reversed_next(reversedobject
*ro
)
295 Py_ssize_t index
= ro
->index
;
298 item
= PySequence_GetItem(ro
->seq
, index
);
303 if (PyErr_ExceptionMatches(PyExc_IndexError
) ||
304 PyErr_ExceptionMatches(PyExc_StopIteration
))
312 PyDoc_STRVAR(reversed_doc
,
313 "reversed(sequence) -> reverse iterator over values of the sequence\n"
315 "Return a reverse iterator");
318 reversed_len(reversedobject
*ro
)
320 Py_ssize_t position
, seqsize
;
323 return PyInt_FromLong(0);
324 seqsize
= PySequence_Size(ro
->seq
);
327 position
= ro
->index
+ 1;
328 return PyInt_FromSsize_t((seqsize
< position
) ? 0 : position
);
331 PyDoc_STRVAR(length_hint_doc
, "Private method returning an estimate of len(list(it)).");
333 static PyMethodDef reversediter_methods
[] = {
334 {"__length_hint__", (PyCFunction
)reversed_len
, METH_NOARGS
, length_hint_doc
},
335 {NULL
, NULL
} /* sentinel */
338 PyTypeObject PyReversed_Type
= {
339 PyVarObject_HEAD_INIT(&PyType_Type
, 0)
340 "reversed", /* tp_name */
341 sizeof(reversedobject
), /* tp_basicsize */
344 (destructor
)reversed_dealloc
, /* tp_dealloc */
350 0, /* tp_as_number */
351 0, /* tp_as_sequence */
352 0, /* tp_as_mapping */
356 PyObject_GenericGetAttr
, /* tp_getattro */
358 0, /* tp_as_buffer */
359 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GC
|
360 Py_TPFLAGS_BASETYPE
, /* tp_flags */
361 reversed_doc
, /* tp_doc */
362 (traverseproc
)reversed_traverse
,/* tp_traverse */
364 0, /* tp_richcompare */
365 0, /* tp_weaklistoffset */
366 PyObject_SelfIter
, /* tp_iter */
367 (iternextfunc
)reversed_next
, /* tp_iternext */
368 reversediter_methods
, /* tp_methods */
373 0, /* tp_descr_get */
374 0, /* tp_descr_set */
375 0, /* tp_dictoffset */
377 PyType_GenericAlloc
, /* tp_alloc */
378 reversed_new
, /* tp_new */
379 PyObject_GC_Del
, /* tp_free */