Skip to content

Commit 87283c1

Browse files
committed
extmod/vfs: Implement mp_vfs_ilistdir().
uos.ilistdir() is the core function, returning an iterator that yields 3-tuples. uos.listdir() is implemented in terms of ilistdir().
1 parent edc02bd commit 87283c1

2 files changed

Lines changed: 70 additions & 15 deletions

File tree

extmod/vfs.c

Lines changed: 64 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,49 @@ mp_obj_t mp_vfs_getcwd(void) {
286286
}
287287
MP_DEFINE_CONST_FUN_OBJ_0(mp_vfs_getcwd_obj, mp_vfs_getcwd);
288288

289-
mp_obj_t mp_vfs_listdir(size_t n_args, const mp_obj_t *args) {
289+
typedef struct _mp_vfs_ilistdir_it_t {
290+
mp_obj_base_t base;
291+
mp_fun_1_t iternext;
292+
union {
293+
mp_vfs_mount_t *vfs;
294+
mp_obj_t iter;
295+
} cur;
296+
bool is_str;
297+
bool is_iter;
298+
} mp_vfs_ilistdir_it_t;
299+
300+
STATIC mp_obj_t mp_vfs_ilistdir_it_iternext(mp_obj_t self_in) {
301+
mp_vfs_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in);
302+
if (self->is_iter) {
303+
// continue delegating to root dir
304+
return mp_iternext(self->cur.iter);
305+
} else if (self->cur.vfs == NULL) {
306+
// finished iterating mount points and no root dir is mounted
307+
return MP_OBJ_STOP_ITERATION;
308+
} else {
309+
// continue iterating mount points
310+
mp_vfs_mount_t *vfs = self->cur.vfs;
311+
self->cur.vfs = vfs->next;
312+
if (vfs->len == 1) {
313+
// vfs is mounted at root dir, delegate to it
314+
mp_obj_t root = mp_obj_new_str("/", 1, false);
315+
self->is_iter = true;
316+
self->cur.iter = mp_vfs_proxy_call(vfs, MP_QSTR_ilistdir, 1, &root);
317+
return mp_iternext(self->cur.iter);
318+
} else {
319+
// a mounted directory
320+
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL));
321+
t->items[0] = mp_obj_new_str_of_type(
322+
self->is_str ? &mp_type_str : &mp_type_bytes,
323+
(const byte*)vfs->str + 1, vfs->len - 1);
324+
t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFDIR);
325+
t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // no inode number
326+
return MP_OBJ_FROM_PTR(t);
327+
}
328+
}
329+
}
330+
331+
mp_obj_t mp_vfs_ilistdir(size_t n_args, const mp_obj_t *args) {
290332
mp_obj_t path_in;
291333
if (n_args == 1) {
292334
path_in = args[0];
@@ -299,22 +341,29 @@ mp_obj_t mp_vfs_listdir(size_t n_args, const mp_obj_t *args) {
299341

300342
if (vfs == MP_VFS_ROOT) {
301343
// list the root directory
302-
mp_obj_t dir_list = mp_obj_new_list(0, NULL);
303-
for (vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) {
304-
if (vfs->len == 1) {
305-
// vfs is mounted at root dir, delegate to it
306-
mp_obj_t root = mp_obj_new_str("/", 1, false);
307-
mp_obj_t dir_list2 = mp_vfs_proxy_call(vfs, MP_QSTR_listdir, 1, &root);
308-
dir_list = mp_binary_op(MP_BINARY_OP_ADD, dir_list, dir_list2);
309-
} else {
310-
mp_obj_list_append(dir_list, mp_obj_new_str_of_type(mp_obj_get_type(path_in),
311-
(const byte*)vfs->str + 1, vfs->len - 1));
312-
}
313-
}
314-
return dir_list;
344+
mp_vfs_ilistdir_it_t *iter = m_new_obj(mp_vfs_ilistdir_it_t);
345+
iter->base.type = &mp_type_polymorph_iter;
346+
iter->iternext = mp_vfs_ilistdir_it_iternext;
347+
iter->cur.vfs = MP_STATE_VM(vfs_mount_table);
348+
iter->is_str = mp_obj_get_type(path_in) == &mp_type_str;
349+
iter->is_iter = false;
350+
return MP_OBJ_FROM_PTR(iter);
315351
}
316352

317-
return mp_vfs_proxy_call(vfs, MP_QSTR_listdir, 1, &path_out);
353+
return mp_vfs_proxy_call(vfs, MP_QSTR_ilistdir, 1, &path_out);
354+
}
355+
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_vfs_ilistdir_obj, 0, 1, mp_vfs_ilistdir);
356+
357+
mp_obj_t mp_vfs_listdir(size_t n_args, const mp_obj_t *args) {
358+
mp_obj_t iter = mp_vfs_ilistdir(n_args, args);
359+
mp_obj_t dir_list = mp_obj_new_list(0, NULL);
360+
mp_obj_t next;
361+
while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
362+
mp_obj_t *items;
363+
mp_obj_get_array_fixed_n(next, 3, &items);
364+
mp_obj_list_append(dir_list, items[0]);
365+
}
366+
return dir_list;
318367
}
319368
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_vfs_listdir_obj, 0, 1, mp_vfs_listdir);
320369

extmod/vfs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535
#define MP_VFS_NONE ((mp_vfs_mount_t*)1)
3636
#define MP_VFS_ROOT ((mp_vfs_mount_t*)0)
3737

38+
// MicroPython's port-standardized versions of stat constants
39+
#define MP_S_IFDIR (0x4000)
40+
#define MP_S_IFREG (0x8000)
41+
3842
// constants for block protocol ioctl
3943
#define BP_IOCTL_INIT (1)
4044
#define BP_IOCTL_DEINIT (2)
@@ -56,6 +60,7 @@ mp_obj_t mp_vfs_umount(mp_obj_t mnt_in);
5660
mp_obj_t mp_vfs_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
5761
mp_obj_t mp_vfs_chdir(mp_obj_t path_in);
5862
mp_obj_t mp_vfs_getcwd(void);
63+
mp_obj_t mp_vfs_ilistdir(size_t n_args, const mp_obj_t *args);
5964
mp_obj_t mp_vfs_listdir(size_t n_args, const mp_obj_t *args);
6065
mp_obj_t mp_vfs_mkdir(mp_obj_t path_in);
6166
mp_obj_t mp_vfs_remove(mp_obj_t path_in);
@@ -69,6 +74,7 @@ MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_umount_obj);
6974
MP_DECLARE_CONST_FUN_OBJ_KW(mp_vfs_open_obj);
7075
MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_chdir_obj);
7176
MP_DECLARE_CONST_FUN_OBJ_0(mp_vfs_getcwd_obj);
77+
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_vfs_ilistdir_obj);
7278
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_vfs_listdir_obj);
7379
MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_mkdir_obj);
7480
MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_remove_obj);

0 commit comments

Comments
 (0)