[pypy-commit] creflect default: ffi.string
arigo
noreply at buildbot.pypy.org
Fri Dec 5 16:56:01 CET 2014
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r166:030aea977e7e
Date: 2014-12-05 16:52 +0100
http://bitbucket.org/cffi/creflect/changeset/030aea977e7e/
Log: ffi.string
diff --git a/zeffir/ffi_obj.c b/zeffir/ffi_obj.c
--- a/zeffir/ffi_obj.c
+++ b/zeffir/ffi_obj.c
@@ -255,12 +255,75 @@
return (PyObject *)cd;
}
+static PyObject *ffi_string(PyObject *self, PyObject *args)
+{
+ CDataObject *cd;
+ Py_ssize_t maxlen = -1;
+ if (!PyArg_ParseTuple(args, "O!|n:string",
+ &CData_Type, &cd, &maxlen))
+ return NULL;
+
+ if (cd->c_type->ct_itemdescr != NULL &&
+ cd->c_type->ct_itemdescr->ct_flags & (CT_PRIMITIVE_CHAR |
+ CT_PRIMITIVE_SIGNED |
+ CT_PRIMITIVE_UNSIGNED)) {
+ Py_ssize_t length = maxlen;
+ if (cd->c_data == NULL) {
+ PyObject *s = cdata_repr(cd);
+ if (s != NULL) {
+ PyErr_Format(PyExc_RuntimeError,
+ "cannot use string() on %s",
+ PyText_AS_UTF8(s));
+ Py_DECREF(s);
+ }
+ return NULL;
+ }
+ if (length < 0 && cd->c_type->ct_flags & CT_ARRAY) {
+ length = get_array_length(cd);
+ }
+ if (cd->c_type->ct_itemdescr->ct_size == sizeof(char)) {
+ const char *start = cd->c_data;
+ if (length < 0) {
+ /*READ(start, 1)*/
+ length = strlen(start);
+ /*READ(start, length)*/
+ }
+ else {
+ const char *end;
+ /*READ(start, length)*/
+ end = (const char *)memchr(start, 0, length);
+ if (end != NULL)
+ length = end - start;
+ }
+ return PyBytes_FromStringAndSize(start, length);
+ }
+ }
+ else if (cd->c_type->ct_flags & CT_IS_ENUM) {
+ abort();
+ //return convert_cdata_to_enum_string(cd, 0);
+ }
+ else if (cd->c_type->ct_flags & CT_IS_BOOL) {
+ /* fall through to TypeError */
+ }
+ else if (cd->c_type->ct_flags & (CT_PRIMITIVE_CHAR |
+ CT_PRIMITIVE_SIGNED |
+ CT_PRIMITIVE_UNSIGNED)) {
+ /*READ(cd->c_data, cd->c_type->ct_size)*/
+ if (cd->c_type->ct_size == sizeof(char))
+ return PyBytes_FromStringAndSize(cd->c_data, 1);
+ }
+ PyErr_Format(PyExc_TypeError, "string(): unexpected cdata '%s' argument",
+ cd->c_type->ct_name);
+ return NULL;
+}
+
static PyMethodDef ffi_methods[] = {
{"close_library", ffi_close_library, METH_VARARGS | METH_STATIC},
{"load_library", (PyCFunction)ffi_load_library,
METH_VARARGS | METH_KEYWORDS},
{"new", (PyCFunction)ffi_new, METH_VARARGS},
{"sizeof", (PyCFunction)ffi_sizeof, METH_O},
+ {"string", (PyCFunction)ffi_string, METH_VARARGS},
{"typeof", (PyCFunction)ffi_typeof, METH_O},
{NULL}
};
diff --git a/zeffir/test/test_basic.py b/zeffir/test/test_basic.py
--- a/zeffir/test/test_basic.py
+++ b/zeffir/test/test_basic.py
@@ -36,3 +36,11 @@
ffi = support.new_ffi()
assert repr(ffi.NULL) == "<cdata 'void *' NULL>"
assert repr(type(ffi).NULL) == "<cdata 'void *' NULL>"
+
+def test_string():
+ ffi = support.new_ffi()
+ p = ffi.new("char[]", "hello\x00world")
+ assert ffi.string(p) == "hello"
+ for i in range(50):
+ p = ffi.new("char[]", "12345678" * i)
+ assert ffi.string(p) == "12345678" * i
More information about the pypy-commit
mailing list