@@ -67,6 +67,26 @@ static void check_is_str_or_bytes(mp_obj_t self_in) {
6767 mp_check_self (mp_obj_is_str_or_bytes (self_in ));
6868}
6969
70+ static const byte * get_substring_data (const mp_obj_t obj , size_t n_args , const mp_obj_t * args , size_t * len ) {
71+ // Get substring data from obj, using args[0,1] to specify start and end indices.
72+ GET_STR_DATA_LEN (obj , str , str_len );
73+ if (n_args > 0 ) {
74+ const mp_obj_type_t * self_type = mp_obj_get_type (obj );
75+ const byte * end = str + str_len ;
76+ if (n_args > 1 && args [1 ] != mp_const_none ) {
77+ end = str_index_to_ptr (self_type , str , str_len , args [1 ], true);
78+ }
79+ if (args [0 ] != mp_const_none ) {
80+ str = str_index_to_ptr (self_type , str , str_len , args [0 ], true);
81+ }
82+ str_len = MAX (end - str , 0 );
83+ }
84+ if (len ) {
85+ * len = str_len ;
86+ }
87+ return str ;
88+ }
89+
7090/******************************************************************************/
7191/* str */
7292
@@ -802,37 +822,34 @@ static mp_obj_t str_rindex(size_t n_args, const mp_obj_t *args) {
802822}
803823MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (str_rindex_obj , 2 , 4 , str_rindex );
804824
805- // TODO: (Much) more variety in args
806- static mp_obj_t str_startswith (size_t n_args , const mp_obj_t * args ) {
807- const mp_obj_type_t * self_type = mp_obj_get_type (args [0 ]);
808- GET_STR_DATA_LEN (args [0 ], str , str_len );
809- size_t prefix_len ;
810- const char * prefix = mp_obj_str_get_data (args [1 ], & prefix_len );
811- const byte * start = str ;
812- if (n_args > 2 ) {
813- start = str_index_to_ptr (self_type , str , str_len , args [2 ], true);
825+ static mp_obj_t str_startendswith (size_t n_args , const mp_obj_t * args , bool ends_with ) {
826+ size_t str_len ;
827+ const byte * str = get_substring_data (args [0 ], n_args - 2 , args + 2 , & str_len );
828+ mp_obj_t * prefixes = (mp_obj_t * )& args [1 ];
829+ size_t n_prefixes = 1 ;
830+ if (mp_obj_is_type (args [1 ], & mp_type_tuple )) {
831+ mp_obj_tuple_get (args [1 ], & n_prefixes , & prefixes );
814832 }
815- if (prefix_len + (start - str ) > str_len ) {
816- return mp_const_false ;
833+ size_t prefix_len ;
834+ for (size_t i = 0 ; i < n_prefixes ; i ++ ) {
835+ const char * prefix = mp_obj_str_get_data (prefixes [i ], & prefix_len );
836+ const byte * s = str + (ends_with ? str_len - prefix_len : 0 );
837+ if (prefix_len <= str_len && memcmp (s , prefix , prefix_len ) == 0 ) {
838+ return mp_const_true ;
839+ }
817840 }
818- return mp_obj_new_bool ( memcmp ( start , prefix , prefix_len ) == 0 ) ;
841+ return mp_const_false ;
819842}
820- MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (str_startswith_obj , 2 , 3 , str_startswith );
821843
822- static mp_obj_t str_endswith (size_t n_args , const mp_obj_t * args ) {
823- GET_STR_DATA_LEN (args [0 ], str , str_len );
824- size_t suffix_len ;
825- const char * suffix = mp_obj_str_get_data (args [1 ], & suffix_len );
826- if (n_args > 2 ) {
827- mp_raise_NotImplementedError (MP_ERROR_TEXT ("start/end indices" ));
828- }
844+ static mp_obj_t str_startswith (size_t n_args , const mp_obj_t * args ) {
845+ return str_startendswith (n_args , args , false);
846+ }
847+ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (str_startswith_obj , 2 , 4 , str_startswith );
829848
830- if (suffix_len > str_len ) {
831- return mp_const_false ;
832- }
833- return mp_obj_new_bool (memcmp (str + (str_len - suffix_len ), suffix , suffix_len ) == 0 );
849+ static mp_obj_t str_endswith (size_t n_args , const mp_obj_t * args ) {
850+ return str_startendswith (n_args , args , true);
834851}
835- MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (str_endswith_obj , 2 , 3 , str_endswith );
852+ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (str_endswith_obj , 2 , 4 , str_endswith );
836853
837854enum { LSTRIP , RSTRIP , STRIP };
838855
0 commit comments