From 61b9762269bc9296febabdf9bf8a667b0eac11d3 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Sat, 26 Jun 2021 23:50:30 -0400 Subject: [PATCH] feat(CCIO): add many `Seq.t` based functions each generator function can now produce a seq. --- src/core/CCIO.ml | 51 ++++++++++++++++++++++++++++++++++++++++++++--- src/core/CCIO.mli | 21 +++++++++++++++++++ 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/src/core/CCIO.ml b/src/core/CCIO.ml index 54292dd7..1ae7744d 100644 --- a/src/core/CCIO.ml +++ b/src/core/CCIO.ml @@ -52,6 +52,27 @@ let gen_flat_map f next_elem = in next +type 'a seq_of_gen_state_ = + | Of_gen_thunk of 'a gen + | Of_gen_saved of 'a Seq.node + +let seq_of_gen_ g = + let rec consume r () = match !r with + | Of_gen_saved cons -> cons + | Of_gen_thunk g -> + begin match g() with + | None -> + r := Of_gen_saved Seq.Nil; + Nil + | Some x -> + let tl = consume (ref (Of_gen_thunk g)) in + let l = Seq.Cons (x, tl) in + r := Of_gen_saved l; + l + end + in + consume (ref (Of_gen_thunk g)) + let finally_ f x ~h = try let res = f x in @@ -75,6 +96,9 @@ let read_chunks_gen ?(size=1024) ic = in next +let read_chunks_seq ?size ic = + seq_of_gen_ (read_chunks_gen ?size ic) + let read_line ic = try Some (input_line ic) with End_of_file -> None @@ -86,6 +110,9 @@ let read_lines_gen ic = else try Some (input_line ic) with End_of_file -> (stop:=true; None) +let read_lines_seq ic = + seq_of_gen_ (read_chunks_gen ic) + let read_lines_l ic = let l = ref [] in try @@ -152,17 +179,30 @@ let write_line oc s = output_char oc '\n' let write_gen ?(sep="") oc g = - let rec recurse () = match g() with + let rec recurse g = match g() with | None -> () | Some s -> output_string oc sep; output_string oc s; - recurse () + recurse g in match g() with | None -> () | Some s -> output_string oc s; - recurse () + recurse g + +let write_seq ?(sep="") oc seq : unit = + let rec recurse g = match g() with + | Seq.Nil -> () + | Seq.Cons(s,seq) -> + output_string oc sep; + output_string oc s; + recurse seq + in match seq() with + | Seq.Nil -> () + | Seq.Cons(s,seq) -> + output_string oc s; + recurse seq let rec write_lines oc g = match g () with | None -> () @@ -170,6 +210,9 @@ let rec write_lines oc g = match g () with write_line oc l; write_lines oc g +let write_lines_seq oc seq = + Seq.iter (write_line oc) seq + let write_lines_l oc l = List.iter (write_line oc) l @@ -342,6 +385,8 @@ module File = struct ) *) + let walk_seq d = seq_of_gen_ (walk d) + let walk_l d = let l = ref [] in let g = walk d in diff --git a/src/core/CCIO.mli b/src/core/CCIO.mli index 323b33ab..4cb58707 100644 --- a/src/core/CCIO.mli +++ b/src/core/CCIO.mli @@ -71,6 +71,12 @@ val read_chunks_gen : ?size:int -> in_channel -> string gen {b NOTE} the generator must be used within the lifetime of the channel, see warning at the top of the file. *) +val read_chunks_seq : ?size:int -> in_channel -> string Seq.t +(** Read the channel's content into chunks of size [size]. + {b NOTE} the generator must be used within the lifetime of the channel, + see warning at the top of the file. + @since NEXT_RELEASE *) + val read_line : in_channel -> string option (** Read a line from the channel. Returns [None] if the input is terminated. The "\n" is removed from the line. *) @@ -80,6 +86,12 @@ val read_lines_gen : in_channel -> string gen {b NOTE} the generator must be used within the lifetime of the channel, see warning at the top of the file. *) +val read_lines_seq : in_channel -> string Seq.t +(** Read all lines. + {b NOTE} the seq must be used within the lifetime of the channel, + see warning at the top of the file. + @since NEXT_RELEASE *) + val read_lines_l : in_channel -> string list (** Read all lines into a list. *) @@ -115,9 +127,18 @@ val write_gen : ?sep:string -> out_channel -> string gen -> unit (** Write the given strings on the output. If provided, add [sep] between every two strings (but not at the end). *) +val write_seq : ?sep:string -> out_channel -> string Seq.t -> unit +(** Write the given strings on the output. If provided, add [sep] between + every two strings (but not at the end). + @since NEXT_RELEASE *) + val write_lines : out_channel -> string gen -> unit (** Write every string on the output, followed by "\n". *) +val write_lines_seq : out_channel -> string Seq.t -> unit +(** Write every string on the output, followed by "\n". + @since NEXT_RELEASE *) + val write_lines_l : out_channel -> string list -> unit (** {2 Both} *)