[mpy/files] readline

This commit is contained in:
M4x1m3
2020-07-05 15:24:31 +02:00
parent a47ef29236
commit fba5295502
2 changed files with 82 additions and 29 deletions

View File

@@ -504,6 +504,7 @@ Q(fileno)
Q(flush)
Q(isatty)
Q(readable)
Q(readline)
Q(seekable)
Q(write)
Q(writable)

View File

@@ -32,6 +32,14 @@ const mp_obj_fun_builtin_var_t file_seek_obj = {
{(mp_fun_var_t)file_seek}
};
STATIC mp_obj_t file_readline(size_t n_args, const mp_obj_t* args);
const mp_obj_fun_builtin_var_t file_readline_obj = {
{&mp_type_fun_builtin_var},
MP_OBJ_FUN_MAKE_SIG(1, 2, false),
{(mp_fun_var_t)file_readline}
};
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 = {
@@ -212,6 +220,9 @@ STATIC void file_attr(mp_obj_t self_in, qstr attribute, mp_obj_t *destination) {
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;
@@ -663,6 +674,46 @@ 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_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;
size_t start = file->position;
if (start >= file_size || size == 0) {
if (file->binary_mode == TEXT)
return mp_obj_new_str("", 0);
if (file->binary_mode == BINARY)
return mp_const_empty_bytes;
}
size_t end = 0;
// size == 0 handled earlier.
if (size < 0) {
end = file_size;
} else {
end = std::min(file_size, file->position + size);
}
if (with_line_sep) {
for(size_t i = start; i < end; i++) {
if (*((uint8_t*)(file->record.value().buffer) + i) == '\n') {
end = i + 1;
break;
}
}
}
file->position = end;
if (file->binary_mode == TEXT)
return mp_obj_new_str((const char*)file->record.value().buffer + start, end - start);
if (file->binary_mode == BINARY)
return mp_obj_new_bytes((const byte*)file->record.value().buffer + start, end - start);
}
return mp_const_none;
}
STATIC mp_obj_t file_read(size_t n_args, const mp_obj_t* args) {
mp_arg_check_num(n_args, 0, 1, 2, false);
@@ -687,34 +738,35 @@ STATIC mp_obj_t file_read(size_t n_args, const mp_obj_t* args) {
size = mp_obj_get_int(args[1]);
}
if (file->location == RAM) {
size_t file_size = file->record.value().size;
size_t start = file->position;
if (start >= file_size || size == 0) {
if (file->binary_mode == TEXT)
return mp_obj_new_str("", 0);
if (file->binary_mode == BINARY)
return mp_const_empty_bytes;
}
size_t end = 0;
// size == 0 handled earlier.
if (size < 0) {
end = file_size;
} else {
end = std::min(file_size, file->position + size);
}
file->position = end;
if (file->binary_mode == TEXT)
return mp_obj_new_str((const char*)file->record.value().buffer + start, end - start);
if (file->binary_mode == BINARY)
return mp_obj_new_bytes((const byte*)file->record.value().buffer + start, end - start);
}
return mp_const_none;
return __file_read_backend(file, size, false);
}
STATIC mp_obj_t file_readline(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 size = -1;
if (n_args > 1) {
if (!mp_obj_is_integer(args[1])) {
mp_raise_ValueError("size must be an int!");
}
size = mp_obj_get_int(args[1]);
}
return __file_read_backend(file, size, true);
}