ยปCore Development>Code coverage>Objects/enumobject.c

Python code coverage for Objects/enumobject.c

#countcontent
1n/a/* enumerate object */
2n/a
3n/a#include "Python.h"
4n/a
5n/a#include "clinic/enumobject.c.h"
6n/a
7n/a/*[clinic input]
8n/aclass enumerate "enumobject *" "&PyEnum_Type"
9n/aclass reversed "reversedobject *" "&PyReversed_Type"
10n/a[clinic start generated code]*/
11n/a/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d2dfdf1a88c88975]*/
12n/a
13n/atypedef struct {
14n/a PyObject_HEAD
15n/a Py_ssize_t en_index; /* current index of enumeration */
16n/a PyObject* en_sit; /* secondary iterator of enumeration */
17n/a PyObject* en_result; /* result tuple */
18n/a PyObject* en_longindex; /* index for sequences >= PY_SSIZE_T_MAX */
19n/a} enumobject;
20n/a
21n/a
22n/a/*[clinic input]
23n/a@classmethod
24n/aenumerate.__new__ as enum_new
25n/a
26n/a iterable: object
27n/a an object supporting iteration
28n/a start: object = 0
29n/a
30n/aReturn an enumerate object.
31n/a
32n/aThe enumerate object yields pairs containing a count (from start, which
33n/adefaults to zero) and a value yielded by the iterable argument.
34n/a
35n/aenumerate is useful for obtaining an indexed list:
36n/a (0, seq[0]), (1, seq[1]), (2, seq[2]), ...
37n/a[clinic start generated code]*/
38n/a
39n/astatic PyObject *
40n/aenum_new_impl(PyTypeObject *type, PyObject *iterable, PyObject *start)
41n/a/*[clinic end generated code: output=e95e6e439f812c10 input=782e4911efcb8acf]*/
42n/a{
43n/a enumobject *en;
44n/a
45n/a en = (enumobject *)type->tp_alloc(type, 0);
46n/a if (en == NULL)
47n/a return NULL;
48n/a if (start != NULL) {
49n/a start = PyNumber_Index(start);
50n/a if (start == NULL) {
51n/a Py_DECREF(en);
52n/a return NULL;
53n/a }
54n/a assert(PyLong_Check(start));
55n/a en->en_index = PyLong_AsSsize_t(start);
56n/a if (en->en_index == -1 && PyErr_Occurred()) {
57n/a PyErr_Clear();
58n/a en->en_index = PY_SSIZE_T_MAX;
59n/a en->en_longindex = start;
60n/a } else {
61n/a en->en_longindex = NULL;
62n/a Py_DECREF(start);
63n/a }
64n/a } else {
65n/a en->en_index = 0;
66n/a en->en_longindex = NULL;
67n/a }
68n/a en->en_sit = PyObject_GetIter(iterable);
69n/a if (en->en_sit == NULL) {
70n/a Py_DECREF(en);
71n/a return NULL;
72n/a }
73n/a en->en_result = PyTuple_Pack(2, Py_None, Py_None);
74n/a if (en->en_result == NULL) {
75n/a Py_DECREF(en);
76n/a return NULL;
77n/a }
78n/a return (PyObject *)en;
79n/a}
80n/a
81n/astatic void
82n/aenum_dealloc(enumobject *en)
83n/a{
84n/a PyObject_GC_UnTrack(en);
85n/a Py_XDECREF(en->en_sit);
86n/a Py_XDECREF(en->en_result);
87n/a Py_XDECREF(en->en_longindex);
88n/a Py_TYPE(en)->tp_free(en);
89n/a}
90n/a
91n/astatic int
92n/aenum_traverse(enumobject *en, visitproc visit, void *arg)
93n/a{
94n/a Py_VISIT(en->en_sit);
95n/a Py_VISIT(en->en_result);
96n/a Py_VISIT(en->en_longindex);
97n/a return 0;
98n/a}
99n/a
100n/astatic PyObject *
101n/aenum_next_long(enumobject *en, PyObject* next_item)
102n/a{
103n/a static PyObject *one = NULL;
104n/a PyObject *result = en->en_result;
105n/a PyObject *next_index;
106n/a PyObject *stepped_up;
107n/a
108n/a if (en->en_longindex == NULL) {
109n/a en->en_longindex = PyLong_FromSsize_t(PY_SSIZE_T_MAX);
110n/a if (en->en_longindex == NULL)
111n/a return NULL;
112n/a }
113n/a if (one == NULL) {
114n/a one = PyLong_FromLong(1);
115n/a if (one == NULL)
116n/a return NULL;
117n/a }
118n/a next_index = en->en_longindex;
119n/a assert(next_index != NULL);
120n/a stepped_up = PyNumber_Add(next_index, one);
121n/a if (stepped_up == NULL)
122n/a return NULL;
123n/a en->en_longindex = stepped_up;
124n/a
125n/a if (result->ob_refcnt == 1) {
126n/a Py_INCREF(result);
127n/a Py_DECREF(PyTuple_GET_ITEM(result, 0));
128n/a Py_DECREF(PyTuple_GET_ITEM(result, 1));
129n/a } else {
130n/a result = PyTuple_New(2);
131n/a if (result == NULL) {
132n/a Py_DECREF(next_index);
133n/a Py_DECREF(next_item);
134n/a return NULL;
135n/a }
136n/a }
137n/a PyTuple_SET_ITEM(result, 0, next_index);
138n/a PyTuple_SET_ITEM(result, 1, next_item);
139n/a return result;
140n/a}
141n/a
142n/astatic PyObject *
143n/aenum_next(enumobject *en)
144n/a{
145n/a PyObject *next_index;
146n/a PyObject *next_item;
147n/a PyObject *result = en->en_result;
148n/a PyObject *it = en->en_sit;
149n/a
150n/a next_item = (*Py_TYPE(it)->tp_iternext)(it);
151n/a if (next_item == NULL)
152n/a return NULL;
153n/a
154n/a if (en->en_index == PY_SSIZE_T_MAX)
155n/a return enum_next_long(en, next_item);
156n/a
157n/a next_index = PyLong_FromSsize_t(en->en_index);
158n/a if (next_index == NULL) {
159n/a Py_DECREF(next_item);
160n/a return NULL;
161n/a }
162n/a en->en_index++;
163n/a
164n/a if (result->ob_refcnt == 1) {
165n/a Py_INCREF(result);
166n/a Py_DECREF(PyTuple_GET_ITEM(result, 0));
167n/a Py_DECREF(PyTuple_GET_ITEM(result, 1));
168n/a } else {
169n/a result = PyTuple_New(2);
170n/a if (result == NULL) {
171n/a Py_DECREF(next_index);
172n/a Py_DECREF(next_item);
173n/a return NULL;
174n/a }
175n/a }
176n/a PyTuple_SET_ITEM(result, 0, next_index);
177n/a PyTuple_SET_ITEM(result, 1, next_item);
178n/a return result;
179n/a}
180n/a
181n/astatic PyObject *
182n/aenum_reduce(enumobject *en)
183n/a{
184n/a if (en->en_longindex != NULL)
185n/a return Py_BuildValue("O(OO)", Py_TYPE(en), en->en_sit, en->en_longindex);
186n/a else
187n/a return Py_BuildValue("O(On)", Py_TYPE(en), en->en_sit, en->en_index);
188n/a}
189n/a
190n/aPyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
191n/a
192n/astatic PyMethodDef enum_methods[] = {
193n/a {"__reduce__", (PyCFunction)enum_reduce, METH_NOARGS, reduce_doc},
194n/a {NULL, NULL} /* sentinel */
195n/a};
196n/a
197n/aPyTypeObject PyEnum_Type = {
198n/a PyVarObject_HEAD_INIT(&PyType_Type, 0)
199n/a "enumerate", /* tp_name */
200n/a sizeof(enumobject), /* tp_basicsize */
201n/a 0, /* tp_itemsize */
202n/a /* methods */
203n/a (destructor)enum_dealloc, /* tp_dealloc */
204n/a 0, /* tp_print */
205n/a 0, /* tp_getattr */
206n/a 0, /* tp_setattr */
207n/a 0, /* tp_reserved */
208n/a 0, /* tp_repr */
209n/a 0, /* tp_as_number */
210n/a 0, /* tp_as_sequence */
211n/a 0, /* tp_as_mapping */
212n/a 0, /* tp_hash */
213n/a 0, /* tp_call */
214n/a 0, /* tp_str */
215n/a PyObject_GenericGetAttr, /* tp_getattro */
216n/a 0, /* tp_setattro */
217n/a 0, /* tp_as_buffer */
218n/a Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
219n/a Py_TPFLAGS_BASETYPE, /* tp_flags */
220n/a enum_new__doc__, /* tp_doc */
221n/a (traverseproc)enum_traverse, /* tp_traverse */
222n/a 0, /* tp_clear */
223n/a 0, /* tp_richcompare */
224n/a 0, /* tp_weaklistoffset */
225n/a PyObject_SelfIter, /* tp_iter */
226n/a (iternextfunc)enum_next, /* tp_iternext */
227n/a enum_methods, /* tp_methods */
228n/a 0, /* tp_members */
229n/a 0, /* tp_getset */
230n/a 0, /* tp_base */
231n/a 0, /* tp_dict */
232n/a 0, /* tp_descr_get */
233n/a 0, /* tp_descr_set */
234n/a 0, /* tp_dictoffset */
235n/a 0, /* tp_init */
236n/a PyType_GenericAlloc, /* tp_alloc */
237n/a enum_new, /* tp_new */
238n/a PyObject_GC_Del, /* tp_free */
239n/a};
240n/a
241n/a/* Reversed Object ***************************************************************/
242n/a
243n/atypedef struct {
244n/a PyObject_HEAD
245n/a Py_ssize_t index;
246n/a PyObject* seq;
247n/a} reversedobject;
248n/a
249n/a/*[clinic input]
250n/a@classmethod
251n/areversed.__new__ as reversed_new
252n/a
253n/a sequence as seq: object
254n/a /
255n/a
256n/aReturn a reverse iterator over the values of the given sequence.
257n/a[clinic start generated code]*/
258n/a
259n/astatic PyObject *
260n/areversed_new_impl(PyTypeObject *type, PyObject *seq)
261n/a/*[clinic end generated code: output=f7854cc1df26f570 input=aeb720361e5e3f1d]*/
262n/a{
263n/a Py_ssize_t n;
264n/a PyObject *reversed_meth;
265n/a reversedobject *ro;
266n/a _Py_IDENTIFIER(__reversed__);
267n/a
268n/a reversed_meth = _PyObject_LookupSpecial(seq, &PyId___reversed__);
269n/a if (reversed_meth == Py_None) {
270n/a Py_DECREF(reversed_meth);
271n/a PyErr_Format(PyExc_TypeError,
272n/a "'%.200s' object is not reversible",
273n/a Py_TYPE(seq)->tp_name);
274n/a return NULL;
275n/a }
276n/a if (reversed_meth != NULL) {
277n/a PyObject *res = _PyObject_CallNoArg(reversed_meth);
278n/a Py_DECREF(reversed_meth);
279n/a return res;
280n/a }
281n/a else if (PyErr_Occurred())
282n/a return NULL;
283n/a
284n/a if (!PySequence_Check(seq)) {
285n/a PyErr_Format(PyExc_TypeError,
286n/a "'%.200s' object is not reversible",
287n/a Py_TYPE(seq)->tp_name);
288n/a return NULL;
289n/a }
290n/a
291n/a n = PySequence_Size(seq);
292n/a if (n == -1)
293n/a return NULL;
294n/a
295n/a ro = (reversedobject *)type->tp_alloc(type, 0);
296n/a if (ro == NULL)
297n/a return NULL;
298n/a
299n/a ro->index = n-1;
300n/a Py_INCREF(seq);
301n/a ro->seq = seq;
302n/a return (PyObject *)ro;
303n/a}
304n/a
305n/astatic void
306n/areversed_dealloc(reversedobject *ro)
307n/a{
308n/a PyObject_GC_UnTrack(ro);
309n/a Py_XDECREF(ro->seq);
310n/a Py_TYPE(ro)->tp_free(ro);
311n/a}
312n/a
313n/astatic int
314n/areversed_traverse(reversedobject *ro, visitproc visit, void *arg)
315n/a{
316n/a Py_VISIT(ro->seq);
317n/a return 0;
318n/a}
319n/a
320n/astatic PyObject *
321n/areversed_next(reversedobject *ro)
322n/a{
323n/a PyObject *item;
324n/a Py_ssize_t index = ro->index;
325n/a
326n/a if (index >= 0) {
327n/a item = PySequence_GetItem(ro->seq, index);
328n/a if (item != NULL) {
329n/a ro->index--;
330n/a return item;
331n/a }
332n/a if (PyErr_ExceptionMatches(PyExc_IndexError) ||
333n/a PyErr_ExceptionMatches(PyExc_StopIteration))
334n/a PyErr_Clear();
335n/a }
336n/a ro->index = -1;
337n/a Py_CLEAR(ro->seq);
338n/a return NULL;
339n/a}
340n/a
341n/astatic PyObject *
342n/areversed_len(reversedobject *ro)
343n/a{
344n/a Py_ssize_t position, seqsize;
345n/a
346n/a if (ro->seq == NULL)
347n/a return PyLong_FromLong(0);
348n/a seqsize = PySequence_Size(ro->seq);
349n/a if (seqsize == -1)
350n/a return NULL;
351n/a position = ro->index + 1;
352n/a return PyLong_FromSsize_t((seqsize < position) ? 0 : position);
353n/a}
354n/a
355n/aPyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
356n/a
357n/astatic PyObject *
358n/areversed_reduce(reversedobject *ro)
359n/a{
360n/a if (ro->seq)
361n/a return Py_BuildValue("O(O)n", Py_TYPE(ro), ro->seq, ro->index);
362n/a else
363n/a return Py_BuildValue("O(())", Py_TYPE(ro));
364n/a}
365n/a
366n/astatic PyObject *
367n/areversed_setstate(reversedobject *ro, PyObject *state)
368n/a{
369n/a Py_ssize_t index = PyLong_AsSsize_t(state);
370n/a if (index == -1 && PyErr_Occurred())
371n/a return NULL;
372n/a if (ro->seq != 0) {
373n/a Py_ssize_t n = PySequence_Size(ro->seq);
374n/a if (n < 0)
375n/a return NULL;
376n/a if (index < -1)
377n/a index = -1;
378n/a else if (index > n-1)
379n/a index = n-1;
380n/a ro->index = index;
381n/a }
382n/a Py_RETURN_NONE;
383n/a}
384n/a
385n/aPyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
386n/a
387n/astatic PyMethodDef reversediter_methods[] = {
388n/a {"__length_hint__", (PyCFunction)reversed_len, METH_NOARGS, length_hint_doc},
389n/a {"__reduce__", (PyCFunction)reversed_reduce, METH_NOARGS, reduce_doc},
390n/a {"__setstate__", (PyCFunction)reversed_setstate, METH_O, setstate_doc},
391n/a {NULL, NULL} /* sentinel */
392n/a};
393n/a
394n/aPyTypeObject PyReversed_Type = {
395n/a PyVarObject_HEAD_INIT(&PyType_Type, 0)
396n/a "reversed", /* tp_name */
397n/a sizeof(reversedobject), /* tp_basicsize */
398n/a 0, /* tp_itemsize */
399n/a /* methods */
400n/a (destructor)reversed_dealloc, /* tp_dealloc */
401n/a 0, /* tp_print */
402n/a 0, /* tp_getattr */
403n/a 0, /* tp_setattr */
404n/a 0, /* tp_reserved */
405n/a 0, /* tp_repr */
406n/a 0, /* tp_as_number */
407n/a 0, /* tp_as_sequence */
408n/a 0, /* tp_as_mapping */
409n/a 0, /* tp_hash */
410n/a 0, /* tp_call */
411n/a 0, /* tp_str */
412n/a PyObject_GenericGetAttr, /* tp_getattro */
413n/a 0, /* tp_setattro */
414n/a 0, /* tp_as_buffer */
415n/a Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
416n/a Py_TPFLAGS_BASETYPE, /* tp_flags */
417n/a reversed_new__doc__, /* tp_doc */
418n/a (traverseproc)reversed_traverse,/* tp_traverse */
419n/a 0, /* tp_clear */
420n/a 0, /* tp_richcompare */
421n/a 0, /* tp_weaklistoffset */
422n/a PyObject_SelfIter, /* tp_iter */
423n/a (iternextfunc)reversed_next, /* tp_iternext */
424n/a reversediter_methods, /* tp_methods */
425n/a 0, /* tp_members */
426n/a 0, /* tp_getset */
427n/a 0, /* tp_base */
428n/a 0, /* tp_dict */
429n/a 0, /* tp_descr_get */
430n/a 0, /* tp_descr_set */
431n/a 0, /* tp_dictoffset */
432n/a 0, /* tp_init */
433n/a PyType_GenericAlloc, /* tp_alloc */
434n/a reversed_new, /* tp_new */
435n/a PyObject_GC_Del, /* tp_free */
436n/a};