blob: c19617d4e1dd64566aff07eb404a46a027401c4b [file] [log] [blame]
Damien George04b91472014-05-03 23:27:38 +01001/*
Alexander Steffen55f33242017-06-30 09:22:17 +02002 * This file is part of the MicroPython project, http://micropython.org/
Damien George04b91472014-05-03 23:27:38 +01003 *
4 * The MIT License (MIT)
5 *
6 * Copyright (c) 2013, 2014 Damien P. George
Paul Sokolovskyda9f0922014-05-13 08:44:45 +03007 * Copyright (c) 2014 Paul Sokolovsky
Damien George04b91472014-05-03 23:27:38 +01008 *
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
Paul Sokolovsky427905c2014-01-18 19:24:47 +020028#include <string.h>
Paul Sokolovsky427905c2014-01-18 19:24:47 +020029#include <assert.h>
stijn49c47da2014-10-28 17:20:52 +010030#include <stdint.h>
Paul Sokolovsky427905c2014-01-18 19:24:47 +020031
Damien George51dfcb42015-01-01 20:27:54 +000032#include "py/runtime.h"
33#include "py/binary.h"
Paul Sokolovskyc38809e2016-02-14 18:55:16 +020034#include "py/objstr.h"
Paul Sokolovskyec7fe922016-07-06 18:18:46 +030035#include "py/objarray.h"
Paul Sokolovsky427905c2014-01-18 19:24:47 +020036
Damien Georgedd4f4532014-10-23 13:34:35 +010037#if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_BUILTINS_MEMORYVIEW
Paul Sokolovskycb78f862014-06-27 20:39:09 +030038
Damien Georgede3c8062014-10-26 13:20:50 +000039// 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
Damien Georgede3c8062014-10-26 13:20:50 +000053#if MICROPY_PY_BUILTINS_MEMORYVIEW
54#define TYPECODE_MASK (0x7f)
Paul Sokolovskya261d8b2018-09-16 13:41:30 +030055#define memview_offset free
Damien Georgede3c8062014-10-26 13:20:50 +000056#else
Paul Sokolovskya261d8b2018-09-16 13:41:30 +030057// make (& TYPECODE_MASK) a null operation if memorview not enabled
Damien Georgeccc52542017-02-16 16:31:43 +110058#define TYPECODE_MASK (~(size_t)0)
Paul Sokolovskya261d8b2018-09-16 13:41:30 +030059// memview_offset should not be accessed if memoryview is not enabled,
60// so not defined to catch errors
Damien Georgede3c8062014-10-26 13:20:50 +000061#endif
62
Damien Georgeae8d8672016-01-09 23:14:54 +000063STATIC mp_obj_t array_iterator_new(mp_obj_t array_in, mp_obj_iter_buf_t *iter_buf);
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +020064STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg);
Damien Georgeb2e73112014-11-30 00:00:55 +000065STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in);
Damien George4d917232014-08-30 14:28:06 +010066STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags);
Paul Sokolovsky427905c2014-01-18 19:24:47 +020067
68/******************************************************************************/
Damien Georgedd4f4532014-10-23 13:34:35 +010069// array
Paul Sokolovsky427905c2014-01-18 19:24:47 +020070
Damien Georgedd4f4532014-10-23 13:34:35 +010071#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
Damien George7f9d1d62015-04-09 23:56:15 +010072STATIC void array_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
Damien Georgeff8dd3f2015-01-20 12:47:20 +000073 (void)kind;
Damien George999cedb2015-11-27 17:01:44 +000074 mp_obj_array_t *o = MP_OBJ_TO_PTR(o_in);
Paul Sokolovsky427905c2014-01-18 19:24:47 +020075 if (o->typecode == BYTEARRAY_TYPECODE) {
Damien George7f9d1d62015-04-09 23:56:15 +010076 mp_print_str(print, "bytearray(b");
77 mp_str_print_quoted(print, o->items, o->len, true);
Paul Sokolovsky427905c2014-01-18 19:24:47 +020078 } else {
Damien George7f9d1d62015-04-09 23:56:15 +010079 mp_printf(print, "array('%c'", o->typecode);
Paul Sokolovsky18014212014-01-28 03:40:48 +020080 if (o->len > 0) {
Damien George7f9d1d62015-04-09 23:56:15 +010081 mp_print_str(print, ", [");
Damien Georgeccc52542017-02-16 16:31:43 +110082 for (size_t i = 0; i < o->len; i++) {
Paul Sokolovsky18014212014-01-28 03:40:48 +020083 if (i > 0) {
Damien George7f9d1d62015-04-09 23:56:15 +010084 mp_print_str(print, ", ");
Paul Sokolovsky18014212014-01-28 03:40:48 +020085 }
Damien George7f9d1d62015-04-09 23:56:15 +010086 mp_obj_print_helper(print, mp_binary_get_val_array(o->typecode, o->items, i), PRINT_REPR);
Paul Sokolovsky7e652af2014-01-28 03:14:20 +020087 }
Damien George7f9d1d62015-04-09 23:56:15 +010088 mp_print_str(print, "]");
Paul Sokolovsky427905c2014-01-18 19:24:47 +020089 }
Paul Sokolovsky427905c2014-01-18 19:24:47 +020090 }
Damien George7f9d1d62015-04-09 23:56:15 +010091 mp_print_str(print, ")");
Paul Sokolovsky427905c2014-01-18 19:24:47 +020092}
Damien Georgedd4f4532014-10-23 13:34:35 +010093#endif
Paul Sokolovsky427905c2014-01-18 19:24:47 +020094
Damien Georgedd4f4532014-10-23 13:34:35 +010095#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
Damien Georgeccc52542017-02-16 16:31:43 +110096STATIC mp_obj_array_t *array_new(char typecode, size_t n) {
Damien Georgedd4f4532014-10-23 13:34:35 +010097 int typecode_size = mp_binary_get_size('@', typecode, NULL);
Damien Georgedd4f4532014-10-23 13:34:35 +010098 mp_obj_array_t *o = m_new_obj(mp_obj_array_t);
99 #if MICROPY_PY_BUILTINS_BYTEARRAY && MICROPY_PY_ARRAY
100 o->base.type = (typecode == BYTEARRAY_TYPECODE) ? &mp_type_bytearray : &mp_type_array;
101 #elif MICROPY_PY_BUILTINS_BYTEARRAY
102 o->base.type = &mp_type_bytearray;
103 #else
104 o->base.type = &mp_type_array;
105 #endif
106 o->typecode = typecode;
107 o->free = 0;
108 o->len = n;
Damien George4d77e1a2015-02-27 09:34:51 +0000109 o->items = m_new(byte, typecode_size * o->len);
Damien Georgedd4f4532014-10-23 13:34:35 +0100110 return o;
111}
112#endif
113
114#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200115STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) {
Damien George32ef3a32014-12-04 15:46:14 +0000116 // bytearrays can be raw-initialised from anything with the buffer protocol
117 // other arrays can only be raw-initialised from bytes and bytearray objects
118 mp_buffer_info_t bufinfo;
119 if (((MICROPY_PY_BUILTINS_BYTEARRAY
120 && typecode == BYTEARRAY_TYPECODE)
121 || (MICROPY_PY_ARRAY
Damien Georgeeee1e882019-01-30 18:49:52 +1100122 && (mp_obj_is_type(initializer, &mp_type_bytes)
123 || (MICROPY_PY_BUILTINS_BYTEARRAY && mp_obj_is_type(initializer, &mp_type_bytearray)))))
Damien George32ef3a32014-12-04 15:46:14 +0000124 && mp_get_buffer(initializer, &bufinfo, MP_BUFFER_READ)) {
125 // construct array from raw bytes
126 // we round-down the len to make it a multiple of sz (CPython raises error)
Kaspar Schleiserf5dd6f72015-05-10 13:04:38 +0200127 size_t sz = mp_binary_get_size('@', typecode, NULL);
Damien Georgeccc52542017-02-16 16:31:43 +1100128 size_t len = bufinfo.len / sz;
Damien George32ef3a32014-12-04 15:46:14 +0000129 mp_obj_array_t *o = array_new(typecode, len);
130 memcpy(o->items, bufinfo.buf, len * sz);
Damien George999cedb2015-11-27 17:01:44 +0000131 return MP_OBJ_FROM_PTR(o);
Damien George32ef3a32014-12-04 15:46:14 +0000132 }
133
Damien Georgeccc52542017-02-16 16:31:43 +1100134 size_t len;
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200135 // Try to create array of exact len if initializer len is known
136 mp_obj_t len_in = mp_obj_len_maybe(initializer);
137 if (len_in == MP_OBJ_NULL) {
138 len = 0;
139 } else {
140 len = MP_OBJ_SMALL_INT_VALUE(len_in);
141 }
142
143 mp_obj_array_t *array = array_new(typecode, len);
144
Damien Georgee6003f42017-02-13 15:44:31 +1100145 mp_obj_t iterable = mp_getiter(initializer, NULL);
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200146 mp_obj_t item;
Damien Georgeccc52542017-02-16 16:31:43 +1100147 size_t i = 0;
Damien Georgeea8d06c2014-04-17 23:19:36 +0100148 while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200149 if (len == 0) {
Damien George999cedb2015-11-27 17:01:44 +0000150 array_append(MP_OBJ_FROM_PTR(array), item);
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200151 } else {
Paul Sokolovskyef9124f2014-04-11 03:46:09 +0300152 mp_binary_set_val_array(typecode, array->items, i++, item);
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200153 }
154 }
155
Damien George999cedb2015-11-27 17:01:44 +0000156 return MP_OBJ_FROM_PTR(array);
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200157}
Damien Georgedd4f4532014-10-23 13:34:35 +0100158#endif
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200159
Damien Georgedd4f4532014-10-23 13:34:35 +0100160#if MICROPY_PY_ARRAY
Damien George5b3f0b72016-01-03 15:55:55 +0000161STATIC 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) {
Damien Georgeff8dd3f2015-01-20 12:47:20 +0000162 (void)type_in;
Damien Georgea3f94e02014-04-20 00:13:22 +0100163 mp_arg_check_num(n_args, n_kw, 1, 2, false);
Damien George32ca1642014-04-18 22:04:06 +0100164
165 // get typecode
Damien Georgeab5689b2017-03-25 19:53:31 +1100166 const char *typecode = mp_obj_str_get_str(args[0]);
Paul Sokolovsky11973b42014-01-28 02:31:52 +0200167
Damien George32ca1642014-04-18 22:04:06 +0100168 if (n_args == 1) {
169 // 1 arg: make an empty array
Damien George999cedb2015-11-27 17:01:44 +0000170 return MP_OBJ_FROM_PTR(array_new(*typecode, 0));
Damien George32ca1642014-04-18 22:04:06 +0100171 } else {
Damien George32ef3a32014-12-04 15:46:14 +0000172 // 2 args: construct the array from the given object
Damien George32ca1642014-04-18 22:04:06 +0100173 return array_construct(*typecode, args[1]);
174 }
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200175}
Damien Georgedd4f4532014-10-23 13:34:35 +0100176#endif
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200177
Damien Georgedd4f4532014-10-23 13:34:35 +0100178#if MICROPY_PY_BUILTINS_BYTEARRAY
Damien George5b3f0b72016-01-03 15:55:55 +0000179STATIC 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) {
Damien Georgeff8dd3f2015-01-20 12:47:20 +0000180 (void)type_in;
Paul Sokolovsky674e0692018-09-03 21:52:35 +0300181 // Can take 2nd/3rd arg if constructs from str
182 mp_arg_check_num(n_args, n_kw, 0, 3, false);
Paul Sokolovsky4dcb6052014-04-08 22:09:14 +0300183
Damien George32ca1642014-04-18 22:04:06 +0100184 if (n_args == 0) {
185 // no args: construct an empty bytearray
Damien George999cedb2015-11-27 17:01:44 +0000186 return MP_OBJ_FROM_PTR(array_new(BYTEARRAY_TYPECODE, 0));
Damien Georgeeee1e882019-01-30 18:49:52 +1100187 } else if (mp_obj_is_int(args[0])) {
Damien George32ca1642014-04-18 22:04:06 +0100188 // 1 arg, an integer: construct a blank bytearray of that length
Paul Sokolovsky343ca1e2015-01-04 17:19:16 +0200189 mp_uint_t len = mp_obj_get_int(args[0]);
Paul Sokolovskyb9cf3d32014-04-08 04:42:44 +0300190 mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, len);
191 memset(o->items, 0, len);
Damien George999cedb2015-11-27 17:01:44 +0000192 return MP_OBJ_FROM_PTR(o);
Damien George32ca1642014-04-18 22:04:06 +0100193 } else {
Damien George32ef3a32014-12-04 15:46:14 +0000194 // 1 arg: construct the bytearray from that
Damien George32ca1642014-04-18 22:04:06 +0100195 return array_construct(BYTEARRAY_TYPECODE, args[0]);
Paul Sokolovskyb9cf3d32014-04-08 04:42:44 +0300196 }
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200197}
Damien Georgedd4f4532014-10-23 13:34:35 +0100198#endif
199
200#if MICROPY_PY_BUILTINS_MEMORYVIEW
Paul Sokolovskycb0fc062015-03-06 21:35:26 +0200201
Damien Georgeccc52542017-02-16 16:31:43 +1100202mp_obj_t mp_obj_new_memoryview(byte typecode, size_t nitems, void *items) {
Paul Sokolovskycb0fc062015-03-06 21:35:26 +0200203 mp_obj_array_t *self = m_new_obj(mp_obj_array_t);
204 self->base.type = &mp_type_memoryview;
205 self->typecode = typecode;
Paul Sokolovskya261d8b2018-09-16 13:41:30 +0300206 self->memview_offset = 0;
Paul Sokolovskycb0fc062015-03-06 21:35:26 +0200207 self->len = nitems;
208 self->items = items;
Damien George999cedb2015-11-27 17:01:44 +0000209 return MP_OBJ_FROM_PTR(self);
Paul Sokolovskycb0fc062015-03-06 21:35:26 +0200210}
211
Damien George5b3f0b72016-01-03 15:55:55 +0000212STATIC 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) {
Damien George2e2e4042015-03-19 00:21:29 +0000213 (void)type_in;
214
Damien Georgedd4f4532014-10-23 13:34:35 +0100215 // TODO possibly allow memoryview constructor to take start/stop so that one
216 // can do memoryview(b, 4, 8) instead of memoryview(b)[4:8] (uses less RAM)
217
218 mp_arg_check_num(n_args, n_kw, 1, 1, false);
219
220 mp_buffer_info_t bufinfo;
221 mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
222
Damien George999cedb2015-11-27 17:01:44 +0000223 mp_obj_array_t *self = MP_OBJ_TO_PTR(mp_obj_new_memoryview(bufinfo.typecode,
Paul Sokolovskycb0fc062015-03-06 21:35:26 +0200224 bufinfo.len / mp_binary_get_size('@', bufinfo.typecode, NULL),
Damien George999cedb2015-11-27 17:01:44 +0000225 bufinfo.buf));
Damien Georgedd4f4532014-10-23 13:34:35 +0100226
227 // test if the object can be written to
228 if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_RW)) {
Damien Georgec00ee202018-06-18 13:40:53 +1000229 self->typecode |= MP_OBJ_ARRAY_TYPECODE_FLAG_RW; // indicate writable buffer
Damien Georgedd4f4532014-10-23 13:34:35 +0100230 }
231
Damien George999cedb2015-11-27 17:01:44 +0000232 return MP_OBJ_FROM_PTR(self);
Damien Georgedd4f4532014-10-23 13:34:35 +0100233}
stijn90fae912019-05-08 16:16:17 +0200234
235#if MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE
236STATIC void memoryview_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
237 if (dest[0] != MP_OBJ_NULL) {
238 return;
239 }
240 if (attr == MP_QSTR_itemsize) {
241 mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in);
242 dest[0] = MP_OBJ_NEW_SMALL_INT(mp_binary_get_size('@', self->typecode & TYPECODE_MASK, NULL));
243 }
244}
245#endif
246
Damien Georgedd4f4532014-10-23 13:34:35 +0100247#endif
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200248
Damien George58321dd2017-08-29 13:04:01 +1000249STATIC mp_obj_t array_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
Damien George999cedb2015-11-27 17:01:44 +0000250 mp_obj_array_t *o = MP_OBJ_TO_PTR(o_in);
Paul Sokolovskyc1d9bbc2014-01-30 04:37:19 +0200251 switch (op) {
Paul Sokolovsky1b586f32015-10-11 12:09:43 +0300252 case MP_UNARY_OP_BOOL: return mp_obj_new_bool(o->len != 0);
Damien Georged17926d2014-03-30 13:35:08 +0100253 case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(o->len);
Damien George6ac5dce2014-05-21 19:42:43 +0100254 default: return MP_OBJ_NULL; // op not supported
Paul Sokolovskyc1d9bbc2014-01-30 04:37:19 +0200255 }
256}
257
Damien George58321dd2017-08-29 13:04:01 +1000258STATIC mp_obj_t array_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
Damien George999cedb2015-11-27 17:01:44 +0000259 mp_obj_array_t *lhs = MP_OBJ_TO_PTR(lhs_in);
Paul Sokolovsky5f930332014-08-10 11:49:23 +0300260 switch (op) {
Damien Georgeb2e73112014-11-30 00:00:55 +0000261 case MP_BINARY_OP_ADD: {
Damien Georgec7ca01a2014-11-30 14:01:33 +0000262 // allow to add anything that has the buffer protocol (extension to CPython)
263 mp_buffer_info_t lhs_bufinfo;
264 mp_buffer_info_t rhs_bufinfo;
265 array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ);
266 mp_get_buffer_raise(rhs_in, &rhs_bufinfo, MP_BUFFER_READ);
267
Kaspar Schleiserf5dd6f72015-05-10 13:04:38 +0200268 size_t sz = mp_binary_get_size('@', lhs_bufinfo.typecode, NULL);
Damien Georgec7ca01a2014-11-30 14:01:33 +0000269
270 // convert byte count to element count (in case rhs is not multiple of sz)
Damien Georgeccc52542017-02-16 16:31:43 +1100271 size_t rhs_len = rhs_bufinfo.len / sz;
Damien Georgec7ca01a2014-11-30 14:01:33 +0000272
273 // note: lhs->len is element count of lhs, lhs_bufinfo.len is byte count
274 mp_obj_array_t *res = array_new(lhs_bufinfo.typecode, lhs->len + rhs_len);
275 mp_seq_cat((byte*)res->items, lhs_bufinfo.buf, lhs_bufinfo.len, rhs_bufinfo.buf, rhs_len * sz, byte);
Damien George999cedb2015-11-27 17:01:44 +0000276 return MP_OBJ_FROM_PTR(res);
Damien Georgeb2e73112014-11-30 00:00:55 +0000277 }
278
279 case MP_BINARY_OP_INPLACE_ADD: {
280 #if MICROPY_PY_BUILTINS_MEMORYVIEW
281 if (lhs->base.type == &mp_type_memoryview) {
282 return MP_OBJ_NULL; // op not supported
283 }
284 #endif
Damien George999cedb2015-11-27 17:01:44 +0000285 array_extend(lhs_in, rhs_in);
286 return lhs_in;
Damien Georgeb2e73112014-11-30 00:00:55 +0000287 }
288
Damien George5e34a112017-11-24 13:04:24 +1100289 case MP_BINARY_OP_CONTAINS: {
Damien Georgea785a3d2018-08-14 16:23:21 +1000290 #if MICROPY_PY_BUILTINS_BYTEARRAY
291 // Can search string only in bytearray
Paul Sokolovskyc38809e2016-02-14 18:55:16 +0200292 mp_buffer_info_t lhs_bufinfo;
293 mp_buffer_info_t rhs_bufinfo;
Paul Sokolovskyc38809e2016-02-14 18:55:16 +0200294 if (mp_get_buffer(rhs_in, &rhs_bufinfo, MP_BUFFER_READ)) {
Damien Georgeeee1e882019-01-30 18:49:52 +1100295 if (!mp_obj_is_type(lhs_in, &mp_type_bytearray)) {
Paul Sokolovskyc38809e2016-02-14 18:55:16 +0200296 return mp_const_false;
297 }
298 array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ);
299 return mp_obj_new_bool(
300 find_subbytes(lhs_bufinfo.buf, lhs_bufinfo.len, rhs_bufinfo.buf, rhs_bufinfo.len, 1) != NULL);
301 }
Damien Georgea785a3d2018-08-14 16:23:21 +1000302 #endif
Paul Sokolovskyc38809e2016-02-14 18:55:16 +0200303
304 // Otherwise, can only look for a scalar numeric value in an array
Damien Georgeeee1e882019-01-30 18:49:52 +1100305 if (mp_obj_is_int(rhs_in) || mp_obj_is_float(rhs_in)) {
Damien Georgef4059dc2017-10-24 22:39:36 +1100306 mp_raise_NotImplementedError(NULL);
Paul Sokolovskyc38809e2016-02-14 18:55:16 +0200307 }
308
309 return mp_const_false;
310 }
311
Paul Sokolovsky5f930332014-08-10 11:49:23 +0300312 case MP_BINARY_OP_EQUAL: {
313 mp_buffer_info_t lhs_bufinfo;
314 mp_buffer_info_t rhs_bufinfo;
315 array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ);
316 if (!mp_get_buffer(rhs_in, &rhs_bufinfo, MP_BUFFER_READ)) {
Damien Georgede3c8062014-10-26 13:20:50 +0000317 return mp_const_false;
Paul Sokolovsky5f930332014-08-10 11:49:23 +0300318 }
Paul Sokolovsky1b586f32015-10-11 12:09:43 +0300319 return mp_obj_new_bool(mp_seq_cmp_bytes(op, lhs_bufinfo.buf, lhs_bufinfo.len, rhs_bufinfo.buf, rhs_bufinfo.len));
Paul Sokolovsky5f930332014-08-10 11:49:23 +0300320 }
Damien Georgeb2e73112014-11-30 00:00:55 +0000321
Paul Sokolovsky5f930332014-08-10 11:49:23 +0300322 default:
323 return MP_OBJ_NULL; // op not supported
324 }
325}
326
Damien Georgeb2e73112014-11-30 00:00:55 +0000327#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200328STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg) {
Damien Georgeb2e73112014-11-30 00:00:55 +0000329 // self is not a memoryview, so we don't need to use (& TYPECODE_MASK)
Damien Georgeeee1e882019-01-30 18:49:52 +1100330 assert((MICROPY_PY_BUILTINS_BYTEARRAY && mp_obj_is_type(self_in, &mp_type_bytearray))
331 || (MICROPY_PY_ARRAY && mp_obj_is_type(self_in, &mp_type_array)));
Damien George999cedb2015-11-27 17:01:44 +0000332 mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in);
Damien Georgeb2e73112014-11-30 00:00:55 +0000333
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200334 if (self->free == 0) {
Kaspar Schleiserf5dd6f72015-05-10 13:04:38 +0200335 size_t item_sz = mp_binary_get_size('@', self->typecode, NULL);
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200336 // TODO: alloc policy
337 self->free = 8;
Damien George4d77e1a2015-02-27 09:34:51 +0000338 self->items = m_renew(byte, self->items, item_sz * self->len, item_sz * (self->len + self->free));
Paul Sokolovskya2240672014-04-28 00:16:57 +0300339 mp_seq_clear(self->items, self->len + 1, self->len + self->free, item_sz);
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200340 }
Damien George04d5e642016-04-07 09:03:33 +0100341 mp_binary_set_val_array(self->typecode, self->items, self->len, arg);
342 // only update length/free if set succeeded
343 self->len++;
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200344 self->free--;
345 return mp_const_none; // return None, as per CPython
346}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200347STATIC MP_DEFINE_CONST_FUN_OBJ_2(array_append_obj, array_append);
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200348
Damien Georgeb2e73112014-11-30 00:00:55 +0000349STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in) {
350 // self is not a memoryview, so we don't need to use (& TYPECODE_MASK)
Damien Georgeeee1e882019-01-30 18:49:52 +1100351 assert((MICROPY_PY_BUILTINS_BYTEARRAY && mp_obj_is_type(self_in, &mp_type_bytearray))
352 || (MICROPY_PY_ARRAY && mp_obj_is_type(self_in, &mp_type_array)));
Damien George999cedb2015-11-27 17:01:44 +0000353 mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in);
Damien Georgeb2e73112014-11-30 00:00:55 +0000354
Damien Georgec7ca01a2014-11-30 14:01:33 +0000355 // allow to extend by anything that has the buffer protocol (extension to CPython)
356 mp_buffer_info_t arg_bufinfo;
357 mp_get_buffer_raise(arg_in, &arg_bufinfo, MP_BUFFER_READ);
Damien Georgeb2e73112014-11-30 00:00:55 +0000358
Kaspar Schleiserf5dd6f72015-05-10 13:04:38 +0200359 size_t sz = mp_binary_get_size('@', self->typecode, NULL);
Damien Georgeb2e73112014-11-30 00:00:55 +0000360
Damien Georgec7ca01a2014-11-30 14:01:33 +0000361 // convert byte count to element count
Damien Georgeccc52542017-02-16 16:31:43 +1100362 size_t len = arg_bufinfo.len / sz;
Damien Georgec7ca01a2014-11-30 14:01:33 +0000363
Damien Georgeb2e73112014-11-30 00:00:55 +0000364 // make sure we have enough room to extend
Damien Georgec7ca01a2014-11-30 14:01:33 +0000365 // TODO: alloc policy; at the moment we go conservative
366 if (self->free < len) {
Damien George4d77e1a2015-02-27 09:34:51 +0000367 self->items = m_renew(byte, self->items, (self->len + self->free) * sz, (self->len + len) * sz);
Damien Georgec7ca01a2014-11-30 14:01:33 +0000368 self->free = 0;
369 } else {
370 self->free -= len;
Damien Georgeb2e73112014-11-30 00:00:55 +0000371 }
372
373 // extend
Damien Georgec7ca01a2014-11-30 14:01:33 +0000374 mp_seq_copy((byte*)self->items + self->len * sz, arg_bufinfo.buf, len * sz, byte);
375 self->len += len;
Damien Georgeb2e73112014-11-30 00:00:55 +0000376
377 return mp_const_none;
378}
379STATIC MP_DEFINE_CONST_FUN_OBJ_2(array_extend_obj, array_extend);
380#endif
381
Damien George729f7b42014-04-17 22:10:53 +0100382STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) {
Damien Georgef4c9b332014-04-08 21:32:29 +0100383 if (value == MP_OBJ_NULL) {
Damien George32ca1642014-04-18 22:04:06 +0100384 // delete item
385 // TODO implement
Paul Sokolovsky26905252014-04-20 20:58:33 +0300386 // TODO: confirmed that both bytearray and array.array support
387 // slice deletion
Damien George6ac5dce2014-05-21 19:42:43 +0100388 return MP_OBJ_NULL; // op not supported
Damien George729f7b42014-04-17 22:10:53 +0100389 } else {
Damien George999cedb2015-11-27 17:01:44 +0000390 mp_obj_array_t *o = MP_OBJ_TO_PTR(self_in);
Damien Georgec49ddb92014-06-01 13:49:35 +0100391#if MICROPY_PY_BUILTINS_SLICE
Jun Wu089c9b72019-05-04 20:29:43 -0700392 if (mp_obj_is_type(index_in, &mp_type_slice)) {
Paul Sokolovskyde4b9322014-05-25 21:21:57 +0300393 mp_bound_slice_t slice;
394 if (!mp_seq_get_fast_slice_indexes(o->len, index_in, &slice)) {
Javier Candeira35a1fea2017-08-09 14:40:45 +1000395 mp_raise_NotImplementedError("only slices with step=1 (aka None) are supported");
Paul Sokolovskyd6e12722014-04-19 20:06:57 +0300396 }
Paul Sokolovskycefcbb22015-02-27 22:16:05 +0200397 if (value != MP_OBJ_SENTINEL) {
398 #if MICROPY_PY_ARRAY_SLICE_ASSIGN
399 // Assign
Damien Georgeccc52542017-02-16 16:31:43 +1100400 size_t src_len;
Paul Sokolovsky56beb012015-04-16 00:48:36 +0300401 void *src_items;
Delio Brignoli32aba402015-06-03 07:07:35 +0200402 size_t item_sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);
Damien Georgeeee1e882019-01-30 18:49:52 +1100403 if (mp_obj_is_obj(value) && ((mp_obj_base_t*)MP_OBJ_TO_PTR(value))->type->subscr == array_subscr) {
Damien George4915c2b2015-07-20 16:12:26 +0100404 // value is array, bytearray or memoryview
Damien George999cedb2015-11-27 17:01:44 +0000405 mp_obj_array_t *src_slice = MP_OBJ_TO_PTR(value);
Delio Brignoli32aba402015-06-03 07:07:35 +0200406 if (item_sz != mp_binary_get_size('@', src_slice->typecode & TYPECODE_MASK, NULL)) {
Paul Sokolovsky56beb012015-04-16 00:48:36 +0300407 compat_error:
Damien George94c41bb2017-03-28 22:37:26 +1100408 mp_raise_ValueError("lhs and rhs should be compatible");
Paul Sokolovsky56beb012015-04-16 00:48:36 +0300409 }
410 src_len = src_slice->len;
411 src_items = src_slice->items;
Damien George4915c2b2015-07-20 16:12:26 +0100412 #if MICROPY_PY_BUILTINS_MEMORYVIEW
Damien Georgeeee1e882019-01-30 18:49:52 +1100413 if (mp_obj_is_type(value, &mp_type_memoryview)) {
Paul Sokolovskya261d8b2018-09-16 13:41:30 +0300414 src_items = (uint8_t*)src_items + (src_slice->memview_offset * item_sz);
Damien George4915c2b2015-07-20 16:12:26 +0100415 }
416 #endif
Damien Georgeeee1e882019-01-30 18:49:52 +1100417 } else if (mp_obj_is_type(value, &mp_type_bytes)) {
Paul Sokolovsky56beb012015-04-16 00:48:36 +0300418 if (item_sz != 1) {
419 goto compat_error;
420 }
421 mp_buffer_info_t bufinfo;
422 mp_get_buffer_raise(value, &bufinfo, MP_BUFFER_READ);
423 src_len = bufinfo.len;
424 src_items = bufinfo.buf;
425 } else {
Javier Candeira35a1fea2017-08-09 14:40:45 +1000426 mp_raise_NotImplementedError("array/bytes required on right side");
Paul Sokolovskycefcbb22015-02-27 22:16:05 +0200427 }
428
429 // TODO: check src/dst compat
Paul Sokolovsky56beb012015-04-16 00:48:36 +0300430 mp_int_t len_adj = src_len - (slice.stop - slice.start);
Delio Brignoli6a388aa2015-06-06 20:14:08 +0200431 uint8_t* dest_items = o->items;
432 #if MICROPY_PY_BUILTINS_MEMORYVIEW
433 if (o->base.type == &mp_type_memoryview) {
Damien Georgec00ee202018-06-18 13:40:53 +1000434 if (!(o->typecode & MP_OBJ_ARRAY_TYPECODE_FLAG_RW)) {
Damien Georgef4a12dc2017-02-27 16:09:57 +1100435 // store to read-only memoryview not allowed
436 return MP_OBJ_NULL;
437 }
Delio Brignoli6a388aa2015-06-06 20:14:08 +0200438 if (len_adj != 0) {
Delio Brignoli32aba402015-06-03 07:07:35 +0200439 goto compat_error;
440 }
Paul Sokolovskya261d8b2018-09-16 13:41:30 +0300441 dest_items += o->memview_offset * item_sz;
Delio Brignoli6a388aa2015-06-06 20:14:08 +0200442 }
443 #endif
444 if (len_adj > 0) {
Paul Sokolovskycefcbb22015-02-27 22:16:05 +0200445 if (len_adj > o->free) {
446 // TODO: alloc policy; at the moment we go conservative
Damien Georged8914522015-02-27 09:54:12 +0000447 o->items = m_renew(byte, o->items, (o->len + o->free) * item_sz, (o->len + len_adj) * item_sz);
Damien Georgeacfbb9f2019-08-15 23:02:04 +1000448 o->free = len_adj;
Damien George77f85db2016-03-14 23:12:54 +0000449 dest_items = o->items;
Paul Sokolovskycefcbb22015-02-27 22:16:05 +0200450 }
Delio Brignoli6a388aa2015-06-06 20:14:08 +0200451 mp_seq_replace_slice_grow_inplace(dest_items, o->len,
Paul Sokolovsky56beb012015-04-16 00:48:36 +0300452 slice.start, slice.stop, src_items, src_len, len_adj, item_sz);
Paul Sokolovskycefcbb22015-02-27 22:16:05 +0200453 } else {
Delio Brignoli6a388aa2015-06-06 20:14:08 +0200454 mp_seq_replace_slice_no_grow(dest_items, o->len,
455 slice.start, slice.stop, src_items, src_len, item_sz);
456 // Clear "freed" elements at the end of list
457 // TODO: This is actually only needed for typecode=='O'
458 mp_seq_clear(dest_items, o->len + len_adj, o->len, item_sz);
459 // TODO: alloc policy after shrinking
Paul Sokolovskycefcbb22015-02-27 22:16:05 +0200460 }
Damien Georgeacfbb9f2019-08-15 23:02:04 +1000461 o->free -= len_adj;
Paul Sokolovskycefcbb22015-02-27 22:16:05 +0200462 o->len += len_adj;
463 return mp_const_none;
464 #else
465 return MP_OBJ_NULL; // op not supported
466 #endif
467 }
468
Damien Georgedd4f4532014-10-23 13:34:35 +0100469 mp_obj_array_t *res;
Kaspar Schleiserf5dd6f72015-05-10 13:04:38 +0200470 size_t sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);
Paul Sokolovskyd6e12722014-04-19 20:06:57 +0300471 assert(sz > 0);
Damien Georgedd4f4532014-10-23 13:34:35 +0100472 #if MICROPY_PY_BUILTINS_MEMORYVIEW
Jun Wu089c9b72019-05-04 20:29:43 -0700473 if (o->base.type == &mp_type_memoryview) {
Damien Georgedd4f4532014-10-23 13:34:35 +0100474 res = m_new_obj(mp_obj_array_t);
475 *res = *o;
Paul Sokolovskya261d8b2018-09-16 13:41:30 +0300476 res->memview_offset += slice.start;
Damien Georgedd4f4532014-10-23 13:34:35 +0100477 res->len = slice.stop - slice.start;
Jun Wu089c9b72019-05-04 20:29:43 -0700478 } else
Damien Georgedd4f4532014-10-23 13:34:35 +0100479 #endif
Jun Wu089c9b72019-05-04 20:29:43 -0700480 {
Damien Georgedd4f4532014-10-23 13:34:35 +0100481 res = array_new(o->typecode, slice.stop - slice.start);
stijn49c47da2014-10-28 17:20:52 +0100482 memcpy(res->items, (uint8_t*)o->items + slice.start * sz, (slice.stop - slice.start) * sz);
Damien Georgedd4f4532014-10-23 13:34:35 +0100483 }
Damien George999cedb2015-11-27 17:01:44 +0000484 return MP_OBJ_FROM_PTR(res);
Jun Wu089c9b72019-05-04 20:29:43 -0700485 } else
Damien Georgec49ddb92014-06-01 13:49:35 +0100486#endif
Jun Wu089c9b72019-05-04 20:29:43 -0700487 {
Damien Georgec88cfe12017-03-23 16:17:40 +1100488 size_t index = mp_get_index(o->base.type, o->len, index_in, false);
Damien Georgede3c8062014-10-26 13:20:50 +0000489 #if MICROPY_PY_BUILTINS_MEMORYVIEW
490 if (o->base.type == &mp_type_memoryview) {
Paul Sokolovskya261d8b2018-09-16 13:41:30 +0300491 index += o->memview_offset;
Damien Georgec00ee202018-06-18 13:40:53 +1000492 if (value != MP_OBJ_SENTINEL && !(o->typecode & MP_OBJ_ARRAY_TYPECODE_FLAG_RW)) {
Damien Georgede3c8062014-10-26 13:20:50 +0000493 // store to read-only memoryview
Damien Georgedd4f4532014-10-23 13:34:35 +0100494 return MP_OBJ_NULL;
495 }
Damien Georgede3c8062014-10-26 13:20:50 +0000496 }
497 #endif
498 if (value == MP_OBJ_SENTINEL) {
499 // load
500 return mp_binary_get_val_array(o->typecode & TYPECODE_MASK, o->items, index);
501 } else {
502 // store
503 mp_binary_set_val_array(o->typecode & TYPECODE_MASK, o->items, index, value);
Paul Sokolovskyd6e12722014-04-19 20:06:57 +0300504 return mp_const_none;
505 }
Damien George729f7b42014-04-17 22:10:53 +0100506 }
Damien Georgef4c9b332014-04-08 21:32:29 +0100507 }
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200508}
509
Damien George4d917232014-08-30 14:28:06 +0100510STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
Damien George999cedb2015-11-27 17:01:44 +0000511 mp_obj_array_t *o = MP_OBJ_TO_PTR(o_in);
Kaspar Schleiserf5dd6f72015-05-10 13:04:38 +0200512 size_t sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);
Damien Georgede3c8062014-10-26 13:20:50 +0000513 bufinfo->buf = o->items;
514 bufinfo->len = o->len * sz;
515 bufinfo->typecode = o->typecode & TYPECODE_MASK;
Damien Georgedd4f4532014-10-23 13:34:35 +0100516 #if MICROPY_PY_BUILTINS_MEMORYVIEW
Damien Georgede3c8062014-10-26 13:20:50 +0000517 if (o->base.type == &mp_type_memoryview) {
Damien Georgec00ee202018-06-18 13:40:53 +1000518 if (!(o->typecode & MP_OBJ_ARRAY_TYPECODE_FLAG_RW) && (flags & MP_BUFFER_WRITE)) {
Damien Georgede3c8062014-10-26 13:20:50 +0000519 // read-only memoryview
520 return 1;
521 }
Paul Sokolovskya261d8b2018-09-16 13:41:30 +0300522 bufinfo->buf = (uint8_t*)bufinfo->buf + (size_t)o->memview_offset * sz;
Damien Georgedd4f4532014-10-23 13:34:35 +0100523 }
Damien George3a2171e2015-09-04 16:53:46 +0100524 #else
525 (void)flags;
Damien Georgedd4f4532014-10-23 13:34:35 +0100526 #endif
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200527 return 0;
528}
529
Damien Georgedd4f4532014-10-23 13:34:35 +0100530#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
Damien Georgecbf76742015-11-27 13:38:15 +0000531STATIC const mp_rom_map_elem_t array_locals_dict_table[] = {
532 { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&array_append_obj) },
533 { MP_ROM_QSTR(MP_QSTR_extend), MP_ROM_PTR(&array_extend_obj) },
stijnfb547362019-05-20 10:35:31 +0200534 #if MICROPY_CPYTHON_COMPAT
535 { MP_ROM_QSTR(MP_QSTR_decode), MP_ROM_PTR(&bytes_decode_obj) },
536 #endif
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200537};
538
Damien George9b196cd2014-03-26 21:47:19 +0000539STATIC MP_DEFINE_CONST_DICT(array_locals_dict, array_locals_dict_table);
Damien Georgedd4f4532014-10-23 13:34:35 +0100540#endif
Damien George9b196cd2014-03-26 21:47:19 +0000541
Damien Georgedd4f4532014-10-23 13:34:35 +0100542#if MICROPY_PY_ARRAY
Damien Georgecaac5422014-03-25 14:18:18 +0000543const mp_obj_type_t mp_type_array = {
Damien Georgec5966122014-02-15 16:10:44 +0000544 { &mp_type_type },
Damien Georgea71c83a2014-02-15 11:34:50 +0000545 .name = MP_QSTR_array,
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200546 .print = array_print,
547 .make_new = array_make_new,
Paul Sokolovsky09ce0592014-01-21 23:45:19 +0200548 .getiter = array_iterator_new,
Paul Sokolovskyc1d9bbc2014-01-30 04:37:19 +0200549 .unary_op = array_unary_op,
Paul Sokolovsky5f930332014-08-10 11:49:23 +0300550 .binary_op = array_binary_op,
Damien George729f7b42014-04-17 22:10:53 +0100551 .subscr = array_subscr,
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200552 .buffer_p = { .get_buffer = array_get_buffer },
Damien George999cedb2015-11-27 17:01:44 +0000553 .locals_dict = (mp_obj_dict_t*)&array_locals_dict,
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200554};
Damien Georgedd4f4532014-10-23 13:34:35 +0100555#endif
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200556
Damien Georgedd4f4532014-10-23 13:34:35 +0100557#if MICROPY_PY_BUILTINS_BYTEARRAY
Paul Sokolovsky4dcb6052014-04-08 22:09:14 +0300558const mp_obj_type_t mp_type_bytearray = {
559 { &mp_type_type },
560 .name = MP_QSTR_bytearray,
561 .print = array_print,
562 .make_new = bytearray_make_new,
563 .getiter = array_iterator_new,
564 .unary_op = array_unary_op,
Paul Sokolovsky5f930332014-08-10 11:49:23 +0300565 .binary_op = array_binary_op,
Damien George729f7b42014-04-17 22:10:53 +0100566 .subscr = array_subscr,
Paul Sokolovsky4dcb6052014-04-08 22:09:14 +0300567 .buffer_p = { .get_buffer = array_get_buffer },
Damien George999cedb2015-11-27 17:01:44 +0000568 .locals_dict = (mp_obj_dict_t*)&array_locals_dict,
Paul Sokolovsky4dcb6052014-04-08 22:09:14 +0300569};
Damien Georgedd4f4532014-10-23 13:34:35 +0100570#endif
Paul Sokolovsky4dcb6052014-04-08 22:09:14 +0300571
Damien Georgedd4f4532014-10-23 13:34:35 +0100572#if MICROPY_PY_BUILTINS_MEMORYVIEW
573const mp_obj_type_t mp_type_memoryview = {
574 { &mp_type_type },
575 .name = MP_QSTR_memoryview,
576 .make_new = memoryview_make_new,
577 .getiter = array_iterator_new,
578 .unary_op = array_unary_op,
579 .binary_op = array_binary_op,
stijn90fae912019-05-08 16:16:17 +0200580 #if MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE
581 .attr = memoryview_attr,
582 #endif
Damien Georgedd4f4532014-10-23 13:34:35 +0100583 .subscr = array_subscr,
584 .buffer_p = { .get_buffer = array_get_buffer },
585};
586#endif
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200587
Damien Georgedd4f4532014-10-23 13:34:35 +0100588/* unused
Damien Georgeccc52542017-02-16 16:31:43 +1100589size_t mp_obj_array_len(mp_obj_t self_in) {
Paul Sokolovsky33996682014-01-21 23:30:10 +0200590 return ((mp_obj_array_t *)self_in)->len;
591}
Damien Georgedd4f4532014-10-23 13:34:35 +0100592*/
Paul Sokolovsky33996682014-01-21 23:30:10 +0200593
Damien Georgedd4f4532014-10-23 13:34:35 +0100594#if MICROPY_PY_BUILTINS_BYTEARRAY
Damien Georgeccc52542017-02-16 16:31:43 +1100595mp_obj_t mp_obj_new_bytearray(size_t n, void *items) {
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200596 mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, n);
597 memcpy(o->items, items, n);
Damien George999cedb2015-11-27 17:01:44 +0000598 return MP_OBJ_FROM_PTR(o);
Paul Sokolovsky427905c2014-01-18 19:24:47 +0200599}
Paul Sokolovsky09ce0592014-01-21 23:45:19 +0200600
Paul Sokolovsky7f11c792014-01-29 00:21:41 +0200601// Create bytearray which references specified memory area
Damien Georgeccc52542017-02-16 16:31:43 +1100602mp_obj_t mp_obj_new_bytearray_by_ref(size_t n, void *items) {
Paul Sokolovsky7f11c792014-01-29 00:21:41 +0200603 mp_obj_array_t *o = m_new_obj(mp_obj_array_t);
Damien Georgedd4f4532014-10-23 13:34:35 +0100604 o->base.type = &mp_type_bytearray;
Paul Sokolovsky7f11c792014-01-29 00:21:41 +0200605 o->typecode = BYTEARRAY_TYPECODE;
606 o->free = 0;
607 o->len = n;
608 o->items = items;
Damien George999cedb2015-11-27 17:01:44 +0000609 return MP_OBJ_FROM_PTR(o);
Paul Sokolovsky7f11c792014-01-29 00:21:41 +0200610}
Damien Georgedd4f4532014-10-23 13:34:35 +0100611#endif
Paul Sokolovsky7f11c792014-01-29 00:21:41 +0200612
Paul Sokolovsky09ce0592014-01-21 23:45:19 +0200613/******************************************************************************/
Damien Georgedd4f4532014-10-23 13:34:35 +0100614// array iterator
Paul Sokolovsky09ce0592014-01-21 23:45:19 +0200615
616typedef struct _mp_obj_array_it_t {
617 mp_obj_base_t base;
618 mp_obj_array_t *array;
Damien Georgeccc52542017-02-16 16:31:43 +1100619 size_t offset;
620 size_t cur;
Paul Sokolovsky09ce0592014-01-21 23:45:19 +0200621} mp_obj_array_it_t;
622
Damien Georgecaac5422014-03-25 14:18:18 +0000623STATIC mp_obj_t array_it_iternext(mp_obj_t self_in) {
Damien George999cedb2015-11-27 17:01:44 +0000624 mp_obj_array_it_t *self = MP_OBJ_TO_PTR(self_in);
Paul Sokolovsky09ce0592014-01-21 23:45:19 +0200625 if (self->cur < self->array->len) {
Damien Georgede3c8062014-10-26 13:20:50 +0000626 return mp_binary_get_val_array(self->array->typecode & TYPECODE_MASK, self->array->items, self->offset + self->cur++);
Paul Sokolovsky09ce0592014-01-21 23:45:19 +0200627 } else {
Damien Georgeea8d06c2014-04-17 23:19:36 +0100628 return MP_OBJ_STOP_ITERATION;
Paul Sokolovsky09ce0592014-01-21 23:45:19 +0200629 }
630}
631
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200632STATIC const mp_obj_type_t array_it_type = {
Damien Georgec5966122014-02-15 16:10:44 +0000633 { &mp_type_type },
Damien Georgea71c83a2014-02-15 11:34:50 +0000634 .name = MP_QSTR_iterator,
Damien Georgeae8d8672016-01-09 23:14:54 +0000635 .getiter = mp_identity_getiter,
Paul Sokolovsky09ce0592014-01-21 23:45:19 +0200636 .iternext = array_it_iternext,
637};
638
Damien Georgeae8d8672016-01-09 23:14:54 +0000639STATIC mp_obj_t array_iterator_new(mp_obj_t array_in, mp_obj_iter_buf_t *iter_buf) {
640 assert(sizeof(mp_obj_array_t) <= sizeof(mp_obj_iter_buf_t));
Damien George999cedb2015-11-27 17:01:44 +0000641 mp_obj_array_t *array = MP_OBJ_TO_PTR(array_in);
Damien Georgeae8d8672016-01-09 23:14:54 +0000642 mp_obj_array_it_t *o = (mp_obj_array_it_t*)iter_buf;
Paul Sokolovsky09ce0592014-01-21 23:45:19 +0200643 o->base.type = &array_it_type;
644 o->array = array;
Damien Georgeae8d8672016-01-09 23:14:54 +0000645 o->offset = 0;
646 o->cur = 0;
Damien Georgede3c8062014-10-26 13:20:50 +0000647 #if MICROPY_PY_BUILTINS_MEMORYVIEW
648 if (array->base.type == &mp_type_memoryview) {
Paul Sokolovskya261d8b2018-09-16 13:41:30 +0300649 o->offset = array->memview_offset;
Damien Georgede3c8062014-10-26 13:20:50 +0000650 }
651 #endif
Damien George999cedb2015-11-27 17:01:44 +0000652 return MP_OBJ_FROM_PTR(o);
Paul Sokolovsky09ce0592014-01-21 23:45:19 +0200653}
Paul Sokolovskycb78f862014-06-27 20:39:09 +0300654
Damien Georgedd4f4532014-10-23 13:34:35 +0100655#endif // MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_BUILTINS_MEMORYVIEW