예제 #1
0
STATIC mp_obj_t os_urandom(mp_obj_t num) {
    machine_int_t n = mp_obj_get_int(num);
    byte *data;
    mp_obj_t o = mp_obj_str_builder_start(&mp_type_bytes, n, &data);
    for (int i = 0; i < n; i++) {
        data[i] = rng_get();
    }
    return mp_obj_str_builder_end(o);
}
예제 #2
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"));
}
예제 #3
0
STATIC mp_obj_t struct_pack(uint n_args, mp_obj_t *args) {
    // TODO: "The arguments must match the values required by the format exactly."
    const char *fmt = mp_obj_str_get_str(args[0]);
    char fmt_type = get_fmt_type(&fmt);
    int size = MP_OBJ_SMALL_INT_VALUE(struct_calcsize(args[0]));
    byte *p;
    mp_obj_t res = mp_obj_str_builder_start(&mp_type_bytes, size, &p);
    memset(p, 0, size);

    for (uint i = 1; i < n_args; i++) {
        machine_uint_t sz = 1;
        if (unichar_isdigit(*fmt)) {
            sz = get_fmt_num(&fmt);
        }
        if (sz > 1) {
            // TODO: size spec support only for string len
            assert(*fmt == 's');
        }

        if (*fmt == 's') {
            mp_buffer_info_t bufinfo;
            mp_get_buffer_raise(args[i], &bufinfo, MP_BUFFER_READ);
            machine_uint_t to_copy = sz;
            if (bufinfo.len < to_copy) {
                to_copy = bufinfo.len;
            }
            memcpy(p, bufinfo.buf, to_copy);
            memset(p + to_copy, 0, sz - to_copy);
            p += sz;
            fmt++;
        } else {
            mp_binary_set_val(fmt_type, *fmt++, args[i], &p);
        }
    }
    return res;
}
예제 #4
0
mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
    GET_STR_DATA_LEN(lhs_in, lhs_data, lhs_len);
    switch (op) {
        case RT_BINARY_OP_SUBSCR:
            // TODO: need predicate to check for int-like type (bools are such for example)
            // ["no", "yes"][1 == 2] is common idiom
            if (MP_OBJ_IS_SMALL_INT(rhs_in)) {
                uint index = mp_get_index(mp_obj_get_type(lhs_in), lhs_len, rhs_in);
                return mp_obj_new_str(lhs_data + index, 1, true);
#if MICROPY_ENABLE_SLICE
            } else if (MP_OBJ_IS_TYPE(rhs_in, &slice_type)) {
                machine_int_t start, stop, step;
                mp_obj_slice_get(rhs_in, &start, &stop, &step);
                assert(step == 1);
                if (start < 0) {
                    start = lhs_len + start;
                    if (start < 0) {
                        start = 0;
                    }
                } else if (start > lhs_len) {
                    start = lhs_len;
                }
                if (stop <= 0) {
                    stop = lhs_len + stop;
                    // CPython returns empty string in such case
                    if (stop < 0) {
                        stop = start;
                    }
                } else if (stop > lhs_len) {
                    stop = lhs_len;
                }
                return mp_obj_new_str(lhs_data + start, stop - start, false);
#endif
            } else {
                // Message doesn't match CPython, but we don't have so much bytes as they
                // to spend them on verbose wording
                nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "index must be int"));
            }

        case RT_BINARY_OP_ADD:
        case RT_BINARY_OP_INPLACE_ADD:
            if (MP_OBJ_IS_STR(rhs_in)) {
                // add 2 strings

                GET_STR_DATA_LEN(rhs_in, rhs_data, rhs_len);
                int alloc_len = lhs_len + rhs_len;

                /* code for making qstr
                byte *q_ptr;
                byte *val = qstr_build_start(alloc_len, &q_ptr);
                memcpy(val, lhs_data, lhs_len);
                memcpy(val + lhs_len, rhs_data, rhs_len);
                return MP_OBJ_NEW_QSTR(qstr_build_end(q_ptr));
                */

                // code for non-qstr
                byte *data;
                mp_obj_t s = mp_obj_str_builder_start(alloc_len, &data);
                memcpy(data, lhs_data, lhs_len);
                memcpy(data + lhs_len, rhs_data, rhs_len);
                return mp_obj_str_builder_end(s);
            }
            break;

        case RT_COMPARE_OP_IN:
        case RT_COMPARE_OP_NOT_IN:
            /* NOTE `a in b` is `b.__contains__(a)` */
            if (MP_OBJ_IS_STR(rhs_in)) {
                GET_STR_DATA_LEN(rhs_in, rhs_data, rhs_len);
                return MP_BOOL((op == RT_COMPARE_OP_IN) ^ (find_subbytes(lhs_data, lhs_len, rhs_data, rhs_len) == NULL));
            }
            break;

        case RT_BINARY_OP_MULTIPLY:
        {
            if (!MP_OBJ_IS_SMALL_INT(rhs_in)) {
                return NULL;
            }
            int n = MP_OBJ_SMALL_INT_VALUE(rhs_in);
            byte *data;
            mp_obj_t s = mp_obj_str_builder_start(lhs_len * n, &data);
            mp_seq_multiply(lhs_data, sizeof(*lhs_data), lhs_len, n, data);
            return mp_obj_str_builder_end(s);
        }
    }

    return MP_OBJ_NULL; // op not supported
}
예제 #5
0
STATIC mp_obj_t os_listdir(uint n_args, const mp_obj_t *args) {
    const mp_obj_type_t *local_str_type = &mp_type_str;
    const char *path;
    if (n_args == 1) {
        if (mp_obj_get_type(args[0]) == &mp_type_bytes) {
            local_str_type = &mp_type_bytes;
        }
        path = mp_obj_str_get_str(args[0]);
    } else {
        path = "0:";
    }

    FRESULT res;
    FILINFO fno;
    DIR dir;
#if _USE_LFN
    fno.lfname = lfn;
    fno.lfsize = sizeof lfn;
#endif

    res = f_opendir(&dir, path);                       /* Open the directory */
    if (res != FR_OK) {
        // TODO should be mp_type_FileNotFoundError
        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "No such file or directory: '%s'", path));
    }

    mp_obj_t dir_list = mp_obj_new_list(0, NULL);

    uint path_len = strlen(path);
    if (path[path_len - 1] == '/') {
        path_len--;
    }

    for (;;) {
        res = f_readdir(&dir, &fno);                   /* Read a directory item */
        if (res != FR_OK || fno.fname[0] == 0) break;  /* Break on error or end of dir */
        if (fno.fname[0] == '.' && fno.fname[1] == 0) continue;             /* Ignore . entry */
        if (fno.fname[0] == '.' && fno.fname[1] == '.' && fno.fname[2] == 0) continue;             /* Ignore .. entry */

#if _USE_LFN
        char *fn = *fno.lfname ? fno.lfname : fno.fname;
#else
        char *fn = fno.fname;
#endif

        if (fno.fattrib & AM_DIR) {                    /* It is a directory */
        } else {                                       /* It is a file. */
        }

        // make a string object for this entry
        byte *data;
        uint fn_len = strlen(fn);
        mp_obj_t entry_o = mp_obj_str_builder_start(local_str_type, path_len + 1 + fn_len, &data);
        memcpy(data, path, path_len);
        data[path_len] = '/';
        memcpy(data + path_len + 1, fn, fn_len);

        // add the entry to the list
        mp_obj_list_append(dir_list, mp_obj_str_builder_end(entry_o));
    }

    f_closedir(&dir);

    return dir_list;
}