improve API of chunk_stack

This commit is contained in:
Simon Cruanes 2021-10-14 23:40:58 -04:00
parent 7df124f94c
commit ca4a42f28a
No known key found for this signature in database
GPG key ID: 4AC01D0849AA62B6
2 changed files with 19 additions and 16 deletions

View file

@ -75,10 +75,8 @@ module Reader = struct
read: 'a. yield:(bytes -> int -> int -> 'a) -> finish:(unit -> 'a) -> 'a; read: 'a. yield:(bytes -> int -> int -> 'a) -> finish:(unit -> 'a) -> 'a;
} [@@unboxed] } [@@unboxed]
let[@inline] next (self:t) f : bool = let[@inline] next (self:t) ~yield ~finish =
self.read self.read ~yield ~finish
~yield:(fun b i len -> f b i len; true)
~finish:(fun () -> false)
let next_string (self:t) : string option = let next_string (self:t) : string option =
self.read self.read
@ -108,14 +106,11 @@ module Reader = struct
in in
{ read; } { read; }
let with_file_backward (filename:string) f = let from_channel_backward ic =
CCIO.with_in ~flags:[Open_binary; Open_rdonly] filename @@ fun ic ->
let len = in_channel_length ic in let len = in_channel_length ic in
seek_in ic len; seek_in ic len;
let blen = Bytes.create 4 in (* to read length *) let buf = Buf.create ~cap:32 () in (* local buffer *)
let buf = Buf.create() in (* local buffer *)
let read ~yield ~finish = let read ~yield ~finish =
let pos = pos_in ic in let pos = pos_in ic in
@ -124,21 +119,27 @@ module Reader = struct
assert (pos>=4); assert (pos>=4);
seek_in ic (pos - 4); seek_in ic (pos - 4);
really_input ic blen 0 4; really_input ic buf.Buf.b 0 4;
let chunk_len = Int32.to_int (Bytes.get_int32_le blen 0) in let chunk_len = Int32.to_int (Bytes.get_int32_le buf.Buf.b 0) in
(* now read chunk *) (* now read chunk *)
Buf.ensure_size_ buf chunk_len; Buf.ensure_size_ buf chunk_len;
seek_in ic (pos - 4 - chunk_len); seek_in ic (pos - 4 - chunk_len);
really_input ic buf.Buf.b 0 chunk_len; really_input ic buf.Buf.b 0 chunk_len;
buf.Buf.len <- chunk_len; buf.Buf.len <- chunk_len;
seek_in ic (pos - 4 - chunk_len);
yield buf.Buf.b 0 buf.Buf.len yield buf.Buf.b 0 buf.Buf.len
) else ( ) else (
finish() finish()
) )
in in
f {read} {read}
let with_file_backward (filename:string) f =
CCIO.with_in ~flags:[Open_binary; Open_rdonly] filename @@ fun ic ->
let r = from_channel_backward ic in
f r
end end
(*$T (*$T

View file

@ -46,9 +46,8 @@ end
module Reader : sig module Reader : sig
type t type t
val next : t -> (bytes -> int -> int -> unit) -> bool val next : t -> yield:(bytes -> int -> int -> 'a) -> finish:(unit -> 'a) -> 'a
(** Read next chunk, call the function with a slice of bytes. (** Read next chunk, call [yield] with a slice of bytes, otherwise call [finish()]. *)
Returns [true] if a chunk was read, [false] if no more chunks are there. *)
val next_string : t -> string option val next_string : t -> string option
(** Read next chunk as a string *) (** Read next chunk as a string *)
@ -57,9 +56,12 @@ module Reader : sig
val from_buf : Buf.t -> t val from_buf : Buf.t -> t
val from_channel_backward : in_channel -> t
(** Read channel from the end, assuming that is possible. *)
val with_file_backward : string -> (t -> 'a) -> 'a
(** [read_file_backward filename f] calls [f] with an iterator (** [read_file_backward filename f] calls [f] with an iterator
over chunks of the file, read from the end. over chunks of the file, read from the end.
Each chunk is assumed to be followed by its length as an int32 LE. *) Each chunk is assumed to be followed by its length as an int32 LE. *)
val with_file_backward : string -> (t -> 'a) -> 'a
end end