
/* Range object implementation */

#include "Python.h"
#include "structmember.h"
#include <string.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);

	if (obj == NULL)
		return NULL;

	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 PyObject *
range_repr(rangeobject *r)
{
	/* buffers must be big enough to hold 3 longs + an int +
	 * a bit of "(xrange(...) * ...)" text.
	 */
	char buf1[250];
	char buf2[250];

	if (r->start == 0 && r->step == 1)
		sprintf(buf1, "xrange(%ld)", r->start + r->len * r->step);

	else if (r->step == 1)
		sprintf(buf1, "xrange(%ld, %ld)",
			r->start,
			r->start + r->len * r->step);

	else
		sprintf(buf1, "xrange(%ld, %ld, %ld)",
			r->start,
			r->start + r->len * r->step,
			r->step);

	if (r->reps != 1)
		sprintf(buf2, "(%s * %d)", buf1, r->reps);

	return PyString_FromString(r->reps == 1 ? buf1 : buf2);
}

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_ParseTuple(args, ":tolist"))
		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)
{
	PyObject *result;

	static PyMethodDef range_methods[] = {
		{"tolist",	(PyCFunction)range_tolist, METH_VARARGS,
                 "tolist() -> list\n"
                 "Return a list object with the same values."},
		{NULL,		NULL}
	};
	static struct memberlist range_members[] = {
		{"step",  T_LONG, offsetof(rangeobject, step), RO},
		{"start", T_LONG, offsetof(rangeobject, start), RO},
		{"stop",  T_LONG, 0, RO},
		{NULL, 0, 0, 0}
	};

	result = Py_FindMethod(range_methods, (PyObject *) r, name);
	if (result == NULL) {
		PyErr_Clear();
		if (strcmp("stop", name) == 0)
			result = PyInt_FromLong(r->start + (r->len * r->step));
		else
			result = PyMember_Get((char *)r, range_members, name);
	}
	return result;
}

static int
range_contains(rangeobject *r, PyObject *obj)
{
	long num = PyInt_AsLong(obj);

	if (num < 0 && PyErr_Occurred())
		return -1;

	if (r->step > 0) {
		if ((num < r->start) || ((num - r->start) % r->step))
			return 0;
		if (num >= (r->start + (r->len * r->step)))
			return 0;
	}
	else {
		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*/
	0,			/*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*/
};
