Skip to content

Commit 32aba40

Browse files
dxxbdpgeorge
authored andcommitted
py: Implement memoryview slice assignment.
Adds ability to do "memcpy" with memoryview objects, such as: m1[0:3] = m2[2:5].
1 parent f576057 commit 32aba40

2 files changed

Lines changed: 69 additions & 9 deletions

File tree

py/objarray.c

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -373,12 +373,12 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
373373
// Assign
374374
mp_uint_t src_len;
375375
void *src_items;
376-
size_t item_sz = mp_binary_get_size('@', o->typecode, NULL);
376+
size_t item_sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);
377377
if (MP_OBJ_IS_TYPE(value, &mp_type_array) || MP_OBJ_IS_TYPE(value, &mp_type_bytearray)) {
378378
mp_obj_array_t *src_slice = value;
379-
if (item_sz != mp_binary_get_size('@', src_slice->typecode, NULL)) {
379+
if (item_sz != mp_binary_get_size('@', src_slice->typecode & TYPECODE_MASK, NULL)) {
380380
compat_error:
381-
mp_not_implemented("lhs and rhs should be compatible");
381+
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "lhs and rhs should be compatible"));
382382
}
383383
src_len = src_slice->len;
384384
src_items = src_slice->items;
@@ -390,13 +390,23 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
390390
mp_get_buffer_raise(value, &bufinfo, MP_BUFFER_READ);
391391
src_len = bufinfo.len;
392392
src_items = bufinfo.buf;
393+
} else if (MP_OBJ_IS_TYPE(value, &mp_type_memoryview)) {
394+
mp_obj_array_t *src_slice = value;
395+
if (item_sz != mp_binary_get_size('@', src_slice->typecode & TYPECODE_MASK, NULL)) {
396+
goto compat_error;
397+
}
398+
src_len = src_slice->len;
399+
src_items = (uint8_t*)src_slice->items + (src_slice->free * item_sz);
393400
} else {
394401
mp_not_implemented("array/bytes required on right side");
395402
}
396403

397404
// TODO: check src/dst compat
398405
mp_int_t len_adj = src_len - (slice.stop - slice.start);
399406
if (len_adj > 0) {
407+
if (o->base.type == &mp_type_memoryview) {
408+
goto compat_error;
409+
}
400410
if (len_adj > o->free) {
401411
// TODO: alloc policy; at the moment we go conservative
402412
o->items = m_renew(byte, o->items, (o->len + o->free) * item_sz, (o->len + len_adj) * item_sz);
@@ -405,12 +415,20 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
405415
mp_seq_replace_slice_grow_inplace(o->items, o->len,
406416
slice.start, slice.stop, src_items, src_len, len_adj, item_sz);
407417
} else {
408-
mp_seq_replace_slice_no_grow(o->items, o->len,
409-
slice.start, slice.stop, src_items, src_len, item_sz);
410-
// Clear "freed" elements at the end of list
411-
// TODO: This is actually only needed for typecode=='O'
412-
mp_seq_clear(o->items, o->len + len_adj, o->len, item_sz);
413-
// TODO: alloc policy after shrinking
418+
if (o->base.type == &mp_type_memoryview) {
419+
if (len_adj != 0) {
420+
goto compat_error;
421+
}
422+
mp_seq_replace_slice_no_grow((uint8_t*)o->items + (o->free * item_sz), o->len,
423+
slice.start, slice.stop, src_items, src_len, item_sz);
424+
} else {
425+
mp_seq_replace_slice_no_grow(o->items, o->len,
426+
slice.start, slice.stop, src_items, src_len, item_sz);
427+
// Clear "freed" elements at the end of list
428+
// TODO: This is actually only needed for typecode=='O'
429+
mp_seq_clear(o->items, o->len + len_adj, o->len, item_sz);
430+
// TODO: alloc policy after shrinking
431+
}
414432
}
415433
o->len += len_adj;
416434
return mp_const_none;

tests/basics/memoryview1.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,45 @@
3636
print(list(m[1:-1]))
3737
m[2] = 6
3838
print(a)
39+
40+
# test slice assignment between memoryviews
41+
b1 = bytearray(b'1234')
42+
b2 = bytearray(b'5678')
43+
b3 = bytearray(b'5678')
44+
m1 = memoryview(b1)
45+
m2 = memoryview(b2)
46+
m3 = memoryview(b3)
47+
m2[1:3] = m1[0:2]
48+
print(b2)
49+
b3[1:3] = m1[0:2]
50+
print(b3)
51+
m1[2:4] = b3[1:3]
52+
print(b1)
53+
54+
try:
55+
m2[1:3] = b1[0:4]
56+
except ValueError:
57+
print("ValueError")
58+
59+
try:
60+
m2[1:3] = m1[0:4]
61+
except ValueError:
62+
print("ValueError")
63+
64+
try:
65+
m2[0:4] = m1[1:3]
66+
except ValueError:
67+
print("ValueError")
68+
69+
# test memoryview of arrays with items sized larger than 1
70+
a1 = array.array('i', [0]*5)
71+
m4 = memoryview(a1)
72+
a2 = array.array('i', [3]*5)
73+
m5 = memoryview(a2)
74+
m4[1:3] = m5[1:3]
75+
print(a1)
76+
77+
try:
78+
m4[1:3] = m2[1:3]
79+
except ValueError:
80+
print("ValueError")

0 commit comments

Comments
 (0)