Commits

Armin Rigo committed dc27146

Add a past path for slice assignment with a cdata-of-same-type source.

Comments (0)

Files changed (2)

c/_cffi_backend.c

     CTypeDescrObject *ct = _cdata_getslicearg(cd, slice, bounds);
     if (ct == NULL)
         return -1;
+    ct = ct->ct_itemdescr;
+    itemsize = ct->ct_size;
+    cdata = cd->c_data + itemsize * bounds[0];
+    length = bounds[1];
+
+    if (CData_Check(v)) {
+        CTypeDescrObject *ctv = ((CDataObject *)v)->c_type;
+        if ((ctv->ct_flags & CT_ARRAY) && (ctv->ct_itemdescr == ct) &&
+            (get_array_length((CDataObject *)v) == length)) {
+            /* fast path: copying from exactly the correct type */
+            memcpy(cdata, ((CDataObject *)v)->c_data, itemsize * length);
+            return 0;
+        }
+    }
 
     it = PyObject_GetIter(v);
     if (it == NULL)
         return -1;
     iternext = *it->ob_type->tp_iternext;
 
-    ct = ct->ct_itemdescr;
-    itemsize = ct->ct_size;
-    cdata = cd->c_data + itemsize * bounds[0];
-    length = bounds[1];
     for (i = 0; i < length; i++) {
         item = iternext(it);
         if (item == NULL) {
     assert list(c) == [0, 100, 1000, 600, 0]
     py.test.raises(ValueError, "cp[-1:1] = (700, 800, 900)")
     assert list(c) == [0, 100, 700, 800, 0]
+
+def test_setslice_array():
+    BIntP = new_pointer_type(new_primitive_type("int"))
+    BIntArray = new_array_type(BIntP, None)
+    c = newp(BIntArray, 5)
+    d = newp(BIntArray, [10, 20, 30])
+    c[1:4] = d
+    assert list(c) == [0, 10, 20, 30, 0]
+    #
+    BShortP = new_pointer_type(new_primitive_type("short"))
+    BShortArray = new_array_type(BShortP, None)
+    d = newp(BShortArray, [40, 50])
+    c[1:3] = d
+    assert list(c) == [0, 40, 50, 30, 0]