From de4b9329f99794dc2025a7f9aa203811a156b3c4 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 25 May 2014 21:21:57 +0300 Subject: [PATCH] py: Refactor slice helpers, preparing to support arbitrary slicing. --- py/obj.h | 10 +++++++++- py/objarray.c | 8 ++++---- py/objlist.c | 28 +++++++++++++++------------- py/objstr.c | 6 +++--- py/objtuple.c | 8 ++++---- py/sequence.c | 19 +++++++++++-------- 6 files changed, 46 insertions(+), 33 deletions(-) diff --git a/py/obj.h b/py/obj.h index 611873d2ea..6bcebcf6ef 100644 --- a/py/obj.h +++ b/py/obj.h @@ -563,8 +563,16 @@ typedef struct _mp_obj_static_class_method_t { const mp_obj_t *mp_obj_property_get(mp_obj_t self_in); // sequence helpers + +// slice indexes resolved to particular sequence +typedef struct { + machine_uint_t start; + machine_uint_t stop; + machine_int_t step; +} mp_bound_slice_t; + void mp_seq_multiply(const void *items, uint item_sz, uint len, uint times, void *dest); -bool mp_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, machine_uint_t *begin, machine_uint_t *end); +bool mp_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes); #define mp_seq_copy(dest, src, len, item_t) memcpy(dest, src, len * sizeof(item_t)) #define mp_seq_cat(dest, src1, len1, src2, len2, item_t) { memcpy(dest, src1, (len1) * sizeof(item_t)); memcpy(dest + (len1), src2, (len2) * sizeof(item_t)); } bool mp_seq_cmp_bytes(int op, const byte *data1, uint len1, const byte *data2, uint len2); diff --git a/py/objarray.c b/py/objarray.c index d973a4c563..da57709ece 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -176,15 +176,15 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value // slice assignment (incl. of different size) return MP_OBJ_NULL; // op not supported } - machine_uint_t start, stop; - if (!mp_seq_get_fast_slice_indexes(o->len, index_in, &start, &stop)) { + mp_bound_slice_t slice; + if (!mp_seq_get_fast_slice_indexes(o->len, index_in, &slice)) { assert(0); } - mp_obj_array_t *res = array_new(o->typecode, stop - start); + mp_obj_array_t *res = array_new(o->typecode, slice.stop - slice.start); int sz = mp_binary_get_size('@', o->typecode, NULL); assert(sz > 0); byte *p = o->items; - memcpy(res->items, p + start * sz, (stop - start) * sz); + memcpy(res->items, p + slice.start * sz, (slice.stop - slice.start) * sz); return res; } else { uint index = mp_get_index(o->base.type, o->len, index_in, false); diff --git a/py/objlist.c b/py/objlist.c index 7d9f56d2e4..8643be41a1 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -153,15 +153,15 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { #if MICROPY_PY_SLICE if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) { mp_obj_list_t *self = self_in; - machine_uint_t start, stop; - if (!mp_seq_get_fast_slice_indexes(self->len, index, &start, &stop)) { + mp_bound_slice_t slice; + if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) { assert(0); } - int len_adj = start - stop; + int len_adj = slice.start - slice.stop; //printf("Len adj: %d\n", len_adj); assert(len_adj <= 0); - mp_seq_replace_slice_no_grow(self->items, self->len, start, stop, self->items/*NULL*/, 0, mp_obj_t); + mp_seq_replace_slice_no_grow(self->items, self->len, slice.start, slice.stop, self->items/*NULL*/, 0, 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)); self->len += len_adj; @@ -176,12 +176,12 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_list_t *self = self_in; #if MICROPY_PY_SLICE if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) { - machine_uint_t start, stop; - if (!mp_seq_get_fast_slice_indexes(self->len, index, &start, &stop)) { + mp_bound_slice_t slice; + if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) { assert(0); } - mp_obj_list_t *res = list_new(stop - start); - mp_seq_copy(res->items, self->items + start, res->len, mp_obj_t); + mp_obj_list_t *res = list_new(slice.stop - slice.start); + mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t); return res; } #endif @@ -193,11 +193,11 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_list_t *self = self_in; assert(MP_OBJ_IS_TYPE(value, &mp_type_list)); mp_obj_list_t *slice = value; - machine_uint_t start, stop; - if (!mp_seq_get_fast_slice_indexes(self->len, index, &start, &stop)) { + mp_bound_slice_t slice_out; + if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice_out)) { assert(0); } - int len_adj = slice->len - (stop - start); + int len_adj = slice->len - (slice_out.stop - slice_out.start); //printf("Len adj: %d\n", len_adj); if (len_adj > 0) { if (self->len + len_adj > self->alloc) { @@ -206,9 +206,11 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { 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); + mp_seq_replace_slice_grow_inplace(self->items, self->len, + slice_out.start, slice_out.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); + mp_seq_replace_slice_no_grow(self->items, self->len, + slice_out.start, slice_out.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 diff --git a/py/objstr.c b/py/objstr.c index 4ec1034e1e..84a6f30aad 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -351,11 +351,11 @@ STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { // load #if MICROPY_PY_SLICE if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) { - machine_uint_t start, stop; - if (!mp_seq_get_fast_slice_indexes(self_len, index, &start, &stop)) { + mp_bound_slice_t slice; + if (!mp_seq_get_fast_slice_indexes(self_len, index, &slice)) { assert(0); } - return str_new(type, self_data + start, stop - start); + return str_new(type, self_data + slice.start, slice.stop - slice.start); } #endif uint index_val = mp_get_index(type, self_len, index, false); diff --git a/py/objtuple.c b/py/objtuple.c index b56c6433f6..ffc94b5d27 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -163,12 +163,12 @@ mp_obj_t mp_obj_tuple_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_tuple_t *self = self_in; #if MICROPY_PY_SLICE if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) { - machine_uint_t start, stop; - if (!mp_seq_get_fast_slice_indexes(self->len, index, &start, &stop)) { + mp_bound_slice_t slice; + if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) { assert(0); } - mp_obj_tuple_t *res = mp_obj_new_tuple(stop - start, NULL); - mp_seq_copy(res->items, self->items + start, res->len, mp_obj_t); + mp_obj_tuple_t *res = mp_obj_new_tuple(slice.stop - slice.start, NULL); + mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t); return res; } #endif diff --git a/py/sequence.c b/py/sequence.c index 8418f1ef67..db5eed4c8e 100644 --- a/py/sequence.c +++ b/py/sequence.c @@ -51,15 +51,10 @@ void mp_seq_multiply(const void *items, uint item_sz, uint len, uint times, void } } -bool mp_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, machine_uint_t *begin, machine_uint_t *end) { +bool mp_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes) { mp_obj_t ostart, ostop, ostep; machine_int_t start, stop; mp_obj_slice_get(slice, &ostart, &ostop, &ostep); - if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError, - "Only slices with step=1 (aka None) are supported")); - return false; - } if (ostart == mp_const_none) { start = 0; @@ -96,8 +91,16 @@ bool mp_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, machine_u stop = start; } - *begin = start; - *end = stop; + indexes->start = start; + indexes->stop = stop; + + if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError, + "Only slices with step=1 (aka None) are supported")); + indexes->step = MP_OBJ_SMALL_INT_VALUE(ostep); + return false; + } + indexes->step = 1; return true; }