|
34 | 34 | #include "extmod/vfs_fat.h" |
35 | 35 | #include "py/lexer.h" |
36 | 36 |
|
37 | | -// TODO: actually, the core function should be ilistdir() |
38 | | - |
39 | | -mp_obj_t fat_vfs_listdir2(fs_user_mount_t *vfs, const char *path, bool is_str_type) { |
40 | | - FRESULT res; |
41 | | - FILINFO fno; |
| 37 | +typedef struct _mp_vfs_fat_ilistdir_it_t { |
| 38 | + mp_obj_base_t base; |
| 39 | + mp_fun_1_t iternext; |
| 40 | + bool is_str; |
42 | 41 | FF_DIR dir; |
| 42 | +} mp_vfs_fat_ilistdir_it_t; |
43 | 43 |
|
44 | | - res = f_opendir(&vfs->fatfs, &dir, path); |
45 | | - if (res != FR_OK) { |
46 | | - mp_raise_OSError(fresult_to_errno_table[res]); |
47 | | - } |
48 | | - |
49 | | - mp_obj_t dir_list = mp_obj_new_list(0, NULL); |
| 44 | +STATIC mp_obj_t mp_vfs_fat_ilistdir_it_iternext(mp_obj_t self_in) { |
| 45 | + mp_vfs_fat_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in); |
50 | 46 |
|
51 | 47 | for (;;) { |
52 | | - res = f_readdir(&dir, &fno); /* Read a directory item */ |
53 | | - if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */ |
54 | | - if (fno.fname[0] == '.' && fno.fname[1] == 0) continue; /* Ignore . entry */ |
55 | | - if (fno.fname[0] == '.' && fno.fname[1] == '.' && fno.fname[2] == 0) continue; /* Ignore .. entry */ |
56 | | - |
| 48 | + FILINFO fno; |
| 49 | + FRESULT res = f_readdir(&self->dir, &fno); |
57 | 50 | char *fn = fno.fname; |
| 51 | + if (res != FR_OK || fn[0] == 0) { |
| 52 | + // stop on error or end of dir |
| 53 | + break; |
| 54 | + } |
| 55 | + if (fn[0] == '.' && (fn[1] == 0 || (fn[1] == '.' && fn[2] == 0))) { |
| 56 | + // skip . and .. |
| 57 | + continue; |
| 58 | + } |
58 | 59 |
|
59 | | - /* |
| 60 | + // make 3-tuple with info about this entry |
| 61 | + mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); |
| 62 | + if (self->is_str) { |
| 63 | + t->items[0] = mp_obj_new_str(fn, strlen(fn), false); |
| 64 | + } else { |
| 65 | + t->items[0] = mp_obj_new_bytes((const byte*)fn, strlen(fn)); |
| 66 | + } |
60 | 67 | if (fno.fattrib & AM_DIR) { |
61 | 68 | // dir |
| 69 | + t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFDIR); |
62 | 70 | } else { |
63 | 71 | // file |
| 72 | + t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFREG); |
64 | 73 | } |
65 | | - */ |
| 74 | + t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // no inode number |
66 | 75 |
|
67 | | - // make a string object for this entry |
68 | | - mp_obj_t entry_o; |
69 | | - if (is_str_type) { |
70 | | - entry_o = mp_obj_new_str(fn, strlen(fn), false); |
71 | | - } else { |
72 | | - entry_o = mp_obj_new_bytes((const byte*)fn, strlen(fn)); |
73 | | - } |
74 | | - |
75 | | - // add the entry to the list |
76 | | - mp_obj_list_append(dir_list, entry_o); |
| 76 | + return MP_OBJ_FROM_PTR(t); |
77 | 77 | } |
78 | 78 |
|
79 | | - f_closedir(&dir); |
| 79 | + // ignore error because we may be closing a second time |
| 80 | + f_closedir(&self->dir); |
80 | 81 |
|
81 | | - return dir_list; |
| 82 | + return MP_OBJ_STOP_ITERATION; |
| 83 | +} |
| 84 | + |
| 85 | +mp_obj_t fat_vfs_ilistdir2(fs_user_mount_t *vfs, const char *path, bool is_str_type) { |
| 86 | + mp_vfs_fat_ilistdir_it_t *iter = m_new_obj(mp_vfs_fat_ilistdir_it_t); |
| 87 | + iter->base.type = &mp_type_polymorph_iter; |
| 88 | + iter->iternext = mp_vfs_fat_ilistdir_it_iternext; |
| 89 | + iter->is_str = is_str_type; |
| 90 | + FRESULT res = f_opendir(&vfs->fatfs, &iter->dir, path); |
| 91 | + if (res != FR_OK) { |
| 92 | + mp_raise_OSError(fresult_to_errno_table[res]); |
| 93 | + } |
| 94 | + return MP_OBJ_FROM_PTR(iter); |
82 | 95 | } |
83 | 96 |
|
84 | 97 | mp_import_stat_t fat_vfs_import_stat(fs_user_mount_t *vfs, const char *path) { |
|
0 commit comments