[pypy-commit] cffi cffi-1.0: Arrays

arigo noreply at buildbot.pypy.org
Tue Apr 14 16:13:04 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r1702:802ad7fc65d4
Date: 2015-04-14 16:13 +0200
http://bitbucket.org/cffi/cffi/changeset/802ad7fc65d4/

Log:	Arrays

diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -1902,8 +1902,8 @@
     return cd->c_data + i * cd->c_type->ct_itemdescr->ct_size;
 }
 
-static PyObject *
-new_array_type(CTypeDescrObject *ctptr, PyObject *lengthobj);   /* forward */
+static CTypeDescrObject *
+new_array_type(CTypeDescrObject *ctptr, Py_ssize_t length);   /* forward */
 
 static CTypeDescrObject *
 _cdata_getslicearg(CDataObject *cd, PySliceObject *slice, Py_ssize_t bounds[])
@@ -1968,7 +1968,7 @@
         return NULL;
 
     if (ct->ct_stuff == NULL) {
-        ct->ct_stuff = new_array_type(ct, Py_None);
+        ct->ct_stuff = (PyObject *)new_array_type(ct, -1);
         if (ct->ct_stuff == NULL)
             return NULL;
     }
@@ -3540,41 +3540,15 @@
 static PyObject *b_new_array_type(PyObject *self, PyObject *args)
 {
     PyObject *lengthobj;
+    Py_ssize_t length;
     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;
-    int flags = CT_ARRAY;
-
-    if (!(ctptr->ct_flags & CT_POINTER)) {
-        PyErr_SetString(PyExc_TypeError, "first arg must be a pointer ctype");
-        return NULL;
-    }
-    ctitem = ctptr->ct_itemdescr;
-    if (ctitem->ct_size < 0) {
-        PyErr_Format(PyExc_ValueError, "array item of unknown size: '%s'",
-                     ctitem->ct_name);
-        return NULL;
-    }
-
     if (lengthobj == Py_None) {
-        sprintf(extra_text, "[]");
         length = -1;
-        arraysize = -1;
-        if ((ctitem->ct_flags & CT_PRIMITIVE_CHAR) &&
-                ctitem->ct_size == sizeof(char))
-            flags |= CT_IS_UNSIZED_CHAR_A;
     }
     else {
         length = PyNumber_AsSsize_t(lengthobj, PyExc_OverflowError);
@@ -3583,6 +3557,38 @@
                 PyErr_SetString(PyExc_ValueError, "negative array length");
             return NULL;
         }
+    }
+    return (PyObject *)new_array_type(ctptr, length);
+}
+
+static CTypeDescrObject *
+new_array_type(CTypeDescrObject *ctptr, Py_ssize_t length)
+{
+    CTypeDescrObject *td, *ctitem;
+    char extra_text[32];
+    Py_ssize_t arraysize;
+    int flags = CT_ARRAY;
+
+    if (!(ctptr->ct_flags & CT_POINTER)) {
+        PyErr_SetString(PyExc_TypeError, "first arg must be a pointer ctype");
+        return NULL;
+    }
+    ctitem = ctptr->ct_itemdescr;
+    if (ctitem->ct_size < 0) {
+        PyErr_Format(PyExc_ValueError, "array item of unknown size: '%s'",
+                     ctitem->ct_name);
+        return NULL;
+    }
+
+    if (length < 0) {
+        sprintf(extra_text, "[]");
+        length = -1;
+        arraysize = -1;
+        if ((ctitem->ct_flags & CT_PRIMITIVE_CHAR) &&
+                ctitem->ct_size == sizeof(char))
+            flags |= CT_IS_UNSIZED_CHAR_A;
+    }
+    else {
         sprintf(extra_text, "[%llu]", (unsigned PY_LONG_LONG)length);
         arraysize = length * ctitem->ct_size;
         if (length > 0 && (arraysize / length) != ctitem->ct_size) {
@@ -3600,7 +3606,7 @@
     td->ct_size = arraysize;
     td->ct_length = length;
     td->ct_flags = flags;
-    return (PyObject *)td;
+    return td;
 }
 
 static CTypeDescrObject *new_void_type(void)
diff --git a/new/parse_c_type.c b/new/parse_c_type.c
--- a/new/parse_c_type.c
+++ b/new/parse_c_type.c
@@ -330,7 +330,7 @@
                 length = strtoull(tok->p, NULL, 10);
             else
                 length = strtoul(tok->p, NULL, 10);
-            if (errno == ERANGE)
+            if (errno == ERANGE || ((ssize_t)length) < 0)
                 return parse_error(tok, "number too large");
             next_token(tok);
 
diff --git a/new/realize_c_type.c b/new/realize_c_type.c
--- a/new/realize_c_type.c
+++ b/new/realize_c_type.c
@@ -34,8 +34,9 @@
                                  _cffi_opcode_t opcodes[], int index)
 {
     CTypeDescrObject *ct;
-    CTypeDescrObject *x, *y;
+    CTypeDescrObject *x, *y, *z;
     _cffi_opcode_t op = opcodes[index];
+    Py_ssize_t length = -1;
 
     if ((((uintptr_t)op) & 1) == 0) {
         ct = (CTypeDescrObject *)op;
@@ -60,6 +61,25 @@
         Py_DECREF(y);
         break;
 
+    case _CFFI_OP_ARRAY:
+        length = (Py_ssize_t)opcodes[_CFFI_GETARG(op) + 1];
+        /* fall-through */
+    case _CFFI_OP_OPEN_ARRAY:
+        y = realize_c_type(ctx, opcodes, _CFFI_GETARG(op));
+        if (y == NULL)
+            return NULL;
+        z = new_pointer_type(y);
+        Py_DECREF(y);
+        if (z == NULL)
+            return NULL;
+        x = new_array_type(z, length);
+        Py_DECREF(z);
+        break;
+
+    case _CFFI_OP_NOOP:
+        x = realize_c_type(ctx, opcodes, _CFFI_GETARG(op));
+        break;
+
     default:
         PyErr_Format(PyExc_NotImplementedError, "op=%d", (int)_CFFI_GETOP(op));
         return NULL;
diff --git a/new/test_realize_c_type.py b/new/test_realize_c_type.py
--- a/new/test_realize_c_type.py
+++ b/new/test_realize_c_type.py
@@ -14,3 +14,10 @@
 def test_int_star():
     check("int")
     check("int *")
+    check("int*", "int *")
+
+def test_noop():
+    check("int(*)", "int *")
+
+def test_array():
+    check("int[5]")


More information about the pypy-commit mailing list