@@ -17,6 +17,7 @@ typedef struct _mp_obj_str_t {
1717 const byte * data ;
1818} mp_obj_str_t ;
1919
20+ STATIC mp_obj_t str_modulo_format (mp_obj_t pattern , uint n_args , const mp_obj_t * args );
2021const mp_obj_t mp_const_empty_bytes ;
2122
2223// use this macro to extract the string hash
@@ -283,6 +284,19 @@ STATIC mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
283284 return mp_obj_str_builder_end (s );
284285 }
285286
287+ case MP_BINARY_OP_MODULO : {
288+ mp_obj_t * args ;
289+ uint n_args ;
290+ if (MP_OBJ_IS_TYPE (rhs_in , & mp_type_tuple )) {
291+ // TODO: Support tuple subclasses?
292+ mp_obj_tuple_get (rhs_in , & n_args , & args );
293+ } else {
294+ args = & rhs_in ;
295+ n_args = 1 ;
296+ }
297+ return str_modulo_format (lhs_in , n_args , args );
298+ }
299+
286300 // These 2 are never passed here, dealt with as a special case in mp_binary_op().
287301 //case MP_BINARY_OP_EQUAL:
288302 //case MP_BINARY_OP_NOT_EQUAL:
@@ -508,6 +522,47 @@ mp_obj_t str_format(uint n_args, const mp_obj_t *args) {
508522 return s ;
509523}
510524
525+ STATIC mp_obj_t str_modulo_format (mp_obj_t pattern , uint n_args , const mp_obj_t * args ) {
526+ assert (MP_OBJ_IS_STR (pattern ));
527+
528+ GET_STR_DATA_LEN (pattern , str , len );
529+ int arg_i = 0 ;
530+ vstr_t * vstr = vstr_new ();
531+ for (const byte * top = str + len ; str < top ; str ++ ) {
532+ if (* str == '%' ) {
533+ if (++ str >= top ) {
534+ break ;
535+ }
536+ if (* str == '%' ) {
537+ vstr_add_char (vstr , '%' );
538+ } else {
539+ if (arg_i >= n_args ) {
540+ nlr_jump (mp_obj_new_exception_msg (& mp_type_TypeError , "not enough arguments for format string" ));
541+ }
542+ switch (* str ) {
543+ case 's' :
544+ mp_obj_print_helper ((void (* )(void * , const char * , ...))vstr_printf , vstr , args [arg_i ], PRINT_STR );
545+ break ;
546+ case 'r' :
547+ mp_obj_print_helper ((void (* )(void * , const char * , ...))vstr_printf , vstr , args [arg_i ], PRINT_REPR );
548+ break ;
549+ }
550+ arg_i ++ ;
551+ }
552+ } else {
553+ vstr_add_char (vstr , * str );
554+ }
555+ }
556+
557+ if (arg_i != n_args ) {
558+ nlr_jump (mp_obj_new_exception_msg (& mp_type_TypeError , "not all arguments converted during string formatting" ));
559+ }
560+
561+ mp_obj_t s = mp_obj_new_str ((byte * )vstr -> buf , vstr -> len , false);
562+ vstr_free (vstr );
563+ return s ;
564+ }
565+
511566STATIC mp_obj_t str_replace (uint n_args , const mp_obj_t * args ) {
512567 assert (MP_OBJ_IS_STR (args [0 ]));
513568 assert (MP_OBJ_IS_STR (args [1 ]));
0 commit comments