@@ -67,6 +67,26 @@ static void check_is_str_or_bytes(mp_obj_t self_in) {
67
67
mp_check_self (mp_obj_is_str_or_bytes (self_in ));
68
68
}
69
69
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
+
70
90
/******************************************************************************/
71
91
/* str */
72
92
@@ -802,37 +822,34 @@ static mp_obj_t str_rindex(size_t n_args, const mp_obj_t *args) {
802
822
}
803
823
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (str_rindex_obj , 2 , 4 , str_rindex );
804
824
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 );
814
832
}
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
+ }
817
840
}
818
- return mp_obj_new_bool ( memcmp ( start , prefix , prefix_len ) == 0 ) ;
841
+ return mp_const_false ;
819
842
}
820
- MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (str_startswith_obj , 2 , 3 , str_startswith );
821
843
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 );
829
848
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);
834
851
}
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 );
836
853
837
854
enum { LSTRIP , RSTRIP , STRIP };
838
855
0 commit comments