@@ -229,22 +229,20 @@ STATIC mp_obj_t array_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in)
229229 mp_obj_array_t * lhs = lhs_in ;
230230 switch (op ) {
231231 case MP_BINARY_OP_ADD : {
232- #if MICROPY_PY_BUILTINS_MEMORYVIEW
233- if (lhs -> base .type == & mp_type_memoryview ) {
234- return MP_OBJ_NULL ; // op not supported
235- }
236- #endif
237- // if we get here then lhs is not a memoryview, so we don't need to use (& TYPECODE_MASK)
238- if (mp_obj_get_type (rhs_in ) != lhs -> base .type ) {
239- return MP_OBJ_NULL ; // op not supported
240- }
241- mp_obj_array_t * rhs = rhs_in ;
242- if (lhs -> typecode != rhs -> typecode ) {
243- return MP_OBJ_NULL ; // op not supported
244- }
245- int sz = mp_binary_get_size ('@' , lhs -> typecode , NULL );
246- mp_obj_array_t * res = array_new (lhs -> typecode , lhs -> len + rhs -> len );
247- mp_seq_cat ((byte * )res -> items , lhs -> items , lhs -> len * sz , rhs -> items , rhs -> len * sz , byte );
232+ // allow to add anything that has the buffer protocol (extension to CPython)
233+ mp_buffer_info_t lhs_bufinfo ;
234+ mp_buffer_info_t rhs_bufinfo ;
235+ array_get_buffer (lhs_in , & lhs_bufinfo , MP_BUFFER_READ );
236+ mp_get_buffer_raise (rhs_in , & rhs_bufinfo , MP_BUFFER_READ );
237+
238+ int sz = mp_binary_get_size ('@' , lhs_bufinfo .typecode , NULL );
239+
240+ // convert byte count to element count (in case rhs is not multiple of sz)
241+ mp_uint_t rhs_len = rhs_bufinfo .len / sz ;
242+
243+ // note: lhs->len is element count of lhs, lhs_bufinfo.len is byte count
244+ mp_obj_array_t * res = array_new (lhs_bufinfo .typecode , lhs -> len + rhs_len );
245+ mp_seq_cat ((byte * )res -> items , lhs_bufinfo .buf , lhs_bufinfo .len , rhs_bufinfo .buf , rhs_len * sz , byte );
248246 return res ;
249247 }
250248
@@ -297,32 +295,27 @@ STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in) {
297295 assert (MP_OBJ_IS_TYPE (self_in , & mp_type_array ) || MP_OBJ_IS_TYPE (self_in , & mp_type_bytearray ));
298296 mp_obj_array_t * self = self_in ;
299297
300- // check for compatible types (array & array, or bytearray & bytearray)
301- if (mp_obj_get_type (arg_in ) != self -> base .type ) {
302- type_error :
303- nlr_raise (mp_obj_new_exception_msg (& mp_type_TypeError ,
304- "incompatible type for array operation" ));
305- }
306-
307- // check for compatible typecode
308- mp_obj_array_t * arg = arg_in ;
309- if (self -> typecode != arg -> typecode ) {
310- goto type_error ;
311- }
298+ // allow to extend by anything that has the buffer protocol (extension to CPython)
299+ mp_buffer_info_t arg_bufinfo ;
300+ mp_get_buffer_raise (arg_in , & arg_bufinfo , MP_BUFFER_READ );
312301
313302 int sz = mp_binary_get_size ('@' , self -> typecode , NULL );
314303
304+ // convert byte count to element count
305+ mp_uint_t len = arg_bufinfo .len / sz ;
306+
315307 // make sure we have enough room to extend
316- if (self -> free < arg -> len ) {
317- // TODO: alloc policy; at the moment we go conservative
318- self -> items = m_realloc (self -> items , (self -> len + self -> free ) * sz , (self -> len + arg -> len ) * sz );
319- self -> free += arg -> len ;
308+ // TODO: alloc policy; at the moment we go conservative
309+ if (self -> free < len ) {
310+ self -> items = m_realloc (self -> items , (self -> len + self -> free ) * sz , (self -> len + len ) * sz );
311+ self -> free = 0 ;
312+ } else {
313+ self -> free -= len ;
320314 }
321315
322316 // extend
323- mp_seq_copy ((byte * )self -> items + self -> len * sz , arg -> items , arg -> len * sz , byte );
324- self -> len += arg -> len ;
325- self -> free -= arg -> len ;
317+ mp_seq_copy ((byte * )self -> items + self -> len * sz , arg_bufinfo .buf , len * sz , byte );
318+ self -> len += len ;
326319
327320 return mp_const_none ;
328321}
0 commit comments