xref: /third_party/python/Objects/sliceobject.c (revision 7db96d56)
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