summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorPaul Sokolovsky <pfalcon@users.sourceforge.net>2014-05-25 02:36:12 +0300
committerPaul Sokolovsky <pfalcon@users.sourceforge.net>2014-05-25 02:36:12 +0300
commit2705f4c782292eeb0b5ce77aadd1a1ea8a106164 (patch)
tree9d8e8b3fc5ab68e8ce1632dbdaad2cfe2a08ae79
parent69d081a7cf7e0ae1e815365af8b3c19be293da84 (diff)
downloadmicropython-2705f4c782292eeb0b5ce77aadd1a1ea8a106164.tar.gz
micropython-2705f4c782292eeb0b5ce77aadd1a1ea8a106164.zip
objlist: Implement growing slice assignment.
This means that complete slice operations are supported for lists (but not for bytearray's and array.array's).
-rw-r--r--py/obj.h5
-rw-r--r--py/objlist.c19
-rw-r--r--tests/basics/list_slice_assign_grow.py28
3 files changed, 47 insertions, 5 deletions
diff --git a/py/obj.h b/py/obj.h
index 5f2b9d3bef..611873d2ea 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -578,3 +578,8 @@ mp_obj_t mp_seq_count_obj(const mp_obj_t *items, uint len, mp_obj_t value);
memcpy(dest + beg, slice, slice_len * sizeof(item_t)); \
/*printf("memcpy(%p, %p, %d)\n", dest + (beg + slice_len), dest + end, (dest_len - end) * sizeof(item_t));*/ \
memcpy(dest + (beg + slice_len), dest + end, (dest_len - end) * sizeof(item_t));
+
+#define mp_seq_replace_slice_grow_inplace(dest, dest_len, beg, end, slice, slice_len, len_adj, item_t) \
+ /*printf("memmove(%p, %p, %d)\n", dest + beg + len_adj, dest + beg, (dest_len - beg) * sizeof(item_t));*/ \
+ memmove(dest + beg + len_adj, dest + beg, (dest_len - beg) * sizeof(item_t)); \
+ memcpy(dest + beg, slice, slice_len * sizeof(item_t));
diff --git a/py/objlist.c b/py/objlist.c
index 7a15006adf..7d9f56d2e4 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -199,12 +199,21 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
}
int len_adj = slice->len - (stop - start);
//printf("Len adj: %d\n", len_adj);
- assert(len_adj <= 0);
- mp_seq_replace_slice_no_grow(self->items, self->len, start, stop, slice->items, slice->len, mp_obj_t);
- // Clear "freed" elements at the end of list
- mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items));
+ if (len_adj > 0) {
+ if (self->len + len_adj > self->alloc) {
+ // TODO: Might optimize memory copies here by checking if block can
+ // be grown inplace or not
+ self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + len_adj);
+ self->alloc = self->len + len_adj;
+ }
+ mp_seq_replace_slice_grow_inplace(self->items, self->len, start, stop, slice->items, slice->len, len_adj, mp_obj_t);
+ } else {
+ mp_seq_replace_slice_no_grow(self->items, self->len, start, stop, slice->items, slice->len, mp_obj_t);
+ // Clear "freed" elements at the end of list
+ mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items));
+ // TODO: apply allocation policy re: alloc_size
+ }
self->len += len_adj;
- // TODO: apply allocation policy re: alloc_size
return mp_const_none;
}
#endif
diff --git a/tests/basics/list_slice_assign_grow.py b/tests/basics/list_slice_assign_grow.py
new file mode 100644
index 0000000000..12b1541e35
--- /dev/null
+++ b/tests/basics/list_slice_assign_grow.py
@@ -0,0 +1,28 @@
+x = list(range(2))
+
+l = list(x)
+l[0:0] = [10]
+print(l)
+l = list(x)
+l[:0] = [10, 20]
+print(l)
+l = list(x)
+l[0:0] = [10, 20, 30, 40]
+print(l)
+
+l = list(x)
+l[1:1] = [10, 20, 30, 40]
+print(l)
+
+l = list(x)
+l[2:] = [10, 20, 30, 40]
+print(l)
+
+# Weird cases
+l = list(x)
+l[1:0] = [10, 20, 30, 40]
+print(l)
+
+l = list(x)
+l[100:100] = [10, 20, 30, 40]
+print(l)