diff options
-rw-r--r-- | Objects/rangeobject.c | 313 |
1 files changed, 40 insertions, 273 deletions
diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index 9992185..d28fb3a 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -2,78 +2,33 @@ /* Range object implementation */ #include "Python.h" -#include "structmember.h" -#include <string.h> - -#define WARN(msg) if (PyErr_Warn(PyExc_DeprecationWarning, msg) < 0) \ - return NULL; typedef struct { PyObject_HEAD long start; long step; long len; - int reps; - long totlen; } rangeobject; -static int -long_mul(long i, long j, long *kk) -{ - PyObject *a; - PyObject *b; - PyObject *c; - - if ((a = PyInt_FromLong(i)) == NULL) - return 0; - - if ((b = PyInt_FromLong(j)) == NULL) - return 0; - - c = PyNumber_Multiply(a, b); - - Py_DECREF(a); - Py_DECREF(b); - - if (c == NULL) - return 0; - - if (!PyInt_Check(c)) { - Py_DECREF(c); - goto overflow; - } - - *kk = PyInt_AS_LONG(c); - Py_DECREF(c); - - if (*kk > INT_MAX) { - overflow: - PyErr_SetString(PyExc_OverflowError, - "integer multiplication"); - return 0; - } - else - return 1; -} - PyObject * PyRange_New(long start, long len, long step, int reps) { - long totlen = -1; - rangeobject *obj = PyObject_New(rangeobject, &PyRange_Type); + rangeobject *obj; + if (reps != 1) { + PyErr_SetString(PyExc_ValueError, + "PyRange_New's 'repetitions' argument must be 1"); + return NULL; + } + + obj = PyObject_New(rangeobject, &PyRange_Type); if (obj == NULL) return NULL; - - if (reps != 1) - WARN("PyRange_New's 'repetitions' argument is deprecated"); - if (len == 0 || reps <= 0) { + if (len == 0) { start = 0; len = 0; step = 1; - reps = 1; - totlen = 0; } else { long last = start + (len - 1) * step; @@ -84,49 +39,29 @@ PyRange_New(long start, long len, long step, int reps) "integer addition"); return NULL; } - if (! long_mul(len, (long) reps, &totlen)) { - if(!PyErr_ExceptionMatches(PyExc_OverflowError)) - return NULL; - PyErr_Clear(); - totlen = -1; - } } - obj->start = start; obj->len = len; obj->step = step; - obj->reps = reps; - obj->totlen = totlen; return (PyObject *) obj; } -static void -range_dealloc(rangeobject *r) -{ - PyObject_Del(r); -} - static PyObject * range_item(rangeobject *r, int i) { - if (i < 0 || i >= r->totlen) - if (r->totlen!=-1) { - PyErr_SetString(PyExc_IndexError, + if (i < 0 || i >= r->len) { + PyErr_SetString(PyExc_IndexError, "xrange object index out of range"); - return NULL; - } - + return NULL; + } return PyInt_FromLong(r->start + (i % r->len) * r->step); } static int range_length(rangeobject *r) { - if (r->totlen == -1) - PyErr_SetString(PyExc_OverflowError, - "xrange object has too many items"); - return r->totlen; + return r->len; } static PyObject * @@ -148,206 +83,38 @@ range_repr(rangeobject *r) r->start, r->start + r->len * r->step, r->step); - if (r->reps != 1) { - PyObject *extra = PyString_FromFormat( - "(%s * %d)", - PyString_AS_STRING(rtn), r->reps); - Py_DECREF(rtn); - rtn = extra; - } return rtn; } -static PyObject * -range_repeat(rangeobject *r, int n) -{ - long lreps = 0; - - WARN("xrange object multiplication is deprecated; " - "convert to list instead"); - - if (n <= 0) - return (PyObject *) PyRange_New(0, 0, 1, 1); - - else if (n == 1) { - Py_INCREF(r); - return (PyObject *) r; - } - - else if (! long_mul((long) r->reps, (long) n, &lreps)) - return NULL; - - else - return (PyObject *) PyRange_New( - r->start, - r->len, - r->step, - (int) lreps); -} - -static int -range_compare(rangeobject *r1, rangeobject *r2) -{ - - if (PyErr_Warn(PyExc_DeprecationWarning, - "xrange object comparison is deprecated; " - "convert to list instead") < 0) - return -1; - - if (r1->start != r2->start) - return r1->start - r2->start; - - else if (r1->step != r2->step) - return r1->step - r2->step; - - else if (r1->len != r2->len) - return r1->len - r2->len; - - else - return r1->reps - r2->reps; -} - -static PyObject * -range_slice(rangeobject *r, int low, int high) -{ - WARN("xrange object slicing is deprecated; " - "convert to list instead"); - - if (r->reps != 1) { - PyErr_SetString(PyExc_TypeError, - "cannot slice a replicated xrange"); - return NULL; - } - if (low < 0) - low = 0; - else if (low > r->len) - low = r->len; - if (high < 0) - high = 0; - if (high < low) - high = low; - else if (high > r->len) - high = r->len; - - if (low == 0 && high == r->len) { - Py_INCREF(r); - return (PyObject *) r; - } - - return (PyObject *) PyRange_New( - low * r->step + r->start, - high - low, - r->step, - 1); -} - -static PyObject * -range_tolist(rangeobject *self, PyObject *args) -{ - PyObject *thelist; - int j; - - WARN("xrange.tolist() is deprecated; use list(xrange) instead"); - - if (self->totlen == -1) - return PyErr_NoMemory(); - - if ((thelist = PyList_New(self->totlen)) == NULL) - return NULL; - - for (j = 0; j < self->totlen; ++j) - if ((PyList_SetItem(thelist, j, (PyObject *) PyInt_FromLong( - self->start + (j % self->len) * self->step))) < 0) - return NULL; - - return thelist; -} - -static PyObject * -range_get_stop(rangeobject *self, void *closure) -{ - return PyInt_FromLong(self->start + (self->len * self->step)); -} - -static PyMethodDef range_methods[] = { - {"tolist", (PyCFunction)range_tolist, METH_NOARGS, - "tolist() -> list\n" - "Return a list object with the same values.\n" - "(This method is deprecated; use list() instead.)"}, - {NULL, NULL} -}; - -static PyMemberDef range_members[] = { - {"step", T_LONG, offsetof(rangeobject, step), RO, - "Interval between indexes of the slice; also known as the 'stride'."}, - {"start", T_LONG, offsetof(rangeobject, start), RO, - "First index of the slice."}, - {NULL, 0, 0, 0} -}; - -static PyGetSetDef range_getsets[] = { - {"stop", (getter)range_get_stop, NULL, - ""}, - {NULL}, -}; - -static PyObject * -range_getattro(rangeobject *self, PyObject *name) -{ - PyObject *result; - result = PyObject_GenericGetAttr((PyObject *)self, name); - if (result && PyInt_CheckExact(result)) { - WARN("xrange object's 'start', 'stop' and 'step' " - "attributes are deprecated"); - } - return result; -} - static PySequenceMethods range_as_sequence = { - (inquiry)range_length, /*sq_length*/ - 0, /*sq_concat*/ - (intargfunc)range_repeat, /*sq_repeat*/ - (intargfunc)range_item, /*sq_item*/ - (intintargfunc)range_slice, /*sq_slice*/ - 0, /*sq_ass_item*/ - 0, /*sq_ass_slice*/ - 0, /*sq_contains*/ + (inquiry)range_length, /* sq_length */ + 0, /* sq_concat */ + 0, /* sq_repeat */ + (intargfunc)range_item, /* sq_item */ + 0, /* sq_slice */ }; PyTypeObject PyRange_Type = { PyObject_HEAD_INIT(&PyType_Type) - 0, /* Number of items for varobject */ - "xrange", /* Name of this type */ - sizeof(rangeobject), /* Basic object size */ - 0, /* Item size for varobject */ - (destructor)range_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - (cmpfunc)range_compare, /*tp_compare*/ - (reprfunc)range_repr, /*tp_repr*/ - 0, /*tp_as_number*/ - &range_as_sequence, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - (getattrofunc)range_getattro, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - range_methods, /* tp_methods */ - range_members, /* tp_members */ - range_getsets, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ + 0, /* Number of items for varobject */ + "xrange", /* Name of this type */ + sizeof(rangeobject), /* Basic object size */ + 0, /* Item size for varobject */ + (destructor)PyObject_Del, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + (reprfunc)range_repr, /* tp_repr */ + 0, /* tp_as_number */ + &range_as_sequence, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ }; - -#undef WARN |