static mp_obj_t str_find(uint n_args, const mp_obj_t *args) { assert(2 <= n_args && n_args <= 4); assert(MP_OBJ_IS_STR(args[0])); assert(MP_OBJ_IS_STR(args[1])); GET_STR_DATA_LEN(args[0], haystack, haystack_len); GET_STR_DATA_LEN(args[1], needle, needle_len); size_t start = 0; size_t end = haystack_len; /* TODO use a non-exception-throwing mp_get_index */ if (n_args >= 3 && args[2] != mp_const_none) { start = mp_get_index(&str_type, haystack_len, args[2]); } if (n_args >= 4 && args[3] != mp_const_none) { end = mp_get_index(&str_type, haystack_len, args[3]); } const byte *p = find_subbytes(haystack + start, haystack_len - start, needle, needle_len); if (p == NULL) { // not found return MP_OBJ_NEW_SMALL_INT(-1); } else { // found machine_int_t pos = p - haystack; if (pos + needle_len > end) { pos = -1; } return MP_OBJ_NEW_SMALL_INT(pos); } }
// this function implements the '==' operator (and so the inverse of '!=') // from the python language reference: // "The objects need not have the same type. If both are numbers, they are converted // to a common type. Otherwise, the == and != operators always consider objects of // different types to be unequal." // note also that False==0 and True==1 are true expressions bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) { if (o1 == o2) { return true; } if (o1 == mp_const_none || o2 == mp_const_none) { return false; } // fast path for small ints if (MP_OBJ_IS_SMALL_INT(o1)) { if (MP_OBJ_IS_SMALL_INT(o2)) { // both SMALL_INT, and not equal if we get here return false; } else { mp_obj_t temp = o2; o2 = o1; o1 = temp; // o2 is now the SMALL_INT, o1 is not // fall through to generic op } } // fast path for strings if (MP_OBJ_IS_STR(o1)) { if (MP_OBJ_IS_STR(o2)) { // both strings, use special function return mp_obj_str_equal(o1, o2); } else { // a string is never equal to anything else return false; } } else if (MP_OBJ_IS_STR(o2)) { // o1 is not a string (else caught above), so the objects are not equal return false; } // generic type, call binary_op(MP_BINARY_OP_EQUAL) mp_obj_type_t *type = mp_obj_get_type(o1); if (type->binary_op != NULL) { mp_obj_t r = type->binary_op(MP_BINARY_OP_EQUAL, o1, o2); if (r != MP_OBJ_NULL) { return r == mp_const_true ? true : false; } } if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError, "equality for given types not yet implemented")); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_NotImplementedError, "equality for '%s' and '%s' types not yet implemented", mp_obj_get_type_str(o1), mp_obj_get_type_str(o2))); } }
mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { assert(MP_OBJ_IS_STR(self_in)); // get separation string GET_STR_DATA_LEN(self_in, sep_str, sep_len); // process args uint seq_len; mp_obj_t *seq_items; if (MP_OBJ_IS_TYPE(arg, &tuple_type)) { mp_obj_tuple_get(arg, &seq_len, &seq_items); } else if (MP_OBJ_IS_TYPE(arg, &list_type)) { mp_obj_list_get(arg, &seq_len, &seq_items); } else { goto bad_arg; } // count required length int required_len = 0; for (int i = 0; i < seq_len; i++) { if (!MP_OBJ_IS_STR(seq_items[i])) { goto bad_arg; } if (i > 0) { required_len += sep_len; } GET_STR_LEN(seq_items[i], l); required_len += l; } // make joined string byte *data; mp_obj_t joined_str = mp_obj_str_builder_start(required_len, &data); for (int i = 0; i < seq_len; i++) { if (i > 0) { memcpy(data, sep_str, sep_len); data += sep_len; } GET_STR_DATA_LEN(seq_items[i], s, l); memcpy(data, s, l); data += l; } // return joined string return mp_obj_str_builder_end(joined_str); bad_arg: nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "?str.join expecting a list of str's")); }
// This dispatcher function is expected to be independent of the implementation of long int STATIC mp_obj_t mp_obj_int_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 2, false); switch (n_args) { case 0: return MP_OBJ_NEW_SMALL_INT(0); case 1: if (MP_OBJ_IS_INT(args[0])) { // already an int (small or long), just return it return args[0]; } else if (MP_OBJ_IS_STR(args[0])) { // a string, parse it uint l; const char *s = mp_obj_str_get_data(args[0], &l); return mp_parse_num_integer(s, l, 0); #if MICROPY_PY_BUILTINS_FLOAT } else if (MP_OBJ_IS_TYPE(args[0], &mp_type_float)) { return MP_OBJ_NEW_SMALL_INT((machine_int_t)(MICROPY_FLOAT_C_FUN(trunc)(mp_obj_float_get(args[0])))); #endif } else { // try to convert to small int (eg from bool) return MP_OBJ_NEW_SMALL_INT(mp_obj_get_int(args[0])); } case 2: default: { // should be a string, parse it // TODO proper error checking of argument types uint l; const char *s = mp_obj_str_get_data(args[0], &l); return mp_parse_num_integer(s, l, mp_obj_get_int(args[1])); } } }
mp_obj_t str_format(uint n_args, const mp_obj_t *args) { assert(MP_OBJ_IS_STR(args[0])); GET_STR_DATA_LEN(args[0], str, len); int arg_i = 1; vstr_t *vstr = vstr_new(); for (const byte *top = str + len; str < top; str++) { if (*str == '{') { str++; if (str < top && *str == '{') { vstr_add_char(vstr, '{'); } else { while (str < top && *str != '}') str++; if (arg_i >= n_args) { nlr_jump(mp_obj_new_exception_msg(MP_QSTR_IndexError, "tuple index out of range")); } // TODO: may be PRINT_REPR depending on formatting code mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, vstr, args[arg_i], PRINT_STR); arg_i++; } } else { vstr_add_char(vstr, *str); } } mp_obj_t s = mp_obj_new_str((byte*)vstr->buf, vstr->len, false); vstr_free(vstr); return s; }
machine_int_t mp_obj_hash(mp_obj_t o_in) { if (o_in == mp_const_false) { return 0; // needs to hash to same as the integer 0, since False==0 } else if (o_in == mp_const_true) { return 1; // needs to hash to same as the integer 1, since True==1 } else if (MP_OBJ_IS_SMALL_INT(o_in)) { return MP_OBJ_SMALL_INT_VALUE(o_in); } else if (MP_OBJ_IS_STR(o_in)) { return mp_obj_str_get_hash(o_in); } else if (MP_OBJ_IS_TYPE(o_in, &mp_type_NoneType)) { return (machine_int_t)o_in; } else if (MP_OBJ_IS_TYPE(o_in, &mp_type_fun_native) || MP_OBJ_IS_TYPE(o_in, &mp_type_fun_bc)) { return (machine_int_t)o_in; } else if (MP_OBJ_IS_TYPE(o_in, &mp_type_tuple)) { return mp_obj_tuple_hash(o_in); } else if (MP_OBJ_IS_TYPE(o_in, &mp_type_type)) { return (machine_int_t)o_in; // TODO hash class and instances // TODO delegate to __hash__ method if it exists } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unhashable type: '%s'", mp_obj_get_type_str(o_in))); } }
mp_obj_t mp_obj_str_builder_end(mp_obj_t o_in) { assert(MP_OBJ_IS_STR(o_in)); mp_obj_str_t *o = o_in; o->hash = qstr_compute_hash(o->data, o->len); o->data[o->len] = '\0'; // for now we add null for compatibility with C ASCIIZ strings return o; }
mp_obj_t microbit_display_show_func(mp_uint_t n_args, const mp_obj_t *args) { // TODO: Support async mode. microbit_display_obj_t *self = (microbit_display_obj_t*)args[0]; // Cancel any animations. MP_STATE_PORT(async_data)[0] = NULL; MP_STATE_PORT(async_data)[1] = NULL; MP_STATE_PORT(async_data)[2] = NULL; if (MP_OBJ_IS_STR(args[1])) { // arg is a string object mp_uint_t len; const char *str = mp_obj_str_get_data(args[1], &len); if (len == 0) { // There are no chars; do nothing. } else if (len == 1) { // A single char; convert to an image and print that. microbit_display_show(self, microbit_image_for_char(str[0])); } else { mp_int_t delay; if (n_args == 3) { delay = mp_obj_get_int(args[2]); } else { delay = MICROBIT_DEFAULT_PRINT_SPEED; } microbit_display_animate(self, args[1], delay, false, false); } } else if (mp_obj_get_type(args[1]) == µbit_image_type) { microbit_display_show(self, (microbit_image_obj_t *)args[1]); } else { nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "expecting an image or a string.")); } return mp_const_none; }
// This dispatcher function is expected to be independent of the implementation of long int STATIC mp_obj_t mp_obj_int_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 MP_OBJ_NEW_SMALL_INT(0); case 1: if (MP_OBJ_IS_STR(args[0])) { // a string, parse it uint l; const char *s = mp_obj_str_get_data(args[0], &l); return mp_parse_num_integer(s, l, 0); #if MICROPY_ENABLE_FLOAT } else if (MP_OBJ_IS_TYPE(args[0], &mp_type_float)) { return MP_OBJ_NEW_SMALL_INT((machine_int_t)(MICROPY_FLOAT_C_FUN(trunc)(mp_obj_float_get(args[0])))); #endif } else { return MP_OBJ_NEW_SMALL_INT(mp_obj_get_int(args[0])); } case 2: { // should be a string, parse it // TODO proper error checking of argument types uint l; const char *s = mp_obj_str_get_data(args[0], &l); return mp_parse_num_integer(s, l, mp_obj_get_int(args[1])); } default: nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "int takes at most 2 arguments, %d given", n_args)); } }
mp_obj_t ffifunc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) { mp_obj_ffifunc_t *self = self_in; assert(n_kw == 0); assert(n_args == self->cif.nargs); ffi_arg values[n_args]; void *valueptrs[n_args]; int i; for (i = 0; i < n_args; i++) { mp_obj_t a = args[i]; if (a == mp_const_none) { values[i] = 0; } else if (MP_OBJ_IS_INT(a)) { values[i] = mp_obj_int_get(a); } else if (MP_OBJ_IS_STR(a) || MP_OBJ_IS_TYPE(a, &mp_type_bytes)) { const char *s = mp_obj_str_get_str(a); values[i] = (ffi_arg)s; } else if (MP_OBJ_IS_TYPE(a, &fficallback_type)) { mp_obj_fficallback_t *p = a; values[i] = (ffi_arg)p->func; } else { assert(0); } valueptrs[i] = &values[i]; } ffi_arg retval; ffi_call(&self->cif, self->func, &retval, valueptrs); return return_ffi_value(retval, self->rettype); }
// This function implements the '==' operator (and so the inverse of '!='). // // From the Python language reference: // (https://docs.python.org/3/reference/expressions.html#not-in) // "The objects need not have the same type. If both are numbers, they are converted // to a common type. Otherwise, the == and != operators always consider objects of // different types to be unequal." // // This means that False==0 and True==1 are true expressions. // // Furthermore, from the v3.4.2 code for object.c: "Practical amendments: If rich // comparison returns NotImplemented, == and != are decided by comparing the object // pointer." bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) { if (o1 == o2) { return true; } if (o1 == mp_const_none || o2 == mp_const_none) { return false; } // fast path for small ints if (MP_OBJ_IS_SMALL_INT(o1)) { if (MP_OBJ_IS_SMALL_INT(o2)) { // both SMALL_INT, and not equal if we get here return false; } else { mp_obj_t temp = o2; o2 = o1; o1 = temp; // o2 is now the SMALL_INT, o1 is not // fall through to generic op } } // fast path for strings if (MP_OBJ_IS_STR(o1)) { if (MP_OBJ_IS_STR(o2)) { // both strings, use special function return mp_obj_str_equal(o1, o2); } else { // a string is never equal to anything else return false; } } else if (MP_OBJ_IS_STR(o2)) { // o1 is not a string (else caught above), so the objects are not equal return false; } // generic type, call binary_op(MP_BINARY_OP_EQUAL) mp_obj_type_t *type = mp_obj_get_type(o1); if (type->binary_op != NULL) { mp_obj_t r = type->binary_op(MP_BINARY_OP_EQUAL, o1, o2); if (r != MP_OBJ_NULL) { return r == mp_const_true ? true : false; } } // equality not implemented, and objects are not the same object, so // they are defined as not equal return false; }
STATIC mp_obj_t machine_main(mp_obj_t main) { if (MP_OBJ_IS_STR(main)) { MP_STATE_PORT(machine_config_main) = main; } else { nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); } return mp_const_none; }
STATIC mp_obj_t machine_main(mp_obj_t main) { if (MP_OBJ_IS_STR(main)) { MP_STATE_PORT(machine_config_main) = main; } else { mp_raise_ValueError(mpexception_value_invalid_arguments); } return mp_const_none; }
uint mp_obj_str_get_len(mp_obj_t self_in) { if (MP_OBJ_IS_STR(self_in)) { GET_STR_LEN(self_in, l); return l; } else { nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "Can't convert '%s' object to str implicitly", mp_obj_get_type_str(self_in))); } }
// this function implements the '==' operator (and so the inverse of '!=') // from the python language reference: // "The objects need not have the same type. If both are numbers, they are converted // to a common type. Otherwise, the == and != operators always consider objects of // different types to be unequal." // note also that False==0 and True==1 are true expressions bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) { if (o1 == o2) { return true; } else if (o1 == mp_const_none || o2 == mp_const_none) { return false; } else if (MP_OBJ_IS_SMALL_INT(o1) || MP_OBJ_IS_SMALL_INT(o2)) { if (MP_OBJ_IS_SMALL_INT(o1) && MP_OBJ_IS_SMALL_INT(o2)) { return false; } else { if (MP_OBJ_IS_SMALL_INT(o2)) { mp_obj_t temp = o1; o1 = o2; o2 = temp; } // o1 is the SMALL_INT, o2 is not mp_small_int_t val = MP_OBJ_SMALL_INT_VALUE(o1); if (o2 == mp_const_false) { return val == 0; } else if (o2 == mp_const_true) { return val == 1; } else if (MP_OBJ_IS_TYPE(o2, &mp_type_int)) { // If o2 is long int, dispatch to its virtual methods mp_obj_base_t *o = o2; if (o->type->binary_op != NULL) { mp_obj_t r = o->type->binary_op(MP_BINARY_OP_EQUAL, o2, o1); return r == mp_const_true ? true : false; } } return false; } } else if (MP_OBJ_IS_STR(o1) && MP_OBJ_IS_STR(o2)) { return mp_obj_str_equal(o1, o2); } else { mp_obj_base_t *o = o1; if (o->type->binary_op != NULL) { mp_obj_t r = o->type->binary_op(MP_BINARY_OP_EQUAL, o1, o2); if (r != MP_OBJ_NULL) { return r == mp_const_true ? true : false; } } nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_NotImplementedError, "Equality for '%s' and '%s' types not yet implemented", mp_obj_get_type_str(o1), mp_obj_get_type_str(o2))); return false; } }
const byte *mp_obj_str_get_data(mp_obj_t self_in, uint *len) { if (MP_OBJ_IS_STR(self_in)) { GET_STR_DATA_LEN(self_in, s, l); *len = l; return s; } else { nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "Can't convert '%s' object to str implicitly", mp_obj_get_type_str(self_in))); } }
mp_obj_t str_strip(uint n_args, const mp_obj_t *args) { assert(1 <= n_args && n_args <= 2); assert(MP_OBJ_IS_STR(args[0])); const byte *chars_to_del; uint chars_to_del_len; static const byte whitespace[] = " \t\n\r\v\f"; if (n_args == 1) { chars_to_del = whitespace; chars_to_del_len = sizeof(whitespace); } else { assert(MP_OBJ_IS_STR(args[1])); GET_STR_DATA_LEN(args[1], s, l); chars_to_del = s; chars_to_del_len = l; } GET_STR_DATA_LEN(args[0], orig_str, orig_str_len); size_t first_good_char_pos = 0; bool first_good_char_pos_set = false; size_t last_good_char_pos = 0; for (size_t i = 0; i < orig_str_len; i++) { if (!chr_in_str(chars_to_del, chars_to_del_len, orig_str[i])) { last_good_char_pos = i; if (!first_good_char_pos_set) { first_good_char_pos = i; first_good_char_pos_set = true; } } } if (first_good_char_pos == 0 && last_good_char_pos == 0) { // string is all whitespace, return '' return MP_OBJ_NEW_QSTR(MP_QSTR_); } assert(last_good_char_pos >= first_good_char_pos); //+1 to accomodate the last character size_t stripped_len = last_good_char_pos - first_good_char_pos + 1; return mp_obj_new_str(orig_str + first_good_char_pos, stripped_len, false); }
// only use this function if you need the str data to be zero terminated // at the moment all strings are zero terminated to help with C ASCIIZ compatibility const char *mp_obj_str_get_str(mp_obj_t self_in) { if (MP_OBJ_IS_STR(self_in)) { GET_STR_DATA_LEN(self_in, s, l); (void)l; // len unused return (const char*)s; } else { nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "Can't convert '%s' object to str implicitly", mp_obj_get_type_str(self_in))); } }
static mp_obj_t usart_obj_tx_str(mp_obj_t self_in, mp_obj_t s) { pyb_usart_obj_t *self = self_in; if (self->is_enabled) { if (MP_OBJ_IS_STR(s)) { uint len; const char *data = mp_obj_str_get_data(s, &len); usart_tx_bytes(self->usart_id, data, len); } } return mp_const_none; }
// may return MP_OBJ_NULL mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) { if (MP_OBJ_IS_STR(o_in)) { return MP_OBJ_NEW_SMALL_INT((machine_int_t)mp_obj_str_get_len(o_in)); } else { mp_obj_type_t *type = mp_obj_get_type(o_in); if (type->unary_op != NULL) { return type->unary_op(MP_UNARY_OP_LEN, o_in); } else { return MP_OBJ_NULL; } } }
STATIC mp_obj_t new_namedtuple_type(mp_obj_t name_in, mp_obj_t fields_in) { qstr name = mp_obj_str_get_qstr(name_in); mp_uint_t n_fields; mp_obj_t *fields; #if MICROPY_CPYTHON_COMPAT if (MP_OBJ_IS_STR(fields_in)) { fields_in = mp_obj_str_split(1, &fields_in); } #endif mp_obj_get_array(fields_in, &n_fields, &fields); return mp_obj_new_namedtuple_type(name, n_fields, fields); }
STATIC ffi_type *get_ffi_type(mp_obj_t o_in) { if (MP_OBJ_IS_STR(o_in)) { const char *s = mp_obj_str_get_str(o_in); ffi_type *t = char2ffi_type(*s); if (t != NULL) { return t; } } // TODO: Support actual libffi type objects nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "Unknown type")); }
STATIC ffi_type *get_ffi_type(mp_obj_t o_in) { if (MP_OBJ_IS_STR(o_in)) { const char *s = mp_obj_str_get_str(o_in); ffi_type *t = char2ffi_type(*s); if (t != NULL) { return t; } } // TODO: Support actual libffi type objects mp_raise_TypeError("Unknown type"); }
mp_obj_t ffifunc_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { mp_obj_ffifunc_t *self = self_in; assert(n_kw == 0); assert(n_args == self->cif.nargs); ffi_arg values[n_args]; void *valueptrs[n_args]; int i; for (i = 0; i < n_args; i++) { mp_obj_t a = args[i]; if (a == mp_const_none) { values[i] = 0; } else if (MP_OBJ_IS_INT(a)) { values[i] = mp_obj_int_get(a); } else if (MP_OBJ_IS_STR(a)) { const char *s = mp_obj_str_get_str(a); values[i] = (ffi_arg)s; } else if (((mp_obj_base_t*)a)->type->buffer_p.get_buffer != NULL) { mp_obj_base_t *o = (mp_obj_base_t*)a; mp_buffer_info_t bufinfo; int ret = o->type->buffer_p.get_buffer(o, &bufinfo, MP_BUFFER_READ); // TODO: MP_BUFFER_READ? if (ret != 0 || bufinfo.buf == NULL) { goto error; } values[i] = (ffi_arg)bufinfo.buf; } else if (MP_OBJ_IS_TYPE(a, &fficallback_type)) { mp_obj_fficallback_t *p = a; values[i] = (ffi_arg)p->func; } else { goto error; } valueptrs[i] = &values[i]; } // If ffi_arg is not big enough to hold a double, then we must pass along a // pointer to a memory location of the correct size. // TODO check if this needs to be done for other types which don't fit into // ffi_arg. if (sizeof(ffi_arg) == 4 && self->rettype == 'd') { double retval; ffi_call(&self->cif, self->func, &retval, valueptrs); return mp_obj_new_float(retval); } else { ffi_arg retval; ffi_call(&self->cif, self->func, &retval, valueptrs); return return_ffi_value(retval, self->rettype); } error: nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "Don't know how to pass object to native function")); }
static ffi_type *get_ffi_type(mp_obj_t o_in) { if (MP_OBJ_IS_STR(o_in)) { uint len; const char *s = mp_obj_str_get_data(o_in, &len); ffi_type *t = char2ffi_type(*s); if (t != NULL) { return t; } } // TODO: Support actual libffi type objects nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Unknown type")); }
static void microbit_display_update(void) { async_tick += FIBER_TICK_PERIOD_MS; if (async_tick < async_delay) { return; } async_tick = 0; switch (async_mode) { case ASYNC_MODE_ANIMATION: { if (MP_STATE_PORT(async_data)[0] == NULL || MP_STATE_PORT(async_data)[1] == NULL) { async_stop(); break; } microbit_display_obj_t *display = (microbit_display_obj_t*)MP_STATE_PORT(async_data)[0]; /* WARNING: We are executing in an interrupt handler. * If an exception is raised here, then a reset is the only way to recover. */ mp_obj_t obj = mp_iternext(async_iterator); if (obj == MP_OBJ_STOP_ITERATION) { if (async_repeat_iterable) { async_iterator = mp_getiter(async_repeat_iterable); } else { microbit_display_show(display, BLANK_IMAGE); async_stop(); } } else if (mp_obj_get_type(obj) == µbit_image_type) { microbit_display_show(display, (microbit_image_obj_t *)obj); } else if (MP_OBJ_IS_STR(obj)) { mp_uint_t len; const char *str = mp_obj_str_get_data(obj, &len); if (len == 1) { microbit_display_show(display, microbit_image_for_char(str[0])); } else { async_error = true; async_stop(); } } else { async_error = true; async_stop(); } break; } case ASYNC_MODE_CLEAR: microbit_display_show(µbit_display_obj, BLANK_IMAGE); async_stop(); break; } }
STATIC mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) { // TODO: Implement all args assert(n_args == 2); assert(MP_OBJ_IS_STR(args[0])); const char *host = mp_obj_str_get_str(args[0]); const char *serv = NULL; // getaddrinfo accepts port in string notation, so however // it may seem stupid, we need to convert int to str if (MP_OBJ_IS_SMALL_INT(args[1])) { int port = (short)MP_OBJ_SMALL_INT_VALUE(args[1]); char buf[6]; sprintf(buf, "%d", port); serv = buf; } else { serv = mp_obj_str_get_str(args[1]); } struct addrinfo hints; struct addrinfo *addr; memset(&hints, 0, sizeof(hints)); int res = getaddrinfo(host, serv, NULL/*&hints*/, &addr); if (res != 0) { // CPython: socket.gaierror nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[addrinfo error %d]", res)); } assert(addr); mp_obj_t list = mp_obj_new_list(0, NULL); for (; addr; addr = addr->ai_next) { mp_obj_tuple_t *t = mp_obj_new_tuple(5, NULL); t->items[0] = MP_OBJ_NEW_SMALL_INT((machine_int_t)addr->ai_family); t->items[1] = MP_OBJ_NEW_SMALL_INT((machine_int_t)addr->ai_socktype); t->items[2] = MP_OBJ_NEW_SMALL_INT((machine_int_t)addr->ai_protocol); // "canonname will be a string representing the canonical name of the host // if AI_CANONNAME is part of the flags argument; else canonname will be empty." ?? if (addr->ai_canonname) { t->items[3] = MP_OBJ_NEW_QSTR(qstr_from_str(addr->ai_canonname)); } else { t->items[3] = mp_const_none; } t->items[4] = mp_obj_new_bytearray(addr->ai_addrlen, addr->ai_addr); mp_obj_list_append(list, t); } return list; }
// may return MP_OBJ_NULL mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) { if ( #if !MICROPY_PY_BUILTINS_STR_UNICODE // It's simple - unicode is slow, non-unicode is fast MP_OBJ_IS_STR(o_in) || #endif MP_OBJ_IS_TYPE(o_in, &mp_type_bytes)) { return MP_OBJ_NEW_SMALL_INT(mp_obj_str_get_len(o_in)); } else { mp_obj_type_t *type = mp_obj_get_type(o_in); if (type->unary_op != NULL) { return type->unary_op(MP_UNARY_OP_LEN, o_in); } else { return MP_OBJ_NULL; } } }
// 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 mod_jni_array(mp_obj_t type_in, mp_obj_t size_in) { if (!env) { create_jvm(); } mp_int_t size = mp_obj_get_int(size_in); jobject res = NULL; if (MP_OBJ_IS_TYPE(type_in, &jclass_type)) { mp_obj_jclass_t *jcls = type_in; res = JJ(NewObjectArray, size, jcls->cls, NULL); } else if (MP_OBJ_IS_STR(type_in)) { const char *type = mp_obj_str_get_str(type_in); switch (*type) { case 'Z': res = JJ(NewBooleanArray, size); break; case 'B': res = JJ(NewByteArray, size); break; case 'C': res = JJ(NewCharArray, size); break; case 'S': res = JJ(NewShortArray, size); break; case 'I': res = JJ(NewIntArray, size); break; case 'J': res = JJ(NewLongArray, size); break; case 'F': res = JJ(NewFloatArray, size); break; case 'D': res = JJ(NewDoubleArray, size); break; } } return new_jobject(res); }