diff options
-rw-r--r-- | py/objstr.c | 67 | ||||
-rw-r--r-- | tests/basics/string_endswith.py | 27 | ||||
-rw-r--r-- | tests/basics/string_endswith_upy.py | 6 | ||||
-rw-r--r-- | tests/basics/string_endswith_upy.py.exp | 1 | ||||
-rw-r--r-- | tests/basics/string_startswith.py | 19 | ||||
-rw-r--r-- | tests/basics/string_startswith_upy.py | 6 | ||||
-rw-r--r-- | tests/basics/string_startswith_upy.py.exp | 1 | ||||
-rw-r--r-- | tests/misc/non_compliant.py | 6 | ||||
-rw-r--r-- | tests/misc/non_compliant.py.exp | 1 |
9 files changed, 83 insertions, 51 deletions
diff --git a/py/objstr.c b/py/objstr.c index fc0623eb7..307e956a1 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -67,6 +67,26 @@ static void check_is_str_or_bytes(mp_obj_t self_in) { mp_check_self(mp_obj_is_str_or_bytes(self_in)); } +static const byte *get_substring_data(const mp_obj_t obj, size_t n_args, const mp_obj_t *args, size_t *len) { + // Get substring data from obj, using args[0,1] to specify start and end indices. + GET_STR_DATA_LEN(obj, str, str_len); + if (n_args > 0) { + const mp_obj_type_t *self_type = mp_obj_get_type(obj); + const byte *end = str + str_len; + if (n_args > 1 && args[1] != mp_const_none) { + end = str_index_to_ptr(self_type, str, str_len, args[1], true); + } + if (args[0] != mp_const_none) { + str = str_index_to_ptr(self_type, str, str_len, args[0], true); + } + str_len = MAX(end - str, 0); + } + if (len) { + *len = str_len; + } + return str; +} + /******************************************************************************/ /* str */ @@ -802,37 +822,34 @@ static mp_obj_t str_rindex(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rindex_obj, 2, 4, str_rindex); -// TODO: (Much) more variety in args -static mp_obj_t str_startswith(size_t n_args, const mp_obj_t *args) { - const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); - GET_STR_DATA_LEN(args[0], str, str_len); - size_t prefix_len; - const char *prefix = mp_obj_str_get_data(args[1], &prefix_len); - const byte *start = str; - if (n_args > 2) { - start = str_index_to_ptr(self_type, str, str_len, args[2], true); +static mp_obj_t str_startendswith(size_t n_args, const mp_obj_t *args, bool ends_with) { + size_t str_len; + const byte *str = get_substring_data(args[0], n_args - 2, args + 2, &str_len); + mp_obj_t *prefixes = (mp_obj_t *)&args[1]; + size_t n_prefixes = 1; + if (mp_obj_is_type(args[1], &mp_type_tuple)) { + mp_obj_tuple_get(args[1], &n_prefixes, &prefixes); } - if (prefix_len + (start - str) > str_len) { - return mp_const_false; + size_t prefix_len; + for (size_t i = 0; i < n_prefixes; i++) { + const char *prefix = mp_obj_str_get_data(prefixes[i], &prefix_len); + const byte *s = str + (ends_with ? str_len - prefix_len : 0); + if (prefix_len <= str_len && memcmp(s, prefix, prefix_len) == 0) { + return mp_const_true; + } } - return mp_obj_new_bool(memcmp(start, prefix, prefix_len) == 0); + return mp_const_false; } -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj, 2, 3, str_startswith); -static mp_obj_t str_endswith(size_t n_args, const mp_obj_t *args) { - GET_STR_DATA_LEN(args[0], str, str_len); - size_t suffix_len; - const char *suffix = mp_obj_str_get_data(args[1], &suffix_len); - if (n_args > 2) { - mp_raise_NotImplementedError(MP_ERROR_TEXT("start/end indices")); - } +static mp_obj_t str_startswith(size_t n_args, const mp_obj_t *args) { + return str_startendswith(n_args, args, false); +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj, 2, 4, str_startswith); - if (suffix_len > str_len) { - return mp_const_false; - } - return mp_obj_new_bool(memcmp(str + (str_len - suffix_len), suffix, suffix_len) == 0); +static mp_obj_t str_endswith(size_t n_args, const mp_obj_t *args) { + return str_startendswith(n_args, args, true); } -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj, 2, 3, str_endswith); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj, 2, 4, str_endswith); enum { LSTRIP, RSTRIP, STRIP }; diff --git a/tests/basics/string_endswith.py b/tests/basics/string_endswith.py index 683562d10..2b0a06398 100644 --- a/tests/basics/string_endswith.py +++ b/tests/basics/string_endswith.py @@ -5,11 +5,28 @@ print("foobar".endswith("foobar")) print("foobar".endswith("")) print("foobar".endswith("foobarbaz")) -#print("1foobar".startswith("foo", 1)) -#print("1foo".startswith("foo", 1)) -#print("1foo".startswith("1foo", 1)) -#print("1fo".startswith("foo", 1)) -#print("1fo".startswith("foo", 10)) +print("foobar".endswith("bar", 3)) +print("foobar".endswith("bar", 4)) +print("foobar".endswith("foo", 0, 3)) +print("foobar".endswith("foo", 0, 4)) +print("foobar".endswith("foo", 1, 3)) +print("foobar".endswith("foo", 1, 3)) +print("foobar".endswith("oo", 1, 3)) +print("foobar".endswith("o", 2, 3)) +print("foobar".endswith("o", 3, 3)) +print("foobar".endswith("o", 4, 3)) + +print("foobar".endswith("bar", None, None)) +print("foobar".endswith("bar", None, 3)) +print("foobar".endswith("bar", 3, None)) +print("foobar".endswith("bar", 2, None)) +print("foobar".endswith("foo", None, 3)) + +print("foobar".endswith(("bar", "foo"))) +print("foobar".endswith(("foo", "bar"))) +print("foobar".endswith(("foo", "bar1"))) +print("foobar".endswith(("bar", ))) +print("foobar".endswith(("foo", ))) try: "foobar".endswith(1) diff --git a/tests/basics/string_endswith_upy.py b/tests/basics/string_endswith_upy.py deleted file mode 100644 index 06a4e71d2..000000000 --- a/tests/basics/string_endswith_upy.py +++ /dev/null @@ -1,6 +0,0 @@ -# MicroPython doesn't support tuple argument - -try: - "foobar".endswith(("bar", "sth")) -except TypeError: - print("TypeError") diff --git a/tests/basics/string_endswith_upy.py.exp b/tests/basics/string_endswith_upy.py.exp deleted file mode 100644 index 6002b71c5..000000000 --- a/tests/basics/string_endswith_upy.py.exp +++ /dev/null @@ -1 +0,0 @@ -TypeError diff --git a/tests/basics/string_startswith.py b/tests/basics/string_startswith.py index e63ae3c18..eefdea821 100644 --- a/tests/basics/string_startswith.py +++ b/tests/basics/string_startswith.py @@ -10,6 +10,25 @@ print("1foo".startswith("1foo", 1)) print("1fo".startswith("foo", 1)) print("1fo".startswith("foo", 10)) +print("1foobar".startswith("foo", 1, 5)) +print("1foobar".startswith("foo", 1, 4)) +print("1foobar".startswith("foo", 1, 3)) +print("1foobar".startswith("oo", 2, 4)) +print("1foobar".startswith("o", 3, 4)) +print("1foobar".startswith("o", 4, 4)) +print("1foobar".startswith("o", 5, 4)) + +print("foobar".startswith("foo", None, None)) +print("foobar".startswith("foo", None, 3)) +print("foobar".startswith("foo", None, 2)) +print("foobar".startswith("bar", 3, None)) + + +print("foobar".startswith(("foo", "sth"))) +print("foobar".startswith(("sth", "foo"))) +print("foobar".startswith(("sth", "foo2"))) +print("foobar".startswith(("foo", ))) + try: "foobar".startswith(1) except TypeError: diff --git a/tests/basics/string_startswith_upy.py b/tests/basics/string_startswith_upy.py deleted file mode 100644 index 9ea1796c2..000000000 --- a/tests/basics/string_startswith_upy.py +++ /dev/null @@ -1,6 +0,0 @@ -# MicroPython doesn't support tuple argument - -try: - "foobar".startswith(("foo", "sth")) -except TypeError: - print("TypeError") diff --git a/tests/basics/string_startswith_upy.py.exp b/tests/basics/string_startswith_upy.py.exp deleted file mode 100644 index 6002b71c5..000000000 --- a/tests/basics/string_startswith_upy.py.exp +++ /dev/null @@ -1 +0,0 @@ -TypeError diff --git a/tests/misc/non_compliant.py b/tests/misc/non_compliant.py index da90f90ac..dd62f6325 100644 --- a/tests/misc/non_compliant.py +++ b/tests/misc/non_compliant.py @@ -63,12 +63,6 @@ try: except NotImplementedError: print("NotImplementedError") -# str.endswith(s, start) not implemented -try: - "abc".endswith("c", 1) -except NotImplementedError: - print("NotImplementedError") - # str subscr with step!=1 not implemented try: print("abc"[1:2:3]) diff --git a/tests/misc/non_compliant.py.exp b/tests/misc/non_compliant.py.exp index 3f15a1440..deefe78a7 100644 --- a/tests/misc/non_compliant.py.exp +++ b/tests/misc/non_compliant.py.exp @@ -13,7 +13,6 @@ NotImplementedError NotImplementedError NotImplementedError NotImplementedError -NotImplementedError b'\x01\x02' b'\x01\x00' NotImplementedError |