Пример #1
0
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);
    }
}
Пример #2
0
// 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)));
    }
}
Пример #3
0
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"));
}
Пример #4
0
// 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]));
        }
    }
}
Пример #5
0
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;
}
Пример #6
0
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)));
    }
}
Пример #7
0
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]) == &microbit_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;
}
Пример #9
0
// 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));
    }
}
Пример #10
0
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);
}
Пример #11
0
// 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;
}
Пример #12
0
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;
}
Пример #13
0
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;
}
Пример #14
0
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)));
    }
}
Пример #15
0
// 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;
    }
}
Пример #16
0
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)));
    }
}
Пример #17
0
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);
}
Пример #18
0
// 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)));
    }
}
Пример #19
0
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;
}
Пример #20
0
// 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;
        }
    }
}
Пример #21
0
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);
}
Пример #22
0
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"));
}
Пример #23
0
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");
}
Пример #24
0
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"));
}
Пример #25
0
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"));
}
Пример #26
0
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) == &microbit_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(&microbit_display_obj, BLANK_IMAGE);
            async_stop();
            break;
    }
}
Пример #27
0
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;
}
Пример #28
0
// 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;
        }
    }
}
Пример #29
0
// 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;
            }
        }
    }
}
Пример #30
0
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);
}