@@ -132,8 +132,6 @@ STATIC void str_print(void (*print)(void *env, const char *fmt, ...), void *env,
132132
133133#if !MICROPY_PY_BUILTINS_STR_UNICODE || MICROPY_CPYTHON_COMPAT
134134STATIC mp_obj_t str_make_new (mp_obj_t type_in , mp_uint_t n_args , mp_uint_t n_kw , const mp_obj_t * args ) {
135- (void )type_in ;
136-
137135#if MICROPY_CPYTHON_COMPAT
138136 if (n_kw != 0 ) {
139137 mp_arg_error_unimpl_kw ();
@@ -147,19 +145,18 @@ STATIC mp_obj_t str_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw,
147145 return MP_OBJ_NEW_QSTR (MP_QSTR_ );
148146
149147 case 1 : {
150- vstr_t * vstr = vstr_new ();
151- mp_obj_print_helper ((void (* )(void * , const char * , ...))vstr_printf , vstr , args [0 ], PRINT_STR );
152- mp_obj_t s = mp_obj_new_str (vstr -> buf , vstr -> len , false);
153- vstr_free (vstr );
154- return s ;
148+ vstr_t vstr ;
149+ vstr_init (& vstr , 16 );
150+ mp_obj_print_helper ((void (* )(void * , const char * , ...))vstr_printf , & vstr , args [0 ], PRINT_STR );
151+ return mp_obj_new_str_from_vstr (type_in , & vstr );
155152 }
156153
157154 default : // 2 or 3 args
158155 // TODO: validate 2nd/3rd args
159156 if (MP_OBJ_IS_TYPE (args [0 ], & mp_type_bytes )) {
160157 GET_STR_DATA_LEN (args [0 ], str_data , str_len );
161158 GET_STR_HASH (args [0 ], str_hash );
162- mp_obj_str_t * o = mp_obj_new_str_of_type (& mp_type_str , NULL , str_len );
159+ mp_obj_str_t * o = mp_obj_new_str_of_type (type_in , NULL , str_len );
163160 o -> data = str_data ;
164161 o -> hash = str_hash ;
165162 return o ;
@@ -216,40 +213,23 @@ STATIC mp_obj_t bytes_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_k
216213 return mp_obj_new_str_of_type (& mp_type_bytes , bufinfo .buf , bufinfo .len );
217214 }
218215
219- mp_int_t len ;
220- byte * data ;
221- vstr_t * vstr = NULL ;
222- mp_obj_t o = MP_OBJ_NULL ;
216+ vstr_t vstr ;
223217 // Try to create array of exact len if initializer len is known
224218 mp_obj_t len_in = mp_obj_len_maybe (args [0 ]);
225219 if (len_in == MP_OBJ_NULL ) {
226- len = -1 ;
227- vstr = vstr_new ();
220+ vstr_init (& vstr , 16 );
228221 } else {
229- len = MP_OBJ_SMALL_INT_VALUE (len_in );
230- o = mp_obj_str_builder_start ( & mp_type_bytes , len , & data );
222+ mp_int_t len = MP_OBJ_SMALL_INT_VALUE (len_in );
223+ vstr_init ( & vstr , len + 1 );
231224 }
232225
233226 mp_obj_t iterable = mp_getiter (args [0 ]);
234227 mp_obj_t item ;
235228 while ((item = mp_iternext (iterable )) != MP_OBJ_STOP_ITERATION ) {
236- if (len == -1 ) {
237- vstr_add_char (vstr , MP_OBJ_SMALL_INT_VALUE (item ));
238- } else {
239- * data ++ = MP_OBJ_SMALL_INT_VALUE (item );
240- }
229+ vstr_add_char (& vstr , MP_OBJ_SMALL_INT_VALUE (item ));
241230 }
242231
243- if (len == -1 ) {
244- vstr_shrink (vstr );
245- // TODO: Optimize, borrow buffer from vstr
246- len = vstr_len (vstr );
247- o = mp_obj_str_builder_start (& mp_type_bytes , len , & data );
248- memcpy (data , vstr_str (vstr ), len );
249- vstr_free (vstr );
250- }
251-
252- return mp_obj_str_builder_end (o );
232+ return mp_obj_new_str_from_vstr (& mp_type_bytes , & vstr );
253233
254234wrong_args :
255235 nlr_raise (mp_obj_new_exception_msg (& mp_type_TypeError , "wrong number of arguments" ));
@@ -837,16 +817,17 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
837817
838818 GET_STR_DATA_LEN (args [0 ], str , len );
839819 int arg_i = 0 ;
840- vstr_t * vstr = vstr_new ();
820+ vstr_t vstr ;
821+ vstr_init (& vstr , 16 );
841822 pfenv_t pfenv_vstr ;
842- pfenv_vstr .data = vstr ;
823+ pfenv_vstr .data = & vstr ;
843824 pfenv_vstr .print_strn = pfenv_vstr_add_strn ;
844825
845826 for (const byte * top = str + len ; str < top ; str ++ ) {
846827 if (* str == '}' ) {
847828 str ++ ;
848829 if (str < top && * str == '}' ) {
849- vstr_add_char (vstr , '}' );
830+ vstr_add_char (& vstr , '}' );
850831 continue ;
851832 }
852833 if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE ) {
@@ -857,13 +838,13 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
857838 }
858839 }
859840 if (* str != '{' ) {
860- vstr_add_char (vstr , * str );
841+ vstr_add_char (& vstr , * str );
861842 continue ;
862843 }
863844
864845 str ++ ;
865846 if (str < top && * str == '{' ) {
866- vstr_add_char (vstr , '{' );
847+ vstr_add_char (& vstr , '{' );
867848 continue ;
868849 }
869850
@@ -996,10 +977,10 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
996977 "unknown conversion specifier %c" , conversion ));
997978 }
998979 }
999- vstr_t * arg_vstr = vstr_new () ;
1000- mp_obj_print_helper (( void ( * )( void * , const char * , ...)) vstr_printf , arg_vstr , arg , print_kind );
1001- arg = mp_obj_new_str ( vstr_str ( arg_vstr ), vstr_len ( arg_vstr ), false );
1002- vstr_free ( arg_vstr );
980+ vstr_t arg_vstr ;
981+ vstr_init ( & arg_vstr , 16 );
982+ mp_obj_print_helper (( void ( * )( void * , const char * , ...)) vstr_printf , & arg_vstr , arg , print_kind );
983+ arg = mp_obj_new_str_from_vstr ( & mp_type_str , & arg_vstr );
1003984 }
1004985
1005986 char sign = '\0' ;
@@ -1243,7 +1224,7 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
12431224
12441225 switch (type ) {
12451226 case '\0' :
1246- mp_obj_print_helper ((void (* )(void * , const char * , ...))vstr_printf , vstr , arg , PRINT_STR );
1227+ mp_obj_print_helper ((void (* )(void * , const char * , ...))vstr_printf , & vstr , arg , PRINT_STR );
12471228 break ;
12481229
12491230 case 's' : {
@@ -1271,9 +1252,7 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
12711252 }
12721253 }
12731254
1274- mp_obj_t s = mp_obj_new_str (vstr -> buf , vstr -> len , false);
1275- vstr_free (vstr );
1276- return s ;
1255+ return mp_obj_new_str_from_vstr (& mp_type_str , & vstr );
12771256}
12781257
12791258STATIC mp_obj_t str_modulo_format (mp_obj_t pattern , mp_uint_t n_args , const mp_obj_t * args , mp_obj_t dict ) {
@@ -1282,22 +1261,23 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, mp_uint_t n_args, const mp_o
12821261 GET_STR_DATA_LEN (pattern , str , len );
12831262 const byte * start_str = str ;
12841263 int arg_i = 0 ;
1285- vstr_t * vstr = vstr_new ();
1264+ vstr_t vstr ;
1265+ vstr_init (& vstr , 16 );
12861266 pfenv_t pfenv_vstr ;
1287- pfenv_vstr .data = vstr ;
1267+ pfenv_vstr .data = & vstr ;
12881268 pfenv_vstr .print_strn = pfenv_vstr_add_strn ;
12891269
12901270 for (const byte * top = str + len ; str < top ; str ++ ) {
12911271 mp_obj_t arg = MP_OBJ_NULL ;
12921272 if (* str != '%' ) {
1293- vstr_add_char (vstr , * str );
1273+ vstr_add_char (& vstr , * str );
12941274 continue ;
12951275 }
12961276 if (++ str >= top ) {
12971277 break ;
12981278 }
12991279 if (* str == '%' ) {
1300- vstr_add_char (vstr , '%' );
1280+ vstr_add_char (& vstr , '%' );
13011281 continue ;
13021282 }
13031283
@@ -1426,18 +1406,19 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, mp_uint_t n_args, const mp_o
14261406 case 'r' :
14271407 case 's' :
14281408 {
1429- vstr_t * arg_vstr = vstr_new ();
1409+ vstr_t arg_vstr ;
1410+ vstr_init (& arg_vstr , 16 );
14301411 mp_obj_print_helper ((void (* )(void * , const char * , ...))vstr_printf ,
1431- arg_vstr , arg , * str == 'r' ? PRINT_REPR : PRINT_STR );
1432- uint vlen = vstr_len ( arg_vstr ) ;
1412+ & arg_vstr , arg , * str == 'r' ? PRINT_REPR : PRINT_STR );
1413+ uint vlen = arg_vstr . len ;
14331414 if (prec < 0 ) {
14341415 prec = vlen ;
14351416 }
14361417 if (vlen > (uint )prec ) {
14371418 vlen = prec ;
14381419 }
1439- pfenv_print_strn (& pfenv_vstr , vstr_str ( arg_vstr ) , vlen , flags , ' ' , width );
1440- vstr_free ( arg_vstr );
1420+ pfenv_print_strn (& pfenv_vstr , arg_vstr . buf , vlen , flags , ' ' , width );
1421+ vstr_clear ( & arg_vstr );
14411422 break ;
14421423 }
14431424
@@ -1461,9 +1442,7 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, mp_uint_t n_args, const mp_o
14611442 nlr_raise (mp_obj_new_exception_msg (& mp_type_TypeError , "not all arguments converted during string formatting" ));
14621443 }
14631444
1464- mp_obj_t s = mp_obj_new_str (vstr -> buf , vstr -> len , false);
1465- vstr_free (vstr );
1466- return s ;
1445+ return mp_obj_new_str_from_vstr (& mp_type_str , & vstr );
14671446}
14681447
14691448STATIC mp_obj_t str_replace (mp_uint_t n_args , const mp_obj_t * args ) {
@@ -1746,7 +1725,7 @@ STATIC mp_obj_t bytes_decode(mp_uint_t n_args, const mp_obj_t *args) {
17461725 args = new_args ;
17471726 n_args ++ ;
17481727 }
1749- return str_make_new (NULL , n_args , 0 , args );
1728+ return str_make_new (( mp_obj_t ) & mp_type_str , n_args , 0 , args );
17501729}
17511730
17521731// TODO: should accept kwargs too
@@ -1920,6 +1899,28 @@ mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, mp_
19201899 return o ;
19211900}
19221901
1902+ mp_obj_t mp_obj_new_str_from_vstr (const mp_obj_type_t * type , vstr_t * vstr ) {
1903+ // if not a bytes object, look if a qstr with this data already exists
1904+ if (type == & mp_type_str ) {
1905+ qstr q = qstr_find_strn (vstr -> buf , vstr -> len );
1906+ if (q != MP_QSTR_NULL ) {
1907+ vstr_clear (vstr );
1908+ vstr -> alloc = 0 ;
1909+ return MP_OBJ_NEW_QSTR (q );
1910+ }
1911+ }
1912+
1913+ // make a new str/bytes object
1914+ mp_obj_str_t * o = m_new_obj (mp_obj_str_t );
1915+ o -> base .type = type ;
1916+ o -> len = vstr -> len ;
1917+ o -> hash = qstr_compute_hash ((byte * )vstr -> buf , vstr -> len );
1918+ o -> data = (byte * )m_renew (char , vstr -> buf , vstr -> alloc , vstr -> len + 1 );
1919+ vstr -> buf = NULL ;
1920+ vstr -> alloc = 0 ;
1921+ return o ;
1922+ }
1923+
19231924mp_obj_t mp_obj_new_str (const char * data , mp_uint_t len , bool make_qstr_if_not_already ) {
19241925 if (make_qstr_if_not_already ) {
19251926 // use existing, or make a new qstr
0 commit comments