bool m_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, machine_uint_t *begin, machine_uint_t *end) { machine_int_t start, stop, step; mp_obj_slice_get(slice, &start, &stop, &step); if (step != 1) { return false; } // Unlike subscription, out-of-bounds slice indexes are never error if (start < 0) { start = len + start; if (start < 0) { start = 0; } } else if (start > len) { start = len; } if (stop <= 0) { stop = len + stop; // CPython returns empty sequence in such case if (stop < 0) { stop = start; } } else if (stop > len) { stop = len; } *begin = start; *end = stop; return true; }
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 (ostart == mp_const_none) { start = 0; } else { start = MP_OBJ_SMALL_INT_VALUE(ostart); } if (ostop == mp_const_none) { stop = len; } else { stop = MP_OBJ_SMALL_INT_VALUE(ostop); } // Unlike subscription, out-of-bounds slice indexes are never error if (start < 0) { start = len + start; if (start < 0) { start = 0; } } else if (start > len) { start = len; } if (stop < 0) { stop = len + stop; } else if (stop > len) { stop = len; } // CPython returns empty sequence in such case, or point for assignment is at start if (start > stop) { stop = start; } 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; }
STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_type_t *type = mp_obj_get_type(self_in); assert(type == &mp_type_str); GET_STR_DATA_LEN(self_in, self_data, self_len); if (value == MP_OBJ_SENTINEL) { // load #if MICROPY_PY_BUILTINS_SLICE if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) { mp_obj_t ostart, ostop, ostep; mp_obj_slice_get(index, &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")); } const byte *pstart, *pstop; if (ostart != mp_const_none) { pstart = str_index_to_ptr(type, self_data, self_len, ostart, true); } else { pstart = self_data; } if (ostop != mp_const_none) { // pstop will point just after the stop character. This depends on // the \0 at the end of the string. pstop = str_index_to_ptr(type, self_data, self_len, ostop, true); } else { pstop = self_data + self_len; } if (pstop < pstart) { return MP_OBJ_NEW_QSTR(MP_QSTR_); } return mp_obj_new_str_of_type(type, (const byte *)pstart, pstop - pstart); } #endif const byte *s = str_index_to_ptr(type, self_data, self_len, index, false); int len = 1; if (UTF8_IS_NONASCII(*s)) { // Count the number of 1 bits (after the first) for (char mask = 0x40; *s & mask; mask >>= 1) { ++len; } } return mp_obj_new_str((const char*)s, len, true); // This will create a one-character string } else { return MP_OBJ_NULL; // op not supported
bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes) { mp_obj_t ostart, ostop, ostep; mp_int_t start, stop; mp_obj_slice_get(slice, &ostart, &ostop, &ostep); if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) { indexes->step = mp_obj_get_int(ostep); if (indexes->step == 0) { mp_raise_ValueError("slice step cannot be zero"); } } else { indexes->step = 1; } if (ostart == mp_const_none) { if (indexes->step > 0) { start = 0; } else { start = len - 1; } } else { start = mp_obj_get_int(ostart); } if (ostop == mp_const_none) { if (indexes->step > 0) { stop = len; } else { stop = 0; } } else { stop = mp_obj_get_int(ostop); if (stop >= 0 && indexes->step < 0) { stop += 1; } } // Unlike subscription, out-of-bounds slice indexes are never error if (start < 0) { start = len + start; if (start < 0) { if (indexes->step < 0) { start = -1; } else { start = 0; } } } else if (indexes->step > 0 && (mp_uint_t)start > len) { start = len; } else if (indexes->step < 0 && (mp_uint_t)start >= len) { start = len - 1; } if (stop < 0) { stop = len + stop; if (stop < 0) { stop = -1; } if (indexes->step < 0) { stop += 1; } } else if ((mp_uint_t)stop > len) { stop = len; } // CPython returns empty sequence in such case, or point for assignment is at start if (indexes->step > 0 && start > stop) { stop = start; } else if (indexes->step < 0 && start < stop) { stop = start + 1; } indexes->start = start; indexes->stop = stop; return indexes->step == 1; }
mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { GET_STR_DATA_LEN(lhs_in, lhs_data, lhs_len); switch (op) { case RT_BINARY_OP_SUBSCR: // TODO: need predicate to check for int-like type (bools are such for example) // ["no", "yes"][1 == 2] is common idiom if (MP_OBJ_IS_SMALL_INT(rhs_in)) { uint index = mp_get_index(mp_obj_get_type(lhs_in), lhs_len, rhs_in); return mp_obj_new_str(lhs_data + index, 1, true); #if MICROPY_ENABLE_SLICE } else if (MP_OBJ_IS_TYPE(rhs_in, &slice_type)) { machine_int_t start, stop, step; mp_obj_slice_get(rhs_in, &start, &stop, &step); assert(step == 1); if (start < 0) { start = lhs_len + start; if (start < 0) { start = 0; } } else if (start > lhs_len) { start = lhs_len; } if (stop <= 0) { stop = lhs_len + stop; // CPython returns empty string in such case if (stop < 0) { stop = start; } } else if (stop > lhs_len) { stop = lhs_len; } return mp_obj_new_str(lhs_data + start, stop - start, false); #endif } else { // Message doesn't match CPython, but we don't have so much bytes as they // to spend them on verbose wording nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "index must be int")); } case RT_BINARY_OP_ADD: case RT_BINARY_OP_INPLACE_ADD: if (MP_OBJ_IS_STR(rhs_in)) { // add 2 strings GET_STR_DATA_LEN(rhs_in, rhs_data, rhs_len); int alloc_len = lhs_len + rhs_len; /* code for making qstr byte *q_ptr; byte *val = qstr_build_start(alloc_len, &q_ptr); memcpy(val, lhs_data, lhs_len); memcpy(val + lhs_len, rhs_data, rhs_len); return MP_OBJ_NEW_QSTR(qstr_build_end(q_ptr)); */ // code for non-qstr byte *data; mp_obj_t s = mp_obj_str_builder_start(alloc_len, &data); memcpy(data, lhs_data, lhs_len); memcpy(data + lhs_len, rhs_data, rhs_len); return mp_obj_str_builder_end(s); } break; case RT_COMPARE_OP_IN: case RT_COMPARE_OP_NOT_IN: /* NOTE `a in b` is `b.__contains__(a)` */ if (MP_OBJ_IS_STR(rhs_in)) { GET_STR_DATA_LEN(rhs_in, rhs_data, rhs_len); return MP_BOOL((op == RT_COMPARE_OP_IN) ^ (find_subbytes(lhs_data, lhs_len, rhs_data, rhs_len) == NULL)); } break; case RT_BINARY_OP_MULTIPLY: { if (!MP_OBJ_IS_SMALL_INT(rhs_in)) { return NULL; } int n = MP_OBJ_SMALL_INT_VALUE(rhs_in); byte *data; mp_obj_t s = mp_obj_str_builder_start(lhs_len * n, &data); mp_seq_multiply(lhs_data, sizeof(*lhs_data), lhs_len, n, data); return mp_obj_str_builder_end(s); } } return MP_OBJ_NULL; // op not supported }