cpython/Objects/rangeobject.c

/* Range object implementation */

#include "Python.h"
#include "pycore_abstract.h"      // _PyIndex_Check()
#include "pycore_ceval.h"         // _PyEval_GetBuiltin()
#include "pycore_long.h"          // _PyLong_GetZero()
#include "pycore_modsupport.h"    // _PyArg_NoKwnames()
#include "pycore_range.h"
#include "pycore_tuple.h"         // _PyTuple_ITEMS()


/* Support objects whose length is > PY_SSIZE_T_MAX.

   This could be sped up for small PyLongs if they fit in a Py_ssize_t.
   This only matters on Win64.  Though we could use long long which
   would presumably help perf.
*/

rangeobject;

/* Helper function for validating step.  Always returns a new reference or
   NULL on error.
*/
static PyObject *
validate_step(PyObject *step)
{}

static PyObject *
compute_range_length(PyObject *start, PyObject *stop, PyObject *step);

static rangeobject *
make_range_object(PyTypeObject *type, PyObject *start,
                  PyObject *stop, PyObject *step)
{}

/* XXX(nnorwitz): should we error check if the user passes any empty ranges?
   range(-10)
   range(0, -5)
   range(0, 5, -1)
*/
static PyObject *
range_from_array(PyTypeObject *type, PyObject *const *args, Py_ssize_t num_args)
{}

static PyObject *
range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{}


static PyObject *
range_vectorcall(PyObject *rangetype, PyObject *const *args,
                 size_t nargsf, PyObject *kwnames)
{}

PyDoc_STRVAR(range_doc,
"range(stop) -> range object\n\
range(start, stop[, step]) -> range object\n\
\n\
Return an object that produces a sequence of integers from start (inclusive)\n\
to stop (exclusive) by step.  range(i, j) produces i, i+1, i+2, ..., j-1.\n\
start defaults to 0, and stop is omitted!  range(4) produces 0, 1, 2, 3.\n\
These are exactly the valid indices for a list of 4 elements.\n\
When step is given, it specifies the increment (or decrement).");

static void
range_dealloc(rangeobject *r)
{}

static unsigned long
get_len_of_range(long lo, long hi, long step);

/* Return the length as a long, -2 for an overflow and -1 for any other type of error
 *
 * In case of an overflow no error is set
 */
static long compute_range_length_long(PyObject *start,
                PyObject *stop, PyObject *step) {}

/* Return number of items in range (lo, hi, step) as a PyLong object,
 * when arguments are PyLong objects.  Arguments MUST return 1 with
 * PyLong_Check().  Return NULL when there is an error.
 */
static PyObject*
compute_range_length(PyObject *start, PyObject *stop, PyObject *step)
{}

static Py_ssize_t
range_length(rangeobject *r)
{}

static PyObject *
compute_item(rangeobject *r, PyObject *i)
{}

static PyObject *
compute_range_item(rangeobject *r, PyObject *arg)
{}

static PyObject *
range_item(rangeobject *r, Py_ssize_t i)
{}

static PyObject *
compute_slice(rangeobject *r, PyObject *_slice)
{}

/* Assumes (PyLong_CheckExact(ob) || PyBool_Check(ob)) */
static int
range_contains_long(rangeobject *r, PyObject *ob)
{}

static int
range_contains(rangeobject *r, PyObject *ob)
{}

/* Compare two range objects.  Return 1 for equal, 0 for not equal
   and -1 on error.  The algorithm is roughly the C equivalent of

   if r0 is r1:
       return True
   if len(r0) != len(r1):
       return False
   if not len(r0):
       return True
   if r0.start != r1.start:
       return False
   if len(r0) == 1:
       return True
   return r0.step == r1.step
*/
static int
range_equals(rangeobject *r0, rangeobject *r1)
{}

static PyObject *
range_richcompare(PyObject *self, PyObject *other, int op)
{}

/* Hash function for range objects.  Rough C equivalent of

   if not len(r):
       return hash((len(r), None, None))
   if len(r) == 1:
       return hash((len(r), r.start, None))
   return hash((len(r), r.start, r.step))
*/
static Py_hash_t
range_hash(rangeobject *r)
{}

static PyObject *
range_count(rangeobject *r, PyObject *ob)
{}

static PyObject *
range_index(rangeobject *r, PyObject *ob)
{}

static PySequenceMethods range_as_sequence =;

static PyObject *
range_repr(rangeobject *r)
{}

/* Pickling support */
static PyObject *
range_reduce(rangeobject *r, PyObject *args)
{}

static PyObject *
range_subscript(rangeobject* self, PyObject* item)
{}


static PyMappingMethods range_as_mapping =;

static int
range_bool(rangeobject* self)
{}

static PyNumberMethods range_as_number =;

static PyObject * range_iter(PyObject *seq);
static PyObject * range_reverse(PyObject *seq, PyObject *Py_UNUSED(ignored));

PyDoc_STRVAR(reverse_doc,
"Return a reverse iterator.");

PyDoc_STRVAR(count_doc,
"rangeobject.count(value) -> integer -- return number of occurrences of value");

PyDoc_STRVAR(index_doc,
"rangeobject.index(value) -> integer -- return index of value.\n"
"Raise ValueError if the value is not present.");

static PyMethodDef range_methods[] =;

static PyMemberDef range_members[] =;

PyTypeObject PyRange_Type =;

/*********************** range Iterator **************************/

/* There are 2 types of iterators, one for C longs, the other for
   Python ints (ie, PyObjects).  This should make iteration fast
   in the normal case, but possible for any numeric value.
*/

static PyObject *
rangeiter_next(_PyRangeIterObject *r)
{}

static PyObject *
rangeiter_len(_PyRangeIterObject *r, PyObject *Py_UNUSED(ignored))
{}

PyDoc_STRVAR(length_hint_doc,
             "Private method returning an estimate of len(list(it)).");

static PyObject *
rangeiter_reduce(_PyRangeIterObject *r, PyObject *Py_UNUSED(ignored))
{}

static PyObject *
rangeiter_setstate(_PyRangeIterObject *r, PyObject *state)
{}

PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");

static PyMethodDef rangeiter_methods[] =;

PyTypeObject PyRangeIter_Type =;

/* Return number of items in range (lo, hi, step).  step != 0
 * required.  The result always fits in an unsigned long.
 */
static unsigned long
get_len_of_range(long lo, long hi, long step)
{}

/* Initialize a rangeiter object.  If the length of the rangeiter object
   is not representable as a C long, OverflowError is raised. */

static PyObject *
fast_range_iter(long start, long stop, long step, long len)
{}

longrangeiterobject;

static PyObject *
longrangeiter_len(longrangeiterobject *r, PyObject *no_args)
{}

static PyObject *
longrangeiter_reduce(longrangeiterobject *r, PyObject *Py_UNUSED(ignored))
{}

static PyObject *
longrangeiter_setstate(longrangeiterobject *r, PyObject *state)
{}

static PyMethodDef longrangeiter_methods[] =;

static void
longrangeiter_dealloc(longrangeiterobject *r)
{}

static PyObject *
longrangeiter_next(longrangeiterobject *r)
{}

PyTypeObject PyLongRangeIter_Type =;

static PyObject *
range_iter(PyObject *seq)
{}

static PyObject *
range_reverse(PyObject *seq, PyObject *Py_UNUSED(ignored))
{}