STATIC mp_obj_t array_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { switch (op) { case MP_BINARY_OP_EQUAL: { mp_buffer_info_t lhs_bufinfo; mp_buffer_info_t rhs_bufinfo; array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ); if (!mp_get_buffer(rhs_in, &rhs_bufinfo, MP_BUFFER_READ)) { return mp_const_false; } return MP_BOOL(mp_seq_cmp_bytes(op, lhs_bufinfo.buf, lhs_bufinfo.len, rhs_bufinfo.buf, rhs_bufinfo.len)); } default: return MP_OBJ_NULL; // op not supported } }
// convert a Micro Python object to a sensible value for inline asm STATIC machine_uint_t convert_obj_for_inline_asm(mp_obj_t obj) { // TODO for byte_array, pass pointer to the array if (MP_OBJ_IS_SMALL_INT(obj)) { return MP_OBJ_SMALL_INT_VALUE(obj); } else if (obj == mp_const_none) { return 0; } else if (obj == mp_const_false) { return 0; } else if (obj == mp_const_true) { return 1; } else if (MP_OBJ_IS_STR(obj)) { // pointer to the string (it's probably constant though!) uint l; return (machine_uint_t)mp_obj_str_get_data(obj, &l); } else { mp_obj_type_t *type = mp_obj_get_type(obj); if (0) { #if MICROPY_PY_BUILTINS_FLOAT } else if (type == &mp_type_float) { // convert float to int (could also pass in float registers) return (machine_int_t)mp_obj_float_get(obj); #endif } else if (type == &mp_type_tuple) { // pointer to start of tuple (could pass length, but then could use len(x) for that) uint len; mp_obj_t *items; mp_obj_tuple_get(obj, &len, &items); return (machine_uint_t)items; } else if (type == &mp_type_list) { // pointer to start of list (could pass length, but then could use len(x) for that) uint len; mp_obj_t *items; mp_obj_list_get(obj, &len, &items); return (machine_uint_t)items; } else { mp_buffer_info_t bufinfo; if (mp_get_buffer(obj, &bufinfo, MP_BUFFER_WRITE)) { // supports the buffer protocol, return a pointer to the data return (machine_uint_t)bufinfo.buf; } else { // just pass along a pointer to the object return (machine_uint_t)obj; } } } }
STATIC mp_obj_t array_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_array_t *lhs = lhs_in; switch (op) { case MP_BINARY_OP_ADD: { // allow to add anything that has the buffer protocol (extension to CPython) mp_buffer_info_t lhs_bufinfo; mp_buffer_info_t rhs_bufinfo; array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ); mp_get_buffer_raise(rhs_in, &rhs_bufinfo, MP_BUFFER_READ); size_t sz = mp_binary_get_size('@', lhs_bufinfo.typecode, NULL); // convert byte count to element count (in case rhs is not multiple of sz) mp_uint_t rhs_len = rhs_bufinfo.len / sz; // note: lhs->len is element count of lhs, lhs_bufinfo.len is byte count mp_obj_array_t *res = array_new(lhs_bufinfo.typecode, lhs->len + rhs_len); mp_seq_cat((byte*)res->items, lhs_bufinfo.buf, lhs_bufinfo.len, rhs_bufinfo.buf, rhs_len * sz, byte); return res; } case MP_BINARY_OP_INPLACE_ADD: { #if MICROPY_PY_BUILTINS_MEMORYVIEW if (lhs->base.type == &mp_type_memoryview) { return MP_OBJ_NULL; // op not supported } #endif array_extend(lhs, rhs_in); return lhs; } case MP_BINARY_OP_EQUAL: { mp_buffer_info_t lhs_bufinfo; mp_buffer_info_t rhs_bufinfo; array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ); if (!mp_get_buffer(rhs_in, &rhs_bufinfo, MP_BUFFER_READ)) { return mp_const_false; } return MP_BOOL(mp_seq_cmp_bytes(op, lhs_bufinfo.buf, lhs_bufinfo.len, rhs_bufinfo.buf, rhs_bufinfo.len)); } default: return MP_OBJ_NULL; // op not supported } }
// convert a MicroPython object to a valid native value based on type mp_uint_t mp_convert_obj_to_native(mp_obj_t obj, mp_uint_t type) { DEBUG_printf("mp_convert_obj_to_native(%p, " UINT_FMT ")\n", obj, type); switch (type & 0xf) { case MP_NATIVE_TYPE_OBJ: return (mp_uint_t)obj; case MP_NATIVE_TYPE_BOOL: case MP_NATIVE_TYPE_INT: case MP_NATIVE_TYPE_UINT: return mp_obj_get_int_truncated(obj); default: { // cast obj to a pointer mp_buffer_info_t bufinfo; if (mp_get_buffer(obj, &bufinfo, MP_BUFFER_RW)) { return (mp_uint_t)bufinfo.buf; } else { // assume obj is an integer that represents an address return mp_obj_get_int_truncated(obj); } } } }
// convert a Micro Python object to a valid native value based on type mp_uint_t mp_convert_obj_to_native(mp_obj_t obj, mp_uint_t type) { DEBUG_printf("mp_convert_obj_to_native(%p, " UINT_FMT ")\n", obj, type); switch (type & 3) { case MP_NATIVE_TYPE_OBJ: return (mp_uint_t)obj; case MP_NATIVE_TYPE_BOOL: case MP_NATIVE_TYPE_INT: return mp_obj_get_int(obj); case MP_NATIVE_TYPE_UINT: { mp_buffer_info_t bufinfo; if (mp_get_buffer(obj, &bufinfo, MP_BUFFER_RW)) { return (mp_uint_t)bufinfo.buf; } else { // TODO should be mp_obj_get_uint_truncated or something return mp_obj_get_int(obj); } } default: assert(0); return 0; } }
STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) { // bytearrays can be raw-initialised from anything with the buffer protocol // other arrays can only be raw-initialised from bytes and bytearray objects mp_buffer_info_t bufinfo; if (((MICROPY_PY_BUILTINS_BYTEARRAY && typecode == BYTEARRAY_TYPECODE) || (MICROPY_PY_ARRAY && (MP_OBJ_IS_TYPE(initializer, &mp_type_bytes) || (MICROPY_PY_BUILTINS_BYTEARRAY && MP_OBJ_IS_TYPE(initializer, &mp_type_bytearray))))) && mp_get_buffer(initializer, &bufinfo, MP_BUFFER_READ)) { // construct array from raw bytes // we round-down the len to make it a multiple of sz (CPython raises error) size_t sz = mp_binary_get_size('@', typecode, NULL); mp_uint_t len = bufinfo.len / sz; mp_obj_array_t *o = array_new(typecode, len); memcpy(o->items, bufinfo.buf, len * sz); return o; } mp_uint_t len; // Try to create array of exact len if initializer len is known mp_obj_t len_in = mp_obj_len_maybe(initializer); if (len_in == MP_OBJ_NULL) { len = 0; } else { len = MP_OBJ_SMALL_INT_VALUE(len_in); } mp_obj_array_t *array = array_new(typecode, len); mp_obj_t iterable = mp_getiter(initializer); mp_obj_t item; mp_uint_t i = 0; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { if (len == 0) { array_append(array, item); } else { mp_binary_set_val_array(typecode, array->items, i++, item); } } return array; }
STATIC mp_obj_t stream_ioctl(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo; uintptr_t val = 0; if (n_args > 2) { if (mp_get_buffer(args[2], &bufinfo, MP_BUFFER_WRITE)) { val = (uintptr_t)bufinfo.buf; } else { val = mp_obj_get_int_truncated(args[2]); } } const mp_stream_p_t *stream_p = mp_get_stream(args[0]); int error; mp_uint_t res = stream_p->ioctl(args[0], mp_obj_get_int(args[1]), val, &error); if (res == MP_STREAM_ERROR) { mp_raise_OSError(error); } return mp_obj_new_int(res); }
STATIC mp_obj_t memoryview_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { (void)type_in; // TODO possibly allow memoryview constructor to take start/stop so that one // can do memoryview(b, 4, 8) instead of memoryview(b)[4:8] (uses less RAM) mp_arg_check_num(n_args, n_kw, 1, 1, false); mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); mp_obj_array_t *self = mp_obj_new_memoryview(bufinfo.typecode, bufinfo.len / mp_binary_get_size('@', bufinfo.typecode, NULL), bufinfo.buf); // test if the object can be written to if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_RW)) { self->typecode |= 0x80; // used to indicate writable buffer } return self; }
void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) { if (!mp_get_buffer(obj, bufinfo, flags)) { nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "object with buffer protocol required")); } }
void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) { if (!mp_get_buffer(obj, bufinfo, flags)) { mp_raise_TypeError("object with buffer protocol required"); } }