17db96d56Sopenharmony_ci/* 27db96d56Sopenharmony_ciWritten by Jim Hugunin and Chris Chase. 37db96d56Sopenharmony_ci 47db96d56Sopenharmony_ciThis includes both the singular ellipsis object and slice objects. 57db96d56Sopenharmony_ci 67db96d56Sopenharmony_ciGuido, feel free to do whatever you want in the way of copyrights 77db96d56Sopenharmony_cifor this file. 87db96d56Sopenharmony_ci*/ 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_ci/* 117db96d56Sopenharmony_ciPy_Ellipsis encodes the '...' rubber index token. It is similar to 127db96d56Sopenharmony_cithe Py_NoneStruct in that there is no way to create other objects of 137db96d56Sopenharmony_cithis type and there is exactly one in existence. 147db96d56Sopenharmony_ci*/ 157db96d56Sopenharmony_ci 167db96d56Sopenharmony_ci#include "Python.h" 177db96d56Sopenharmony_ci#include "pycore_abstract.h" // _PyIndex_Check() 187db96d56Sopenharmony_ci#include "pycore_long.h" // _PyLong_GetZero() 197db96d56Sopenharmony_ci#include "pycore_object.h" // _PyObject_GC_TRACK() 207db96d56Sopenharmony_ci#include "structmember.h" // PyMemberDef 217db96d56Sopenharmony_ci 227db96d56Sopenharmony_cistatic PyObject * 237db96d56Sopenharmony_ciellipsis_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) 247db96d56Sopenharmony_ci{ 257db96d56Sopenharmony_ci if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_GET_SIZE(kwargs))) { 267db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, "EllipsisType takes no arguments"); 277db96d56Sopenharmony_ci return NULL; 287db96d56Sopenharmony_ci } 297db96d56Sopenharmony_ci Py_INCREF(Py_Ellipsis); 307db96d56Sopenharmony_ci return Py_Ellipsis; 317db96d56Sopenharmony_ci} 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_cistatic PyObject * 347db96d56Sopenharmony_ciellipsis_repr(PyObject *op) 357db96d56Sopenharmony_ci{ 367db96d56Sopenharmony_ci return PyUnicode_FromString("Ellipsis"); 377db96d56Sopenharmony_ci} 387db96d56Sopenharmony_ci 397db96d56Sopenharmony_cistatic PyObject * 407db96d56Sopenharmony_ciellipsis_reduce(PyObject *op, PyObject *Py_UNUSED(ignored)) 417db96d56Sopenharmony_ci{ 427db96d56Sopenharmony_ci return PyUnicode_FromString("Ellipsis"); 437db96d56Sopenharmony_ci} 447db96d56Sopenharmony_ci 457db96d56Sopenharmony_cistatic PyMethodDef ellipsis_methods[] = { 467db96d56Sopenharmony_ci {"__reduce__", ellipsis_reduce, METH_NOARGS, NULL}, 477db96d56Sopenharmony_ci {NULL, NULL} 487db96d56Sopenharmony_ci}; 497db96d56Sopenharmony_ci 507db96d56Sopenharmony_ciPyTypeObject PyEllipsis_Type = { 517db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(&PyType_Type, 0) 527db96d56Sopenharmony_ci "ellipsis", /* tp_name */ 537db96d56Sopenharmony_ci 0, /* tp_basicsize */ 547db96d56Sopenharmony_ci 0, /* tp_itemsize */ 557db96d56Sopenharmony_ci 0, /*never called*/ /* tp_dealloc */ 567db96d56Sopenharmony_ci 0, /* tp_vectorcall_offset */ 577db96d56Sopenharmony_ci 0, /* tp_getattr */ 587db96d56Sopenharmony_ci 0, /* tp_setattr */ 597db96d56Sopenharmony_ci 0, /* tp_as_async */ 607db96d56Sopenharmony_ci ellipsis_repr, /* tp_repr */ 617db96d56Sopenharmony_ci 0, /* tp_as_number */ 627db96d56Sopenharmony_ci 0, /* tp_as_sequence */ 637db96d56Sopenharmony_ci 0, /* tp_as_mapping */ 647db96d56Sopenharmony_ci 0, /* tp_hash */ 657db96d56Sopenharmony_ci 0, /* tp_call */ 667db96d56Sopenharmony_ci 0, /* tp_str */ 677db96d56Sopenharmony_ci PyObject_GenericGetAttr, /* tp_getattro */ 687db96d56Sopenharmony_ci 0, /* tp_setattro */ 697db96d56Sopenharmony_ci 0, /* tp_as_buffer */ 707db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT, /* tp_flags */ 717db96d56Sopenharmony_ci 0, /* tp_doc */ 727db96d56Sopenharmony_ci 0, /* tp_traverse */ 737db96d56Sopenharmony_ci 0, /* tp_clear */ 747db96d56Sopenharmony_ci 0, /* tp_richcompare */ 757db96d56Sopenharmony_ci 0, /* tp_weaklistoffset */ 767db96d56Sopenharmony_ci 0, /* tp_iter */ 777db96d56Sopenharmony_ci 0, /* tp_iternext */ 787db96d56Sopenharmony_ci ellipsis_methods, /* tp_methods */ 797db96d56Sopenharmony_ci 0, /* tp_members */ 807db96d56Sopenharmony_ci 0, /* tp_getset */ 817db96d56Sopenharmony_ci 0, /* tp_base */ 827db96d56Sopenharmony_ci 0, /* tp_dict */ 837db96d56Sopenharmony_ci 0, /* tp_descr_get */ 847db96d56Sopenharmony_ci 0, /* tp_descr_set */ 857db96d56Sopenharmony_ci 0, /* tp_dictoffset */ 867db96d56Sopenharmony_ci 0, /* tp_init */ 877db96d56Sopenharmony_ci 0, /* tp_alloc */ 887db96d56Sopenharmony_ci ellipsis_new, /* tp_new */ 897db96d56Sopenharmony_ci}; 907db96d56Sopenharmony_ci 917db96d56Sopenharmony_ciPyObject _Py_EllipsisObject = { 927db96d56Sopenharmony_ci _PyObject_EXTRA_INIT 937db96d56Sopenharmony_ci 1, &PyEllipsis_Type 947db96d56Sopenharmony_ci}; 957db96d56Sopenharmony_ci 967db96d56Sopenharmony_ci 977db96d56Sopenharmony_ci/* Slice object implementation */ 987db96d56Sopenharmony_ci 997db96d56Sopenharmony_ci 1007db96d56Sopenharmony_civoid _PySlice_Fini(PyInterpreterState *interp) 1017db96d56Sopenharmony_ci{ 1027db96d56Sopenharmony_ci PySliceObject *obj = interp->slice_cache; 1037db96d56Sopenharmony_ci if (obj != NULL) { 1047db96d56Sopenharmony_ci interp->slice_cache = NULL; 1057db96d56Sopenharmony_ci PyObject_GC_Del(obj); 1067db96d56Sopenharmony_ci } 1077db96d56Sopenharmony_ci} 1087db96d56Sopenharmony_ci 1097db96d56Sopenharmony_ci/* start, stop, and step are python objects with None indicating no 1107db96d56Sopenharmony_ci index is present. 1117db96d56Sopenharmony_ci*/ 1127db96d56Sopenharmony_ci 1137db96d56Sopenharmony_ciPyObject * 1147db96d56Sopenharmony_ciPySlice_New(PyObject *start, PyObject *stop, PyObject *step) 1157db96d56Sopenharmony_ci{ 1167db96d56Sopenharmony_ci if (step == NULL) { 1177db96d56Sopenharmony_ci step = Py_None; 1187db96d56Sopenharmony_ci } 1197db96d56Sopenharmony_ci if (start == NULL) { 1207db96d56Sopenharmony_ci start = Py_None; 1217db96d56Sopenharmony_ci } 1227db96d56Sopenharmony_ci if (stop == NULL) { 1237db96d56Sopenharmony_ci stop = Py_None; 1247db96d56Sopenharmony_ci } 1257db96d56Sopenharmony_ci 1267db96d56Sopenharmony_ci PyInterpreterState *interp = _PyInterpreterState_GET(); 1277db96d56Sopenharmony_ci PySliceObject *obj; 1287db96d56Sopenharmony_ci if (interp->slice_cache != NULL) { 1297db96d56Sopenharmony_ci obj = interp->slice_cache; 1307db96d56Sopenharmony_ci interp->slice_cache = NULL; 1317db96d56Sopenharmony_ci _Py_NewReference((PyObject *)obj); 1327db96d56Sopenharmony_ci } 1337db96d56Sopenharmony_ci else { 1347db96d56Sopenharmony_ci obj = PyObject_GC_New(PySliceObject, &PySlice_Type); 1357db96d56Sopenharmony_ci if (obj == NULL) { 1367db96d56Sopenharmony_ci return NULL; 1377db96d56Sopenharmony_ci } 1387db96d56Sopenharmony_ci } 1397db96d56Sopenharmony_ci 1407db96d56Sopenharmony_ci Py_INCREF(step); 1417db96d56Sopenharmony_ci obj->step = step; 1427db96d56Sopenharmony_ci Py_INCREF(start); 1437db96d56Sopenharmony_ci obj->start = start; 1447db96d56Sopenharmony_ci Py_INCREF(stop); 1457db96d56Sopenharmony_ci obj->stop = stop; 1467db96d56Sopenharmony_ci 1477db96d56Sopenharmony_ci _PyObject_GC_TRACK(obj); 1487db96d56Sopenharmony_ci return (PyObject *) obj; 1497db96d56Sopenharmony_ci} 1507db96d56Sopenharmony_ci 1517db96d56Sopenharmony_ciPyObject * 1527db96d56Sopenharmony_ci_PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop) 1537db96d56Sopenharmony_ci{ 1547db96d56Sopenharmony_ci PyObject *start, *end, *slice; 1557db96d56Sopenharmony_ci start = PyLong_FromSsize_t(istart); 1567db96d56Sopenharmony_ci if (!start) 1577db96d56Sopenharmony_ci return NULL; 1587db96d56Sopenharmony_ci end = PyLong_FromSsize_t(istop); 1597db96d56Sopenharmony_ci if (!end) { 1607db96d56Sopenharmony_ci Py_DECREF(start); 1617db96d56Sopenharmony_ci return NULL; 1627db96d56Sopenharmony_ci } 1637db96d56Sopenharmony_ci 1647db96d56Sopenharmony_ci slice = PySlice_New(start, end, NULL); 1657db96d56Sopenharmony_ci Py_DECREF(start); 1667db96d56Sopenharmony_ci Py_DECREF(end); 1677db96d56Sopenharmony_ci return slice; 1687db96d56Sopenharmony_ci} 1697db96d56Sopenharmony_ci 1707db96d56Sopenharmony_ciint 1717db96d56Sopenharmony_ciPySlice_GetIndices(PyObject *_r, Py_ssize_t length, 1727db96d56Sopenharmony_ci Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step) 1737db96d56Sopenharmony_ci{ 1747db96d56Sopenharmony_ci PySliceObject *r = (PySliceObject*)_r; 1757db96d56Sopenharmony_ci /* XXX support long ints */ 1767db96d56Sopenharmony_ci if (r->step == Py_None) { 1777db96d56Sopenharmony_ci *step = 1; 1787db96d56Sopenharmony_ci } else { 1797db96d56Sopenharmony_ci if (!PyLong_Check(r->step)) return -1; 1807db96d56Sopenharmony_ci *step = PyLong_AsSsize_t(r->step); 1817db96d56Sopenharmony_ci } 1827db96d56Sopenharmony_ci if (r->start == Py_None) { 1837db96d56Sopenharmony_ci *start = *step < 0 ? length-1 : 0; 1847db96d56Sopenharmony_ci } else { 1857db96d56Sopenharmony_ci if (!PyLong_Check(r->start)) return -1; 1867db96d56Sopenharmony_ci *start = PyLong_AsSsize_t(r->start); 1877db96d56Sopenharmony_ci if (*start < 0) *start += length; 1887db96d56Sopenharmony_ci } 1897db96d56Sopenharmony_ci if (r->stop == Py_None) { 1907db96d56Sopenharmony_ci *stop = *step < 0 ? -1 : length; 1917db96d56Sopenharmony_ci } else { 1927db96d56Sopenharmony_ci if (!PyLong_Check(r->stop)) return -1; 1937db96d56Sopenharmony_ci *stop = PyLong_AsSsize_t(r->stop); 1947db96d56Sopenharmony_ci if (*stop < 0) *stop += length; 1957db96d56Sopenharmony_ci } 1967db96d56Sopenharmony_ci if (*stop > length) return -1; 1977db96d56Sopenharmony_ci if (*start >= length) return -1; 1987db96d56Sopenharmony_ci if (*step == 0) return -1; 1997db96d56Sopenharmony_ci return 0; 2007db96d56Sopenharmony_ci} 2017db96d56Sopenharmony_ci 2027db96d56Sopenharmony_ciint 2037db96d56Sopenharmony_ciPySlice_Unpack(PyObject *_r, 2047db96d56Sopenharmony_ci Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step) 2057db96d56Sopenharmony_ci{ 2067db96d56Sopenharmony_ci PySliceObject *r = (PySliceObject*)_r; 2077db96d56Sopenharmony_ci /* this is harder to get right than you might think */ 2087db96d56Sopenharmony_ci 2097db96d56Sopenharmony_ci static_assert(PY_SSIZE_T_MIN + 1 <= -PY_SSIZE_T_MAX, 2107db96d56Sopenharmony_ci "-PY_SSIZE_T_MAX < PY_SSIZE_T_MIN + 1"); 2117db96d56Sopenharmony_ci 2127db96d56Sopenharmony_ci if (r->step == Py_None) { 2137db96d56Sopenharmony_ci *step = 1; 2147db96d56Sopenharmony_ci } 2157db96d56Sopenharmony_ci else { 2167db96d56Sopenharmony_ci if (!_PyEval_SliceIndex(r->step, step)) return -1; 2177db96d56Sopenharmony_ci if (*step == 0) { 2187db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 2197db96d56Sopenharmony_ci "slice step cannot be zero"); 2207db96d56Sopenharmony_ci return -1; 2217db96d56Sopenharmony_ci } 2227db96d56Sopenharmony_ci /* Here *step might be -PY_SSIZE_T_MAX-1; in this case we replace it 2237db96d56Sopenharmony_ci * with -PY_SSIZE_T_MAX. This doesn't affect the semantics, and it 2247db96d56Sopenharmony_ci * guards against later undefined behaviour resulting from code that 2257db96d56Sopenharmony_ci * does "step = -step" as part of a slice reversal. 2267db96d56Sopenharmony_ci */ 2277db96d56Sopenharmony_ci if (*step < -PY_SSIZE_T_MAX) 2287db96d56Sopenharmony_ci *step = -PY_SSIZE_T_MAX; 2297db96d56Sopenharmony_ci } 2307db96d56Sopenharmony_ci 2317db96d56Sopenharmony_ci if (r->start == Py_None) { 2327db96d56Sopenharmony_ci *start = *step < 0 ? PY_SSIZE_T_MAX : 0; 2337db96d56Sopenharmony_ci } 2347db96d56Sopenharmony_ci else { 2357db96d56Sopenharmony_ci if (!_PyEval_SliceIndex(r->start, start)) return -1; 2367db96d56Sopenharmony_ci } 2377db96d56Sopenharmony_ci 2387db96d56Sopenharmony_ci if (r->stop == Py_None) { 2397db96d56Sopenharmony_ci *stop = *step < 0 ? PY_SSIZE_T_MIN : PY_SSIZE_T_MAX; 2407db96d56Sopenharmony_ci } 2417db96d56Sopenharmony_ci else { 2427db96d56Sopenharmony_ci if (!_PyEval_SliceIndex(r->stop, stop)) return -1; 2437db96d56Sopenharmony_ci } 2447db96d56Sopenharmony_ci 2457db96d56Sopenharmony_ci return 0; 2467db96d56Sopenharmony_ci} 2477db96d56Sopenharmony_ci 2487db96d56Sopenharmony_ciPy_ssize_t 2497db96d56Sopenharmony_ciPySlice_AdjustIndices(Py_ssize_t length, 2507db96d56Sopenharmony_ci Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t step) 2517db96d56Sopenharmony_ci{ 2527db96d56Sopenharmony_ci /* this is harder to get right than you might think */ 2537db96d56Sopenharmony_ci 2547db96d56Sopenharmony_ci assert(step != 0); 2557db96d56Sopenharmony_ci assert(step >= -PY_SSIZE_T_MAX); 2567db96d56Sopenharmony_ci 2577db96d56Sopenharmony_ci if (*start < 0) { 2587db96d56Sopenharmony_ci *start += length; 2597db96d56Sopenharmony_ci if (*start < 0) { 2607db96d56Sopenharmony_ci *start = (step < 0) ? -1 : 0; 2617db96d56Sopenharmony_ci } 2627db96d56Sopenharmony_ci } 2637db96d56Sopenharmony_ci else if (*start >= length) { 2647db96d56Sopenharmony_ci *start = (step < 0) ? length - 1 : length; 2657db96d56Sopenharmony_ci } 2667db96d56Sopenharmony_ci 2677db96d56Sopenharmony_ci if (*stop < 0) { 2687db96d56Sopenharmony_ci *stop += length; 2697db96d56Sopenharmony_ci if (*stop < 0) { 2707db96d56Sopenharmony_ci *stop = (step < 0) ? -1 : 0; 2717db96d56Sopenharmony_ci } 2727db96d56Sopenharmony_ci } 2737db96d56Sopenharmony_ci else if (*stop >= length) { 2747db96d56Sopenharmony_ci *stop = (step < 0) ? length - 1 : length; 2757db96d56Sopenharmony_ci } 2767db96d56Sopenharmony_ci 2777db96d56Sopenharmony_ci if (step < 0) { 2787db96d56Sopenharmony_ci if (*stop < *start) { 2797db96d56Sopenharmony_ci return (*start - *stop - 1) / (-step) + 1; 2807db96d56Sopenharmony_ci } 2817db96d56Sopenharmony_ci } 2827db96d56Sopenharmony_ci else { 2837db96d56Sopenharmony_ci if (*start < *stop) { 2847db96d56Sopenharmony_ci return (*stop - *start - 1) / step + 1; 2857db96d56Sopenharmony_ci } 2867db96d56Sopenharmony_ci } 2877db96d56Sopenharmony_ci return 0; 2887db96d56Sopenharmony_ci} 2897db96d56Sopenharmony_ci 2907db96d56Sopenharmony_ci#undef PySlice_GetIndicesEx 2917db96d56Sopenharmony_ci 2927db96d56Sopenharmony_ciint 2937db96d56Sopenharmony_ciPySlice_GetIndicesEx(PyObject *_r, Py_ssize_t length, 2947db96d56Sopenharmony_ci Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, 2957db96d56Sopenharmony_ci Py_ssize_t *slicelength) 2967db96d56Sopenharmony_ci{ 2977db96d56Sopenharmony_ci if (PySlice_Unpack(_r, start, stop, step) < 0) 2987db96d56Sopenharmony_ci return -1; 2997db96d56Sopenharmony_ci *slicelength = PySlice_AdjustIndices(length, start, stop, *step); 3007db96d56Sopenharmony_ci return 0; 3017db96d56Sopenharmony_ci} 3027db96d56Sopenharmony_ci 3037db96d56Sopenharmony_cistatic PyObject * 3047db96d56Sopenharmony_cislice_new(PyTypeObject *type, PyObject *args, PyObject *kw) 3057db96d56Sopenharmony_ci{ 3067db96d56Sopenharmony_ci PyObject *start, *stop, *step; 3077db96d56Sopenharmony_ci 3087db96d56Sopenharmony_ci start = stop = step = NULL; 3097db96d56Sopenharmony_ci 3107db96d56Sopenharmony_ci if (!_PyArg_NoKeywords("slice", kw)) 3117db96d56Sopenharmony_ci return NULL; 3127db96d56Sopenharmony_ci 3137db96d56Sopenharmony_ci if (!PyArg_UnpackTuple(args, "slice", 1, 3, &start, &stop, &step)) 3147db96d56Sopenharmony_ci return NULL; 3157db96d56Sopenharmony_ci 3167db96d56Sopenharmony_ci /* This swapping of stop and start is to maintain similarity with 3177db96d56Sopenharmony_ci range(). */ 3187db96d56Sopenharmony_ci if (stop == NULL) { 3197db96d56Sopenharmony_ci stop = start; 3207db96d56Sopenharmony_ci start = NULL; 3217db96d56Sopenharmony_ci } 3227db96d56Sopenharmony_ci return PySlice_New(start, stop, step); 3237db96d56Sopenharmony_ci} 3247db96d56Sopenharmony_ci 3257db96d56Sopenharmony_ciPyDoc_STRVAR(slice_doc, 3267db96d56Sopenharmony_ci"slice(stop)\n\ 3277db96d56Sopenharmony_cislice(start, stop[, step])\n\ 3287db96d56Sopenharmony_ci\n\ 3297db96d56Sopenharmony_ciCreate a slice object. This is used for extended slicing (e.g. a[0:10:2])."); 3307db96d56Sopenharmony_ci 3317db96d56Sopenharmony_cistatic void 3327db96d56Sopenharmony_cislice_dealloc(PySliceObject *r) 3337db96d56Sopenharmony_ci{ 3347db96d56Sopenharmony_ci PyInterpreterState *interp = _PyInterpreterState_GET(); 3357db96d56Sopenharmony_ci _PyObject_GC_UNTRACK(r); 3367db96d56Sopenharmony_ci Py_DECREF(r->step); 3377db96d56Sopenharmony_ci Py_DECREF(r->start); 3387db96d56Sopenharmony_ci Py_DECREF(r->stop); 3397db96d56Sopenharmony_ci if (interp->slice_cache == NULL) { 3407db96d56Sopenharmony_ci interp->slice_cache = r; 3417db96d56Sopenharmony_ci } 3427db96d56Sopenharmony_ci else { 3437db96d56Sopenharmony_ci PyObject_GC_Del(r); 3447db96d56Sopenharmony_ci } 3457db96d56Sopenharmony_ci} 3467db96d56Sopenharmony_ci 3477db96d56Sopenharmony_cistatic PyObject * 3487db96d56Sopenharmony_cislice_repr(PySliceObject *r) 3497db96d56Sopenharmony_ci{ 3507db96d56Sopenharmony_ci return PyUnicode_FromFormat("slice(%R, %R, %R)", r->start, r->stop, r->step); 3517db96d56Sopenharmony_ci} 3527db96d56Sopenharmony_ci 3537db96d56Sopenharmony_cistatic PyMemberDef slice_members[] = { 3547db96d56Sopenharmony_ci {"start", T_OBJECT, offsetof(PySliceObject, start), READONLY}, 3557db96d56Sopenharmony_ci {"stop", T_OBJECT, offsetof(PySliceObject, stop), READONLY}, 3567db96d56Sopenharmony_ci {"step", T_OBJECT, offsetof(PySliceObject, step), READONLY}, 3577db96d56Sopenharmony_ci {0} 3587db96d56Sopenharmony_ci}; 3597db96d56Sopenharmony_ci 3607db96d56Sopenharmony_ci/* Helper function to convert a slice argument to a PyLong, and raise TypeError 3617db96d56Sopenharmony_ci with a suitable message on failure. */ 3627db96d56Sopenharmony_ci 3637db96d56Sopenharmony_cistatic PyObject* 3647db96d56Sopenharmony_cievaluate_slice_index(PyObject *v) 3657db96d56Sopenharmony_ci{ 3667db96d56Sopenharmony_ci if (_PyIndex_Check(v)) { 3677db96d56Sopenharmony_ci return PyNumber_Index(v); 3687db96d56Sopenharmony_ci } 3697db96d56Sopenharmony_ci else { 3707db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 3717db96d56Sopenharmony_ci "slice indices must be integers or " 3727db96d56Sopenharmony_ci "None or have an __index__ method"); 3737db96d56Sopenharmony_ci return NULL; 3747db96d56Sopenharmony_ci } 3757db96d56Sopenharmony_ci} 3767db96d56Sopenharmony_ci 3777db96d56Sopenharmony_ci/* Compute slice indices given a slice and length. Return -1 on failure. Used 3787db96d56Sopenharmony_ci by slice.indices and rangeobject slicing. Assumes that `len` is a 3797db96d56Sopenharmony_ci nonnegative instance of PyLong. */ 3807db96d56Sopenharmony_ci 3817db96d56Sopenharmony_ciint 3827db96d56Sopenharmony_ci_PySlice_GetLongIndices(PySliceObject *self, PyObject *length, 3837db96d56Sopenharmony_ci PyObject **start_ptr, PyObject **stop_ptr, 3847db96d56Sopenharmony_ci PyObject **step_ptr) 3857db96d56Sopenharmony_ci{ 3867db96d56Sopenharmony_ci PyObject *start=NULL, *stop=NULL, *step=NULL; 3877db96d56Sopenharmony_ci PyObject *upper=NULL, *lower=NULL; 3887db96d56Sopenharmony_ci int step_is_negative, cmp_result; 3897db96d56Sopenharmony_ci 3907db96d56Sopenharmony_ci /* Convert step to an integer; raise for zero step. */ 3917db96d56Sopenharmony_ci if (self->step == Py_None) { 3927db96d56Sopenharmony_ci step = _PyLong_GetOne(); 3937db96d56Sopenharmony_ci Py_INCREF(step); 3947db96d56Sopenharmony_ci step_is_negative = 0; 3957db96d56Sopenharmony_ci } 3967db96d56Sopenharmony_ci else { 3977db96d56Sopenharmony_ci int step_sign; 3987db96d56Sopenharmony_ci step = evaluate_slice_index(self->step); 3997db96d56Sopenharmony_ci if (step == NULL) 4007db96d56Sopenharmony_ci goto error; 4017db96d56Sopenharmony_ci step_sign = _PyLong_Sign(step); 4027db96d56Sopenharmony_ci if (step_sign == 0) { 4037db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 4047db96d56Sopenharmony_ci "slice step cannot be zero"); 4057db96d56Sopenharmony_ci goto error; 4067db96d56Sopenharmony_ci } 4077db96d56Sopenharmony_ci step_is_negative = step_sign < 0; 4087db96d56Sopenharmony_ci } 4097db96d56Sopenharmony_ci 4107db96d56Sopenharmony_ci /* Find lower and upper bounds for start and stop. */ 4117db96d56Sopenharmony_ci if (step_is_negative) { 4127db96d56Sopenharmony_ci lower = PyLong_FromLong(-1L); 4137db96d56Sopenharmony_ci if (lower == NULL) 4147db96d56Sopenharmony_ci goto error; 4157db96d56Sopenharmony_ci 4167db96d56Sopenharmony_ci upper = PyNumber_Add(length, lower); 4177db96d56Sopenharmony_ci if (upper == NULL) 4187db96d56Sopenharmony_ci goto error; 4197db96d56Sopenharmony_ci } 4207db96d56Sopenharmony_ci else { 4217db96d56Sopenharmony_ci lower = _PyLong_GetZero(); 4227db96d56Sopenharmony_ci Py_INCREF(lower); 4237db96d56Sopenharmony_ci upper = length; 4247db96d56Sopenharmony_ci Py_INCREF(upper); 4257db96d56Sopenharmony_ci } 4267db96d56Sopenharmony_ci 4277db96d56Sopenharmony_ci /* Compute start. */ 4287db96d56Sopenharmony_ci if (self->start == Py_None) { 4297db96d56Sopenharmony_ci start = step_is_negative ? upper : lower; 4307db96d56Sopenharmony_ci Py_INCREF(start); 4317db96d56Sopenharmony_ci } 4327db96d56Sopenharmony_ci else { 4337db96d56Sopenharmony_ci start = evaluate_slice_index(self->start); 4347db96d56Sopenharmony_ci if (start == NULL) 4357db96d56Sopenharmony_ci goto error; 4367db96d56Sopenharmony_ci 4377db96d56Sopenharmony_ci if (_PyLong_Sign(start) < 0) { 4387db96d56Sopenharmony_ci /* start += length */ 4397db96d56Sopenharmony_ci PyObject *tmp = PyNumber_Add(start, length); 4407db96d56Sopenharmony_ci Py_DECREF(start); 4417db96d56Sopenharmony_ci start = tmp; 4427db96d56Sopenharmony_ci if (start == NULL) 4437db96d56Sopenharmony_ci goto error; 4447db96d56Sopenharmony_ci 4457db96d56Sopenharmony_ci cmp_result = PyObject_RichCompareBool(start, lower, Py_LT); 4467db96d56Sopenharmony_ci if (cmp_result < 0) 4477db96d56Sopenharmony_ci goto error; 4487db96d56Sopenharmony_ci if (cmp_result) { 4497db96d56Sopenharmony_ci Py_INCREF(lower); 4507db96d56Sopenharmony_ci Py_DECREF(start); 4517db96d56Sopenharmony_ci start = lower; 4527db96d56Sopenharmony_ci } 4537db96d56Sopenharmony_ci } 4547db96d56Sopenharmony_ci else { 4557db96d56Sopenharmony_ci cmp_result = PyObject_RichCompareBool(start, upper, Py_GT); 4567db96d56Sopenharmony_ci if (cmp_result < 0) 4577db96d56Sopenharmony_ci goto error; 4587db96d56Sopenharmony_ci if (cmp_result) { 4597db96d56Sopenharmony_ci Py_INCREF(upper); 4607db96d56Sopenharmony_ci Py_DECREF(start); 4617db96d56Sopenharmony_ci start = upper; 4627db96d56Sopenharmony_ci } 4637db96d56Sopenharmony_ci } 4647db96d56Sopenharmony_ci } 4657db96d56Sopenharmony_ci 4667db96d56Sopenharmony_ci /* Compute stop. */ 4677db96d56Sopenharmony_ci if (self->stop == Py_None) { 4687db96d56Sopenharmony_ci stop = step_is_negative ? lower : upper; 4697db96d56Sopenharmony_ci Py_INCREF(stop); 4707db96d56Sopenharmony_ci } 4717db96d56Sopenharmony_ci else { 4727db96d56Sopenharmony_ci stop = evaluate_slice_index(self->stop); 4737db96d56Sopenharmony_ci if (stop == NULL) 4747db96d56Sopenharmony_ci goto error; 4757db96d56Sopenharmony_ci 4767db96d56Sopenharmony_ci if (_PyLong_Sign(stop) < 0) { 4777db96d56Sopenharmony_ci /* stop += length */ 4787db96d56Sopenharmony_ci PyObject *tmp = PyNumber_Add(stop, length); 4797db96d56Sopenharmony_ci Py_DECREF(stop); 4807db96d56Sopenharmony_ci stop = tmp; 4817db96d56Sopenharmony_ci if (stop == NULL) 4827db96d56Sopenharmony_ci goto error; 4837db96d56Sopenharmony_ci 4847db96d56Sopenharmony_ci cmp_result = PyObject_RichCompareBool(stop, lower, Py_LT); 4857db96d56Sopenharmony_ci if (cmp_result < 0) 4867db96d56Sopenharmony_ci goto error; 4877db96d56Sopenharmony_ci if (cmp_result) { 4887db96d56Sopenharmony_ci Py_INCREF(lower); 4897db96d56Sopenharmony_ci Py_DECREF(stop); 4907db96d56Sopenharmony_ci stop = lower; 4917db96d56Sopenharmony_ci } 4927db96d56Sopenharmony_ci } 4937db96d56Sopenharmony_ci else { 4947db96d56Sopenharmony_ci cmp_result = PyObject_RichCompareBool(stop, upper, Py_GT); 4957db96d56Sopenharmony_ci if (cmp_result < 0) 4967db96d56Sopenharmony_ci goto error; 4977db96d56Sopenharmony_ci if (cmp_result) { 4987db96d56Sopenharmony_ci Py_INCREF(upper); 4997db96d56Sopenharmony_ci Py_DECREF(stop); 5007db96d56Sopenharmony_ci stop = upper; 5017db96d56Sopenharmony_ci } 5027db96d56Sopenharmony_ci } 5037db96d56Sopenharmony_ci } 5047db96d56Sopenharmony_ci 5057db96d56Sopenharmony_ci *start_ptr = start; 5067db96d56Sopenharmony_ci *stop_ptr = stop; 5077db96d56Sopenharmony_ci *step_ptr = step; 5087db96d56Sopenharmony_ci Py_DECREF(upper); 5097db96d56Sopenharmony_ci Py_DECREF(lower); 5107db96d56Sopenharmony_ci return 0; 5117db96d56Sopenharmony_ci 5127db96d56Sopenharmony_ci error: 5137db96d56Sopenharmony_ci *start_ptr = *stop_ptr = *step_ptr = NULL; 5147db96d56Sopenharmony_ci Py_XDECREF(start); 5157db96d56Sopenharmony_ci Py_XDECREF(stop); 5167db96d56Sopenharmony_ci Py_XDECREF(step); 5177db96d56Sopenharmony_ci Py_XDECREF(upper); 5187db96d56Sopenharmony_ci Py_XDECREF(lower); 5197db96d56Sopenharmony_ci return -1; 5207db96d56Sopenharmony_ci} 5217db96d56Sopenharmony_ci 5227db96d56Sopenharmony_ci/* Implementation of slice.indices. */ 5237db96d56Sopenharmony_ci 5247db96d56Sopenharmony_cistatic PyObject* 5257db96d56Sopenharmony_cislice_indices(PySliceObject* self, PyObject* len) 5267db96d56Sopenharmony_ci{ 5277db96d56Sopenharmony_ci PyObject *start, *stop, *step; 5287db96d56Sopenharmony_ci PyObject *length; 5297db96d56Sopenharmony_ci int error; 5307db96d56Sopenharmony_ci 5317db96d56Sopenharmony_ci /* Convert length to an integer if necessary; raise for negative length. */ 5327db96d56Sopenharmony_ci length = PyNumber_Index(len); 5337db96d56Sopenharmony_ci if (length == NULL) 5347db96d56Sopenharmony_ci return NULL; 5357db96d56Sopenharmony_ci 5367db96d56Sopenharmony_ci if (_PyLong_Sign(length) < 0) { 5377db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 5387db96d56Sopenharmony_ci "length should not be negative"); 5397db96d56Sopenharmony_ci Py_DECREF(length); 5407db96d56Sopenharmony_ci return NULL; 5417db96d56Sopenharmony_ci } 5427db96d56Sopenharmony_ci 5437db96d56Sopenharmony_ci error = _PySlice_GetLongIndices(self, length, &start, &stop, &step); 5447db96d56Sopenharmony_ci Py_DECREF(length); 5457db96d56Sopenharmony_ci if (error == -1) 5467db96d56Sopenharmony_ci return NULL; 5477db96d56Sopenharmony_ci else 5487db96d56Sopenharmony_ci return Py_BuildValue("(NNN)", start, stop, step); 5497db96d56Sopenharmony_ci} 5507db96d56Sopenharmony_ci 5517db96d56Sopenharmony_ciPyDoc_STRVAR(slice_indices_doc, 5527db96d56Sopenharmony_ci"S.indices(len) -> (start, stop, stride)\n\ 5537db96d56Sopenharmony_ci\n\ 5547db96d56Sopenharmony_ciAssuming a sequence of length len, calculate the start and stop\n\ 5557db96d56Sopenharmony_ciindices, and the stride length of the extended slice described by\n\ 5567db96d56Sopenharmony_ciS. Out of bounds indices are clipped in a manner consistent with the\n\ 5577db96d56Sopenharmony_cihandling of normal slices."); 5587db96d56Sopenharmony_ci 5597db96d56Sopenharmony_cistatic PyObject * 5607db96d56Sopenharmony_cislice_reduce(PySliceObject* self, PyObject *Py_UNUSED(ignored)) 5617db96d56Sopenharmony_ci{ 5627db96d56Sopenharmony_ci return Py_BuildValue("O(OOO)", Py_TYPE(self), self->start, self->stop, self->step); 5637db96d56Sopenharmony_ci} 5647db96d56Sopenharmony_ci 5657db96d56Sopenharmony_ciPyDoc_STRVAR(reduce_doc, "Return state information for pickling."); 5667db96d56Sopenharmony_ci 5677db96d56Sopenharmony_cistatic PyMethodDef slice_methods[] = { 5687db96d56Sopenharmony_ci {"indices", (PyCFunction)slice_indices, 5697db96d56Sopenharmony_ci METH_O, slice_indices_doc}, 5707db96d56Sopenharmony_ci {"__reduce__", (PyCFunction)slice_reduce, 5717db96d56Sopenharmony_ci METH_NOARGS, reduce_doc}, 5727db96d56Sopenharmony_ci {NULL, NULL} 5737db96d56Sopenharmony_ci}; 5747db96d56Sopenharmony_ci 5757db96d56Sopenharmony_cistatic PyObject * 5767db96d56Sopenharmony_cislice_richcompare(PyObject *v, PyObject *w, int op) 5777db96d56Sopenharmony_ci{ 5787db96d56Sopenharmony_ci if (!PySlice_Check(v) || !PySlice_Check(w)) 5797db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 5807db96d56Sopenharmony_ci 5817db96d56Sopenharmony_ci if (v == w) { 5827db96d56Sopenharmony_ci PyObject *res; 5837db96d56Sopenharmony_ci /* XXX Do we really need this shortcut? 5847db96d56Sopenharmony_ci There's a unit test for it, but is that fair? */ 5857db96d56Sopenharmony_ci switch (op) { 5867db96d56Sopenharmony_ci case Py_EQ: 5877db96d56Sopenharmony_ci case Py_LE: 5887db96d56Sopenharmony_ci case Py_GE: 5897db96d56Sopenharmony_ci res = Py_True; 5907db96d56Sopenharmony_ci break; 5917db96d56Sopenharmony_ci default: 5927db96d56Sopenharmony_ci res = Py_False; 5937db96d56Sopenharmony_ci break; 5947db96d56Sopenharmony_ci } 5957db96d56Sopenharmony_ci Py_INCREF(res); 5967db96d56Sopenharmony_ci return res; 5977db96d56Sopenharmony_ci } 5987db96d56Sopenharmony_ci 5997db96d56Sopenharmony_ci 6007db96d56Sopenharmony_ci PyObject *t1 = PyTuple_Pack(3, 6017db96d56Sopenharmony_ci ((PySliceObject *)v)->start, 6027db96d56Sopenharmony_ci ((PySliceObject *)v)->stop, 6037db96d56Sopenharmony_ci ((PySliceObject *)v)->step); 6047db96d56Sopenharmony_ci if (t1 == NULL) { 6057db96d56Sopenharmony_ci return NULL; 6067db96d56Sopenharmony_ci } 6077db96d56Sopenharmony_ci 6087db96d56Sopenharmony_ci PyObject *t2 = PyTuple_Pack(3, 6097db96d56Sopenharmony_ci ((PySliceObject *)w)->start, 6107db96d56Sopenharmony_ci ((PySliceObject *)w)->stop, 6117db96d56Sopenharmony_ci ((PySliceObject *)w)->step); 6127db96d56Sopenharmony_ci if (t2 == NULL) { 6137db96d56Sopenharmony_ci Py_DECREF(t1); 6147db96d56Sopenharmony_ci return NULL; 6157db96d56Sopenharmony_ci } 6167db96d56Sopenharmony_ci 6177db96d56Sopenharmony_ci PyObject *res = PyObject_RichCompare(t1, t2, op); 6187db96d56Sopenharmony_ci Py_DECREF(t1); 6197db96d56Sopenharmony_ci Py_DECREF(t2); 6207db96d56Sopenharmony_ci return res; 6217db96d56Sopenharmony_ci} 6227db96d56Sopenharmony_ci 6237db96d56Sopenharmony_cistatic int 6247db96d56Sopenharmony_cislice_traverse(PySliceObject *v, visitproc visit, void *arg) 6257db96d56Sopenharmony_ci{ 6267db96d56Sopenharmony_ci Py_VISIT(v->start); 6277db96d56Sopenharmony_ci Py_VISIT(v->stop); 6287db96d56Sopenharmony_ci Py_VISIT(v->step); 6297db96d56Sopenharmony_ci return 0; 6307db96d56Sopenharmony_ci} 6317db96d56Sopenharmony_ci 6327db96d56Sopenharmony_ciPyTypeObject PySlice_Type = { 6337db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(&PyType_Type, 0) 6347db96d56Sopenharmony_ci "slice", /* Name of this type */ 6357db96d56Sopenharmony_ci sizeof(PySliceObject), /* Basic object size */ 6367db96d56Sopenharmony_ci 0, /* Item size for varobject */ 6377db96d56Sopenharmony_ci (destructor)slice_dealloc, /* tp_dealloc */ 6387db96d56Sopenharmony_ci 0, /* tp_vectorcall_offset */ 6397db96d56Sopenharmony_ci 0, /* tp_getattr */ 6407db96d56Sopenharmony_ci 0, /* tp_setattr */ 6417db96d56Sopenharmony_ci 0, /* tp_as_async */ 6427db96d56Sopenharmony_ci (reprfunc)slice_repr, /* tp_repr */ 6437db96d56Sopenharmony_ci 0, /* tp_as_number */ 6447db96d56Sopenharmony_ci 0, /* tp_as_sequence */ 6457db96d56Sopenharmony_ci 0, /* tp_as_mapping */ 6467db96d56Sopenharmony_ci PyObject_HashNotImplemented, /* tp_hash */ 6477db96d56Sopenharmony_ci 0, /* tp_call */ 6487db96d56Sopenharmony_ci 0, /* tp_str */ 6497db96d56Sopenharmony_ci PyObject_GenericGetAttr, /* tp_getattro */ 6507db96d56Sopenharmony_ci 0, /* tp_setattro */ 6517db96d56Sopenharmony_ci 0, /* tp_as_buffer */ 6527db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 6537db96d56Sopenharmony_ci slice_doc, /* tp_doc */ 6547db96d56Sopenharmony_ci (traverseproc)slice_traverse, /* tp_traverse */ 6557db96d56Sopenharmony_ci 0, /* tp_clear */ 6567db96d56Sopenharmony_ci slice_richcompare, /* tp_richcompare */ 6577db96d56Sopenharmony_ci 0, /* tp_weaklistoffset */ 6587db96d56Sopenharmony_ci 0, /* tp_iter */ 6597db96d56Sopenharmony_ci 0, /* tp_iternext */ 6607db96d56Sopenharmony_ci slice_methods, /* tp_methods */ 6617db96d56Sopenharmony_ci slice_members, /* tp_members */ 6627db96d56Sopenharmony_ci 0, /* tp_getset */ 6637db96d56Sopenharmony_ci 0, /* tp_base */ 6647db96d56Sopenharmony_ci 0, /* tp_dict */ 6657db96d56Sopenharmony_ci 0, /* tp_descr_get */ 6667db96d56Sopenharmony_ci 0, /* tp_descr_set */ 6677db96d56Sopenharmony_ci 0, /* tp_dictoffset */ 6687db96d56Sopenharmony_ci 0, /* tp_init */ 6697db96d56Sopenharmony_ci 0, /* tp_alloc */ 6707db96d56Sopenharmony_ci slice_new, /* tp_new */ 6717db96d56Sopenharmony_ci}; 672