feat: IO.FS.Handle.size

This commit is contained in:
Wojciech Nawrocki 2020-12-22 21:56:01 -05:00 committed by Sebastian Ullrich
parent f6b3fedcc6
commit 3fca58ea8c
2 changed files with 33 additions and 3 deletions

View file

@ -166,6 +166,7 @@ def fopenFlags (m : FS.Mode) (b : Bool) : String :=
mode ++ bin
@[extern "lean_io_prim_handle_mk"] constant Handle.mk (s : @& String) (mode : @& String) : IO Handle
@[extern "lean_io_prim_handle_size"] constant Handle.size (h : @& Handle) : IO Nat
@[extern "lean_io_prim_handle_is_eof"] constant Handle.isEof (h : @& Handle) : IO Bool
@[extern "lean_io_prim_handle_flush"] constant Handle.flush (h : @& Handle) : IO Unit
@[extern "lean_io_prim_handle_read"] constant Handle.read (h : @& Handle) (bytes : USize) : IO ByteArray
@ -193,6 +194,8 @@ def Handle.mk (s : String) (Mode : Mode) (bin : Bool := true) : m Handle :=
def withFile (fn : String) (mode : Mode) (f : Handle → m α) : m α :=
Handle.mk fn mode >>= f
/-- Returns the size of the underlying file. -/
def Handle.size : Handle → m Nat := liftM ∘ Prim.Handle.size
/-- returns whether the end of the file has been reached while reading a file.
`h.isEof` returns true /after/ the first attempt at reading past the end of `h`.
Once `h.isEof` is true, the reading `h` raises `IO.Error.eof`.
@ -210,14 +213,25 @@ def Handle.putStr (h : Handle) (s : String) : m Unit :=
def Handle.putStrLn (h : Handle) (s : String) : m Unit :=
h.putStr (s.push '\n')
-- TODO: support for binary files
partial def Handle.readToEnd (h : Handle) : m String :=
partial def Handle.readBinToEnd (h : Handle) : m ByteArray := do
let rec loop (left : Nat) : m ByteArray := do
if left == 0 then ByteArray.empty
else
let buf ← h.read left
let left := left - buf.size
pure $ buf ++ (←loop left)
loop (←h.size)
partial def Handle.readToEnd (h : Handle) : m String := do
let rec read (s : String) := do
let line ← h.getLine
if line.length == 0 then pure s else read (s ++ line)
read ""
-- TODO: support for binary files
def readBinFile (fname : String) : m ByteArray := do
let h ← Handle.mk fname Mode.read true
h.readBinToEnd
def readFile (fname : String) : m String := do
let h ← Handle.mk fname Mode.read false
h.readToEnd

View file

@ -289,6 +289,22 @@ extern "C" obj_res lean_io_prim_handle_is_eof(b_obj_arg h, obj_arg /* w */) {
return io_result_mk_ok(box(std::feof(fp) != 0));
}
/* Handle.size : (@& Handle) → IO USize */
extern "C" obj_res lean_io_prim_handle_size(b_obj_arg h, obj_arg /* w */) {
FILE * fp = io_get_handle(h);
std::fpos_t pos;
long fsize = 0;
if (std::fgetpos(fp, &pos)) goto fail;
if (std::fseek(fp, 0, SEEK_END)) goto fail;
fsize = std::ftell(fp);
if (fsize == -1) goto fail;
if (std::fsetpos(fp, &pos)) goto fail;
return io_result_mk_ok(usize_to_nat(size_t(fsize)));
fail:
return io_result_mk_error(decode_io_error(errno, nullptr));
}
/* Handle.flush : (@& Handle) → IO Bool */
extern "C" obj_res lean_io_prim_handle_flush(b_obj_arg h, obj_arg /* w */) {
FILE * fp = io_get_handle(h);