summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/obj.h11
-rw-r--r--py/objarray.c11
-rw-r--r--py/objlist.c30
-rw-r--r--py/objstr.c9
-rw-r--r--py/objtuple.c11
-rw-r--r--py/sequence.c38
6 files changed, 73 insertions, 37 deletions
diff --git a/py/obj.h b/py/obj.h
index 611873d2ea..b1d9be2096 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -563,14 +563,23 @@ 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);
bool mp_seq_cmp_objs(int op, const mp_obj_t *items1, uint len1, const mp_obj_t *items2, uint len2);
mp_obj_t mp_seq_index_obj(const mp_obj_t *items, uint len, uint n_args, const mp_obj_t *args);
mp_obj_t mp_seq_count_obj(const mp_obj_t *items, uint len, mp_obj_t value);
+mp_obj_t mp_seq_extract_slice(uint len, const mp_obj_t *seq, mp_bound_slice_t *indexes);
// Helper to clear stale pointers from allocated, but unused memory, to preclude GC problems
#define mp_seq_clear(start, len, alloc_len, item_sz) memset((byte*)(start) + (len) * (item_sz), 0, ((alloc_len) - (len)) * (item_sz))
#define mp_seq_replace_slice_no_grow(dest, dest_len, beg, end, slice, slice_len, item_t) \
diff --git a/py/objarray.c b/py/objarray.c
index d973a4c563..91fcec624a 100644
--- a/py/objarray.c
+++ b/py/objarray.c
@@ -176,15 +176,16 @@ 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)) {
- assert(0);
+ mp_bound_slice_t slice;
+ if (!mp_seq_get_fast_slice_indexes(o->len, index_in, &slice)) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError,
+ "Only slices with step=1 (aka None) are supported"));
}
- 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..647096f0dd 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)) {
- assert(0);
+ mp_bound_slice_t slice;
+ if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) {
+ return mp_seq_extract_slice(self->len, self->items, &slice);
}
- 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..f5939d1b1f 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -351,11 +351,12 @@ 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)) {
- assert(0);
+ mp_bound_slice_t slice;
+ if (!mp_seq_get_fast_slice_indexes(self_len, index, &slice)) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError,
+ "Only slices with step=1 (aka None) are supported"));
}
- 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..c0a33dad7e 100644
--- a/py/objtuple.c
+++ b/py/objtuple.c
@@ -163,12 +163,13 @@ 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)) {
- assert(0);
+ mp_bound_slice_t slice;
+ if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError,
+ "Only slices with step=1 (aka None) are supported"));
}
- 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..c940d9f69f 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,11 +91,38 @@ 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)) {
+ indexes->step = MP_OBJ_SMALL_INT_VALUE(ostep);
+ return false;
+ }
+ indexes->step = 1;
return true;
}
+mp_obj_t mp_seq_extract_slice(uint len, const mp_obj_t *seq, mp_bound_slice_t *indexes) {
+ machine_int_t start = indexes->start, stop = indexes->stop;
+ machine_int_t step = indexes->step;
+
+ mp_obj_t res = mp_obj_new_list(0, NULL);
+
+ if (step < 0) {
+ stop--;
+ while (start <= stop) {
+ mp_obj_list_append(res, seq[stop]);
+ stop += step;
+ }
+ } else {
+ while (start < stop) {
+ mp_obj_list_append(res, seq[start]);
+ start += step;
+ }
+ }
+ return res;
+}
+
// Special-case comparison function for sequences of bytes
// Don't pass MP_BINARY_OP_NOT_EQUAL here
bool mp_seq_cmp_bytes(int op, const byte *data1, uint len1, const byte *data2, uint len2) {