History

add hg and python

cinap_lenrek committed 15 years ago

Commit 4bb9e221 parent 987265c3706 files · +1228772 −-233Browse files

Showing the changes to sys/src/cmd/python/Objects/sliceobject.c (1 of 3706 files). Show all

Unified · Split

sys/src/cmd/python/Objects/sliceobject.c+351−0
@@ -0,0 +1,351 @@
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+ PyObject_HEAD_INIT(&PyType_Type)
27+ 0, /* ob_size */
28+ "ellipsis", /* tp_name */
29+ 0, /* tp_basicsize */
30+ 0, /* tp_itemsize */
31+ 0, /*never called*/ /* tp_dealloc */
32+ 0, /* tp_print */
33+ 0, /* tp_getattr */
34+ 0, /* tp_setattr */
35+ 0, /* tp_compare */
36+ ellipsis_repr, /* tp_repr */
37+ 0, /* tp_as_number */
38+ 0, /* tp_as_sequence */
39+ 0, /* tp_as_mapping */
40+ 0, /* tp_hash */
41+ 0, /* tp_call */
42+ 0, /* tp_str */
43+ PyObject_GenericGetAttr, /* tp_getattro */
44+ 0, /* tp_setattro */
45+ 0, /* tp_as_buffer */
46+ Py_TPFLAGS_DEFAULT, /* tp_flags */
47+};
48+
49+PyObject _Py_EllipsisObject = {
50+ PyObject_HEAD_INIT(&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 = -1;
173+ if (*stop > length) *stop = length;
174+ }
175+
176+ if ((*step < 0 && *stop >= *start)
177+ || (*step > 0 && *start >= *stop)) {
178+ *slicelength = 0;
179+ }
180+ else if (*step < 0) {
181+ *slicelength = (*stop-*start+1)/(*step)+1;
182+ }
183+ else {
184+ *slicelength = (*stop-*start-1)/(*step)+1;
185+ }
186+
187+ return 0;
188+}
189+
190+static PyObject *
191+slice_new(PyTypeObject *type, PyObject *args, PyObject *kw)
192+{
193+ PyObject *start, *stop, *step;
194+
195+ start = stop = step = NULL;
196+
197+ if (!_PyArg_NoKeywords("slice()", kw))
198+ return NULL;
199+
200+ if (!PyArg_UnpackTuple(args, "slice", 1, 3, &start, &stop, &step))
201+ return NULL;
202+
203+ /* This swapping of stop and start is to maintain similarity with
204+ range(). */
205+ if (stop == NULL) {
206+ stop = start;
207+ start = NULL;
208+ }
209+ return PySlice_New(start, stop, step);
210+}
211+
212+PyDoc_STRVAR(slice_doc,
213+"slice([start,] stop[, step])\n\
214+\n\
215+Create a slice object. This is used for extended slicing (e.g. a[0:10:2]).");
216+
217+static void
218+slice_dealloc(PySliceObject *r)
219+{
220+ Py_DECREF(r->step);
221+ Py_DECREF(r->start);
222+ Py_DECREF(r->stop);
223+ PyObject_Del(r);
224+}
225+
226+static PyObject *
227+slice_repr(PySliceObject *r)
228+{
229+ PyObject *s, *comma;
230+
231+ s = PyString_FromString("slice(");
232+ comma = PyString_FromString(", ");
233+ PyString_ConcatAndDel(&s, PyObject_Repr(r->start));
234+ PyString_Concat(&s, comma);
235+ PyString_ConcatAndDel(&s, PyObject_Repr(r->stop));
236+ PyString_Concat(&s, comma);
237+ PyString_ConcatAndDel(&s, PyObject_Repr(r->step));
238+ PyString_ConcatAndDel(&s, PyString_FromString(")"));
239+ Py_DECREF(comma);
240+ return s;
241+}
242+
243+static PyMemberDef slice_members[] = {
244+ {"start", T_OBJECT, offsetof(PySliceObject, start), READONLY},
245+ {"stop", T_OBJECT, offsetof(PySliceObject, stop), READONLY},
246+ {"step", T_OBJECT, offsetof(PySliceObject, step), READONLY},
247+ {0}
248+};
249+
250+static PyObject*
251+slice_indices(PySliceObject* self, PyObject* len)
252+{
253+ Py_ssize_t ilen, start, stop, step, slicelength;
254+
255+ ilen = PyNumber_AsSsize_t(len, PyExc_OverflowError);
256+
257+ if (ilen == -1 && PyErr_Occurred()) {
258+ return NULL;
259+ }
260+
261+ if (PySlice_GetIndicesEx(self, ilen, &start, &stop,
262+ &step, &slicelength) < 0) {
263+ return NULL;
264+ }
265+
266+ return Py_BuildValue("(nnn)", start, stop, step);
267+}
268+
269+PyDoc_STRVAR(slice_indices_doc,
270+"S.indices(len) -> (start, stop, stride)\n\
271+\n\
272+Assuming a sequence of length len, calculate the start and stop\n\
273+indices, and the stride length of the extended slice described by\n\
274+S. Out of bounds indices are clipped in a manner consistent with the\n\
275+handling of normal slices.");
276+
277+static PyMethodDef slice_methods[] = {
278+ {"indices", (PyCFunction)slice_indices,
279+ METH_O, slice_indices_doc},
280+ {NULL, NULL}
281+};
282+
283+static int
284+slice_compare(PySliceObject *v, PySliceObject *w)
285+{
286+ int result = 0;
287+
288+ if (v == w)
289+ return 0;
290+
291+ if (PyObject_Cmp(v->start, w->start, &result) < 0)
292+ return -2;
293+ if (result != 0)
294+ return result;
295+ if (PyObject_Cmp(v->stop, w->stop, &result) < 0)
296+ return -2;
297+ if (result != 0)
298+ return result;
299+ if (PyObject_Cmp(v->step, w->step, &result) < 0)
300+ return -2;
301+ return result;
302+}
303+
304+static long
305+slice_hash(PySliceObject *v)
306+{
307+ PyErr_SetString(PyExc_TypeError, "unhashable type");
308+ return -1L;
309+}
310+
311+PyTypeObject PySlice_Type = {
312+ PyObject_HEAD_INIT(&PyType_Type)
313+ 0, /* Number of items for varobject */
314+ "slice", /* Name of this type */
315+ sizeof(PySliceObject), /* Basic object size */
316+ 0, /* Item size for varobject */
317+ (destructor)slice_dealloc, /* tp_dealloc */
318+ 0, /* tp_print */
319+ 0, /* tp_getattr */
320+ 0, /* tp_setattr */
321+ (cmpfunc)slice_compare, /* tp_compare */
322+ (reprfunc)slice_repr, /* tp_repr */
323+ 0, /* tp_as_number */
324+ 0, /* tp_as_sequence */
325+ 0, /* tp_as_mapping */
326+ (hashfunc)slice_hash, /* tp_hash */
327+ 0, /* tp_call */
328+ 0, /* tp_str */
329+ PyObject_GenericGetAttr, /* tp_getattro */
330+ 0, /* tp_setattro */
331+ 0, /* tp_as_buffer */
332+ Py_TPFLAGS_DEFAULT, /* tp_flags */
333+ slice_doc, /* tp_doc */
334+ 0, /* tp_traverse */
335+ 0, /* tp_clear */
336+ 0, /* tp_richcompare */
337+ 0, /* tp_weaklistoffset */
338+ 0, /* tp_iter */
339+ 0, /* tp_iternext */
340+ slice_methods, /* tp_methods */
341+ slice_members, /* tp_members */
342+ 0, /* tp_getset */
343+ 0, /* tp_base */
344+ 0, /* tp_dict */
345+ 0, /* tp_descr_get */
346+ 0, /* tp_descr_set */
347+ 0, /* tp_dictoffset */
348+ 0, /* tp_init */
349+ 0, /* tp_alloc */
350+ slice_new, /* tp_new */
351+};

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t