STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) { mp_obj_t data = args[0]; mp_buffer_info_t bufinfo; mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); TINF_DATA *decomp = m_new_obj(TINF_DATA); memset(decomp, 0, sizeof(*decomp)); DEBUG_printf("sizeof(TINF_DATA)=" UINT_FMT "\n", sizeof(*decomp)); uzlib_uncompress_init(decomp, NULL, 0); mp_uint_t dest_buf_size = (bufinfo.len + 15) & ~15; byte *dest_buf = m_new(byte, dest_buf_size); decomp->dest = dest_buf; decomp->destSize = dest_buf_size; DEBUG_printf("uzlib: Initial out buffer: " UINT_FMT " bytes\n", decomp->destSize); decomp->source = bufinfo.buf; int st; bool is_zlib = true; if (n_args > 1 && MP_OBJ_SMALL_INT_VALUE(args[1]) < 0) { is_zlib = false; } if (is_zlib) { st = uzlib_zlib_parse_header(decomp); if (st < 0) { goto error; } } while (1) { st = uzlib_uncompress_chksum(decomp); if (st < 0) { goto error; } if (st == TINF_DONE) { break; } size_t offset = decomp->dest - dest_buf; dest_buf = m_renew(byte, dest_buf, dest_buf_size, dest_buf_size + 256); dest_buf_size += 256; decomp->dest = dest_buf + offset; decomp->destSize = 256; } mp_uint_t final_sz = decomp->dest - dest_buf; DEBUG_printf("uzlib: Resizing from " UINT_FMT " to final size: " UINT_FMT " bytes\n", dest_buf_size, final_sz); dest_buf = (byte*)m_renew(byte, dest_buf, dest_buf_size, final_sz); mp_obj_t res = mp_obj_new_bytearray_by_ref(final_sz, dest_buf); m_del_obj(TINF_DATA, decomp); return res; error: nlr_raise(mp_obj_new_exception_arg1(&mp_type_ValueError, MP_OBJ_NEW_SMALL_INT(st))); }
STATIC void indent_push(mp_lexer_t *lex, size_t indent) { if (lex->num_indent_level >= lex->alloc_indent_level) { lex->indent_level = m_renew(uint16_t, lex->indent_level, lex->alloc_indent_level, lex->alloc_indent_level + MICROPY_ALLOC_LEXEL_INDENT_INC); lex->alloc_indent_level += MICROPY_ALLOC_LEXEL_INDENT_INC; } lex->indent_level[lex->num_indent_level++] = indent; }
STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in) { // self is not a memoryview, so we don't need to use (& TYPECODE_MASK) assert((MICROPY_PY_BUILTINS_BYTEARRAY && MP_OBJ_IS_TYPE(self_in, &mp_type_bytearray)) || (MICROPY_PY_ARRAY && MP_OBJ_IS_TYPE(self_in, &mp_type_array))); mp_obj_array_t *self = self_in; // allow to extend by anything that has the buffer protocol (extension to CPython) mp_buffer_info_t arg_bufinfo; mp_get_buffer_raise(arg_in, &arg_bufinfo, MP_BUFFER_READ); size_t sz = mp_binary_get_size('@', self->typecode, NULL); // convert byte count to element count mp_uint_t len = arg_bufinfo.len / sz; // make sure we have enough room to extend // TODO: alloc policy; at the moment we go conservative if (self->free < len) { self->items = m_renew(byte, self->items, (self->len + self->free) * sz, (self->len + len) * sz); self->free = 0; } else { self->free -= len; } // extend mp_seq_copy((byte*)self->items + self->len * sz, arg_bufinfo.buf, len * sz, byte); self->len += len; return mp_const_none; }
void indent_push(mp_lexer_t *lex, uint indent) { if (lex->num_indent_level >= lex->alloc_indent_level) { lex->indent_level = m_renew(uint16_t, lex->indent_level, lex->alloc_indent_level, lex->alloc_indent_level * 2); lex->alloc_indent_level *= 2; } lex->indent_level[lex->num_indent_level++] = indent; }
/****************************************************************************** DEFINE PRIVATE FUNCTIONS ******************************************************************************/ STATIC void hash_update_internal(mp_obj_t self_in, mp_obj_t data, bool digest) { mp_obj_hash_t *self = self_in; mp_buffer_info_t bufinfo; if (data) { mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); } if (digest) { CRYPTOHASH_SHAMD5Start (self->algo, self->b_size); } if (self->c_size < self->b_size || !data || !self->fixedlen) { if (digest || self->fixedlen) { // no data means we want to process our internal buffer CRYPTOHASH_SHAMD5Update (data ? bufinfo.buf : self->buffer, data ? bufinfo.len : self->b_size); self->c_size += data ? bufinfo.len : 0; } else { self->buffer = m_renew(byte, self->buffer, self->b_size, self->b_size + bufinfo.len); mp_seq_copy((byte*)self->buffer + self->b_size, bufinfo.buf, bufinfo.len, byte); self->b_size += bufinfo.len; self->digested = false; } } else { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible)); } }
static void push_result_node(parser_t *parser, mp_parse_node_t pn) { if (parser->result_stack_top >= parser->result_stack_alloc) { parser->result_stack = m_renew(mp_parse_node_t, parser->result_stack, parser->result_stack_alloc, parser->result_stack_alloc * 2); parser->result_stack_alloc *= 2; } parser->result_stack[parser->result_stack_top++] = pn; }
id_info_t *scope_find_or_add_id(scope_t *scope, qstr qst, bool *added) { id_info_t *id_info = scope_find(scope, qst); if (id_info != NULL) { *added = false; return id_info; } // make sure we have enough memory if (scope->id_info_len >= scope->id_info_alloc) { scope->id_info = m_renew(id_info_t, scope->id_info, scope->id_info_alloc, scope->id_info_alloc + MICROPY_ALLOC_SCOPE_ID_INC); scope->id_info_alloc += MICROPY_ALLOC_SCOPE_ID_INC; } // add new id to end of array of all ids; this seems to match CPython // important thing is that function arguments are first, but that is // handled by the compiler because it adds arguments before compiling the body id_info = &scope->id_info[scope->id_info_len++]; id_info->kind = 0; id_info->flags = 0; id_info->local_num = 0; id_info->qst = qst; *added = true; return id_info; }
STATIC mp_obj_t mod_zlibd_decompress(uint n_args, mp_obj_t *args) { mp_obj_t data = args[0]; mp_buffer_info_t bufinfo; mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); tinfl_decompressor *decomp = m_new_obj(tinfl_decompressor); tinfl_init(decomp); DEBUG_printf("sizeof(tinfl_decompressor)=" UINT_FMT "\n", sizeof(tinfl_decompressor)); byte *out = m_new(byte, bufinfo.len); size_t out_len = bufinfo.len; size_t in_buf_ofs = 0, dst_buf_ofs = 0; size_t dst_buf_sz = bufinfo.len; while (1) { size_t in_buf_sz = bufinfo.len - in_buf_ofs; DEBUG_printf("tinfl in: in_ofs=%d in_sz=%d dst_ofs=%d, dst_sz=%d\n", in_buf_ofs, in_buf_sz, dst_buf_ofs, dst_buf_sz); tinfl_status st = tinfl_decompress(decomp, (mz_uint8*) bufinfo.buf + in_buf_ofs, &in_buf_sz, out, out + dst_buf_ofs, &dst_buf_sz, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | TINFL_FLAG_PARSE_ZLIB_HEADER); DEBUG_printf("tinfl out: st=%d, in_sz=%d, out_sz=%d\n", st, in_buf_sz, dst_buf_sz); in_buf_ofs += in_buf_sz; dst_buf_ofs += dst_buf_sz; if (st != TINFL_STATUS_HAS_MORE_OUTPUT) { break; } out = m_renew(byte, out, out_len, dst_buf_ofs + 256); out_len = dst_buf_ofs + 256; dst_buf_sz = out_len - dst_buf_ofs; } m_del_obj(tinfl_decompressor, decomp); return mp_obj_new_bytearray_by_ref(dst_buf_ofs, out); }
STATIC mp_obj_t mod_uzlib_decompress(mp_uint_t n_args, const mp_obj_t *args) { (void)n_args; mp_obj_t data = args[0]; mp_buffer_info_t bufinfo; mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); TINF_DATA *decomp = m_new_obj(TINF_DATA); DEBUG_printf("sizeof(TINF_DATA)=" UINT_FMT "\n", sizeof(*decomp)); decomp->destSize = (bufinfo.len + 15) & ~15; decomp->destStart = m_new(byte, decomp->destSize); DEBUG_printf("uzlib: Initial out buffer: " UINT_FMT " bytes\n", decomp->destSize); decomp->destGrow = mod_uzlib_grow_buf; decomp->source = bufinfo.buf; int st; if (n_args > 1 && MP_OBJ_SMALL_INT_VALUE(args[1]) < 0) { st = tinf_uncompress_dyn(decomp); } else { st = tinf_zlib_uncompress_dyn(decomp, bufinfo.len); } if (st != 0) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_ValueError, MP_OBJ_NEW_SMALL_INT(st))); } mp_uint_t final_sz = decomp->dest - decomp->destStart; DEBUG_printf("uzlib: Resizing from " UINT_FMT " to final size: " UINT_FMT " bytes\n", decomp->destSize, final_sz); decomp->destStart = (byte*)m_renew(byte, decomp->destStart, decomp->destSize, final_sz); mp_obj_t res = mp_obj_new_bytearray_by_ref(final_sz, decomp->destStart); m_del_obj(TINF_DATA, decomp); return res; }
STATIC void esp_socket_recv_callback(void *arg, char *pdata, unsigned short len) { struct espconn *conn = arg; esp_socket_obj_t *s = conn->reverse; if (s->cb_recv != mp_const_none) { call_function_2_protected(s->cb_recv, s, mp_obj_new_bytes((byte *)pdata, len)); } else { if (s->recvbuf == NULL) { s->recvbuf = m_new(uint8_t, len); s->recvbuf_len = len; if (s->recvbuf != NULL) { memcpy(s->recvbuf, pdata, len); } } else { s->recvbuf = m_renew(uint8_t, s->recvbuf, s->recvbuf_len, s->recvbuf_len + len); if (s->recvbuf != NULL) { memcpy(&s->recvbuf[s->recvbuf_len], pdata, len); s->recvbuf_len += len; } } if (s->recvbuf == NULL) { esp_socket_close(s); return; } } }
id_info_t *scope_find_or_add_id(scope_t *scope, qstr qstr, bool *added) { for (int i = 0; i < scope->id_info_len; i++) { if (scope->id_info[i].qstr == qstr) { *added = false; return &scope->id_info[i]; } } // make sure we have enough memory if (scope->id_info_len >= scope->id_info_alloc) { scope->id_info = m_renew(id_info_t, scope->id_info, scope->id_info_alloc, scope->id_info_alloc * 2); scope->id_info_alloc *= 2; } // add new id to end of array of all ids; this seems to match CPython // important thing is that function arguments are first, but that is // handled by the compiler because it adds arguments before compiling the body id_info_t *id_info = &scope->id_info[scope->id_info_len++]; id_info->kind = 0; id_info->flags = 0; id_info->local_num = 0; id_info->qstr = qstr; *added = true; return id_info; }
void indent_push(mp_lexer_t *lex, uint indent) { if (lex->num_indent_level >= lex->alloc_indent_level) { // TODO use m_renew_maybe and somehow indicate an error if it fails... probably by using MP_TOKEN_MEMORY_ERROR lex->indent_level = m_renew(uint16_t, lex->indent_level, lex->alloc_indent_level, lex->alloc_indent_level + MICROPY_ALLOC_LEXEL_INDENT_INC); lex->alloc_indent_level += MICROPY_ALLOC_LEXEL_INDENT_INC; } lex->indent_level[lex->num_indent_level++] = indent; }
STATIC void push_result_node(parser_t *parser, mp_parse_node_t pn) { if (parser->result_stack_top >= parser->result_stack_alloc) { mp_parse_node_t *stack = m_renew(mp_parse_node_t, parser->result_stack, parser->result_stack_alloc, parser->result_stack_alloc + MICROPY_ALLOC_PARSE_RESULT_INC); parser->result_stack = stack; parser->result_stack_alloc += MICROPY_ALLOC_PARSE_RESULT_INC; } parser->result_stack[parser->result_stack_top++] = pn; }
STATIC mp_obj_t list_clear(mp_obj_t self_in) { assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); mp_obj_list_t *self = self_in; self->len = 0; self->items = m_renew(mp_obj_t, self->items, self->alloc, LIST_MIN_ALLOC); self->alloc = LIST_MIN_ALLOC; return mp_const_none; }
static void push_rule(parser_t *parser, const rule_t *rule, int arg_i) { if (parser->rule_stack_top >= parser->rule_stack_alloc) { parser->rule_stack = m_renew(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc, parser->rule_stack_alloc * 2); parser->rule_stack_alloc *= 2; } parser->rule_stack[parser->rule_stack_top].rule_id = rule->rule_id; parser->rule_stack[parser->rule_stack_top].arg_i = arg_i; parser->rule_stack_top += 1; }
STATIC int mod_uzlib_grow_buf(TINF_DATA *d, unsigned alloc_req) { if (alloc_req < 256) { alloc_req = 256; } DEBUG_printf("uzlib: Resizing buffer to " UINT_FMT " bytes\n", d->destSize + alloc_req); d->destStart = m_renew(byte, d->destStart, d->destSize, d->destSize + alloc_req); d->destSize += alloc_req; return 0; }
mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) { assert(MP_OBJ_IS_TYPE(self_in, &list_type)); mp_obj_list_t *self = self_in; if (self->len >= self->alloc) { self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc * 2); self->alloc *= 2; } self->items[self->len++] = arg; return mp_const_none; // return None, as per CPython }
STATIC void push_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t arg_i) { if (parser->rule_stack_top >= parser->rule_stack_alloc) { rule_stack_t *rs = m_renew(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc, parser->rule_stack_alloc + MICROPY_ALLOC_PARSE_RULE_INC); parser->rule_stack = rs; parser->rule_stack_alloc += MICROPY_ALLOC_PARSE_RULE_INC; } rule_stack_t *rs = &parser->rule_stack[parser->rule_stack_top++]; rs->src_line = src_line; rs->rule_id = rule->rule_id; rs->arg_i = arg_i; }
mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) { mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); if (self->len >= self->alloc) { self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc * 2); self->alloc *= 2; mp_seq_clear(self->items, self->len + 1, self->alloc, sizeof(*self->items)); } self->items[self->len++] = arg; return mp_const_none; // return None, as per CPython }
STATIC void mp_emit_glue_alloc_unique_codes(void) { if (unique_codes_total > unique_codes_alloc) { DEBUG_printf("allocate more unique codes: " UINT_FMT " -> %u\n", unique_codes_alloc, unique_codes_total); // increase size of unique_codes table (all new entries are already reserved) unique_codes = m_renew(mp_code_t, unique_codes, unique_codes_alloc, unique_codes_total); for (uint i = unique_codes_alloc; i < unique_codes_total; i++) { unique_codes[i].kind = MP_CODE_RESERVED; } unique_codes_alloc = unique_codes_total; } }
id_info_t *scope_find_or_add_id(scope_t *scope, qstr qstr, bool *added) { for (int i = 0; i < scope->id_info_len; i++) { if (scope->id_info[i].qstr == qstr) { *added = false; return &scope->id_info[i]; } } // make sure we have enough memory if (scope->id_info_len >= scope->id_info_alloc) { scope->id_info = m_renew(id_info_t, scope->id_info, scope->id_info_alloc, scope->id_info_alloc * 2); scope->id_info_alloc *= 2; } id_info_t *id_info; { /* // just pick next slot in array id_info = &scope->id_info[scope->id_info_len++]; */ } if (0) { // sort insert into id_info array, so we are equivalent to CPython (no other reason to do it) // actually, seems that this is not what CPython does... scope->id_info_len += 1; for (int i = scope->id_info_len - 1;; i--) { if (i == 0 || strcmp(qstr_str(scope->id_info[i - 1].qstr), qstr_str(qstr)) < 0) { id_info = &scope->id_info[i]; break; } else { scope->id_info[i] = scope->id_info[i - 1]; } } } else { // just add new id to end of array of all ids; this seems to match CPython // important thing is that function arguments are first, but that is // handled by the compiler because it adds arguments before compiling the body id_info = &scope->id_info[scope->id_info_len++]; } id_info->param = false; id_info->kind = 0; id_info->qstr = qstr; id_info->local_num = 0; *added = true; return id_info; }
STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) { assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); assert(MP_OBJ_IS_TYPE(arg_in, &mp_type_list)); mp_obj_list_t *self = self_in; mp_obj_list_t *arg = arg_in; if (self->len + arg->len > self->alloc) { // TODO: use alloc policy for "4" self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + arg->len + 4); self->alloc = self->len + arg->len + 4; } memcpy(self->items + self->len, arg->items, sizeof(mp_obj_t) * arg->len); self->len += arg->len; return mp_const_none; // return None, as per CPython }
STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg) { // self is not a memoryview, so we don't need to use (& TYPECODE_MASK) assert((MICROPY_PY_BUILTINS_BYTEARRAY && MP_OBJ_IS_TYPE(self_in, &mp_type_bytearray)) || (MICROPY_PY_ARRAY && MP_OBJ_IS_TYPE(self_in, &mp_type_array))); mp_obj_array_t *self = self_in; if (self->free == 0) { size_t item_sz = mp_binary_get_size('@', self->typecode, NULL); // TODO: alloc policy self->free = 8; self->items = m_renew(byte, self->items, item_sz * self->len, item_sz * (self->len + self->free)); mp_seq_clear(self->items, self->len + 1, self->len + self->free, item_sz); } mp_binary_set_val_array(self->typecode, self->items, self->len++, arg); self->free--; return mp_const_none; // return None, as per CPython }
STATIC mp_obj_t list_pop(uint n_args, const mp_obj_t *args) { assert(1 <= n_args && n_args <= 2); assert(MP_OBJ_IS_TYPE(args[0], &mp_type_list)); mp_obj_list_t *self = args[0]; if (self->len == 0) { nlr_jump(mp_obj_new_exception_msg(&mp_type_IndexError, "pop from empty list")); } uint index = mp_get_index(self->base.type, self->len, n_args == 1 ? mp_obj_new_int(-1) : args[1], false); mp_obj_t ret = self->items[index]; self->len -= 1; memcpy(self->items + index, self->items + index + 1, (self->len - index) * sizeof(mp_obj_t)); if (self->alloc > LIST_MIN_ALLOC && self->alloc > 2 * self->len) { self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc/2); self->alloc /= 2; } return ret; }
STATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args) { mp_check_self(MP_OBJ_IS_TYPE(args[0], &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(args[0]); if (self->len == 0) { mp_raise_msg(&mp_type_IndexError, "pop from empty list"); } size_t index = mp_get_index(self->base.type, self->len, n_args == 1 ? MP_OBJ_NEW_SMALL_INT(-1) : args[1], false); mp_obj_t ret = self->items[index]; self->len -= 1; memmove(self->items + index, self->items + index + 1, (self->len - index) * sizeof(mp_obj_t)); // Clear stale pointer from slot which just got freed to prevent GC issues self->items[self->len] = MP_OBJ_NULL; if (self->alloc > LIST_MIN_ALLOC && self->alloc > 2 * self->len) { self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc/2); self->alloc /= 2; } return ret; }
STATIC mp_obj_t list_pop(uint n_args, const mp_obj_t *args) { assert(1 <= n_args && n_args <= 2); assert(MP_OBJ_IS_TYPE(args[0], &mp_type_list)); mp_obj_list_t *self = args[0]; if (self->len == 0) { nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "pop from empty list")); } uint index = mp_get_index(self->base.type, self->len, n_args == 1 ? MP_OBJ_NEW_SMALL_INT(-1) : args[1], false); mp_obj_t ret = self->items[index]; self->len -= 1; memcpy(self->items + index, self->items + index + 1, (self->len - index) * sizeof(mp_obj_t)); // Clear stale pointer from slot which just got freed to prevent GC issues self->items[self->len] = MP_OBJ_NULL; if (self->alloc > LIST_MIN_ALLOC && self->alloc > 2 * self->len) { self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc/2); self->alloc /= 2; } return ret; }
STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) { mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); if (MP_OBJ_IS_TYPE(arg_in, &mp_type_list)) { mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_list_t *arg = MP_OBJ_TO_PTR(arg_in); if (self->len + arg->len > self->alloc) { // TODO: use alloc policy for "4" self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + arg->len + 4); self->alloc = self->len + arg->len + 4; mp_seq_clear(self->items, self->len + arg->len, self->alloc, sizeof(*self->items)); } memcpy(self->items + self->len, arg->items, sizeof(mp_obj_t) * arg->len); self->len += arg->len; } else { list_extend_from_iter(self_in, arg_in); } return mp_const_none; // return None, as per CPython }
STATIC mp_obj_t tuple_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { // TODO check n_kw == 0 switch (n_args) { case 0: // return a empty tuple return mp_const_empty_tuple; case 1: { // 1 argument, an iterable from which we make a new tuple if (MP_OBJ_IS_TYPE(args[0], &tuple_type)) { return args[0]; } // TODO optimise for cases where we know the length of the iterator uint alloc = 4; uint len = 0; mp_obj_t *items = m_new(mp_obj_t, alloc); mp_obj_t iterable = rt_getiter(args[0]); mp_obj_t item; while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) { if (len >= alloc) { items = m_renew(mp_obj_t, items, alloc, alloc * 2); alloc *= 2; } items[len++] = item; } mp_obj_t tuple = mp_obj_new_tuple(len, items); m_free(items, alloc); return tuple; } default: nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "tuple takes at most 1 argument, %d given", n_args)); } }
STATIC mp_obj_t mp_obj_tuple_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; mp_arg_check_num(n_args, n_kw, 0, 1, false); switch (n_args) { case 0: // return a empty tuple return mp_const_empty_tuple; case 1: default: { // 1 argument, an iterable from which we make a new tuple if (MP_OBJ_IS_TYPE(args[0], &mp_type_tuple)) { return args[0]; } // TODO optimise for cases where we know the length of the iterator mp_uint_t alloc = 4; mp_uint_t len = 0; mp_obj_t *items = m_new(mp_obj_t, alloc); mp_obj_t iterable = mp_getiter(args[0]); mp_obj_t item; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { if (len >= alloc) { items = m_renew(mp_obj_t, items, alloc, alloc * 2); alloc *= 2; } items[len++] = item; } mp_obj_t tuple = mp_obj_new_tuple(len, items); m_del(mp_obj_t, items, alloc); return tuple; } } }
// method socket.recv(bufsize) STATIC mp_obj_t esp_socket_recv(mp_obj_t self_in, mp_obj_t len_in) { esp_socket_obj_t *s = self_in; if (s->recvbuf == NULL) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "no data available")); } mp_uint_t mxl = mp_obj_get_int(len_in); if (mxl >= s->recvbuf_len) { mp_obj_t trt = mp_obj_new_bytes(s->recvbuf, s->recvbuf_len); m_del(uint8_t, s->recvbuf, s->recvbuf_len); s->recvbuf = NULL; return trt; } else { mp_obj_t trt = mp_obj_new_bytes(s->recvbuf, mxl); memmove(s->recvbuf, &s->recvbuf[mxl], s->recvbuf_len - mxl); s->recvbuf = m_renew(uint8_t, s->recvbuf, s->recvbuf_len, s->recvbuf_len - mxl); s->recvbuf_len -= mxl; return trt; } }