Skip to content

Commit

Permalink
port Stream functions to Seq functions
Browse files Browse the repository at this point in the history
  • Loading branch information
gasche committed Feb 9, 2022
1 parent cd54070 commit 22d0aed
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 56 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

- The function `to_file` now adds a newline at the end of the generated file. An
optional argument allows to return to the original behaviour (#124, @panglesd)
- The `stream_from_*` and `stream_to_*` functions now use a `Seq.t` instead of a
`Stream.t`, and they are renamed into `seq_from_*` and `seq_to_*` (@gasche, #131).

### Fix

Expand Down
6 changes: 3 additions & 3 deletions bench/bench.ml
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ let main () =
ignore (Yojson.Safe.to_channel oc large_int_assoc)));
begin
let buf = Buffer.create 1000 in
Bench.Test.create ~name:"JSON stream roundtrip" (fun () ->
let stream = Yojson.Safe.stream_from_string ~buf streamable_string in
ignore (Yojson.Safe.stream_to_string ~buf stream)
Bench.Test.create ~name:"JSON seq roundtrip" (fun () ->
let stream = Yojson.Safe.seq_from_string ~buf streamable_string in
ignore (Yojson.Safe.seq_to_string ~buf stream)
)
end;
])
Expand Down
2 changes: 1 addition & 1 deletion bin/ydump.ml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ let polycat write_one streaming in_file out_file =
in
try
if streaming then
Stream.iter (write_one oc) (Yojson.Safe.stream_from_channel ~fname ic)
Seq.iter (write_one oc) (Yojson.Safe.seq_from_channel ~fname ic)
else
write_one oc (Yojson.Safe.from_channel ~fname ic);
finally ();
Expand Down
32 changes: 16 additions & 16 deletions lib/read.mli
Original file line number Diff line number Diff line change
Expand Up @@ -71,82 +71,82 @@ val from_lexbuf :
is false and indicates that only JSON whitespace can be found between
the end of the JSON value and the end of the input. *)

val stream_from_string :
val seq_from_string :
?buf:Buffer.t ->
?fname:string ->
?lnum:int ->
string -> t Stream.t
string -> t Seq.t
(** Input a sequence of JSON values from a string.
Whitespace between JSON values is fine but not required.
See [from_string] for the meaning of the optional arguments. *)

val stream_from_channel :
val seq_from_channel :
?buf:Buffer.t ->
?fin:(unit -> unit) ->
?fname:string ->
?lnum:int ->
in_channel -> t Stream.t
in_channel -> t Seq.t
(** Input a sequence of JSON values from a channel.
Whitespace between JSON values is fine but not required.
@param fin finalization function executed once when the end of the
stream is reached either because there is no more input or because
sequence is reached either because there is no more input or because
the input could not be parsed, raising an exception.
@raise Finally When the parsing and the finalizer both raised, [Finally (exn, fin_exn)]
is raised, [exn] being the parsing exception and [fin_exn] the finalizer one.
See [from_string] for the meaning of the other optional arguments. *)

val stream_from_file :
val seq_from_file :
?buf:Buffer.t ->
?fname:string ->
?lnum:int ->
string -> t Stream.t
string -> t Seq.t
(** Input a sequence of JSON values from a file.
Whitespace between JSON values is fine but not required.
See [from_string] for the meaning of the optional arguments. *)

val stream_from_lexbuf :
val seq_from_lexbuf :
lexer_state ->
?fin:(unit -> unit) ->
Lexing.lexbuf -> t Stream.t
Lexing.lexbuf -> t Seq.t
(** Input a sequence of JSON values from a lexbuf.
A valid initial [lexer_state] can be created with [init_lexer].
Whitespace between JSON values is fine but not required.
@raise Finally When the parsing and the finalizer both raised, [Finally (exn, fin_exn)]
is raised, [exn] being the parsing exception and [fin_exn] the finalizer one.
See [stream_from_channel] for the meaning of the optional [fin]
See [seq_from_channel] for the meaning of the optional [fin]
argument. *)


type json_line = [ `Json of t | `Exn of exn ]
(** The type of values resulting from a parsing attempt of a JSON value. *)

val linestream_from_channel :
val lineseq_from_channel :
?buf:Buffer.t ->
?fin:(unit -> unit) ->
?fname:string ->
?lnum:int ->
in_channel -> json_line Stream.t
in_channel -> json_line Seq.t
(** Input a sequence of JSON values, one per line, from a channel.
Exceptions raised when reading malformed lines are caught
and represented using [`Exn].
See [stream_from_channel] for the meaning of the optional [fin]
See [seq_from_channel] for the meaning of the optional [fin]
argument.
See [from_string] for the meaning of the other optional arguments. *)

val linestream_from_file :
val lineseq_from_file :
?buf:Buffer.t ->
?fname:string ->
?lnum:int ->
string -> json_line Stream.t
string -> json_line Seq.t
(** Input a sequence of JSON values, one per line, from a file.
Exceptions raised when reading malformed lines are caught
and represented using [`Exn].
See [stream_from_channel] for the meaning of the optional [fin]
See [seq_from_channel] for the meaning of the optional [fin]
argument.
See [from_string] for the meaning of the other optional arguments. *)

Expand Down
39 changes: 19 additions & 20 deletions lib/read.mll
Original file line number Diff line number Diff line change
Expand Up @@ -1143,30 +1143,30 @@ and junk = parse

exception Finally of exn * exn

let stream_from_lexbuf v ?(fin = fun () -> ()) lexbuf =
let seq_from_lexbuf v ?(fin = fun () -> ()) lexbuf =
let stream = Some true in
let f i =
try Some (from_lexbuf v ?stream lexbuf)
let rec f () =
try Seq.Cons (from_lexbuf v ?stream lexbuf, f)
with
End_of_input ->
fin ();
None
Seq.Nil
| e ->
(try fin () with fin_e -> raise (Finally (e, fin_e)));
raise e
in
Stream.from f
f
let stream_from_string ?buf ?fname ?lnum s =
let seq_from_string ?buf ?fname ?lnum s =
let v = init_lexer ?buf ?fname ?lnum () in
stream_from_lexbuf v (Lexing.from_string s)
seq_from_lexbuf v (Lexing.from_string s)
let stream_from_channel ?buf ?fin ?fname ?lnum ic =
let seq_from_channel ?buf ?fin ?fname ?lnum ic =
let lexbuf = Lexing.from_channel ic in
let v = init_lexer ?buf ?fname ?lnum () in
stream_from_lexbuf v ?fin lexbuf
seq_from_lexbuf v ?fin lexbuf
let stream_from_file ?buf ?fname ?lnum file =
let seq_from_file ?buf ?fname ?lnum file =
let ic = open_in file in
let fin () = close_in ic in
let fname =
Expand All @@ -1176,37 +1176,36 @@ and junk = parse
in
let lexbuf = Lexing.from_channel ic in
let v = init_lexer ?buf ?fname ?lnum () in
stream_from_lexbuf v ~fin lexbuf
seq_from_lexbuf v ~fin lexbuf
type json_line = [ `Json of t | `Exn of exn ]
let linestream_from_channel
let lineseq_from_channel
?buf ?(fin = fun () -> ()) ?fname ?lnum:(lnum0 = 1) ic =
let buf =
match buf with
None -> Some (Buffer.create 256)
| Some _ -> buf
in
let f i =
let rec f lnum = fun () ->
try
let line = input_line ic in
let lnum = lnum0 + i in
Some (`Json (from_string ?buf ?fname ~lnum line))
Seq.Cons (`Json (from_string ?buf ?fname ~lnum line), f (lnum + 1))
with
End_of_file -> fin (); None
| e -> Some (`Exn e)
End_of_file -> fin (); Seq.Nil
| e -> Seq.Cons (`Exn e, f (lnum + 1))
in
Stream.from f
f lnum0
let linestream_from_file ?buf ?fname ?lnum file =
let lineseq_from_file ?buf ?fname ?lnum file =
let ic = open_in file in
let fin () = close_in ic in
let fname =
match fname with
None -> Some file
| x -> x
in
linestream_from_channel ?buf ~fin ?fname ?lnum ic
lineseq_from_channel ?buf ~fin ?fname ?lnum ic
let prettify ?std s =
pretty_to_string ?std (from_string s)
Expand Down
16 changes: 8 additions & 8 deletions lib/write.ml
Original file line number Diff line number Diff line change
Expand Up @@ -467,34 +467,34 @@ let to_file ?len ?std ?(newline = true) file x =
close_out_noerr oc;
raise e

let stream_to_buffer ?std ob st =
Stream.iter (to_buffer ?std ob) st
let seq_to_buffer ?std ob st =
Seq.iter (to_buffer ?std ob) st

let stream_to_string ?buf ?(len = 256) ?std st =
let seq_to_string ?buf ?(len = 256) ?std st =
let ob =
match buf with
None -> Buffer.create len
| Some ob ->
Buffer.clear ob;
ob
in
stream_to_buffer ?std ob st;
seq_to_buffer ?std ob st;
let s = Buffer.contents ob in
Buffer.clear ob;
s

let stream_to_channel ?buf ?(len=2096) ?std oc st =
let seq_to_channel ?buf ?(len=2096) ?std oc st =
let ob =
match buf with
None -> Buffer.create len
| Some ob -> ob
in
stream_to_buffer ?std ob st
seq_to_buffer ?std ob st

let stream_to_file ?len ?std file st =
let seq_to_file ?len ?std file st =
let oc = open_out file in
try
stream_to_channel ?len ?std oc st;
seq_to_channel ?len ?std oc st;
close_out oc
with e ->
close_out_noerr oc;
Expand Down
16 changes: 8 additions & 8 deletions lib/write.mli
Original file line number Diff line number Diff line change
Expand Up @@ -61,36 +61,36 @@ val to_buffer :
(** Write a compact JSON value to an existing buffer.
See [to_string] for the role of the optional argument. *)

val stream_to_string :
val seq_to_string :
?buf:Buffer.t ->
?len:int ->
?std:bool ->
t Stream.t -> string
t Seq.t -> string
(** Write a newline-separated sequence of compact one-line JSON values to
a string.
See [to_string] for the role of the optional arguments. *)

val stream_to_channel :
val seq_to_channel :
?buf:Buffer.t ->
?len:int ->
?std:bool ->
out_channel -> t Stream.t -> unit
out_channel -> t Seq.t -> unit
(** Write a newline-separated sequence of compact one-line JSON values to
a channel.
See [to_channel] for the role of the optional arguments. *)

val stream_to_file :
val seq_to_file :
?len:int ->
?std:bool ->
string -> t Stream.t -> unit
string -> t Seq.t -> unit
(** Write a newline-separated sequence of compact one-line JSON values to
a file.
See [to_string] for the role of the optional arguments. *)

val stream_to_buffer :
val seq_to_buffer :
?std:bool ->
Buffer.t ->
t Stream.t -> unit
t Seq.t -> unit
(** Write a newline-separated sequence of compact one-line JSON values to
an existing buffer.
See [to_string] for the role of the optional arguments. *)
Expand Down
1 change: 1 addition & 0 deletions yojson.opam
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ depends: [
"cppo" {build}
"alcotest" {with-test & >= "0.8.5"}
"odoc" {with-doc}
"seq" {>= "0.2.2"}
]
synopsis:
"Yojson is an optimized parsing and printing library for the JSON format"
Expand Down

0 comments on commit 22d0aed

Please sign in to comment.