feat: IO.FS.Handle.size
This commit is contained in:
parent
f6b3fedcc6
commit
3fca58ea8c
2 changed files with 33 additions and 3 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue