mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[mpy/files] truncate, readlines, writelines, name, mode
This commit is contained in:
@@ -496,18 +496,30 @@ Q(monotonic)
|
||||
|
||||
// file QSTRs
|
||||
Q(file)
|
||||
Q(tell)
|
||||
Q(seek)
|
||||
|
||||
Q(close)
|
||||
Q(closed)
|
||||
Q(fileno)
|
||||
Q(flush)
|
||||
Q(isatty)
|
||||
Q(readable)
|
||||
Q(readline)
|
||||
Q(readlines)
|
||||
Q(seekable)
|
||||
Q(write)
|
||||
Q(tell)
|
||||
Q(writable)
|
||||
Q(writelines)
|
||||
|
||||
Q(fileno)
|
||||
Q(seek)
|
||||
Q(truncate)
|
||||
|
||||
Q(write)
|
||||
|
||||
Q(read)
|
||||
|
||||
Q(name)
|
||||
Q(mode)
|
||||
|
||||
Q(SEEK_SET)
|
||||
Q(SEEK_CUR)
|
||||
Q(SEEK_END)
|
||||
|
||||
@@ -41,6 +41,22 @@ const mp_obj_fun_builtin_var_t file_readline_obj = {
|
||||
{(mp_fun_var_t)file_readline}
|
||||
};
|
||||
|
||||
STATIC mp_obj_t file_readlines(size_t n_args, const mp_obj_t* args);
|
||||
|
||||
const mp_obj_fun_builtin_var_t file_readlines_obj = {
|
||||
{&mp_type_fun_builtin_var},
|
||||
MP_OBJ_FUN_MAKE_SIG(1, 2, false),
|
||||
{(mp_fun_var_t)file_readlines}
|
||||
};
|
||||
|
||||
STATIC mp_obj_t file_truncate(size_t n_args, const mp_obj_t* args);
|
||||
|
||||
const mp_obj_fun_builtin_var_t file_truncate_obj = {
|
||||
{&mp_type_fun_builtin_var},
|
||||
MP_OBJ_FUN_MAKE_SIG(1, 2, false),
|
||||
{(mp_fun_var_t)file_truncate}
|
||||
};
|
||||
|
||||
STATIC mp_obj_t file_read(size_t n_args, const mp_obj_t* args);
|
||||
|
||||
const mp_obj_fun_builtin_var_t file_read_obj = {
|
||||
@@ -56,6 +72,13 @@ const mp_obj_fun_builtin_fixed_t file_write_obj = {
|
||||
{(mp_fun_0_t)file_write}
|
||||
};
|
||||
|
||||
STATIC mp_obj_t file_writelines(mp_obj_t o_in, mp_obj_t o_lines);
|
||||
|
||||
const mp_obj_fun_builtin_fixed_t file_writelines_obj = {
|
||||
{&mp_type_fun_builtin_2},
|
||||
{(mp_fun_0_t)file_writelines}
|
||||
};
|
||||
|
||||
STATIC mp_obj_t file_seekable(mp_obj_t o_in);
|
||||
|
||||
const mp_obj_fun_builtin_fixed_t file_seekable_obj = {
|
||||
@@ -164,6 +187,7 @@ typedef struct _file_obj_t {
|
||||
mp_obj_base_t base;
|
||||
|
||||
mp_obj_t name;
|
||||
mp_obj_t mode_repr;
|
||||
|
||||
file_mode_t open_mode;
|
||||
bool edit_mode;
|
||||
@@ -214,58 +238,85 @@ STATIC mp_obj_t file___iter__(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
|
||||
}
|
||||
|
||||
STATIC void file_attr(mp_obj_t self_in, qstr attribute, mp_obj_t *destination) {
|
||||
destination[1] = self_in;
|
||||
file_obj_t *self = (file_obj_t*) MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
if (destination[0] == nullptr) {
|
||||
switch(attribute) {
|
||||
case MP_QSTR_closed:
|
||||
destination[0] = mp_obj_new_bool(self->closed);
|
||||
break;
|
||||
case MP_QSTR___enter__:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file___enter___obj);
|
||||
break;
|
||||
case MP_QSTR___exit__:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file___exit___obj);
|
||||
break;
|
||||
case MP_QSTR_close:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_close_obj);
|
||||
break;
|
||||
case MP_QSTR_tell:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_tell_obj);
|
||||
break;
|
||||
case MP_QSTR_seek:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_seek_obj);
|
||||
break;
|
||||
case MP_QSTR_seekable:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_seekable_obj);
|
||||
break;
|
||||
case MP_QSTR_fileno:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_fileno_obj);
|
||||
break;
|
||||
case MP_QSTR_flush:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_flush_obj);
|
||||
break;
|
||||
case MP_QSTR_isatty:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_isatty_obj);
|
||||
break;
|
||||
case MP_QSTR_readable:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_readable_obj);
|
||||
break;
|
||||
case MP_QSTR_read:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_read_obj);
|
||||
break;
|
||||
case MP_QSTR_readline:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_readline_obj);
|
||||
break;
|
||||
case MP_QSTR_write:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_write_obj);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch(attribute) {
|
||||
case MP_QSTR_closed:
|
||||
destination[0] = mp_obj_new_bool(self->closed);
|
||||
break;
|
||||
case MP_QSTR_name:
|
||||
destination[0] = (mp_obj_t) self->name;
|
||||
break;
|
||||
case MP_QSTR_mode:
|
||||
destination[0] = (mp_obj_t) self->mode_repr;
|
||||
break;
|
||||
case MP_QSTR___enter__:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file___enter___obj);
|
||||
destination[1] = self_in;
|
||||
break;
|
||||
case MP_QSTR___exit__:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file___exit___obj);
|
||||
destination[1] = self_in;
|
||||
break;
|
||||
case MP_QSTR_close:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_close_obj);
|
||||
destination[1] = self_in;
|
||||
break;
|
||||
case MP_QSTR_tell:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_tell_obj);
|
||||
destination[1] = self_in;
|
||||
break;
|
||||
case MP_QSTR_seek:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_seek_obj);
|
||||
destination[1] = self_in;
|
||||
break;
|
||||
case MP_QSTR_seekable:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_seekable_obj);
|
||||
destination[1] = self_in;
|
||||
break;
|
||||
case MP_QSTR_fileno:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_fileno_obj);
|
||||
destination[1] = self_in;
|
||||
break;
|
||||
case MP_QSTR_flush:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_flush_obj);
|
||||
destination[1] = self_in;
|
||||
break;
|
||||
case MP_QSTR_isatty:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_isatty_obj);
|
||||
destination[1] = self_in;
|
||||
break;
|
||||
case MP_QSTR_readable:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_readable_obj);
|
||||
destination[1] = self_in;
|
||||
break;
|
||||
case MP_QSTR_read:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_read_obj);
|
||||
destination[1] = self_in;
|
||||
break;
|
||||
case MP_QSTR_readline:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_readline_obj);
|
||||
destination[1] = self_in;
|
||||
break;
|
||||
case MP_QSTR_readlines:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_readlines_obj);
|
||||
destination[1] = self_in;
|
||||
break;
|
||||
case MP_QSTR_write:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_write_obj);
|
||||
destination[1] = self_in;
|
||||
break;
|
||||
case MP_QSTR_writelines:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_writelines_obj);
|
||||
destination[1] = self_in;
|
||||
break;
|
||||
case MP_QSTR_truncate:
|
||||
destination[0] = (mp_obj_t) MP_ROM_PTR(&file_truncate_obj);
|
||||
destination[1] = self_in;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
STATIC void file_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
@@ -274,38 +325,7 @@ STATIC void file_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_
|
||||
|
||||
size_t l;
|
||||
const char* file_name = mp_obj_str_get_data(self->name, &l);
|
||||
|
||||
uint8_t offset = 0;
|
||||
char file_mode[4] = {0, 0, 0, 0};
|
||||
|
||||
switch(self->open_mode) {
|
||||
case READ:
|
||||
file_mode[0] = 'r';
|
||||
break;
|
||||
case WRITE:
|
||||
file_mode[0] = 'w';
|
||||
break;
|
||||
case APPEND:
|
||||
file_mode[0] = 'a';
|
||||
break;
|
||||
case CREATE:
|
||||
file_mode[0] = 'x';
|
||||
break;
|
||||
}
|
||||
|
||||
if (self->edit_mode) {
|
||||
file_mode[1] = '+';
|
||||
offset = 1;
|
||||
}
|
||||
|
||||
switch(self->binary_mode) {
|
||||
case TEXT:
|
||||
file_mode[1 + offset] = 't';
|
||||
break;
|
||||
case BINARY:
|
||||
file_mode[1 + offset] = 'b';
|
||||
break;
|
||||
}
|
||||
const char* file_mode = mp_obj_str_get_data(self->mode_repr, &l);
|
||||
|
||||
|
||||
mp_print_str(print, "<ion.file name='");
|
||||
@@ -475,6 +495,43 @@ STATIC mp_obj_t file_make_new(const mp_obj_type_t *type, size_t n_args, size_t n
|
||||
}
|
||||
|
||||
file->base.type = &file_type;
|
||||
|
||||
// Save mode representation
|
||||
uint8_t offset = 0;
|
||||
char file_mode[4] = {0, 0, 0, 0};
|
||||
|
||||
switch(file->open_mode) {
|
||||
case READ:
|
||||
file_mode[0] = 'r';
|
||||
break;
|
||||
case WRITE:
|
||||
file_mode[0] = 'w';
|
||||
break;
|
||||
case APPEND:
|
||||
file_mode[0] = 'a';
|
||||
break;
|
||||
case CREATE:
|
||||
file_mode[0] = 'x';
|
||||
break;
|
||||
}
|
||||
|
||||
if (file->edit_mode) {
|
||||
file_mode[1] = '+';
|
||||
offset = 1;
|
||||
}
|
||||
|
||||
switch(file->binary_mode) {
|
||||
case TEXT:
|
||||
file_mode[1 + offset] = 't';
|
||||
break;
|
||||
case BINARY:
|
||||
file_mode[1 + offset] = 'b';
|
||||
break;
|
||||
}
|
||||
|
||||
file->mode_repr = mp_obj_new_str(file_mode, 2 + offset);
|
||||
|
||||
|
||||
return MP_OBJ_FROM_PTR(file);
|
||||
}
|
||||
|
||||
@@ -686,7 +743,7 @@ STATIC mp_obj_t file_write(mp_obj_t o_in, mp_obj_t o_s) {
|
||||
size_t avaliable_size = Ion::Storage::sharedStorage()->putAvailableSpaceAtEndOfRecord(file->record);
|
||||
|
||||
// Check if there is enough space left
|
||||
if (file->position + len + 1 > avaliable_size) {
|
||||
if (file->position + len > avaliable_size) {
|
||||
Ion::Storage::sharedStorage()->getAvailableSpaceFromEndOfRecord(file->record, avaliable_size - previous_size);
|
||||
mp_raise_OSError(28);
|
||||
}
|
||||
@@ -709,6 +766,16 @@ STATIC mp_obj_t file_write(mp_obj_t o_in, mp_obj_t o_s) {
|
||||
return mp_obj_new_int(len);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t file_writelines(mp_obj_t o_in, mp_obj_t o_lines) {
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iterable = mp_getiter(o_lines, &iter_buf);
|
||||
mp_obj_t item;
|
||||
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
|
||||
file_write(o_in, item);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t __file_read_backend(file_obj_t* file, mp_int_t size, bool with_line_sep) {
|
||||
if (file->location == RAM) {
|
||||
size_t file_size = file->record.value().size;
|
||||
@@ -778,7 +845,11 @@ STATIC mp_obj_t file_read(size_t n_args, const mp_obj_t* args) {
|
||||
return mp_obj_new_str("", 0);
|
||||
if (file->binary_mode == BINARY)
|
||||
return mp_const_empty_bytes;
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t file_readline(size_t n_args, const mp_obj_t* args) {
|
||||
@@ -806,13 +877,124 @@ STATIC mp_obj_t file_readline(size_t n_args, const mp_obj_t* args) {
|
||||
size = mp_obj_get_int(args[1]);
|
||||
}
|
||||
|
||||
mp_obj_t ret = __file_read_backend(file, size, false);
|
||||
mp_obj_t ret = __file_read_backend(file, size, true);
|
||||
|
||||
if (ret == mp_const_none) {
|
||||
if (file->binary_mode == TEXT)
|
||||
return mp_obj_new_str("", 0);
|
||||
if (file->binary_mode == BINARY)
|
||||
return mp_const_empty_bytes;
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t file_readlines(size_t n_args, const mp_obj_t* args) {
|
||||
mp_arg_check_num(n_args, 0, 1, 2, false);
|
||||
|
||||
if(!mp_obj_is_type(args[0], &file_type)) {
|
||||
mp_raise_TypeError("self must be a file!");
|
||||
}
|
||||
|
||||
file_obj_t *file = (file_obj_t*) MP_OBJ_TO_PTR(args[0]);
|
||||
|
||||
check_closed(file);
|
||||
|
||||
if (file->open_mode != READ && file->edit_mode != true) {
|
||||
mp_raise_OSError(1);
|
||||
}
|
||||
|
||||
mp_int_t hint = -1;
|
||||
|
||||
if (n_args > 1) {
|
||||
if (!mp_obj_is_integer(args[1])) {
|
||||
mp_raise_ValueError("hint must be an int!");
|
||||
}
|
||||
|
||||
hint = mp_obj_get_int(args[1]);
|
||||
}
|
||||
|
||||
mp_obj_t list = mp_obj_new_list(0, NULL);
|
||||
|
||||
if (hint <= 0) {
|
||||
mp_obj_t ret = __file_read_backend(file, -1, true);
|
||||
while(ret != mp_const_none) {
|
||||
mp_obj_list_append(list, ret);
|
||||
ret = __file_read_backend(file, -1, true);
|
||||
}
|
||||
} else {
|
||||
mp_int_t curr_len = 0;
|
||||
|
||||
mp_obj_t ret = __file_read_backend(file, -1, true);
|
||||
while(ret != mp_const_none && curr_len <= hint) {
|
||||
mp_obj_list_append(list, ret);
|
||||
size_t l = 0;
|
||||
mp_obj_str_get_data(ret, &l);
|
||||
curr_len += l;
|
||||
ret = __file_read_backend(file, -1, true);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t file_truncate(size_t n_args, const mp_obj_t* args) {
|
||||
mp_arg_check_num(n_args, 0, 1, 2, false);
|
||||
|
||||
if(!mp_obj_is_type(args[0], &file_type)) {
|
||||
mp_raise_TypeError("self must be a file!");
|
||||
}
|
||||
|
||||
file_obj_t *file = (file_obj_t*) MP_OBJ_TO_PTR(args[0]);
|
||||
|
||||
check_closed(file);
|
||||
|
||||
if (file->open_mode == READ && file->edit_mode != true) {
|
||||
mp_raise_OSError(1);
|
||||
}
|
||||
|
||||
if(!mp_obj_is_integer(args[1]) && args[1] != mp_const_none) {
|
||||
mp_raise_TypeError("size must be an integer!");
|
||||
}
|
||||
|
||||
mp_int_t temp_new_end = file->position;
|
||||
|
||||
if (args[1] != mp_const_none) {
|
||||
temp_new_end = mp_obj_get_int(args[1]);
|
||||
}
|
||||
|
||||
if (temp_new_end < 0) {
|
||||
mp_raise_OSError(22);
|
||||
}
|
||||
|
||||
size_t new_end = (size_t) temp_new_end;
|
||||
|
||||
if (file->location == RAM) {
|
||||
size_t previous_size = file->record.value().size;
|
||||
|
||||
// Claim avaliable space.
|
||||
size_t avaliable_size = Ion::Storage::sharedStorage()->putAvailableSpaceAtEndOfRecord(file->record);
|
||||
|
||||
// Check if there is enough space left
|
||||
if (new_end > avaliable_size) {
|
||||
Ion::Storage::sharedStorage()->getAvailableSpaceFromEndOfRecord(file->record, avaliable_size - previous_size);
|
||||
mp_raise_OSError(28);
|
||||
}
|
||||
|
||||
// Check if new_end is higher than file end
|
||||
// If yes, fill space between there with 0x00
|
||||
if (new_end > previous_size) {
|
||||
memset((uint8_t*)(file->record.value().buffer) + new_end, 0x00, new_end - previous_size);
|
||||
}
|
||||
|
||||
// Set new size
|
||||
Ion::Storage::sharedStorage()->getAvailableSpaceFromEndOfRecord(file->record, file->record.value().size - new_end);
|
||||
|
||||
return mp_obj_new_int(new_end);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user