From fba5295502b1f6b3913ef6a7b5cdda3deb118f41 Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Sun, 5 Jul 2020 15:24:31 +0200 Subject: [PATCH] [mpy/files] readline --- python/port/genhdr/qstrdefs.in.h | 1 + python/port/mod/ion/file.cpp | 110 +++++++++++++++++++++++-------- 2 files changed, 82 insertions(+), 29 deletions(-) diff --git a/python/port/genhdr/qstrdefs.in.h b/python/port/genhdr/qstrdefs.in.h index 7d3a3f8be..52bd80e5a 100644 --- a/python/port/genhdr/qstrdefs.in.h +++ b/python/port/genhdr/qstrdefs.in.h @@ -504,6 +504,7 @@ Q(fileno) Q(flush) Q(isatty) Q(readable) +Q(readline) Q(seekable) Q(write) Q(writable) diff --git a/python/port/mod/ion/file.cpp b/python/port/mod/ion/file.cpp index bbccad466..0fbd9941a 100644 --- a/python/port/mod/ion/file.cpp +++ b/python/port/mod/ion/file.cpp @@ -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); }