Object obj_add(Object a, Object b) { if (TM_TYPE(a) == TM_TYPE(b)) { switch (TM_TYPE(a)) { case TYPE_NUM: GET_NUM(a) += GET_NUM(b); return a; case TYPE_STR: { char* sa = GET_STR(a); char* sb = GET_STR(b); int la = GET_STR_LEN(a); int lb = GET_STR_LEN(b); if (la == 0) {return b; } if (lb == 0) {return a; } int len = la + lb; Object des = string_alloc(NULL, len); char*s = GET_STR(des); memcpy(s, sa, la); memcpy(s + la, sb, lb); return des; } case TYPE_LIST: { return list_add(GET_LIST(a), GET_LIST(b)); } } } tm_raise("obj_add: can not add %o and %o", (a), (b)); return NONE_OBJECT; }
Object obj_mul(Object a, Object b) { if (a.type == b.type && a.type == TYPE_NUM) { GET_NUM(a) *= GET_NUM(b); return a; } if (a.type == TYPE_NUM && b.type == TYPE_STR) { Object temp = a; a = b; b = temp; } if (a.type == TYPE_STR && b.type == TYPE_NUM) { int len = GET_STR_LEN(a); Object des; if (len == 0) return a; int times = (int) GET_NUM(b); if (times <= 0) return sz_to_string(""); if (times == 1) return a; des = string_alloc(NULL, len * times); char* s = GET_STR(des); int i; for (i = 0; i < times; i++) { strncpy(s, GET_STR(a), len); s += len; } return des; } tm_raise("obj_mul: can not multiply %o and %o", a, b); return NONE_OBJECT; }
Object obj_get(Object self, Object k) { Object v; switch (TM_TYPE(self)) { case TYPE_STR: { DictNode* node; if (TM_TYPE(k) == TYPE_NUM) { double d = GET_NUM(k); int n = d; if (n < 0) { n += GET_STR_LEN(self); } if (n >= GET_STR_LEN(self) || n < 0) tm_raise("String_get: index overflow ,len=%d,index=%d, str=%o", GET_STR_LEN(self), n, self); return string_chr(0xff & GET_STR(self)[n]); } else if ((node = dict_get_node(GET_DICT(tm->str_proto), k)) != NULL) { return method_new(node->val, self); } break; } case TYPE_LIST:{ DictNode* node; if (TM_TYPE(k) == TYPE_NUM) { return list_get(GET_LIST(self), GET_NUM(k)); } else if ((node = dict_get_node(GET_DICT(tm->list_proto), k))!=NULL) { return method_new(node->val, self); } break; } case TYPE_DICT:{ DictNode* node; node = dict_get_node(GET_DICT(self), k); if (node != NULL) { return node->val; } else if ((node = dict_get_node(GET_DICT(tm->dict_proto), k))!=NULL) { return method_new(node->val, self); } break; } case TYPE_FUNCTION: return get_func_attr(GET_FUNCTION(self), k); case TYPE_DATA: return GET_DATA(self)->get(GET_DATA(self), k); } tm_raise("keyError %o", k); return NONE_OBJECT; }
uint mp_obj_str_get_len(mp_obj_t self_in) { if (MP_OBJ_IS_STR(self_in)) { GET_STR_LEN(self_in, l); return l; } else { nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "Can't convert '%s' object to str implicitly", mp_obj_get_type_str(self_in))); } }
mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { assert(MP_OBJ_IS_STR(self_in)); // get separation string GET_STR_DATA_LEN(self_in, sep_str, sep_len); // process args uint seq_len; mp_obj_t *seq_items; if (MP_OBJ_IS_TYPE(arg, &tuple_type)) { mp_obj_tuple_get(arg, &seq_len, &seq_items); } else if (MP_OBJ_IS_TYPE(arg, &list_type)) { mp_obj_list_get(arg, &seq_len, &seq_items); } else { goto bad_arg; } // count required length int required_len = 0; for (int i = 0; i < seq_len; i++) { if (!MP_OBJ_IS_STR(seq_items[i])) { goto bad_arg; } if (i > 0) { required_len += sep_len; } GET_STR_LEN(seq_items[i], l); required_len += l; } // make joined string byte *data; mp_obj_t joined_str = mp_obj_str_builder_start(required_len, &data); for (int i = 0; i < seq_len; i++) { if (i > 0) { memcpy(data, sep_str, sep_len); data += sep_len; } GET_STR_DATA_LEN(seq_items[i], s, l); memcpy(data, s, l); data += l; } // return joined string return mp_obj_str_builder_end(joined_str); bad_arg: nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "?str.join expecting a list of str's")); }
int tm_len(Object o) { int len = -1; switch (TM_TYPE(o)) { case TYPE_STR: len = GET_STR_LEN(o); case TYPE_LIST: len = LIST_LEN(o); case TYPE_DICT: len = DICT_LEN(o); } if (len < 0) { tm_raise("tm_len: %o has no attribute len", o); } return len; }
int is_true_obj(Object v) { switch (TM_TYPE(v)) { case TYPE_NUM: return GET_NUM(v) != 0; case TYPE_NONE: return 0; case TYPE_STR: return GET_STR_LEN(v) > 0; case TYPE_LIST: return LIST_LEN(v) > 0; case TYPE_DICT: return DICT_LEN(v) > 0; case TYPE_FUNCTION: case TYPE_DATA: return 1; } return 0; }
// may return MP_OBJ_NULL mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) { if ( #if !MICROPY_PY_BUILTINS_STR_UNICODE // It's simple - unicode is slow, non-unicode is fast MP_OBJ_IS_STR(o_in) || #endif MP_OBJ_IS_TYPE(o_in, &mp_type_bytes)) { GET_STR_LEN(o_in, l); return MP_OBJ_NEW_SMALL_INT(l); } else { mp_obj_type_t *type = mp_obj_get_type(o_in); if (type->unary_op != NULL) { return type->unary_op(MP_UNARY_OP_LEN, o_in); } else { return MP_OBJ_NULL; } } }
/** * slice string/list * string.slice(a,b) [a,b), b is not included * string.slice(0,-1) = string.slice(0,len(string)) * @since 2016-11-19 * <code> * 'test'.slice(0,1) = 't' * 'test'.slice(0,-1) = 'test' * </code> */ Object obj_slice(Object self, Object first, Object second) { int start = GET_NUM(first); int end = GET_NUM(second); Object ret = NONE_OBJECT; if (IS_STR(self)) { int length = GET_STR_LEN(self); start = start >= 0 ? start : start + length + 1; end = end >= 0 ? end : end + length + 1; if (start < 0 || start > length) { start = 0; } if (end < 0 || end > length) { end = length; // do not overflow; } if (end <= start) { return string_alloc("", 0); } return string_alloc(GET_STR(self) + start, end - start); } else if (IS_LIST(self)) { int length = LIST_LEN(self); start = start > 0 ? start : start + length + 1; end = end > 0 ? end : end + length + 1; if (start < 0 || start > length) { start = 0; } if (end < 0 || end > length) { end = length; } int i = 0; ret = list_new(end - start); for (i = start; i < end ; i++) { obj_append(ret, LIST_GET(self, i)); } } else { tm_raise("slice not implemented for type %s", tm_type(self.type)); } return ret; }