Author: Armin Rigo <[email protected]>
Branch: slicing
Changeset: r1134:b68c5dd2b9ce
Date: 2013-02-10 14:44 +0100
http://bitbucket.org/cffi/cffi/changeset/b68c5dd2b9ce/
Log: getting a slice
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -102,7 +102,8 @@
PyObject *ct_stuff; /* structs: dict of the fields
arrays: ctypedescr of the ptr type
function: tuple(abi, ctres, ctargs..)
- enum: pair {"name":x},{x:"name"} */
+ enum: pair {"name":x},{x:"name"}
+ ptrs: lazily, ctypedescr of array */
void *ct_extra; /* structs: first field (not a ref!)
function types: cif_description
primitives: prebuilt "cif" object */
@@ -1490,6 +1491,9 @@
s = PyText_FromString(buffer);
}
}
+ else if ((cd->c_type->ct_flags & CT_ARRAY) && cd->c_type->ct_length < 0) {
+ s = PyText_FromFormat("sliced length %zd", get_array_length(cd));
+ }
else {
if (cd->c_data != NULL) {
s = PyText_FromFormat("%p", cd->c_data);
@@ -1717,9 +1721,71 @@
}
static PyObject *
+new_array_type(CTypeDescrObject *ctptr, PyObject *lengthobj); /* forward */
+
+static PyObject *
+cdata_slice(CDataObject *cd, PySliceObject *slice)
+{
+ Py_ssize_t start, stop;
+ CDataObject_own_length *scd;
+ CTypeDescrObject *ct = cd->c_type;
+
+ if (!(ct->ct_flags & (CT_ARRAY | CT_POINTER))) {
+ PyErr_Format(PyExc_TypeError, "cdata of type '%s' cannot be indexed",
+ ct->ct_name);
+ return NULL;
+ }
+ start = PyInt_AsSsize_t(slice->start);
+ if (start == -1 && PyErr_Occurred()) {
+ if (slice->start == Py_None)
+ PyErr_SetString(PyExc_IndexError, "slice start must be specified");
+ return NULL;
+ }
+ stop = PyInt_AsSsize_t(slice->stop);
+ if (stop == -1 && PyErr_Occurred()) {
+ if (slice->stop == Py_None)
+ PyErr_SetString(PyExc_IndexError, "slice stop must be specified");
+ return NULL;
+ }
+ if (slice->step != Py_None) {
+ PyErr_SetString(PyExc_IndexError, "slice with step not supported");
+ return NULL;
+ }
+ if (start > stop) {
+ PyErr_SetString(PyExc_IndexError, "slice start > stop");
+ return NULL;
+ }
+
+ if (ct->ct_flags & CT_ARRAY)
+ ct = (CTypeDescrObject *)ct->ct_stuff;
+ assert(ct->ct_flags & CT_POINTER);
+ if (ct->ct_stuff == NULL) {
+ ct->ct_stuff = new_array_type(ct, Py_None);
+ if (ct->ct_stuff == NULL)
+ return NULL;
+ }
+ ct = (CTypeDescrObject *)ct->ct_stuff;
+
+ scd = (CDataObject_own_length *)PyObject_Malloc(
+ offsetof(CDataObject_own_length, alignment));
+ if (PyObject_Init((PyObject *)scd, &CData_Type) == NULL)
+ return NULL;
+ Py_INCREF(ct);
+ scd->head.c_type = ct;
+ scd->head.c_data = cd->c_data + ct->ct_itemdescr->ct_size * start;
+ scd->head.c_weakreflist = NULL;
+ scd->length = stop - start;
+ return (PyObject *)scd;
+}
+
+static PyObject *
cdataowning_subscript(CDataObject *cd, PyObject *key)
{
- char *c = _cdata_get_indexed_ptr(cd, key);
+ char *c;
+ if (PySlice_Check(key))
+ return cdata_slice(cd, (PySliceObject *)key);
+
+ c = _cdata_get_indexed_ptr(cd, key);
/* use 'mp_subscript' instead of 'sq_item' because we don't want
negative indexes to be corrected automatically */
if (c == NULL && PyErr_Occurred())
@@ -1738,7 +1804,11 @@
static PyObject *
cdata_subscript(CDataObject *cd, PyObject *key)
{
- char *c = _cdata_get_indexed_ptr(cd, key);
+ char *c;
+ if (PySlice_Check(key))
+ return cdata_slice(cd, (PySliceObject *)key);
+
+ c = _cdata_get_indexed_ptr(cd, key);
/* use 'mp_subscript' instead of 'sq_item' because we don't want
negative indexes to be corrected automatically */
if (c == NULL && PyErr_Occurred())
@@ -3122,14 +3192,22 @@
static PyObject *b_new_array_type(PyObject *self, PyObject *args)
{
PyObject *lengthobj;
- CTypeDescrObject *td, *ctitem, *ctptr;
- char extra_text[32];
- Py_ssize_t length, arraysize;
+ CTypeDescrObject *ctptr;
if (!PyArg_ParseTuple(args, "O!O:new_array_type",
&CTypeDescr_Type, &ctptr, &lengthobj))
return NULL;
+ return new_array_type(ctptr, lengthobj);
+}
+
+static PyObject *
+new_array_type(CTypeDescrObject *ctptr, PyObject *lengthobj)
+{
+ CTypeDescrObject *td, *ctitem;
+ char extra_text[32];
+ Py_ssize_t length, arraysize;
+
if (!(ctptr->ct_flags & CT_POINTER)) {
PyErr_SetString(PyExc_TypeError, "first arg must be a pointer ctype");
return NULL;
diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -2574,3 +2574,19 @@
for i in range(20):
buf = buflist[i]
assert buf[:] == str2bytes("hi there %d\x00" % i)
+
+def test_slice():
+ BIntP = new_pointer_type(new_primitive_type("int"))
+ BIntArray = new_array_type(BIntP, None)
+ c = newp(BIntArray, 5)
+ assert len(c) == 5
+ assert repr(c) == "<cdata 'int[]' owning 20 bytes>"
+ d = c[1:4]
+ assert len(d) == 3
+ assert repr(d) == "<cdata 'int[]' sliced length 3>"
+ d[0] = 123
+ d[2] = 456
+ assert c[1] == 123
+ assert c[3] == 456
+ py.test.raises(IndexError, "d[3]")
+ py.test.raises(IndexError, "d[-1]")
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit