Skip to content

Commit

Permalink
Add suf separator to configure what terminates JSON values
Browse files Browse the repository at this point in the history
This is a generalization of `newline`, but it works for all writing
functions and can be overridden.
  • Loading branch information
Leonidas-from-XIV committed Mar 2, 2022
1 parent 700a222 commit 5e7f07e
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 28 deletions.
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
(@tmcgilchrist, #117)
- Add a benchmark to judge the respective performance of providing a buffer vs
letting Yojson create an internal (#134, @Leonidas-from-XIV)
- Add an optional `suf` keyword argument was added to functions that write
serialized JSON, thus allowing NDJSON output. Most functions default to not
adding any suffix except for `to_file` (#124) and functions writing sequences
of values where the default is `\n` (#135, @Lenoidas-from-XIV)

### Change

Expand Down
40 changes: 19 additions & 21 deletions lib/write.ml
Original file line number Diff line number Diff line change
Expand Up @@ -417,89 +417,87 @@ and write_std_variant ob s o =
#endif


let to_buffer ?(std = false) ob x =
let to_buffer ?(suf = "") ?(std = false) ob x =
if std then
write_std_json ob x
else
write_json ob x

write_json ob x;
Buffer.add_string ob suf

let to_string ?buf ?(len = 256) ?std x =
let to_string ?buf ?(len = 256) ?(suf = "") ?std x =
let ob =
match buf with
None -> Buffer.create len
| Some ob ->
Buffer.clear ob;
ob
in
to_buffer ?std ob x;
to_buffer ~suf ?std ob x;
let s = Buffer.contents ob in
Buffer.clear ob;
s

let to_channel ?buf ?(len=4096) ?std oc x =
let to_channel ?buf ?(len=4096) ?(suf = "") ?std oc x =
let ob =
match buf with
None -> Buffer.create len
| Some ob -> Buffer.clear ob; ob
in
to_buffer ?std ob x;
to_buffer ~suf ?std ob x;
Buffer.output_buffer oc ob;
Buffer.clear ob

let to_output ?buf ?(len=4096) ?std out x =
let to_output ?buf ?(len=4096) ?(suf = "") ?std out x =
let ob =
match buf with
None -> Buffer.create len
| Some ob -> Buffer.clear ob; ob
in
to_buffer ?std ob x;
to_buffer ~suf ?std ob x;
out#output (Buffer.contents ob) 0 (Buffer.length ob);
Buffer.clear ob

let to_file ?len ?std ?(newline = true) file x =
let to_file ?len ?std ?(suf = "\n") file x =
let oc = open_out file in
try
to_channel ?len ?std oc x;
if newline then
output_string oc "\n";
to_channel ?len ~suf ?std oc x;
close_out oc
with e ->
close_out_noerr oc;
raise e

let seq_to_buffer ?std ob st =
Seq.iter (to_buffer ?std ob) st
let seq_to_buffer ?(suf = "\n") ?std ob st =
Seq.iter (to_buffer ~suf ?std ob) st

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

let seq_to_channel ?buf ?(len=2096) ?std oc seq =
let seq_to_channel ?buf ?(len=2096) ?(suf = "\n") ?std oc seq =
let ob =
match buf with
None -> Buffer.create len
| Some ob -> Buffer.clear ob; ob
in
Seq.iter (fun json ->
to_buffer ?std ob json;
to_buffer ~suf ?std ob json;
Buffer.output_buffer oc ob;
Buffer.clear ob;
) seq

let seq_to_file ?len ?std file st =
let seq_to_file ?len ?(suf = "\n") ?std file st =
let oc = open_out file in
try
seq_to_channel ?len ?std oc st;
seq_to_channel ?len ~suf ?std oc st;
close_out oc
with e ->
close_out_noerr oc;
Expand Down
27 changes: 20 additions & 7 deletions lib/write.mli
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
val to_string :
?buf:Buffer.t ->
?len:int ->
?suf:string ->
?std:bool ->
t -> string
(** Write a compact JSON value to a string.
@param buf allows to reuse an existing buffer created with
[Buffer.create]. The buffer is cleared of all contents
before starting and right before returning.
@param len initial length of the output buffer.
@param suf appended to the output as a suffix,
defaults to empty string.
@param std use only standard JSON syntax,
i.e. convert tuples and variants into standard JSON (if applicable),
refuse to print NaN and infinities,
Expand All @@ -20,6 +23,7 @@ val to_string :
val to_channel :
?buf:Buffer.t ->
?len:int ->
?suf:string ->
?std:bool ->
out_channel -> t -> unit
(** Write a compact JSON value to a channel.
Expand All @@ -30,6 +34,7 @@ val to_channel :
val to_output :
?buf:Buffer.t ->
?len:int ->
?suf:string ->
?std:bool ->
< output : string -> int -> int -> int; .. > -> t -> unit
(** Write a compact JSON value to an OO channel.
Expand All @@ -39,14 +44,14 @@ val to_output :
val to_file :
?len:int ->
?std:bool ->
?newline:bool ->
?suf:string ->
string -> t -> unit
(** Write a compact JSON value to a file.
See [to_string] for the role of the optional arguments.
@param newline whether to end the content of the file with a new line.
Optional parameter with value [true] by default. *)
@param suf is the final character of the output. Newline by default. *)

val to_buffer :
?suf:string ->
?std:bool ->
Buffer.t -> t -> unit
(** Write a compact JSON value to an existing buffer.
Expand All @@ -55,35 +60,43 @@ val to_buffer :
val seq_to_string :
?buf:Buffer.t ->
?len:int ->
?suf:string ->
?std:bool ->
t Seq.t -> string
(** Write a newline-separated sequence of compact one-line JSON values to
(** Write a [suf]-separated sequence of compact one-line JSON values to
a string.
@param suf is the suffix ouf each value written. Newline by default.
See [to_string] for the role of the optional arguments. *)

val seq_to_channel :
?buf:Buffer.t ->
?len:int ->
?suf:string ->
?std:bool ->
out_channel -> t Seq.t -> unit
(** Write a newline-separated sequence of compact one-line JSON values to
(** Write a [suf]-separated sequence of compact one-line JSON values to
a channel.
@param suf is the suffix of each value written. Newline by default.
See [to_channel] for the role of the optional arguments. *)

val seq_to_file :
?len:int ->
?suf:string ->
?std:bool ->
string -> t Seq.t -> unit
(** Write a newline-separated sequence of compact one-line JSON values to
(** Write a [suf]-separated sequence of compact one-line JSON values to
a file.
@param suf is the suffix of each value written. Newline by default.
See [to_string] for the role of the optional arguments. *)

val seq_to_buffer :
?suf:string ->
?std:bool ->
Buffer.t ->
t Seq.t -> unit
(** Write a newline-separated sequence of compact one-line JSON values to
(** Write a [suf]-separated sequence of compact one-line JSON values to
an existing buffer.
@param suf is the suffix of each value written. Newline by default.
See [to_string] for the role of the optional arguments. *)

val write_t : Buffer.t -> t -> unit
Expand Down

0 comments on commit 5e7f07e

Please sign in to comment.