From 8965a5eb1e9d7df9018fc9537169f7bb9a523d9c Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Mon, 20 Jan 2014 23:33:19 +0200 Subject: objstr: More support for MP_OBJ_QSTR. --- py/objstr.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) (limited to 'py/objstr.c') diff --git a/py/objstr.c b/py/objstr.c index 5e87097a8..68fe7f0fc 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -175,16 +175,8 @@ static bool chr_in_str(const char* const str, const size_t str_len, const char c static mp_obj_t str_find(uint n_args, const mp_obj_t *args) { assert(2 <= n_args && n_args <= 4); - assert(MP_OBJ_IS_TYPE(args[0], &str_type)); - if (!MP_OBJ_IS_TYPE(args[1], &str_type)) { - nlr_jump(mp_obj_new_exception_msg_1_arg( - MP_QSTR_TypeError, - "Can't convert '%s' object to str implicitly", - mp_obj_get_type_str(args[1]))); - } - - const char* haystack = qstr_str(((mp_obj_str_t*)args[0])->qstr); - const char* needle = qstr_str(((mp_obj_str_t*)args[1])->qstr); + const char* haystack = qstr_str(mp_obj_str_get(args[0])); + const char* needle = qstr_str(mp_obj_str_get(args[1])); size_t haystack_len = strlen(haystack); size_t needle_len = strlen(needle); @@ -222,14 +214,11 @@ mp_obj_t str_strip(uint n_args, const mp_obj_t *args) { if (n_args == 1) { chars_to_del = whitespace; } else { - assert(MP_OBJ_IS_TYPE(args[1], &str_type)); - mp_obj_str_t *chars_to_del_obj = args[1]; - chars_to_del = qstr_str(chars_to_del_obj->qstr); + chars_to_del = qstr_str(mp_obj_str_get(args[1])); } const size_t chars_to_del_len = strlen(chars_to_del); - mp_obj_str_t *self = args[0]; - const char *orig_str = qstr_str(self->qstr); + const char *orig_str = qstr_str(mp_obj_str_get(args[0])); const size_t orig_str_len = strlen(orig_str); size_t first_good_char_pos = 0; @@ -321,9 +310,15 @@ mp_obj_t mp_obj_new_str(qstr qstr) { } qstr mp_obj_str_get(mp_obj_t self_in) { - assert(MP_OBJ_IS_TYPE(self_in, &str_type)); - mp_obj_str_t *self = self_in; - return self->qstr; + if (MP_OBJ_IS_QSTR(self_in)) { + return MP_OBJ_QSTR_VALUE(self_in); + } + if (MP_OBJ_IS_TYPE(self_in, &str_type)) { + mp_obj_str_t *self = self_in; + return self->qstr; + } + 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))); } /******************************************************************************/ -- cgit v1.2.3 From 545591a696bdff73f68573c54a05ca70eb58032d Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Tue, 21 Jan 2014 00:27:33 +0200 Subject: Implement string multiplication. --- py/objstr.c | 12 ++++++++++++ tests/basics/string1.py | 2 ++ 2 files changed, 14 insertions(+) (limited to 'py/objstr.c') diff --git a/py/objstr.c b/py/objstr.c index 68fe7f0fc..01de5e367 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -102,6 +102,18 @@ mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { return MP_BOOL((op == RT_COMPARE_OP_IN) ^ (strstr(lhs_str, rhs_str) == 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); + size_t len = strlen(lhs_str); + char *s = m_new(char, len * n + 1); + s[len * n] = 0; + mp_seq_multiply(lhs_str, sizeof(*lhs_str), len, n, s); + return MP_OBJ_NEW_QSTR(qstr_from_str_take(s, len * n + 1)); + } } return MP_OBJ_NULL; // op not supported diff --git a/tests/basics/string1.py b/tests/basics/string1.py index 3fecf799b..40e766b59 100644 --- a/tests/basics/string1.py +++ b/tests/basics/string1.py @@ -8,6 +8,8 @@ print(x) print('123' + "456") +print('123' * 5) + # iter print(list('str')) -- cgit v1.2.3 From 7380a837802b4630bdcef6e01cd5be32f92750ca Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Tue, 21 Jan 2014 02:22:02 +0200 Subject: str: Implement proper string (instead of byte string) indexing. Also, support negative indexes. --- py/objstr.c | 5 ++--- tests/basics/string1.py | 11 +++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'py/objstr.c') diff --git a/py/objstr.c b/py/objstr.c index 01de5e367..4adfef6f8 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -44,9 +44,8 @@ mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { // 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)) { - // TODO: This implements byte string access for single index so far - // TODO: Handle negative indexes. - return mp_obj_new_int(lhs_str[mp_obj_get_int(rhs_in)]); + uint index = mp_get_index(lhs->base.type, strlen(lhs_str), rhs_in); + return mp_obj_new_str(qstr_from_strn_copy(lhs_str + index, 1)); #if MICROPY_ENABLE_SLICE } else if (MP_OBJ_IS_TYPE(rhs_in, &slice_type)) { machine_int_t start, stop, step; diff --git a/tests/basics/string1.py b/tests/basics/string1.py index 40e766b59..074b04ef8 100644 --- a/tests/basics/string1.py +++ b/tests/basics/string1.py @@ -10,6 +10,17 @@ print('123' + "456") print('123' * 5) +print('abc'[1]) +print('abc'[-1]) +try: + 'abc'[100] +except IndexError: + print('caught') +try: + 'abc'[-4] +except IndexError: + print('caught2') + # iter print(list('str')) -- cgit v1.2.3 From 4c316552c16fa2bcb77e007d330dc32beaf6e652 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Tue, 21 Jan 2014 05:00:21 +0200 Subject: Implement str.split(None). Note that splitting by explicit string is not implemented so far. --- py/objstr.c | 40 ++++++++++++++++++++++++++++++++++++++++ tests/basics/string_split.py | 7 +++++++ 2 files changed, 47 insertions(+) create mode 100644 tests/basics/string_split.py (limited to 'py/objstr.c') diff --git a/py/objstr.c b/py/objstr.c index 4adfef6f8..758e8c293 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -175,6 +175,44 @@ bad_arg: nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "?str.join expecting a list of str's")); } +#define is_ws(c) ((c) == ' ' || (c) == '\t') + +static mp_obj_t str_split(uint n_args, const mp_obj_t *args) { + int splits = -1; + mp_obj_t sep = mp_const_none; + if (n_args > 1) { + sep = args[1]; + if (n_args > 2) { + splits = MP_OBJ_SMALL_INT_VALUE(args[2]); + } + } + assert(sep == mp_const_none); + mp_obj_t res = mp_obj_new_list(0, NULL); + const char *s = qstr_str(mp_obj_str_get(args[0])); + const char *start; + + // Initial whitespace is not counted as split, so we pre-do it + while (is_ws(*s)) s++; + while (*s && splits != 0) { + start = s; + while (*s != 0 && !is_ws(*s)) s++; + rt_list_append(res, MP_OBJ_NEW_QSTR(qstr_from_strn_copy(start, s - start))); + if (*s == 0) { + break; + } + while (is_ws(*s)) s++; + if (splits > 0) { + splits--; + } + } + + if (*s != 0) { + rt_list_append(res, MP_OBJ_NEW_QSTR(qstr_from_strn_copy(s, strlen(s)))); + } + + return res; +} + static bool chr_in_str(const char* const str, const size_t str_len, const char c) { for (size_t i = 0; i < str_len; i++) { if (str[i] == c) { @@ -293,12 +331,14 @@ mp_obj_t str_format(uint n_args, const mp_obj_t *args) { static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj, 2, 4, str_find); static MP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj, 1, 3, str_split); static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj, 1, 2, str_strip); static MP_DEFINE_CONST_FUN_OBJ_VAR(str_format_obj, 1, str_format); static const mp_method_t str_type_methods[] = { { "find", &str_find_obj }, { "join", &str_join_obj }, + { "split", &str_split_obj }, { "strip", &str_strip_obj }, { "format", &str_format_obj }, { NULL, NULL }, // end-of-list sentinel diff --git a/tests/basics/string_split.py b/tests/basics/string_split.py new file mode 100644 index 000000000..f73cb4291 --- /dev/null +++ b/tests/basics/string_split.py @@ -0,0 +1,7 @@ +print("a b".split()) +print(" a b ".split(None)) +print(" a b ".split(None, 1)) +print(" a b ".split(None, 2)) +print(" a b c ".split(None, 1)) +print(" a b c ".split(None, 0)) +print(" a b c ".split(None, -1)) -- cgit v1.2.3