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