symbian-qemu-0.9.1-12/python-2.6.1/Objects/sliceobject.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2 Written by Jim Hugunin and Chris Chase.
       
     3 
       
     4 This includes both the singular ellipsis object and slice objects.
       
     5 
       
     6 Guido, feel free to do whatever you want in the way of copyrights
       
     7 for this file.
       
     8 */
       
     9 
       
    10 /* 
       
    11 Py_Ellipsis encodes the '...' rubber index token. It is similar to
       
    12 the Py_NoneStruct in that there is no way to create other objects of
       
    13 this type and there is exactly one in existence.
       
    14 */
       
    15 
       
    16 #include "Python.h"
       
    17 #include "structmember.h"
       
    18 
       
    19 static PyObject *
       
    20 ellipsis_repr(PyObject *op)
       
    21 {
       
    22 	return PyString_FromString("Ellipsis");
       
    23 }
       
    24 
       
    25 static PyTypeObject PyEllipsis_Type = {
       
    26 	PyVarObject_HEAD_INIT(&PyType_Type, 0)
       
    27 	"ellipsis",			/* tp_name */
       
    28 	0,				/* tp_basicsize */
       
    29 	0,				/* tp_itemsize */
       
    30 	0, /*never called*/		/* tp_dealloc */
       
    31 	0,				/* tp_print */
       
    32 	0,				/* tp_getattr */
       
    33 	0,				/* tp_setattr */
       
    34 	0,				/* tp_compare */
       
    35 	ellipsis_repr,			/* tp_repr */
       
    36 	0,				/* tp_as_number */
       
    37 	0,				/* tp_as_sequence */
       
    38 	0,				/* tp_as_mapping */
       
    39 	0,				/* tp_hash */
       
    40 	0,				/* tp_call */
       
    41 	0,				/* tp_str */
       
    42 	PyObject_GenericGetAttr,	/* tp_getattro */
       
    43 	0,				/* tp_setattro */
       
    44 	0,				/* tp_as_buffer */
       
    45 	Py_TPFLAGS_DEFAULT,		/* tp_flags */
       
    46 };
       
    47 
       
    48 PyObject _Py_EllipsisObject = {
       
    49 	_PyObject_EXTRA_INIT
       
    50 	1, &PyEllipsis_Type
       
    51 };
       
    52 
       
    53 
       
    54 /* Slice object implementation
       
    55 
       
    56    start, stop, and step are python objects with None indicating no
       
    57    index is present.
       
    58 */
       
    59 
       
    60 PyObject *
       
    61 PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
       
    62 {
       
    63 	PySliceObject *obj = PyObject_New(PySliceObject, &PySlice_Type);
       
    64 
       
    65 	if (obj == NULL)
       
    66 		return NULL;
       
    67 
       
    68 	if (step == NULL) step = Py_None;
       
    69 	Py_INCREF(step);
       
    70 	if (start == NULL) start = Py_None;
       
    71 	Py_INCREF(start);
       
    72 	if (stop == NULL) stop = Py_None;
       
    73 	Py_INCREF(stop);
       
    74 
       
    75 	obj->step = step;
       
    76 	obj->start = start;
       
    77 	obj->stop = stop;
       
    78 
       
    79 	return (PyObject *) obj;
       
    80 }
       
    81 
       
    82 PyObject *
       
    83 _PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop)
       
    84 {
       
    85 	PyObject *start, *end, *slice;
       
    86 	start = PyInt_FromSsize_t(istart);
       
    87 	if (!start)
       
    88 		return NULL;
       
    89 	end = PyInt_FromSsize_t(istop);
       
    90 	if (!end) {
       
    91 		Py_DECREF(start);
       
    92 		return NULL;
       
    93 	}
       
    94 
       
    95 	slice = PySlice_New(start, end, NULL);
       
    96 	Py_DECREF(start);
       
    97 	Py_DECREF(end);
       
    98 	return slice;
       
    99 }
       
   100 
       
   101 int
       
   102 PySlice_GetIndices(PySliceObject *r, Py_ssize_t length,
       
   103                    Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
       
   104 {
       
   105 	/* XXX support long ints */
       
   106 	if (r->step == Py_None) {
       
   107 		*step = 1;
       
   108 	} else {
       
   109 		if (!PyInt_Check(r->step) && !PyLong_Check(r->step)) return -1;
       
   110 		*step = PyInt_AsSsize_t(r->step);
       
   111 	}
       
   112 	if (r->start == Py_None) {
       
   113 		*start = *step < 0 ? length-1 : 0;
       
   114 	} else {
       
   115 		if (!PyInt_Check(r->start) && !PyLong_Check(r->step)) return -1;
       
   116 		*start = PyInt_AsSsize_t(r->start);
       
   117 		if (*start < 0) *start += length;
       
   118 	}
       
   119 	if (r->stop == Py_None) {
       
   120 		*stop = *step < 0 ? -1 : length;
       
   121 	} else {
       
   122 		if (!PyInt_Check(r->stop) && !PyLong_Check(r->step)) return -1;
       
   123 		*stop = PyInt_AsSsize_t(r->stop);
       
   124 		if (*stop < 0) *stop += length;
       
   125 	}
       
   126 	if (*stop > length) return -1;
       
   127 	if (*start >= length) return -1;
       
   128 	if (*step == 0) return -1;
       
   129 	return 0;
       
   130 }
       
   131 
       
   132 int
       
   133 PySlice_GetIndicesEx(PySliceObject *r, Py_ssize_t length,
       
   134 		     Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, Py_ssize_t *slicelength)
       
   135 {
       
   136 	/* this is harder to get right than you might think */
       
   137 
       
   138 	Py_ssize_t defstart, defstop;
       
   139 
       
   140 	if (r->step == Py_None) {
       
   141 		*step = 1;
       
   142 	} 
       
   143 	else {
       
   144 		if (!_PyEval_SliceIndex(r->step, step)) return -1;
       
   145 		if (*step == 0) {
       
   146 			PyErr_SetString(PyExc_ValueError,
       
   147 					"slice step cannot be zero");
       
   148 			return -1;
       
   149 		}
       
   150 	}
       
   151 
       
   152 	defstart = *step < 0 ? length-1 : 0;
       
   153 	defstop = *step < 0 ? -1 : length;
       
   154 
       
   155 	if (r->start == Py_None) {
       
   156 		*start = defstart;
       
   157 	}
       
   158 	else {
       
   159 		if (!_PyEval_SliceIndex(r->start, start)) return -1;
       
   160 		if (*start < 0) *start += length;
       
   161 		if (*start < 0) *start = (*step < 0) ? -1 : 0;
       
   162 		if (*start >= length) 
       
   163 			*start = (*step < 0) ? length - 1 : length;
       
   164 	}
       
   165 
       
   166 	if (r->stop == Py_None) {
       
   167 		*stop = defstop;
       
   168 	}
       
   169 	else {
       
   170 		if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
       
   171 		if (*stop < 0) *stop += length;
       
   172 		if (*stop < 0) *stop = (*step < 0) ? -1 : 0;
       
   173 		if (*stop >= length)
       
   174 			*stop = (*step < 0) ? length - 1 : length;
       
   175 	}
       
   176 
       
   177 	if ((*step < 0 && *stop >= *start) 
       
   178 	    || (*step > 0 && *start >= *stop)) {
       
   179 		*slicelength = 0;
       
   180 	}
       
   181 	else if (*step < 0) {
       
   182 		*slicelength = (*stop-*start+1)/(*step)+1;
       
   183 	}
       
   184 	else {
       
   185 		*slicelength = (*stop-*start-1)/(*step)+1;
       
   186 	}
       
   187 
       
   188 	return 0;
       
   189 }
       
   190 
       
   191 static PyObject *
       
   192 slice_new(PyTypeObject *type, PyObject *args, PyObject *kw)
       
   193 {
       
   194 	PyObject *start, *stop, *step;
       
   195 
       
   196 	start = stop = step = NULL;
       
   197 
       
   198 	if (!_PyArg_NoKeywords("slice()", kw))
       
   199 		return NULL;
       
   200 
       
   201 	if (!PyArg_UnpackTuple(args, "slice", 1, 3, &start, &stop, &step))
       
   202 		return NULL;
       
   203 
       
   204 	/* This swapping of stop and start is to maintain similarity with
       
   205 	   range(). */
       
   206 	if (stop == NULL) {
       
   207 		stop = start;
       
   208 		start = NULL;
       
   209 	}
       
   210 	return PySlice_New(start, stop, step);
       
   211 }
       
   212 
       
   213 PyDoc_STRVAR(slice_doc,
       
   214 "slice([start,] stop[, step])\n\
       
   215 \n\
       
   216 Create a slice object.  This is used for extended slicing (e.g. a[0:10:2]).");
       
   217 
       
   218 static void
       
   219 slice_dealloc(PySliceObject *r)
       
   220 {
       
   221 	Py_DECREF(r->step);
       
   222 	Py_DECREF(r->start);
       
   223 	Py_DECREF(r->stop);
       
   224 	PyObject_Del(r);
       
   225 }
       
   226 
       
   227 static PyObject *
       
   228 slice_repr(PySliceObject *r)
       
   229 {
       
   230 	PyObject *s, *comma;
       
   231 
       
   232 	s = PyString_FromString("slice(");
       
   233 	comma = PyString_FromString(", ");
       
   234 	PyString_ConcatAndDel(&s, PyObject_Repr(r->start));
       
   235 	PyString_Concat(&s, comma);
       
   236 	PyString_ConcatAndDel(&s, PyObject_Repr(r->stop));
       
   237 	PyString_Concat(&s, comma);
       
   238 	PyString_ConcatAndDel(&s, PyObject_Repr(r->step));
       
   239 	PyString_ConcatAndDel(&s, PyString_FromString(")"));
       
   240 	Py_DECREF(comma);
       
   241 	return s;
       
   242 }
       
   243 
       
   244 static PyMemberDef slice_members[] = {
       
   245 	{"start", T_OBJECT, offsetof(PySliceObject, start), READONLY},
       
   246 	{"stop", T_OBJECT, offsetof(PySliceObject, stop), READONLY},
       
   247 	{"step", T_OBJECT, offsetof(PySliceObject, step), READONLY},
       
   248 	{0}
       
   249 };
       
   250 
       
   251 static PyObject*
       
   252 slice_indices(PySliceObject* self, PyObject* len)
       
   253 {
       
   254 	Py_ssize_t ilen, start, stop, step, slicelength;
       
   255 
       
   256 	ilen = PyNumber_AsSsize_t(len, PyExc_OverflowError);
       
   257 
       
   258 	if (ilen == -1 && PyErr_Occurred()) {
       
   259 		return NULL;
       
   260 	}
       
   261 
       
   262 	if (PySlice_GetIndicesEx(self, ilen, &start, &stop, 
       
   263 				 &step, &slicelength) < 0) {
       
   264 		return NULL;
       
   265 	}
       
   266 
       
   267 	return Py_BuildValue("(nnn)", start, stop, step);
       
   268 }
       
   269 
       
   270 PyDoc_STRVAR(slice_indices_doc,
       
   271 "S.indices(len) -> (start, stop, stride)\n\
       
   272 \n\
       
   273 Assuming a sequence of length len, calculate the start and stop\n\
       
   274 indices, and the stride length of the extended slice described by\n\
       
   275 S. Out of bounds indices are clipped in a manner consistent with the\n\
       
   276 handling of normal slices.");
       
   277 
       
   278 static PyObject *
       
   279 slice_reduce(PySliceObject* self)
       
   280 {
       
   281 	return Py_BuildValue("O(OOO)", Py_TYPE(self), self->start, self->stop, self->step);
       
   282 }
       
   283 
       
   284 PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
       
   285 
       
   286 static PyMethodDef slice_methods[] = {
       
   287 	{"indices",	(PyCFunction)slice_indices,
       
   288 	 METH_O,	slice_indices_doc},
       
   289 	{"__reduce__",	(PyCFunction)slice_reduce,
       
   290 	 METH_NOARGS,	reduce_doc},
       
   291 	{NULL, NULL}
       
   292 };
       
   293 
       
   294 static int
       
   295 slice_compare(PySliceObject *v, PySliceObject *w)
       
   296 {
       
   297 	int result = 0;
       
   298 
       
   299         if (v == w)
       
   300 		return 0;
       
   301 
       
   302 	if (PyObject_Cmp(v->start, w->start, &result) < 0)
       
   303 	    return -2;
       
   304 	if (result != 0)
       
   305 		return result;
       
   306 	if (PyObject_Cmp(v->stop, w->stop, &result) < 0)
       
   307 	    return -2;
       
   308 	if (result != 0)
       
   309 		return result;
       
   310 	if (PyObject_Cmp(v->step, w->step, &result) < 0)
       
   311 	    return -2;
       
   312 	return result;
       
   313 }
       
   314 
       
   315 static long
       
   316 slice_hash(PySliceObject *v)
       
   317 {
       
   318 	PyErr_SetString(PyExc_TypeError, "unhashable type");
       
   319 	return -1L;
       
   320 }
       
   321 
       
   322 PyTypeObject PySlice_Type = {
       
   323 	PyVarObject_HEAD_INIT(&PyType_Type, 0)
       
   324 	"slice",		/* Name of this type */
       
   325 	sizeof(PySliceObject),	/* Basic object size */
       
   326 	0,			/* Item size for varobject */
       
   327 	(destructor)slice_dealloc,		/* tp_dealloc */
       
   328 	0,					/* tp_print */
       
   329 	0,					/* tp_getattr */
       
   330 	0,					/* tp_setattr */
       
   331 	(cmpfunc)slice_compare, 		/* tp_compare */
       
   332 	(reprfunc)slice_repr,   		/* tp_repr */
       
   333 	0,					/* tp_as_number */
       
   334 	0,	    				/* tp_as_sequence */
       
   335 	0,					/* tp_as_mapping */
       
   336 	(hashfunc)slice_hash,			/* tp_hash */
       
   337 	0,					/* tp_call */
       
   338 	0,					/* tp_str */
       
   339 	PyObject_GenericGetAttr,		/* tp_getattro */
       
   340 	0,					/* tp_setattro */
       
   341 	0,					/* tp_as_buffer */
       
   342 	Py_TPFLAGS_DEFAULT,			/* tp_flags */
       
   343 	slice_doc,				/* tp_doc */
       
   344 	0,					/* tp_traverse */
       
   345 	0,					/* tp_clear */
       
   346 	0,					/* tp_richcompare */
       
   347 	0,					/* tp_weaklistoffset */
       
   348 	0,					/* tp_iter */
       
   349 	0,					/* tp_iternext */
       
   350 	slice_methods,				/* tp_methods */
       
   351 	slice_members,				/* tp_members */
       
   352 	0,					/* tp_getset */
       
   353 	0,					/* tp_base */
       
   354 	0,					/* tp_dict */
       
   355 	0,					/* tp_descr_get */
       
   356 	0,					/* tp_descr_set */
       
   357 	0,					/* tp_dictoffset */
       
   358 	0,					/* tp_init */
       
   359 	0,					/* tp_alloc */
       
   360 	slice_new,				/* tp_new */
       
   361 };