summaryrefslogtreecommitdiff
path: root/c
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2018-12-16 08:48:45 +0100
committerArmin Rigo <arigo@tunes.org>2018-12-16 08:48:45 +0100
commitd1320b79e38ee16d73c9e9c72fd0e5112cffbad8 (patch)
tree0f665aaa89b988ca533e1eaac6f31005b92e6bd8 /c
parentcef175a37f0f15d87d61ddefa09664c19ce544da (diff)
downloadcffi-d1320b79e38ee16d73c9e9c72fd0e5112cffbad8.tar.gz
Issue #394
Implement ffi.from_buffer(x, require_writable=True)
Diffstat (limited to 'c')
-rw-r--r--c/_cffi_backend.c11
-rw-r--r--c/ffi_obj.c13
-rw-r--r--c/test_c.py12
3 files changed, 29 insertions, 7 deletions
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
index dc13c61..c6190e7 100644
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -6741,7 +6741,8 @@ static int _my_PyObject_GetContiguousBuffer(PyObject *x, Py_buffer *view,
return 0;
}
-static PyObject *direct_from_buffer(CTypeDescrObject *ct, PyObject *x)
+static PyObject *direct_from_buffer(CTypeDescrObject *ct, PyObject *x,
+ int require_writable)
{
CDataObject *cd;
Py_buffer *view;
@@ -6761,7 +6762,7 @@ static PyObject *direct_from_buffer(CTypeDescrObject *ct, PyObject *x)
PyErr_NoMemory();
return NULL;
}
- if (_my_PyObject_GetContiguousBuffer(x, view, 0) < 0)
+ if (_my_PyObject_GetContiguousBuffer(x, view, require_writable) < 0)
goto error1;
cd = (CDataObject *)PyObject_GC_New(CDataObject_owngc_frombuf,
@@ -6789,15 +6790,17 @@ static PyObject *b_from_buffer(PyObject *self, PyObject *args)
{
CTypeDescrObject *ct;
PyObject *x;
+ int require_writable = 0;
- if (!PyArg_ParseTuple(args, "O!O", &CTypeDescr_Type, &ct, &x))
+ if (!PyArg_ParseTuple(args, "O!O|i", &CTypeDescr_Type, &ct, &x,
+ &require_writable))
return NULL;
if (!(ct->ct_flags & CT_IS_UNSIZED_CHAR_A)) {
PyErr_Format(PyExc_TypeError, "needs 'char[]', got '%s'", ct->ct_name);
return NULL;
}
- return direct_from_buffer(ct, x);
+ return direct_from_buffer(ct, x, require_writable);
}
static int _fetch_as_buffer(PyObject *x, Py_buffer *view, int writable_only)
diff --git a/c/ffi_obj.c b/c/ffi_obj.c
index 9e67466..cc5c715 100644
--- a/c/ffi_obj.c
+++ b/c/ffi_obj.c
@@ -697,9 +697,16 @@ PyDoc_STRVAR(ffi_from_buffer_doc,
"containing large quantities of raw data in some other format, like\n"
"'array.array' or numpy arrays.");
-static PyObject *ffi_from_buffer(PyObject *self, PyObject *arg)
+static PyObject *ffi_from_buffer(PyObject *self, PyObject *args, PyObject *kwds)
{
- return direct_from_buffer(g_ct_chararray, arg);
+ PyObject *arg;
+ int require_writable = 0;
+ static char *keywords[] = {"python_buffer", "require_writable", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:from_buffer", keywords,
+ &arg, &require_writable))
+ return NULL;
+ return direct_from_buffer(g_ct_chararray, arg, require_writable);
}
PyDoc_STRVAR(ffi_gc_doc,
@@ -1072,7 +1079,7 @@ static PyMethodDef ffi_methods[] = {
{"cast", (PyCFunction)ffi_cast, METH_VARARGS, ffi_cast_doc},
{"dlclose", (PyCFunction)ffi_dlclose, METH_VARARGS, ffi_dlclose_doc},
{"dlopen", (PyCFunction)ffi_dlopen, METH_VARARGS, ffi_dlopen_doc},
- {"from_buffer",(PyCFunction)ffi_from_buffer,METH_O, ffi_from_buffer_doc},
+ {"from_buffer",(PyCFunction)ffi_from_buffer,METH_VKW, ffi_from_buffer_doc},
{"from_handle",(PyCFunction)ffi_from_handle,METH_O, ffi_from_handle_doc},
{"gc", (PyCFunction)ffi_gc, METH_VKW, ffi_gc_doc},
{"getctype", (PyCFunction)ffi_getctype, METH_VKW, ffi_getctype_doc},
diff --git a/c/test_c.py b/c/test_c.py
index b83c0aa..b6bb752 100644
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -3741,6 +3741,18 @@ def test_from_buffer_more_cases():
check(4 | 8, "CHB", "GTB")
check(4 | 16, "CHB", "ROB")
+def test_from_buffer_require_writable():
+ BChar = new_primitive_type("char")
+ BCharP = new_pointer_type(BChar)
+ BCharA = new_array_type(BCharP, None)
+ p1 = from_buffer(BCharA, b"foo", False)
+ assert p1 == from_buffer(BCharA, b"foo", False)
+ py.test.raises((TypeError, BufferError), from_buffer, BCharA, b"foo", True)
+ ba = bytearray(b"foo")
+ p1 = from_buffer(BCharA, ba, True)
+ p1[0] = b"g"
+ assert ba == b"goo"
+
def test_memmove():
Short = new_primitive_type("short")
ShortA = new_array_type(new_pointer_type(Short), None)