Numworks Epsilon  1.4.1
Graphing Calculator Operating System
objarray.c
Go to the documentation of this file.
1 /*
2  * This file is part of the MicroPython project, http://micropython.org/
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2013, 2014 Damien P. George
7  * Copyright (c) 2014 Paul Sokolovsky
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy
10  * of this software and associated documentation files (the "Software"), to deal
11  * in the Software without restriction, including without limitation the rights
12  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13  * copies of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included in
17  * all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25  * THE SOFTWARE.
26  */
27 
28 #include <string.h>
29 #include <assert.h>
30 #include <stdint.h>
31 
32 #include "py/runtime.h"
33 #include "py/binary.h"
34 #include "py/objstr.h"
35 #include "py/objarray.h"
36 
37 #if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_BUILTINS_MEMORYVIEW
38 
39 // About memoryview object: We want to reuse as much code as possible from
40 // array, and keep the memoryview object 4 words in size so it fits in 1 GC
41 // block. Also, memoryview must keep a pointer to the base of the buffer so
42 // that the buffer is not GC'd if the original parent object is no longer
43 // around (we are assuming that all memoryview'able objects return a pointer
44 // which points to the start of a GC chunk). Given the above constraints we
45 // do the following:
46 // - typecode high bit is set if the buffer is read-write (else read-only)
47 // - free is the offset in elements to the first item in the memoryview
48 // - len is the length in elements
49 // - items points to the start of the original buffer
50 // Note that we don't handle the case where the original buffer might change
51 // size due to a resize of the original parent object.
52 
53 // make (& TYPECODE_MASK) a null operation if memorview not enabled
54 #if MICROPY_PY_BUILTINS_MEMORYVIEW
55 #define TYPECODE_MASK (0x7f)
56 #else
57 #define TYPECODE_MASK (~(size_t)0)
58 #endif
59 
60 STATIC mp_obj_t array_iterator_new(mp_obj_t array_in, mp_obj_iter_buf_t *iter_buf);
61 STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg);
62 STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in);
63 STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags);
64 
65 /******************************************************************************/
66 // array
67 
68 #if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
69 STATIC void array_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
70  (void)kind;
71  mp_obj_array_t *o = MP_OBJ_TO_PTR(o_in);
72  if (o->typecode == BYTEARRAY_TYPECODE) {
73  mp_print_str(print, "bytearray(b");
74  mp_str_print_quoted(print, o->items, o->len, true);
75  } else {
76  mp_printf(print, "array('%c'", o->typecode);
77  if (o->len > 0) {
78  mp_print_str(print, ", [");
79  for (size_t i = 0; i < o->len; i++) {
80  if (i > 0) {
81  mp_print_str(print, ", ");
82  }
84  }
85  mp_print_str(print, "]");
86  }
87  }
88  mp_print_str(print, ")");
89 }
90 #endif
91 
92 #if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
93 STATIC mp_obj_array_t *array_new(char typecode, size_t n) {
94  int typecode_size = mp_binary_get_size('@', typecode, NULL);
96  #if MICROPY_PY_BUILTINS_BYTEARRAY && MICROPY_PY_ARRAY
97  o->base.type = (typecode == BYTEARRAY_TYPECODE) ? &mp_type_bytearray : &mp_type_array;
98  #elif MICROPY_PY_BUILTINS_BYTEARRAY
99  o->base.type = &mp_type_bytearray;
100  #else
101  o->base.type = &mp_type_array;
102  #endif
103  o->typecode = typecode;
104  o->free = 0;
105  o->len = n;
106  o->items = m_new(byte, typecode_size * o->len);
107  return o;
108 }
109 #endif
110 
111 #if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
112 STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) {
113  // bytearrays can be raw-initialised from anything with the buffer protocol
114  // other arrays can only be raw-initialised from bytes and bytearray objects
115  mp_buffer_info_t bufinfo;
117  && typecode == BYTEARRAY_TYPECODE)
118  || (MICROPY_PY_ARRAY
119  && (MP_OBJ_IS_TYPE(initializer, &mp_type_bytes)
121  && mp_get_buffer(initializer, &bufinfo, MP_BUFFER_READ)) {
122  // construct array from raw bytes
123  // we round-down the len to make it a multiple of sz (CPython raises error)
124  size_t sz = mp_binary_get_size('@', typecode, NULL);
125  size_t len = bufinfo.len / sz;
126  mp_obj_array_t *o = array_new(typecode, len);
127  memcpy(o->items, bufinfo.buf, len * sz);
128  return MP_OBJ_FROM_PTR(o);
129  }
130 
131  size_t len;
132  // Try to create array of exact len if initializer len is known
133  mp_obj_t len_in = mp_obj_len_maybe(initializer);
134  if (len_in == MP_OBJ_NULL) {
135  len = 0;
136  } else {
137  len = MP_OBJ_SMALL_INT_VALUE(len_in);
138  }
139 
140  mp_obj_array_t *array = array_new(typecode, len);
141 
142  mp_obj_t iterable = mp_getiter(initializer, NULL);
143  mp_obj_t item;
144  size_t i = 0;
145  while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
146  if (len == 0) {
147  array_append(MP_OBJ_FROM_PTR(array), item);
148  } else {
149  mp_binary_set_val_array(typecode, array->items, i++, item);
150  }
151  }
152 
153  return MP_OBJ_FROM_PTR(array);
154 }
155 #endif
156 
157 #if MICROPY_PY_ARRAY
158 STATIC mp_obj_t array_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
159  (void)type_in;
160  mp_arg_check_num(n_args, n_kw, 1, 2, false);
161 
162  // get typecode
163  const char *typecode = mp_obj_str_get_str(args[0]);
164 
165  if (n_args == 1) {
166  // 1 arg: make an empty array
167  return MP_OBJ_FROM_PTR(array_new(*typecode, 0));
168  } else {
169  // 2 args: construct the array from the given object
170  return array_construct(*typecode, args[1]);
171  }
172 }
173 #endif
174 
175 #if MICROPY_PY_BUILTINS_BYTEARRAY
176 STATIC mp_obj_t bytearray_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
177  (void)type_in;
178  mp_arg_check_num(n_args, n_kw, 0, 1, false);
179 
180  if (n_args == 0) {
181  // no args: construct an empty bytearray
182  return MP_OBJ_FROM_PTR(array_new(BYTEARRAY_TYPECODE, 0));
183  } else if (MP_OBJ_IS_INT(args[0])) {
184  // 1 arg, an integer: construct a blank bytearray of that length
185  mp_uint_t len = mp_obj_get_int(args[0]);
186  mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, len);
187  memset(o->items, 0, len);
188  return MP_OBJ_FROM_PTR(o);
189  } else {
190  // 1 arg: construct the bytearray from that
191  return array_construct(BYTEARRAY_TYPECODE, args[0]);
192  }
193 }
194 #endif
195 
196 #if MICROPY_PY_BUILTINS_MEMORYVIEW
197 
198 mp_obj_t mp_obj_new_memoryview(byte typecode, size_t nitems, void *items) {
200  self->base.type = &mp_type_memoryview;
201  self->typecode = typecode;
202  self->free = 0;
203  self->len = nitems;
204  self->items = items;
205  return MP_OBJ_FROM_PTR(self);
206 }
207 
208 STATIC mp_obj_t memoryview_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
209  (void)type_in;
210 
211  // TODO possibly allow memoryview constructor to take start/stop so that one
212  // can do memoryview(b, 4, 8) instead of memoryview(b)[4:8] (uses less RAM)
213 
214  mp_arg_check_num(n_args, n_kw, 1, 1, false);
215 
216  mp_buffer_info_t bufinfo;
217  mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
218 
220  bufinfo.len / mp_binary_get_size('@', bufinfo.typecode, NULL),
221  bufinfo.buf));
222 
223  // test if the object can be written to
224  if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_RW)) {
225  self->typecode |= 0x80; // used to indicate writable buffer
226  }
227 
228  return MP_OBJ_FROM_PTR(self);
229 }
230 #endif
231 
232 STATIC mp_obj_t array_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
233  mp_obj_array_t *o = MP_OBJ_TO_PTR(o_in);
234  switch (op) {
235  case MP_UNARY_OP_BOOL: return mp_obj_new_bool(o->len != 0);
236  case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(o->len);
237  default: return MP_OBJ_NULL; // op not supported
238  }
239 }
240 
241 STATIC mp_obj_t array_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
242  mp_obj_array_t *lhs = MP_OBJ_TO_PTR(lhs_in);
243  switch (op) {
244  case MP_BINARY_OP_ADD: {
245  // allow to add anything that has the buffer protocol (extension to CPython)
246  mp_buffer_info_t lhs_bufinfo;
247  mp_buffer_info_t rhs_bufinfo;
248  array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ);
249  mp_get_buffer_raise(rhs_in, &rhs_bufinfo, MP_BUFFER_READ);
250 
251  size_t sz = mp_binary_get_size('@', lhs_bufinfo.typecode, NULL);
252 
253  // convert byte count to element count (in case rhs is not multiple of sz)
254  size_t rhs_len = rhs_bufinfo.len / sz;
255 
256  // note: lhs->len is element count of lhs, lhs_bufinfo.len is byte count
257  mp_obj_array_t *res = array_new(lhs_bufinfo.typecode, lhs->len + rhs_len);
258  mp_seq_cat((byte*)res->items, lhs_bufinfo.buf, lhs_bufinfo.len, rhs_bufinfo.buf, rhs_len * sz, byte);
259  return MP_OBJ_FROM_PTR(res);
260  }
261 
263  #if MICROPY_PY_BUILTINS_MEMORYVIEW
264  if (lhs->base.type == &mp_type_memoryview) {
265  return MP_OBJ_NULL; // op not supported
266  }
267  #endif
268  array_extend(lhs_in, rhs_in);
269  return lhs_in;
270  }
271 
272  case MP_BINARY_OP_IN: {
273  /* NOTE `a in b` is `b.__contains__(a)` */
274  mp_buffer_info_t lhs_bufinfo;
275  mp_buffer_info_t rhs_bufinfo;
276 
277  // Can search string only in bytearray
278  if (mp_get_buffer(rhs_in, &rhs_bufinfo, MP_BUFFER_READ)) {
279  if (!MP_OBJ_IS_TYPE(lhs_in, &mp_type_bytearray)) {
280  return mp_const_false;
281  }
282  array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ);
283  return mp_obj_new_bool(
284  find_subbytes(lhs_bufinfo.buf, lhs_bufinfo.len, rhs_bufinfo.buf, rhs_bufinfo.len, 1) != NULL);
285  }
286 
287  // Otherwise, can only look for a scalar numeric value in an array
288  if (MP_OBJ_IS_INT(rhs_in) || mp_obj_is_float(rhs_in)) {
290  }
291 
292  return mp_const_false;
293  }
294 
295  case MP_BINARY_OP_EQUAL: {
296  mp_buffer_info_t lhs_bufinfo;
297  mp_buffer_info_t rhs_bufinfo;
298  array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ);
299  if (!mp_get_buffer(rhs_in, &rhs_bufinfo, MP_BUFFER_READ)) {
300  return mp_const_false;
301  }
302  return mp_obj_new_bool(mp_seq_cmp_bytes(op, lhs_bufinfo.buf, lhs_bufinfo.len, rhs_bufinfo.buf, rhs_bufinfo.len));
303  }
304 
305  default:
306  return MP_OBJ_NULL; // op not supported
307  }
308 }
309 
310 #if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
311 STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg) {
312  // self is not a memoryview, so we don't need to use (& TYPECODE_MASK)
314  || (MICROPY_PY_ARRAY && MP_OBJ_IS_TYPE(self_in, &mp_type_array)));
315  mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in);
316 
317  if (self->free == 0) {
318  size_t item_sz = mp_binary_get_size('@', self->typecode, NULL);
319  // TODO: alloc policy
320  self->free = 8;
321  self->items = m_renew(byte, self->items, item_sz * self->len, item_sz * (self->len + self->free));
322  mp_seq_clear(self->items, self->len + 1, self->len + self->free, item_sz);
323  }
324  mp_binary_set_val_array(self->typecode, self->items, self->len, arg);
325  // only update length/free if set succeeded
326  self->len++;
327  self->free--;
328  return mp_const_none; // return None, as per CPython
329 }
330 STATIC MP_DEFINE_CONST_FUN_OBJ_2(array_append_obj, array_append);
331 
332 STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in) {
333  // self is not a memoryview, so we don't need to use (& TYPECODE_MASK)
335  || (MICROPY_PY_ARRAY && MP_OBJ_IS_TYPE(self_in, &mp_type_array)));
336  mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in);
337 
338  // allow to extend by anything that has the buffer protocol (extension to CPython)
339  mp_buffer_info_t arg_bufinfo;
340  mp_get_buffer_raise(arg_in, &arg_bufinfo, MP_BUFFER_READ);
341 
342  size_t sz = mp_binary_get_size('@', self->typecode, NULL);
343 
344  // convert byte count to element count
345  size_t len = arg_bufinfo.len / sz;
346 
347  // make sure we have enough room to extend
348  // TODO: alloc policy; at the moment we go conservative
349  if (self->free < len) {
350  self->items = m_renew(byte, self->items, (self->len + self->free) * sz, (self->len + len) * sz);
351  self->free = 0;
352  } else {
353  self->free -= len;
354  }
355 
356  // extend
357  mp_seq_copy((byte*)self->items + self->len * sz, arg_bufinfo.buf, len * sz, byte);
358  self->len += len;
359 
360  return mp_const_none;
361 }
362 STATIC MP_DEFINE_CONST_FUN_OBJ_2(array_extend_obj, array_extend);
363 #endif
364 
365 STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) {
366  if (value == MP_OBJ_NULL) {
367  // delete item
368  // TODO implement
369  // TODO: confirmed that both bytearray and array.array support
370  // slice deletion
371  return MP_OBJ_NULL; // op not supported
372  } else {
373  mp_obj_array_t *o = MP_OBJ_TO_PTR(self_in);
374  if (0) {
375 #if MICROPY_PY_BUILTINS_SLICE
376  } else if (MP_OBJ_IS_TYPE(index_in, &mp_type_slice)) {
377  mp_bound_slice_t slice;
378  if (!mp_seq_get_fast_slice_indexes(o->len, index_in, &slice)) {
379  mp_raise_NotImplementedError("only slices with step=1 (aka None) are supported");
380  }
381  if (value != MP_OBJ_SENTINEL) {
382  #if MICROPY_PY_ARRAY_SLICE_ASSIGN
383  // Assign
384  size_t src_len;
385  void *src_items;
386  size_t item_sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);
387  if (MP_OBJ_IS_OBJ(value) && ((mp_obj_base_t*)MP_OBJ_TO_PTR(value))->type->subscr == array_subscr) {
388  // value is array, bytearray or memoryview
389  mp_obj_array_t *src_slice = MP_OBJ_TO_PTR(value);
390  if (item_sz != mp_binary_get_size('@', src_slice->typecode & TYPECODE_MASK, NULL)) {
391  compat_error:
392  mp_raise_ValueError("lhs and rhs should be compatible");
393  }
394  src_len = src_slice->len;
395  src_items = src_slice->items;
396  #if MICROPY_PY_BUILTINS_MEMORYVIEW
397  if (MP_OBJ_IS_TYPE(value, &mp_type_memoryview)) {
398  src_items = (uint8_t*)src_items + (src_slice->free * item_sz);
399  }
400  #endif
401  } else if (MP_OBJ_IS_TYPE(value, &mp_type_bytes)) {
402  if (item_sz != 1) {
403  goto compat_error;
404  }
405  mp_buffer_info_t bufinfo;
406  mp_get_buffer_raise(value, &bufinfo, MP_BUFFER_READ);
407  src_len = bufinfo.len;
408  src_items = bufinfo.buf;
409  } else {
410  mp_raise_NotImplementedError("array/bytes required on right side");
411  }
412 
413  // TODO: check src/dst compat
414  mp_int_t len_adj = src_len - (slice.stop - slice.start);
415  uint8_t* dest_items = o->items;
416  #if MICROPY_PY_BUILTINS_MEMORYVIEW
417  if (o->base.type == &mp_type_memoryview) {
418  if ((o->typecode & 0x80) == 0) {
419  // store to read-only memoryview not allowed
420  return MP_OBJ_NULL;
421  }
422  if (len_adj != 0) {
423  goto compat_error;
424  }
425  dest_items += o->free * item_sz;
426  }
427  #endif
428  if (len_adj > 0) {
429  if (len_adj > o->free) {
430  // TODO: alloc policy; at the moment we go conservative
431  o->items = m_renew(byte, o->items, (o->len + o->free) * item_sz, (o->len + len_adj) * item_sz);
432  o->free = 0;
433  dest_items = o->items;
434  }
435  mp_seq_replace_slice_grow_inplace(dest_items, o->len,
436  slice.start, slice.stop, src_items, src_len, len_adj, item_sz);
437  } else {
438  mp_seq_replace_slice_no_grow(dest_items, o->len,
439  slice.start, slice.stop, src_items, src_len, item_sz);
440  // Clear "freed" elements at the end of list
441  // TODO: This is actually only needed for typecode=='O'
442  mp_seq_clear(dest_items, o->len + len_adj, o->len, item_sz);
443  // TODO: alloc policy after shrinking
444  }
445  o->len += len_adj;
446  return mp_const_none;
447  #else
448  return MP_OBJ_NULL; // op not supported
449  #endif
450  }
451 
452  mp_obj_array_t *res;
453  size_t sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);
454  assert(sz > 0);
455  if (0) {
456  // dummy
457  #if MICROPY_PY_BUILTINS_MEMORYVIEW
458  } else if (o->base.type == &mp_type_memoryview) {
459  res = m_new_obj(mp_obj_array_t);
460  *res = *o;
461  res->free += slice.start;
462  res->len = slice.stop - slice.start;
463  #endif
464  } else {
465  res = array_new(o->typecode, slice.stop - slice.start);
466  memcpy(res->items, (uint8_t*)o->items + slice.start * sz, (slice.stop - slice.start) * sz);
467  }
468  return MP_OBJ_FROM_PTR(res);
469 #endif
470  } else {
471  size_t index = mp_get_index(o->base.type, o->len, index_in, false);
472  #if MICROPY_PY_BUILTINS_MEMORYVIEW
473  if (o->base.type == &mp_type_memoryview) {
474  index += o->free;
475  if (value != MP_OBJ_SENTINEL && (o->typecode & 0x80) == 0) {
476  // store to read-only memoryview
477  return MP_OBJ_NULL;
478  }
479  }
480  #endif
481  if (value == MP_OBJ_SENTINEL) {
482  // load
483  return mp_binary_get_val_array(o->typecode & TYPECODE_MASK, o->items, index);
484  } else {
485  // store
486  mp_binary_set_val_array(o->typecode & TYPECODE_MASK, o->items, index, value);
487  return mp_const_none;
488  }
489  }
490  }
491 }
492 
493 STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
494  mp_obj_array_t *o = MP_OBJ_TO_PTR(o_in);
495  size_t sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);
496  bufinfo->buf = o->items;
497  bufinfo->len = o->len * sz;
498  bufinfo->typecode = o->typecode & TYPECODE_MASK;
499  #if MICROPY_PY_BUILTINS_MEMORYVIEW
500  if (o->base.type == &mp_type_memoryview) {
501  if ((o->typecode & 0x80) == 0 && (flags & MP_BUFFER_WRITE)) {
502  // read-only memoryview
503  return 1;
504  }
505  bufinfo->buf = (uint8_t*)bufinfo->buf + (size_t)o->free * sz;
506  }
507  #else
508  (void)flags;
509  #endif
510  return 0;
511 }
512 
513 #if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
514 STATIC const mp_rom_map_elem_t array_locals_dict_table[] = {
515  { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&array_append_obj) },
516  { MP_ROM_QSTR(MP_QSTR_extend), MP_ROM_PTR(&array_extend_obj) },
517 };
518 
519 STATIC MP_DEFINE_CONST_DICT(array_locals_dict, array_locals_dict_table);
520 #endif
521 
522 #if MICROPY_PY_ARRAY
524  { &mp_type_type },
525  .name = MP_QSTR_array,
526  .print = array_print,
527  .make_new = array_make_new,
528  .getiter = array_iterator_new,
529  .unary_op = array_unary_op,
530  .binary_op = array_binary_op,
531  .subscr = array_subscr,
532  .buffer_p = { .get_buffer = array_get_buffer },
533  .locals_dict = (mp_obj_dict_t*)&array_locals_dict,
534 };
535 #endif
536 
537 #if MICROPY_PY_BUILTINS_BYTEARRAY
539  { &mp_type_type },
540  .name = MP_QSTR_bytearray,
541  .print = array_print,
542  .make_new = bytearray_make_new,
543  .getiter = array_iterator_new,
544  .unary_op = array_unary_op,
545  .binary_op = array_binary_op,
546  .subscr = array_subscr,
547  .buffer_p = { .get_buffer = array_get_buffer },
548  .locals_dict = (mp_obj_dict_t*)&array_locals_dict,
549 };
550 #endif
551 
552 #if MICROPY_PY_BUILTINS_MEMORYVIEW
554  { &mp_type_type },
555  .name = MP_QSTR_memoryview,
556  .make_new = memoryview_make_new,
557  .getiter = array_iterator_new,
558  .unary_op = array_unary_op,
559  .binary_op = array_binary_op,
560  .subscr = array_subscr,
561  .buffer_p = { .get_buffer = array_get_buffer },
562 };
563 #endif
564 
565 /* unused
566 size_t mp_obj_array_len(mp_obj_t self_in) {
567  return ((mp_obj_array_t *)self_in)->len;
568 }
569 */
570 
571 #if MICROPY_PY_BUILTINS_BYTEARRAY
572 mp_obj_t mp_obj_new_bytearray(size_t n, void *items) {
573  mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, n);
574  memcpy(o->items, items, n);
575  return MP_OBJ_FROM_PTR(o);
576 }
577 
578 // Create bytearray which references specified memory area
579 mp_obj_t mp_obj_new_bytearray_by_ref(size_t n, void *items) {
581  o->base.type = &mp_type_bytearray;
583  o->free = 0;
584  o->len = n;
585  o->items = items;
586  return MP_OBJ_FROM_PTR(o);
587 }
588 #endif
589 
590 /******************************************************************************/
591 // array iterator
592 
593 typedef struct _mp_obj_array_it_t {
594  mp_obj_base_t base;
595  mp_obj_array_t *array;
596  size_t offset;
597  size_t cur;
598 } mp_obj_array_it_t;
599 
600 STATIC mp_obj_t array_it_iternext(mp_obj_t self_in) {
601  mp_obj_array_it_t *self = MP_OBJ_TO_PTR(self_in);
602  if (self->cur < self->array->len) {
603  return mp_binary_get_val_array(self->array->typecode & TYPECODE_MASK, self->array->items, self->offset + self->cur++);
604  } else {
605  return MP_OBJ_STOP_ITERATION;
606  }
607 }
608 
609 STATIC const mp_obj_type_t array_it_type = {
610  { &mp_type_type },
611  .name = MP_QSTR_iterator,
612  .getiter = mp_identity_getiter,
613  .iternext = array_it_iternext,
614 };
615 
616 STATIC mp_obj_t array_iterator_new(mp_obj_t array_in, mp_obj_iter_buf_t *iter_buf) {
617  assert(sizeof(mp_obj_array_t) <= sizeof(mp_obj_iter_buf_t));
618  mp_obj_array_t *array = MP_OBJ_TO_PTR(array_in);
619  mp_obj_array_it_t *o = (mp_obj_array_it_t*)iter_buf;
620  o->base.type = &array_it_type;
621  o->array = array;
622  o->offset = 0;
623  o->cur = 0;
624  #if MICROPY_PY_BUILTINS_MEMORYVIEW
625  if (array->base.type == &mp_type_memoryview) {
626  o->offset = array->free;
627  }
628  #endif
629  return MP_OBJ_FROM_PTR(o);
630 }
631 
632 #endif // MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_BUILTINS_MEMORYVIEW
size_t free
Definition: objarray.h:37
intptr_t mp_int_t
Definition: mpconfigport.h:73
#define MP_BUFFER_WRITE
Definition: obj.h:455
uintptr_t mp_uint_t
Definition: mpconfigport.h:74
#define mp_seq_clear(start, len, alloc_len, item_sz)
Definition: obj.h:856
#define MP_BUFFER_READ
Definition: obj.h:454
void * memset(void *b, int c, size_t len)
Definition: memset.c:3
mp_uint_t stop
Definition: obj.h:840
#define assert(e)
Definition: assert.h:9
const mp_obj_type_t mp_type_bytearray
#define mp_const_none
Definition: obj.h:614
#define MP_DEFINE_CONST_DICT(dict_name, table_name)
Definition: obj.h:317
NORETURN void mp_raise_NotImplementedError(const char *msg)
Definition: runtime.c:1468
mp_obj_t mp_obj_new_memoryview(byte typecode, size_t nitems, void *items)
const mp_obj_type_t mp_type_memoryview
#define MP_OBJ_IS_TYPE(o, t)
Definition: obj.h:254
#define MICROPY_PY_BUILTINS_BYTEARRAY
Definition: mpconfigport.h:35
bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags)
Definition: obj.c:512
bool mp_seq_cmp_bytes(mp_uint_t op, const byte *data1, size_t len1, const byte *data2, size_t len2)
Definition: sequence.c:150
#define MP_OBJ_SENTINEL
Definition: obj.h:75
int mp_print_str(const mp_print_t *print, const char *str)
Definition: mpprint.c:53
#define MP_ROM_QSTR(q)
Definition: obj.h:241
#define MP_OBJ_FROM_PTR(p)
Definition: obj.h:233
size_t mp_binary_get_size(char struct_type, char val_type, mp_uint_t *palign)
Definition: binary.c:44
void mp_arg_check_num(size_t n_args, size_t n_kw, size_t n_args_min, size_t n_args_max, bool takes_kw)
Definition: argcheck.c:32
#define MP_ROM_PTR(p)
Definition: obj.h:242
#define MICROPY_PY_ARRAY
Definition: mpconfigport.h:45
#define BYTEARRAY_TYPECODE
Definition: binary.h:34
void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, size_t str_len, bool is_bytes)
Definition: objstr.c:45
const mp_obj_type_t mp_type_bytes
Definition: objstr.c:1964
size_t len
Definition: obj.h:447
mp_obj_t mp_obj_new_bytearray(size_t n, void *items)
unsigned char uint8_t
Definition: stdint.h:4
mp_unary_op_t
Definition: runtime0.h:45
mp_int_t mp_obj_get_int(mp_const_obj_t arg)
Definition: obj.c:225
#define STATIC
Definition: mpconfig.h:1178
const mp_obj_type_t mp_type_array
#define MP_OBJ_SMALL_INT_VALUE(o)
Definition: obj.h:86
#define mp_obj_is_float(o)
Definition: obj.h:745
size_t mp_get_index(const mp_obj_type_t *type, size_t len, mp_obj_t index, bool is_slice)
Definition: obj.c:376
mp_obj_t mp_obj_len_maybe(mp_obj_t o_in)
Definition: obj.c:448
mp_print_kind_t
Definition: obj.h:412
#define MP_OBJ_NEW_SMALL_INT(small_int)
Definition: obj.h:87
#define NULL
Definition: stddef.h:4
#define MP_OBJ_NULL
Definition: obj.h:73
size_t typecode
Definition: objarray.h:34
void mp_binary_set_val_array(char typecode, void *p, mp_uint_t index, mp_obj_t val_in)
Definition: binary.c:317
void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind)
Definition: obj.c:59
#define MP_BUFFER_RW
Definition: obj.h:456
mp_binary_op_t
Definition: runtime0.h:67
mp_obj_t mp_binary_get_val_array(char typecode, void *p, mp_uint_t index)
Definition: binary.c:115
const byte * find_subbytes(const byte *haystack, size_t hlen, const byte *needle, size_t nlen, int direction)
Definition: objstr.c:263
args
Definition: i18n.py:175
#define MP_OBJ_IS_INT(o)
Definition: obj.h:255
#define mp_seq_replace_slice_no_grow(dest, dest_len, beg, end, slice, slice_len, item_sz)
Definition: obj.h:857
unsigned char byte
Definition: misc.h:37
mp_obj_t mp_obj_new_bytearray_by_ref(size_t n, void *items)
const mp_obj_type_t mp_type_type
Definition: objtype.c:969
#define m_renew(type, ptr, old_num, new_num)
Definition: misc.h:75
#define MP_DEFINE_CONST_FUN_OBJ_2(obj_name, fun_name)
Definition: obj.h:288
NORETURN void mp_raise_ValueError(const char *msg)
Definition: runtime.c:1456
mp_obj_t mp_identity_getiter(mp_obj_t self, mp_obj_iter_buf_t *iter_buf)
Definition: obj.c:507
void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags)
Definition: obj.c:524
#define mp_seq_copy(dest, src, len, item_t)
Definition: obj.h:848
const char * mp_obj_str_get_str(mp_obj_t self_in)
Definition: objstr.c:2095
const mp_obj_type_t mp_type_slice
#define MP_OBJ_TO_PTR(o)
Definition: obj.h:228
#define mp_seq_replace_slice_grow_inplace(dest, dest_len, beg, end, slice, slice_len, len_adj, item_sz)
Definition: obj.h:864
mp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf)
Definition: runtime.c:1120
mp_uint_t start
Definition: obj.h:839
int typecode
Definition: obj.h:448
qstr name
Definition: obj.h:478
#define MP_OBJ_STOP_ITERATION
Definition: obj.h:74
void * items
Definition: objarray.h:39
uint64_t mp_obj_t
Definition: obj.h:39
mp_obj_t mp_iternext(mp_obj_t o_in)
Definition: runtime.c:1186
int mp_printf(const mp_print_t *print, const char *fmt,...)
Definition: mpprint.c:380
mp_obj_base_t base
Definition: objarray.h:33
#define m_new_obj(type)
Definition: misc.h:60
size_t len
Definition: objarray.h:38
void * memcpy(void *dst, const void *src, size_t n)
Definition: memcpy.c:3
void * buf
Definition: obj.h:446
#define m_new(type, num)
Definition: misc.h:57
#define mp_const_false
Definition: obj.h:615
#define mp_seq_cat(dest, src1, len1, src2, len2, item_t)
Definition: obj.h:849