@ -151,72 +151,6 @@ STATIC mp_uint_t file_obj_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg,
}
}
// Note: encoding is ignored for now; it's also not a valid kwarg for CPython's FileIO,
// but by adding it here we can use one single mp_arg_t array for open() and FileIO's constructor
STATIC const mp_arg_t file_open_args [ ] = {
{ MP_QSTR_file , MP_ARG_OBJ | MP_ARG_REQUIRED , { . u_rom_obj = MP_ROM_NONE } } ,
{ MP_QSTR_mode , MP_ARG_OBJ , { . u_obj = MP_OBJ_NEW_QSTR ( MP_QSTR_r ) } } ,
{ MP_QSTR_encoding , MP_ARG_OBJ | MP_ARG_KW_ONLY , { . u_rom_obj = MP_ROM_NONE } } ,
} ;
# define FILE_OPEN_NUM_ARGS MP_ARRAY_SIZE(file_open_args)
STATIC mp_obj_t file_open ( fs_user_mount_t * vfs , const mp_obj_type_t * type , mp_arg_val_t * args ) {
int mode = 0 ;
const char * mode_s = mp_obj_str_get_str ( args [ 1 ] . u_obj ) ;
// TODO make sure only one of r, w, x, a, and b, t are specified
while ( * mode_s ) {
switch ( * mode_s + + ) {
case ' r ' :
mode | = FA_READ ;
break ;
case ' w ' :
mode | = FA_WRITE | FA_CREATE_ALWAYS ;
break ;
case ' x ' :
mode | = FA_WRITE | FA_CREATE_NEW ;
break ;
case ' a ' :
mode | = FA_WRITE | FA_OPEN_ALWAYS ;
break ;
case ' + ' :
mode | = FA_READ | FA_WRITE ;
break ;
# if MICROPY_PY_IO_FILEIO
case ' b ' :
type = & mp_type_vfs_fat_fileio ;
break ;
# endif
case ' t ' :
type = & mp_type_vfs_fat_textio ;
break ;
}
}
pyb_file_obj_t * o = m_new_obj_with_finaliser ( pyb_file_obj_t ) ;
o - > base . type = type ;
const char * fname = mp_obj_str_get_str ( args [ 0 ] . u_obj ) ;
assert ( vfs ! = NULL ) ;
FRESULT res = f_open ( & vfs - > fatfs , & o - > fp , fname , mode ) ;
if ( res ! = FR_OK ) {
m_del_obj ( pyb_file_obj_t , o ) ;
mp_raise_OSError ( fresult_to_errno_table [ res ] ) ;
}
// for 'a' mode, we must begin at the end of the file
if ( ( mode & FA_OPEN_ALWAYS ) ! = 0 ) {
f_lseek ( & o - > fp , f_size ( & o - > fp ) ) ;
}
return MP_OBJ_FROM_PTR ( o ) ;
}
STATIC mp_obj_t file_obj_make_new ( const mp_obj_type_t * type , size_t n_args , size_t n_kw , const mp_obj_t * args ) {
mp_arg_val_t arg_vals [ FILE_OPEN_NUM_ARGS ] ;
mp_arg_parse_all_kw_array ( n_args , n_kw , args , FILE_OPEN_NUM_ARGS , file_open_args , arg_vals ) ;
return file_open ( NULL , type , arg_vals ) ;
}
// TODO gc hook to close the file if not already closed
STATIC const mp_rom_map_elem_t vfs_fat_rawfile_locals_dict_table [ ] = {
@ -247,7 +181,6 @@ const mp_obj_type_t mp_type_vfs_fat_fileio = {
{ & mp_type_type } ,
. name = MP_QSTR_FileIO ,
. print = file_obj_print ,
. make_new = file_obj_make_new ,
. getiter = mp_identity_getiter ,
. iternext = mp_stream_unbuffered_iter ,
. protocol = & vfs_fat_fileio_stream_p ,
@ -266,7 +199,6 @@ const mp_obj_type_t mp_type_vfs_fat_textio = {
{ & mp_type_type } ,
. name = MP_QSTR_TextIOWrapper ,
. print = file_obj_print ,
. make_new = file_obj_make_new ,
. getiter = mp_identity_getiter ,
. iternext = mp_stream_unbuffered_iter ,
. protocol = & vfs_fat_textio_stream_p ,
@ -274,15 +206,58 @@ const mp_obj_type_t mp_type_vfs_fat_textio = {
} ;
// Factory function for I/O stream classes
STATIC mp_obj_t fatfs_builtin_open_self ( mp_obj_t self_in , mp_obj_t path , mp_obj_t mode ) {
// TODO: analyze buffering args and instantiate appropriate type
STATIC mp_obj_t fat_vfs_open ( mp_obj_t self_in , mp_obj_t path_in , mp_obj_t mode_in ) {
fs_user_mount_t * self = MP_OBJ_TO_PTR ( self_in ) ;
mp_arg_val_t arg_vals [ FILE_OPEN_NUM_ARGS ] ;
arg_vals [ 0 ] . u_obj = path ;
arg_vals [ 1 ] . u_obj = mode ;
arg_vals [ 2 ] . u_obj = mp_const_none ;
return file_open ( self , & mp_type_vfs_fat_textio , arg_vals ) ;
const mp_obj_type_t * type = & mp_type_vfs_fat_textio ;
int mode = 0 ;
const char * mode_s = mp_obj_str_get_str ( mode_in ) ;
// TODO make sure only one of r, w, x, a, and b, t are specified
while ( * mode_s ) {
switch ( * mode_s + + ) {
case ' r ' :
mode | = FA_READ ;
break ;
case ' w ' :
mode | = FA_WRITE | FA_CREATE_ALWAYS ;
break ;
case ' x ' :
mode | = FA_WRITE | FA_CREATE_NEW ;
break ;
case ' a ' :
mode | = FA_WRITE | FA_OPEN_ALWAYS ;
break ;
case ' + ' :
mode | = FA_READ | FA_WRITE ;
break ;
# if MICROPY_PY_IO_FILEIO
case ' b ' :
type = & mp_type_vfs_fat_fileio ;
break ;
# endif
case ' t ' :
type = & mp_type_vfs_fat_textio ;
break ;
}
}
pyb_file_obj_t * o = m_new_obj_with_finaliser ( pyb_file_obj_t ) ;
o - > base . type = type ;
const char * fname = mp_obj_str_get_str ( path_in ) ;
FRESULT res = f_open ( & self - > fatfs , & o - > fp , fname , mode ) ;
if ( res ! = FR_OK ) {
m_del_obj ( pyb_file_obj_t , o ) ;
mp_raise_OSError ( fresult_to_errno_table [ res ] ) ;
}
// for 'a' mode, we must begin at the end of the file
if ( ( mode & FA_OPEN_ALWAYS ) ! = 0 ) {
f_lseek ( & o - > fp , f_size ( & o - > fp ) ) ;
}
return MP_OBJ_FROM_PTR ( o ) ;
}
MP_DEFINE_CONST_FUN_OBJ_3 ( fat_vfs_open_obj , fatfs_builtin_open_self ) ;
MP_DEFINE_CONST_FUN_OBJ_3 ( fat_vfs_open_obj , fat_v fs_open ) ;
# endif // MICROPY_VFS && MICROPY_VFS_FAT