17db96d56Sopenharmony_ci/* enumerate object */
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ci#include "Python.h"
47db96d56Sopenharmony_ci#include "pycore_call.h"          // _PyObject_CallNoArgs()
57db96d56Sopenharmony_ci#include "pycore_long.h"          // _PyLong_GetOne()
67db96d56Sopenharmony_ci#include "pycore_object.h"        // _PyObject_GC_TRACK()
77db96d56Sopenharmony_ci
87db96d56Sopenharmony_ci#include "clinic/enumobject.c.h"
97db96d56Sopenharmony_ci
107db96d56Sopenharmony_ci/*[clinic input]
117db96d56Sopenharmony_ciclass enumerate "enumobject *" "&PyEnum_Type"
127db96d56Sopenharmony_ciclass reversed "reversedobject *" "&PyReversed_Type"
137db96d56Sopenharmony_ci[clinic start generated code]*/
147db96d56Sopenharmony_ci/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d2dfdf1a88c88975]*/
157db96d56Sopenharmony_ci
167db96d56Sopenharmony_citypedef struct {
177db96d56Sopenharmony_ci    PyObject_HEAD
187db96d56Sopenharmony_ci    Py_ssize_t en_index;           /* current index of enumeration */
197db96d56Sopenharmony_ci    PyObject* en_sit;              /* secondary iterator of enumeration */
207db96d56Sopenharmony_ci    PyObject* en_result;           /* result tuple  */
217db96d56Sopenharmony_ci    PyObject* en_longindex;        /* index for sequences >= PY_SSIZE_T_MAX */
227db96d56Sopenharmony_ci    PyObject* one;                 /* borrowed reference */
237db96d56Sopenharmony_ci} enumobject;
247db96d56Sopenharmony_ci
257db96d56Sopenharmony_ci
267db96d56Sopenharmony_ci/*[clinic input]
277db96d56Sopenharmony_ci@classmethod
287db96d56Sopenharmony_cienumerate.__new__ as enum_new
297db96d56Sopenharmony_ci
307db96d56Sopenharmony_ci    iterable: object
317db96d56Sopenharmony_ci        an object supporting iteration
327db96d56Sopenharmony_ci    start: object = 0
337db96d56Sopenharmony_ci
347db96d56Sopenharmony_ciReturn an enumerate object.
357db96d56Sopenharmony_ci
367db96d56Sopenharmony_ciThe enumerate object yields pairs containing a count (from start, which
377db96d56Sopenharmony_cidefaults to zero) and a value yielded by the iterable argument.
387db96d56Sopenharmony_ci
397db96d56Sopenharmony_cienumerate is useful for obtaining an indexed list:
407db96d56Sopenharmony_ci    (0, seq[0]), (1, seq[1]), (2, seq[2]), ...
417db96d56Sopenharmony_ci[clinic start generated code]*/
427db96d56Sopenharmony_ci
437db96d56Sopenharmony_cistatic PyObject *
447db96d56Sopenharmony_cienum_new_impl(PyTypeObject *type, PyObject *iterable, PyObject *start)
457db96d56Sopenharmony_ci/*[clinic end generated code: output=e95e6e439f812c10 input=782e4911efcb8acf]*/
467db96d56Sopenharmony_ci{
477db96d56Sopenharmony_ci    enumobject *en;
487db96d56Sopenharmony_ci
497db96d56Sopenharmony_ci    en = (enumobject *)type->tp_alloc(type, 0);
507db96d56Sopenharmony_ci    if (en == NULL)
517db96d56Sopenharmony_ci        return NULL;
527db96d56Sopenharmony_ci    if (start != NULL) {
537db96d56Sopenharmony_ci        start = PyNumber_Index(start);
547db96d56Sopenharmony_ci        if (start == NULL) {
557db96d56Sopenharmony_ci            Py_DECREF(en);
567db96d56Sopenharmony_ci            return NULL;
577db96d56Sopenharmony_ci        }
587db96d56Sopenharmony_ci        assert(PyLong_Check(start));
597db96d56Sopenharmony_ci        en->en_index = PyLong_AsSsize_t(start);
607db96d56Sopenharmony_ci        if (en->en_index == -1 && PyErr_Occurred()) {
617db96d56Sopenharmony_ci            PyErr_Clear();
627db96d56Sopenharmony_ci            en->en_index = PY_SSIZE_T_MAX;
637db96d56Sopenharmony_ci            en->en_longindex = start;
647db96d56Sopenharmony_ci        } else {
657db96d56Sopenharmony_ci            en->en_longindex = NULL;
667db96d56Sopenharmony_ci            Py_DECREF(start);
677db96d56Sopenharmony_ci        }
687db96d56Sopenharmony_ci    } else {
697db96d56Sopenharmony_ci        en->en_index = 0;
707db96d56Sopenharmony_ci        en->en_longindex = NULL;
717db96d56Sopenharmony_ci    }
727db96d56Sopenharmony_ci    en->en_sit = PyObject_GetIter(iterable);
737db96d56Sopenharmony_ci    if (en->en_sit == NULL) {
747db96d56Sopenharmony_ci        Py_DECREF(en);
757db96d56Sopenharmony_ci        return NULL;
767db96d56Sopenharmony_ci    }
777db96d56Sopenharmony_ci    en->en_result = PyTuple_Pack(2, Py_None, Py_None);
787db96d56Sopenharmony_ci    if (en->en_result == NULL) {
797db96d56Sopenharmony_ci        Py_DECREF(en);
807db96d56Sopenharmony_ci        return NULL;
817db96d56Sopenharmony_ci    }
827db96d56Sopenharmony_ci    en->one = _PyLong_GetOne();    /* borrowed reference */
837db96d56Sopenharmony_ci    return (PyObject *)en;
847db96d56Sopenharmony_ci}
857db96d56Sopenharmony_ci
867db96d56Sopenharmony_cistatic int check_keyword(PyObject *kwnames, int index,
877db96d56Sopenharmony_ci                         const char *name)
887db96d56Sopenharmony_ci{
897db96d56Sopenharmony_ci    PyObject *kw = PyTuple_GET_ITEM(kwnames, index);
907db96d56Sopenharmony_ci    if (!_PyUnicode_EqualToASCIIString(kw, name)) {
917db96d56Sopenharmony_ci        PyErr_Format(PyExc_TypeError,
927db96d56Sopenharmony_ci            "'%S' is an invalid keyword argument for enumerate()", kw);
937db96d56Sopenharmony_ci        return 0;
947db96d56Sopenharmony_ci    }
957db96d56Sopenharmony_ci    return 1;
967db96d56Sopenharmony_ci}
977db96d56Sopenharmony_ci
987db96d56Sopenharmony_ci// TODO: Use AC when bpo-43447 is supported
997db96d56Sopenharmony_cistatic PyObject *
1007db96d56Sopenharmony_cienumerate_vectorcall(PyObject *type, PyObject *const *args,
1017db96d56Sopenharmony_ci                     size_t nargsf, PyObject *kwnames)
1027db96d56Sopenharmony_ci{
1037db96d56Sopenharmony_ci    PyTypeObject *tp = _PyType_CAST(type);
1047db96d56Sopenharmony_ci    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
1057db96d56Sopenharmony_ci    Py_ssize_t nkwargs = 0;
1067db96d56Sopenharmony_ci    if (kwnames != NULL) {
1077db96d56Sopenharmony_ci        nkwargs = PyTuple_GET_SIZE(kwnames);
1087db96d56Sopenharmony_ci    }
1097db96d56Sopenharmony_ci
1107db96d56Sopenharmony_ci    // Manually implement enumerate(iterable, start=...)
1117db96d56Sopenharmony_ci    if (nargs + nkwargs == 2) {
1127db96d56Sopenharmony_ci        if (nkwargs == 1) {
1137db96d56Sopenharmony_ci            if (!check_keyword(kwnames, 0, "start")) {
1147db96d56Sopenharmony_ci                return NULL;
1157db96d56Sopenharmony_ci            }
1167db96d56Sopenharmony_ci        } else if (nkwargs == 2) {
1177db96d56Sopenharmony_ci            PyObject *kw0 = PyTuple_GET_ITEM(kwnames, 0);
1187db96d56Sopenharmony_ci            if (_PyUnicode_EqualToASCIIString(kw0, "start")) {
1197db96d56Sopenharmony_ci                if (!check_keyword(kwnames, 1, "iterable")) {
1207db96d56Sopenharmony_ci                    return NULL;
1217db96d56Sopenharmony_ci                }
1227db96d56Sopenharmony_ci                return enum_new_impl(tp, args[1], args[0]);
1237db96d56Sopenharmony_ci            }
1247db96d56Sopenharmony_ci            if (!check_keyword(kwnames, 0, "iterable") ||
1257db96d56Sopenharmony_ci                !check_keyword(kwnames, 1, "start")) {
1267db96d56Sopenharmony_ci                return NULL;
1277db96d56Sopenharmony_ci            }
1287db96d56Sopenharmony_ci
1297db96d56Sopenharmony_ci        }
1307db96d56Sopenharmony_ci        return enum_new_impl(tp, args[0], args[1]);
1317db96d56Sopenharmony_ci    }
1327db96d56Sopenharmony_ci
1337db96d56Sopenharmony_ci    if (nargs + nkwargs == 1) {
1347db96d56Sopenharmony_ci        if (nkwargs == 1 && !check_keyword(kwnames, 0, "iterable")) {
1357db96d56Sopenharmony_ci            return NULL;
1367db96d56Sopenharmony_ci        }
1377db96d56Sopenharmony_ci        return enum_new_impl(tp, args[0], NULL);
1387db96d56Sopenharmony_ci    }
1397db96d56Sopenharmony_ci
1407db96d56Sopenharmony_ci    if (nargs == 0) {
1417db96d56Sopenharmony_ci        PyErr_SetString(PyExc_TypeError,
1427db96d56Sopenharmony_ci            "enumerate() missing required argument 'iterable'");
1437db96d56Sopenharmony_ci        return NULL;
1447db96d56Sopenharmony_ci    }
1457db96d56Sopenharmony_ci
1467db96d56Sopenharmony_ci    PyErr_Format(PyExc_TypeError,
1477db96d56Sopenharmony_ci        "enumerate() takes at most 2 arguments (%d given)", nargs + nkwargs);
1487db96d56Sopenharmony_ci    return NULL;
1497db96d56Sopenharmony_ci}
1507db96d56Sopenharmony_ci
1517db96d56Sopenharmony_cistatic void
1527db96d56Sopenharmony_cienum_dealloc(enumobject *en)
1537db96d56Sopenharmony_ci{
1547db96d56Sopenharmony_ci    PyObject_GC_UnTrack(en);
1557db96d56Sopenharmony_ci    Py_XDECREF(en->en_sit);
1567db96d56Sopenharmony_ci    Py_XDECREF(en->en_result);
1577db96d56Sopenharmony_ci    Py_XDECREF(en->en_longindex);
1587db96d56Sopenharmony_ci    Py_TYPE(en)->tp_free(en);
1597db96d56Sopenharmony_ci}
1607db96d56Sopenharmony_ci
1617db96d56Sopenharmony_cistatic int
1627db96d56Sopenharmony_cienum_traverse(enumobject *en, visitproc visit, void *arg)
1637db96d56Sopenharmony_ci{
1647db96d56Sopenharmony_ci    Py_VISIT(en->en_sit);
1657db96d56Sopenharmony_ci    Py_VISIT(en->en_result);
1667db96d56Sopenharmony_ci    Py_VISIT(en->en_longindex);
1677db96d56Sopenharmony_ci    return 0;
1687db96d56Sopenharmony_ci}
1697db96d56Sopenharmony_ci
1707db96d56Sopenharmony_cistatic PyObject *
1717db96d56Sopenharmony_cienum_next_long(enumobject *en, PyObject* next_item)
1727db96d56Sopenharmony_ci{
1737db96d56Sopenharmony_ci    PyObject *result = en->en_result;
1747db96d56Sopenharmony_ci    PyObject *next_index;
1757db96d56Sopenharmony_ci    PyObject *stepped_up;
1767db96d56Sopenharmony_ci    PyObject *old_index;
1777db96d56Sopenharmony_ci    PyObject *old_item;
1787db96d56Sopenharmony_ci
1797db96d56Sopenharmony_ci    if (en->en_longindex == NULL) {
1807db96d56Sopenharmony_ci        en->en_longindex = PyLong_FromSsize_t(PY_SSIZE_T_MAX);
1817db96d56Sopenharmony_ci        if (en->en_longindex == NULL) {
1827db96d56Sopenharmony_ci            Py_DECREF(next_item);
1837db96d56Sopenharmony_ci            return NULL;
1847db96d56Sopenharmony_ci        }
1857db96d56Sopenharmony_ci    }
1867db96d56Sopenharmony_ci    next_index = en->en_longindex;
1877db96d56Sopenharmony_ci    assert(next_index != NULL);
1887db96d56Sopenharmony_ci    stepped_up = PyNumber_Add(next_index, en->one);
1897db96d56Sopenharmony_ci    if (stepped_up == NULL) {
1907db96d56Sopenharmony_ci        Py_DECREF(next_item);
1917db96d56Sopenharmony_ci        return NULL;
1927db96d56Sopenharmony_ci    }
1937db96d56Sopenharmony_ci    en->en_longindex = stepped_up;
1947db96d56Sopenharmony_ci
1957db96d56Sopenharmony_ci    if (Py_REFCNT(result) == 1) {
1967db96d56Sopenharmony_ci        Py_INCREF(result);
1977db96d56Sopenharmony_ci        old_index = PyTuple_GET_ITEM(result, 0);
1987db96d56Sopenharmony_ci        old_item = PyTuple_GET_ITEM(result, 1);
1997db96d56Sopenharmony_ci        PyTuple_SET_ITEM(result, 0, next_index);
2007db96d56Sopenharmony_ci        PyTuple_SET_ITEM(result, 1, next_item);
2017db96d56Sopenharmony_ci        Py_DECREF(old_index);
2027db96d56Sopenharmony_ci        Py_DECREF(old_item);
2037db96d56Sopenharmony_ci        // bpo-42536: The GC may have untracked this result tuple. Since we're
2047db96d56Sopenharmony_ci        // recycling it, make sure it's tracked again:
2057db96d56Sopenharmony_ci        if (!_PyObject_GC_IS_TRACKED(result)) {
2067db96d56Sopenharmony_ci            _PyObject_GC_TRACK(result);
2077db96d56Sopenharmony_ci        }
2087db96d56Sopenharmony_ci        return result;
2097db96d56Sopenharmony_ci    }
2107db96d56Sopenharmony_ci    result = PyTuple_New(2);
2117db96d56Sopenharmony_ci    if (result == NULL) {
2127db96d56Sopenharmony_ci        Py_DECREF(next_index);
2137db96d56Sopenharmony_ci        Py_DECREF(next_item);
2147db96d56Sopenharmony_ci        return NULL;
2157db96d56Sopenharmony_ci    }
2167db96d56Sopenharmony_ci    PyTuple_SET_ITEM(result, 0, next_index);
2177db96d56Sopenharmony_ci    PyTuple_SET_ITEM(result, 1, next_item);
2187db96d56Sopenharmony_ci    return result;
2197db96d56Sopenharmony_ci}
2207db96d56Sopenharmony_ci
2217db96d56Sopenharmony_cistatic PyObject *
2227db96d56Sopenharmony_cienum_next(enumobject *en)
2237db96d56Sopenharmony_ci{
2247db96d56Sopenharmony_ci    PyObject *next_index;
2257db96d56Sopenharmony_ci    PyObject *next_item;
2267db96d56Sopenharmony_ci    PyObject *result = en->en_result;
2277db96d56Sopenharmony_ci    PyObject *it = en->en_sit;
2287db96d56Sopenharmony_ci    PyObject *old_index;
2297db96d56Sopenharmony_ci    PyObject *old_item;
2307db96d56Sopenharmony_ci
2317db96d56Sopenharmony_ci    next_item = (*Py_TYPE(it)->tp_iternext)(it);
2327db96d56Sopenharmony_ci    if (next_item == NULL)
2337db96d56Sopenharmony_ci        return NULL;
2347db96d56Sopenharmony_ci
2357db96d56Sopenharmony_ci    if (en->en_index == PY_SSIZE_T_MAX)
2367db96d56Sopenharmony_ci        return enum_next_long(en, next_item);
2377db96d56Sopenharmony_ci
2387db96d56Sopenharmony_ci    next_index = PyLong_FromSsize_t(en->en_index);
2397db96d56Sopenharmony_ci    if (next_index == NULL) {
2407db96d56Sopenharmony_ci        Py_DECREF(next_item);
2417db96d56Sopenharmony_ci        return NULL;
2427db96d56Sopenharmony_ci    }
2437db96d56Sopenharmony_ci    en->en_index++;
2447db96d56Sopenharmony_ci
2457db96d56Sopenharmony_ci    if (Py_REFCNT(result) == 1) {
2467db96d56Sopenharmony_ci        Py_INCREF(result);
2477db96d56Sopenharmony_ci        old_index = PyTuple_GET_ITEM(result, 0);
2487db96d56Sopenharmony_ci        old_item = PyTuple_GET_ITEM(result, 1);
2497db96d56Sopenharmony_ci        PyTuple_SET_ITEM(result, 0, next_index);
2507db96d56Sopenharmony_ci        PyTuple_SET_ITEM(result, 1, next_item);
2517db96d56Sopenharmony_ci        Py_DECREF(old_index);
2527db96d56Sopenharmony_ci        Py_DECREF(old_item);
2537db96d56Sopenharmony_ci        // bpo-42536: The GC may have untracked this result tuple. Since we're
2547db96d56Sopenharmony_ci        // recycling it, make sure it's tracked again:
2557db96d56Sopenharmony_ci        if (!_PyObject_GC_IS_TRACKED(result)) {
2567db96d56Sopenharmony_ci            _PyObject_GC_TRACK(result);
2577db96d56Sopenharmony_ci        }
2587db96d56Sopenharmony_ci        return result;
2597db96d56Sopenharmony_ci    }
2607db96d56Sopenharmony_ci    result = PyTuple_New(2);
2617db96d56Sopenharmony_ci    if (result == NULL) {
2627db96d56Sopenharmony_ci        Py_DECREF(next_index);
2637db96d56Sopenharmony_ci        Py_DECREF(next_item);
2647db96d56Sopenharmony_ci        return NULL;
2657db96d56Sopenharmony_ci    }
2667db96d56Sopenharmony_ci    PyTuple_SET_ITEM(result, 0, next_index);
2677db96d56Sopenharmony_ci    PyTuple_SET_ITEM(result, 1, next_item);
2687db96d56Sopenharmony_ci    return result;
2697db96d56Sopenharmony_ci}
2707db96d56Sopenharmony_ci
2717db96d56Sopenharmony_cistatic PyObject *
2727db96d56Sopenharmony_cienum_reduce(enumobject *en, PyObject *Py_UNUSED(ignored))
2737db96d56Sopenharmony_ci{
2747db96d56Sopenharmony_ci    if (en->en_longindex != NULL)
2757db96d56Sopenharmony_ci        return Py_BuildValue("O(OO)", Py_TYPE(en), en->en_sit, en->en_longindex);
2767db96d56Sopenharmony_ci    else
2777db96d56Sopenharmony_ci        return Py_BuildValue("O(On)", Py_TYPE(en), en->en_sit, en->en_index);
2787db96d56Sopenharmony_ci}
2797db96d56Sopenharmony_ci
2807db96d56Sopenharmony_ciPyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
2817db96d56Sopenharmony_ci
2827db96d56Sopenharmony_cistatic PyMethodDef enum_methods[] = {
2837db96d56Sopenharmony_ci    {"__reduce__", (PyCFunction)enum_reduce, METH_NOARGS, reduce_doc},
2847db96d56Sopenharmony_ci    {"__class_getitem__",    Py_GenericAlias,
2857db96d56Sopenharmony_ci    METH_O|METH_CLASS,       PyDoc_STR("See PEP 585")},
2867db96d56Sopenharmony_ci    {NULL,              NULL}           /* sentinel */
2877db96d56Sopenharmony_ci};
2887db96d56Sopenharmony_ci
2897db96d56Sopenharmony_ciPyTypeObject PyEnum_Type = {
2907db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2917db96d56Sopenharmony_ci    "enumerate",                    /* tp_name */
2927db96d56Sopenharmony_ci    sizeof(enumobject),             /* tp_basicsize */
2937db96d56Sopenharmony_ci    0,                              /* tp_itemsize */
2947db96d56Sopenharmony_ci    /* methods */
2957db96d56Sopenharmony_ci    (destructor)enum_dealloc,       /* tp_dealloc */
2967db96d56Sopenharmony_ci    0,                              /* tp_vectorcall_offset */
2977db96d56Sopenharmony_ci    0,                              /* tp_getattr */
2987db96d56Sopenharmony_ci    0,                              /* tp_setattr */
2997db96d56Sopenharmony_ci    0,                              /* tp_as_async */
3007db96d56Sopenharmony_ci    0,                              /* tp_repr */
3017db96d56Sopenharmony_ci    0,                              /* tp_as_number */
3027db96d56Sopenharmony_ci    0,                              /* tp_as_sequence */
3037db96d56Sopenharmony_ci    0,                              /* tp_as_mapping */
3047db96d56Sopenharmony_ci    0,                              /* tp_hash */
3057db96d56Sopenharmony_ci    0,                              /* tp_call */
3067db96d56Sopenharmony_ci    0,                              /* tp_str */
3077db96d56Sopenharmony_ci    PyObject_GenericGetAttr,        /* tp_getattro */
3087db96d56Sopenharmony_ci    0,                              /* tp_setattro */
3097db96d56Sopenharmony_ci    0,                              /* tp_as_buffer */
3107db96d56Sopenharmony_ci    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
3117db96d56Sopenharmony_ci        Py_TPFLAGS_BASETYPE,        /* tp_flags */
3127db96d56Sopenharmony_ci    enum_new__doc__,                /* tp_doc */
3137db96d56Sopenharmony_ci    (traverseproc)enum_traverse,    /* tp_traverse */
3147db96d56Sopenharmony_ci    0,                              /* tp_clear */
3157db96d56Sopenharmony_ci    0,                              /* tp_richcompare */
3167db96d56Sopenharmony_ci    0,                              /* tp_weaklistoffset */
3177db96d56Sopenharmony_ci    PyObject_SelfIter,              /* tp_iter */
3187db96d56Sopenharmony_ci    (iternextfunc)enum_next,        /* tp_iternext */
3197db96d56Sopenharmony_ci    enum_methods,                   /* tp_methods */
3207db96d56Sopenharmony_ci    0,                              /* tp_members */
3217db96d56Sopenharmony_ci    0,                              /* tp_getset */
3227db96d56Sopenharmony_ci    0,                              /* tp_base */
3237db96d56Sopenharmony_ci    0,                              /* tp_dict */
3247db96d56Sopenharmony_ci    0,                              /* tp_descr_get */
3257db96d56Sopenharmony_ci    0,                              /* tp_descr_set */
3267db96d56Sopenharmony_ci    0,                              /* tp_dictoffset */
3277db96d56Sopenharmony_ci    0,                              /* tp_init */
3287db96d56Sopenharmony_ci    PyType_GenericAlloc,            /* tp_alloc */
3297db96d56Sopenharmony_ci    enum_new,                       /* tp_new */
3307db96d56Sopenharmony_ci    PyObject_GC_Del,                /* tp_free */
3317db96d56Sopenharmony_ci    .tp_vectorcall = (vectorcallfunc)enumerate_vectorcall
3327db96d56Sopenharmony_ci};
3337db96d56Sopenharmony_ci
3347db96d56Sopenharmony_ci/* Reversed Object ***************************************************************/
3357db96d56Sopenharmony_ci
3367db96d56Sopenharmony_citypedef struct {
3377db96d56Sopenharmony_ci    PyObject_HEAD
3387db96d56Sopenharmony_ci    Py_ssize_t      index;
3397db96d56Sopenharmony_ci    PyObject* seq;
3407db96d56Sopenharmony_ci} reversedobject;
3417db96d56Sopenharmony_ci
3427db96d56Sopenharmony_ci/*[clinic input]
3437db96d56Sopenharmony_ci@classmethod
3447db96d56Sopenharmony_cireversed.__new__ as reversed_new
3457db96d56Sopenharmony_ci
3467db96d56Sopenharmony_ci    sequence as seq: object
3477db96d56Sopenharmony_ci    /
3487db96d56Sopenharmony_ci
3497db96d56Sopenharmony_ciReturn a reverse iterator over the values of the given sequence.
3507db96d56Sopenharmony_ci[clinic start generated code]*/
3517db96d56Sopenharmony_ci
3527db96d56Sopenharmony_cistatic PyObject *
3537db96d56Sopenharmony_cireversed_new_impl(PyTypeObject *type, PyObject *seq)
3547db96d56Sopenharmony_ci/*[clinic end generated code: output=f7854cc1df26f570 input=aeb720361e5e3f1d]*/
3557db96d56Sopenharmony_ci{
3567db96d56Sopenharmony_ci    Py_ssize_t n;
3577db96d56Sopenharmony_ci    PyObject *reversed_meth;
3587db96d56Sopenharmony_ci    reversedobject *ro;
3597db96d56Sopenharmony_ci
3607db96d56Sopenharmony_ci    reversed_meth = _PyObject_LookupSpecial(seq, &_Py_ID(__reversed__));
3617db96d56Sopenharmony_ci    if (reversed_meth == Py_None) {
3627db96d56Sopenharmony_ci        Py_DECREF(reversed_meth);
3637db96d56Sopenharmony_ci        PyErr_Format(PyExc_TypeError,
3647db96d56Sopenharmony_ci                     "'%.200s' object is not reversible",
3657db96d56Sopenharmony_ci                     Py_TYPE(seq)->tp_name);
3667db96d56Sopenharmony_ci        return NULL;
3677db96d56Sopenharmony_ci    }
3687db96d56Sopenharmony_ci    if (reversed_meth != NULL) {
3697db96d56Sopenharmony_ci        PyObject *res = _PyObject_CallNoArgs(reversed_meth);
3707db96d56Sopenharmony_ci        Py_DECREF(reversed_meth);
3717db96d56Sopenharmony_ci        return res;
3727db96d56Sopenharmony_ci    }
3737db96d56Sopenharmony_ci    else if (PyErr_Occurred())
3747db96d56Sopenharmony_ci        return NULL;
3757db96d56Sopenharmony_ci
3767db96d56Sopenharmony_ci    if (!PySequence_Check(seq)) {
3777db96d56Sopenharmony_ci        PyErr_Format(PyExc_TypeError,
3787db96d56Sopenharmony_ci                     "'%.200s' object is not reversible",
3797db96d56Sopenharmony_ci                     Py_TYPE(seq)->tp_name);
3807db96d56Sopenharmony_ci        return NULL;
3817db96d56Sopenharmony_ci    }
3827db96d56Sopenharmony_ci
3837db96d56Sopenharmony_ci    n = PySequence_Size(seq);
3847db96d56Sopenharmony_ci    if (n == -1)
3857db96d56Sopenharmony_ci        return NULL;
3867db96d56Sopenharmony_ci
3877db96d56Sopenharmony_ci    ro = (reversedobject *)type->tp_alloc(type, 0);
3887db96d56Sopenharmony_ci    if (ro == NULL)
3897db96d56Sopenharmony_ci        return NULL;
3907db96d56Sopenharmony_ci
3917db96d56Sopenharmony_ci    ro->index = n-1;
3927db96d56Sopenharmony_ci    Py_INCREF(seq);
3937db96d56Sopenharmony_ci    ro->seq = seq;
3947db96d56Sopenharmony_ci    return (PyObject *)ro;
3957db96d56Sopenharmony_ci}
3967db96d56Sopenharmony_ci
3977db96d56Sopenharmony_cistatic PyObject *
3987db96d56Sopenharmony_cireversed_vectorcall(PyObject *type, PyObject * const*args,
3997db96d56Sopenharmony_ci                size_t nargsf, PyObject *kwnames)
4007db96d56Sopenharmony_ci{
4017db96d56Sopenharmony_ci    if (!_PyArg_NoKwnames("reversed", kwnames)) {
4027db96d56Sopenharmony_ci        return NULL;
4037db96d56Sopenharmony_ci    }
4047db96d56Sopenharmony_ci
4057db96d56Sopenharmony_ci    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
4067db96d56Sopenharmony_ci    if (!_PyArg_CheckPositional("reversed", nargs, 1, 1)) {
4077db96d56Sopenharmony_ci        return NULL;
4087db96d56Sopenharmony_ci    }
4097db96d56Sopenharmony_ci
4107db96d56Sopenharmony_ci    return reversed_new_impl(_PyType_CAST(type), args[0]);
4117db96d56Sopenharmony_ci}
4127db96d56Sopenharmony_ci
4137db96d56Sopenharmony_cistatic void
4147db96d56Sopenharmony_cireversed_dealloc(reversedobject *ro)
4157db96d56Sopenharmony_ci{
4167db96d56Sopenharmony_ci    PyObject_GC_UnTrack(ro);
4177db96d56Sopenharmony_ci    Py_XDECREF(ro->seq);
4187db96d56Sopenharmony_ci    Py_TYPE(ro)->tp_free(ro);
4197db96d56Sopenharmony_ci}
4207db96d56Sopenharmony_ci
4217db96d56Sopenharmony_cistatic int
4227db96d56Sopenharmony_cireversed_traverse(reversedobject *ro, visitproc visit, void *arg)
4237db96d56Sopenharmony_ci{
4247db96d56Sopenharmony_ci    Py_VISIT(ro->seq);
4257db96d56Sopenharmony_ci    return 0;
4267db96d56Sopenharmony_ci}
4277db96d56Sopenharmony_ci
4287db96d56Sopenharmony_cistatic PyObject *
4297db96d56Sopenharmony_cireversed_next(reversedobject *ro)
4307db96d56Sopenharmony_ci{
4317db96d56Sopenharmony_ci    PyObject *item;
4327db96d56Sopenharmony_ci    Py_ssize_t index = ro->index;
4337db96d56Sopenharmony_ci
4347db96d56Sopenharmony_ci    if (index >= 0) {
4357db96d56Sopenharmony_ci        item = PySequence_GetItem(ro->seq, index);
4367db96d56Sopenharmony_ci        if (item != NULL) {
4377db96d56Sopenharmony_ci            ro->index--;
4387db96d56Sopenharmony_ci            return item;
4397db96d56Sopenharmony_ci        }
4407db96d56Sopenharmony_ci        if (PyErr_ExceptionMatches(PyExc_IndexError) ||
4417db96d56Sopenharmony_ci            PyErr_ExceptionMatches(PyExc_StopIteration))
4427db96d56Sopenharmony_ci            PyErr_Clear();
4437db96d56Sopenharmony_ci    }
4447db96d56Sopenharmony_ci    ro->index = -1;
4457db96d56Sopenharmony_ci    Py_CLEAR(ro->seq);
4467db96d56Sopenharmony_ci    return NULL;
4477db96d56Sopenharmony_ci}
4487db96d56Sopenharmony_ci
4497db96d56Sopenharmony_cistatic PyObject *
4507db96d56Sopenharmony_cireversed_len(reversedobject *ro, PyObject *Py_UNUSED(ignored))
4517db96d56Sopenharmony_ci{
4527db96d56Sopenharmony_ci    Py_ssize_t position, seqsize;
4537db96d56Sopenharmony_ci
4547db96d56Sopenharmony_ci    if (ro->seq == NULL)
4557db96d56Sopenharmony_ci        return PyLong_FromLong(0);
4567db96d56Sopenharmony_ci    seqsize = PySequence_Size(ro->seq);
4577db96d56Sopenharmony_ci    if (seqsize == -1)
4587db96d56Sopenharmony_ci        return NULL;
4597db96d56Sopenharmony_ci    position = ro->index + 1;
4607db96d56Sopenharmony_ci    return PyLong_FromSsize_t((seqsize < position)  ?  0  :  position);
4617db96d56Sopenharmony_ci}
4627db96d56Sopenharmony_ci
4637db96d56Sopenharmony_ciPyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
4647db96d56Sopenharmony_ci
4657db96d56Sopenharmony_cistatic PyObject *
4667db96d56Sopenharmony_cireversed_reduce(reversedobject *ro, PyObject *Py_UNUSED(ignored))
4677db96d56Sopenharmony_ci{
4687db96d56Sopenharmony_ci    if (ro->seq)
4697db96d56Sopenharmony_ci        return Py_BuildValue("O(O)n", Py_TYPE(ro), ro->seq, ro->index);
4707db96d56Sopenharmony_ci    else
4717db96d56Sopenharmony_ci        return Py_BuildValue("O(())", Py_TYPE(ro));
4727db96d56Sopenharmony_ci}
4737db96d56Sopenharmony_ci
4747db96d56Sopenharmony_cistatic PyObject *
4757db96d56Sopenharmony_cireversed_setstate(reversedobject *ro, PyObject *state)
4767db96d56Sopenharmony_ci{
4777db96d56Sopenharmony_ci    Py_ssize_t index = PyLong_AsSsize_t(state);
4787db96d56Sopenharmony_ci    if (index == -1 && PyErr_Occurred())
4797db96d56Sopenharmony_ci        return NULL;
4807db96d56Sopenharmony_ci    if (ro->seq != 0) {
4817db96d56Sopenharmony_ci        Py_ssize_t n = PySequence_Size(ro->seq);
4827db96d56Sopenharmony_ci        if (n < 0)
4837db96d56Sopenharmony_ci            return NULL;
4847db96d56Sopenharmony_ci        if (index < -1)
4857db96d56Sopenharmony_ci            index = -1;
4867db96d56Sopenharmony_ci        else if (index > n-1)
4877db96d56Sopenharmony_ci            index = n-1;
4887db96d56Sopenharmony_ci        ro->index = index;
4897db96d56Sopenharmony_ci    }
4907db96d56Sopenharmony_ci    Py_RETURN_NONE;
4917db96d56Sopenharmony_ci}
4927db96d56Sopenharmony_ci
4937db96d56Sopenharmony_ciPyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
4947db96d56Sopenharmony_ci
4957db96d56Sopenharmony_cistatic PyMethodDef reversediter_methods[] = {
4967db96d56Sopenharmony_ci    {"__length_hint__", (PyCFunction)reversed_len, METH_NOARGS, length_hint_doc},
4977db96d56Sopenharmony_ci    {"__reduce__", (PyCFunction)reversed_reduce, METH_NOARGS, reduce_doc},
4987db96d56Sopenharmony_ci    {"__setstate__", (PyCFunction)reversed_setstate, METH_O, setstate_doc},
4997db96d56Sopenharmony_ci    {NULL,              NULL}           /* sentinel */
5007db96d56Sopenharmony_ci};
5017db96d56Sopenharmony_ci
5027db96d56Sopenharmony_ciPyTypeObject PyReversed_Type = {
5037db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(&PyType_Type, 0)
5047db96d56Sopenharmony_ci    "reversed",                     /* tp_name */
5057db96d56Sopenharmony_ci    sizeof(reversedobject),         /* tp_basicsize */
5067db96d56Sopenharmony_ci    0,                              /* tp_itemsize */
5077db96d56Sopenharmony_ci    /* methods */
5087db96d56Sopenharmony_ci    (destructor)reversed_dealloc,   /* tp_dealloc */
5097db96d56Sopenharmony_ci    0,                              /* tp_vectorcall_offset */
5107db96d56Sopenharmony_ci    0,                              /* tp_getattr */
5117db96d56Sopenharmony_ci    0,                              /* tp_setattr */
5127db96d56Sopenharmony_ci    0,                              /* tp_as_async */
5137db96d56Sopenharmony_ci    0,                              /* tp_repr */
5147db96d56Sopenharmony_ci    0,                              /* tp_as_number */
5157db96d56Sopenharmony_ci    0,                              /* tp_as_sequence */
5167db96d56Sopenharmony_ci    0,                              /* tp_as_mapping */
5177db96d56Sopenharmony_ci    0,                              /* tp_hash */
5187db96d56Sopenharmony_ci    0,                              /* tp_call */
5197db96d56Sopenharmony_ci    0,                              /* tp_str */
5207db96d56Sopenharmony_ci    PyObject_GenericGetAttr,        /* tp_getattro */
5217db96d56Sopenharmony_ci    0,                              /* tp_setattro */
5227db96d56Sopenharmony_ci    0,                              /* tp_as_buffer */
5237db96d56Sopenharmony_ci    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
5247db96d56Sopenharmony_ci        Py_TPFLAGS_BASETYPE,        /* tp_flags */
5257db96d56Sopenharmony_ci    reversed_new__doc__,            /* tp_doc */
5267db96d56Sopenharmony_ci    (traverseproc)reversed_traverse,/* tp_traverse */
5277db96d56Sopenharmony_ci    0,                              /* tp_clear */
5287db96d56Sopenharmony_ci    0,                              /* tp_richcompare */
5297db96d56Sopenharmony_ci    0,                              /* tp_weaklistoffset */
5307db96d56Sopenharmony_ci    PyObject_SelfIter,              /* tp_iter */
5317db96d56Sopenharmony_ci    (iternextfunc)reversed_next,    /* tp_iternext */
5327db96d56Sopenharmony_ci    reversediter_methods,           /* tp_methods */
5337db96d56Sopenharmony_ci    0,                              /* tp_members */
5347db96d56Sopenharmony_ci    0,                              /* tp_getset */
5357db96d56Sopenharmony_ci    0,                              /* tp_base */
5367db96d56Sopenharmony_ci    0,                              /* tp_dict */
5377db96d56Sopenharmony_ci    0,                              /* tp_descr_get */
5387db96d56Sopenharmony_ci    0,                              /* tp_descr_set */
5397db96d56Sopenharmony_ci    0,                              /* tp_dictoffset */
5407db96d56Sopenharmony_ci    0,                              /* tp_init */
5417db96d56Sopenharmony_ci    PyType_GenericAlloc,            /* tp_alloc */
5427db96d56Sopenharmony_ci    reversed_new,                   /* tp_new */
5437db96d56Sopenharmony_ci    PyObject_GC_Del,                /* tp_free */
5447db96d56Sopenharmony_ci    .tp_vectorcall = (vectorcallfunc)reversed_vectorcall,
5457db96d56Sopenharmony_ci};
546