@@ -17,6 +17,8 @@ typedef struct _mp_obj_str_t {
1717 const byte * data ;
1818} mp_obj_str_t ;
1919
20+ const mp_obj_t mp_const_empty_bytes ;
21+
2022// use this macro to extract the string hash
2123#define GET_STR_HASH (str_obj_in , str_hash ) uint str_hash; if (MP_OBJ_IS_QSTR(str_obj_in)) { str_hash = qstr_hash(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_hash = ((mp_obj_str_t*)str_obj_in)->hash; }
2224
@@ -113,6 +115,75 @@ STATIC mp_obj_t str_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_
113115 }
114116}
115117
118+ STATIC mp_obj_t bytes_make_new (mp_obj_t type_in , uint n_args , uint n_kw , const mp_obj_t * args ) {
119+ if (n_args == 0 ) {
120+ return mp_const_empty_bytes ;
121+ }
122+
123+ if (MP_OBJ_IS_STR (args [0 ])) {
124+ if (n_args < 2 || n_args > 3 ) {
125+ goto wrong_args ;
126+ }
127+ GET_STR_DATA_LEN (args [0 ], str_data , str_len );
128+ GET_STR_HASH (args [0 ], str_hash );
129+ mp_obj_str_t * o = str_new (& bytes_type , NULL , str_len );
130+ o -> data = str_data ;
131+ o -> hash = str_hash ;
132+ return o ;
133+ }
134+
135+ if (n_args > 1 ) {
136+ goto wrong_args ;
137+ }
138+
139+ if (MP_OBJ_IS_SMALL_INT (args [0 ])) {
140+ uint len = MP_OBJ_SMALL_INT_VALUE (args [0 ]);
141+ byte * data ;
142+
143+ mp_obj_t o = mp_obj_str_builder_start (& bytes_type , len , & data );
144+ memset (data , 0 , len );
145+ return mp_obj_str_builder_end (o );
146+ }
147+
148+ int len ;
149+ byte * data ;
150+ vstr_t * vstr = NULL ;
151+ mp_obj_t o = NULL ;
152+ // Try to create array of exact len if initializer len is known
153+ mp_obj_t len_in = mp_obj_len_maybe (args [0 ]);
154+ if (len_in == MP_OBJ_NULL ) {
155+ len = -1 ;
156+ vstr = vstr_new ();
157+ } else {
158+ len = MP_OBJ_SMALL_INT_VALUE (len_in );
159+ o = mp_obj_str_builder_start (& bytes_type , len , & data );
160+ }
161+
162+ mp_obj_t iterable = rt_getiter (args [0 ]);
163+ mp_obj_t item ;
164+ while ((item = rt_iternext (iterable )) != mp_const_stop_iteration ) {
165+ if (len == -1 ) {
166+ vstr_add_char (vstr , MP_OBJ_SMALL_INT_VALUE (item ));
167+ } else {
168+ * data ++ = MP_OBJ_SMALL_INT_VALUE (item );
169+ }
170+ }
171+
172+ if (len == -1 ) {
173+ vstr_shrink (vstr );
174+ // TODO: Optimize, borrow buffer from vstr
175+ len = vstr_len (vstr );
176+ o = mp_obj_str_builder_start (& bytes_type , len , & data );
177+ memcpy (data , vstr_str (vstr ), len );
178+ vstr_free (vstr );
179+ }
180+
181+ return mp_obj_str_builder_end (o );
182+
183+ wrong_args :
184+ nlr_jump (mp_obj_new_exception_msg (& mp_type_TypeError , "wrong number of arguments" ));
185+ }
186+
116187// like strstr but with specified length and allows \0 bytes
117188// TODO replace with something more efficient/standard
118189STATIC const byte * find_subbytes (const byte * haystack , uint hlen , const byte * needle , uint nlen ) {
@@ -666,11 +737,16 @@ const mp_obj_type_t bytes_type = {
666737 { & mp_type_type },
667738 .name = MP_QSTR_bytes ,
668739 .print = str_print ,
740+ .make_new = bytes_make_new ,
669741 .binary_op = str_binary_op ,
670742 .getiter = mp_obj_new_bytes_iterator ,
671743 .methods = str_type_methods ,
672744};
673745
746+ // the zero-length bytes
747+ STATIC const mp_obj_str_t empty_bytes_obj = {{& bytes_type }, 0 , 0 , NULL };
748+ const mp_obj_t mp_const_empty_bytes = (mp_obj_t )& empty_bytes_obj ;
749+
674750mp_obj_t mp_obj_str_builder_start (const mp_obj_type_t * type , uint len , byte * * data ) {
675751 mp_obj_str_t * o = m_new_obj (mp_obj_str_t );
676752 o -> base .type = type ;
@@ -682,7 +758,6 @@ mp_obj_t mp_obj_str_builder_start(const mp_obj_type_t *type, uint len, byte **da
682758}
683759
684760mp_obj_t mp_obj_str_builder_end (mp_obj_t o_in ) {
685- assert (MP_OBJ_IS_STR (o_in ));
686761 mp_obj_str_t * o = o_in ;
687762 o -> hash = qstr_compute_hash (o -> data , o -> len );
688763 byte * p = (byte * )o -> data ;
0 commit comments