/*********************************************************** Copyright (c) 2000, BeOpen.com. Copyright (c) 1995-2000, Corporation for National Research Initiatives. Copyright (c) 1990-1995, Stichting Mathematisch Centrum. All rights reserved. See the file "Misc/COPYRIGHT" for information on usage and redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. ******************************************************************/ /* Range object implementation */ #include "Python.h" typedef struct { PyObject_HEAD long start; long step; long len; int reps; } rangeobject; PyObject * PyRange_New(long start, long len, long step, int reps) { rangeobject *obj = PyObject_NEW(rangeobject, &PyRange_Type); obj->start = start; obj->len = len; obj->step = step; obj->reps = reps; 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->len * r->reps) { PyErr_SetString(PyExc_IndexError, "xrange object index out of range"); return NULL; } return PyInt_FromLong(r->start + (i % r->len) * r->step); } static int range_length(rangeobject *r) { return r->len * r->reps; } static int range_print(rangeobject *r, FILE *fp, int flags) { int i, j; fprintf(fp, "("); for (i = 0; i < r->reps; ++i) for (j = 0; j < r->len; ++j) { if (j > 0 || i > 0) fprintf(fp, ", "); fprintf(fp, "%ld", r->start + j * r->step); } if (r->len == 1 && r->reps == 1) fprintf(fp, ","); fprintf(fp, ")"); return 0; } static PyObject * range_repr(rangeobject *r) { char buf[80]; sprintf(buf, "(xrange(%ld, %ld, %ld) * %d)", r->start, r->start + r->len * r->step, r->step, r->reps); return PyString_FromString(buf); } static PyObject * range_concat(rangeobject *r, PyObject *obj) { PyErr_SetString(PyExc_TypeError, "cannot concatenate xrange objects"); return NULL; } static PyObject * range_repeat(rangeobject *r, int n) { if (n < 0) return (PyObject *) PyRange_New(0, 0, 1, 1); else if (n == 1) { Py_INCREF(r); return (PyObject *) r; } else return (PyObject *) PyRange_New( r->start, r->len, r->step, r->reps * n); } static int range_compare(rangeobject *r1, rangeobject *r2) { 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) { 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; int len = self->len * self->reps; if (! PyArg_Parse(args, "")) return NULL; if ((thelist = PyList_New(len)) == NULL) return NULL; for (j = 0; j < len; ++j) if ((PyList_SetItem(thelist, j, (PyObject *) PyInt_FromLong( self->start + (j % self->len) * self->step))) < 0) return NULL; return thelist; } static PyObject * range_getattr(rangeobject *r, char *name) { static PyMethodDef range_methods[] = { {"tolist", (PyCFunction)range_tolist}, {NULL, NULL} }; return Py_FindMethod(range_methods, (PyObject *) r, name); } static int range_contains(rangeobject *r, PyObject *obj) { long num = PyInt_AsLong(obj); if (num < 0 && PyErr_Occurred()) return -1; if (num < r->start || (num - r->start) % r->step) return 0; if (num > (r->start + (r->len * r->step))) return 0; return 1; } static PySequenceMethods range_as_sequence = { (inquiry)range_length, /*sq_length*/ (binaryfunc)range_concat, /*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*/ (objobjproc)range_contains, /*sq_contains*/ }; 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*/ (printfunc)range_print, /*tp_print*/ (getattrfunc)range_getattr, /*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*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT, /*tp_flags*/ };