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); }
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")); }
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; }
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 }
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; }