mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 11:15:31 -05:00
Bencode: sequence bencode <-> sequence string;
BencodeOnDisk: ability to write a list of values in one atomic operation
This commit is contained in:
parent
204cb0dacb
commit
fe86ffcbb8
4 changed files with 57 additions and 2 deletions
28
bencode.ml
28
bencode.ml
|
|
@ -333,3 +333,31 @@ let of_string s =
|
||||||
| ParseOk t -> t
|
| ParseOk t -> t
|
||||||
| ParsePartial -> invalid_arg "Bencode: partial parse"
|
| ParsePartial -> invalid_arg "Bencode: partial parse"
|
||||||
| ParseError msg -> invalid_arg msg
|
| ParseError msg -> invalid_arg msg
|
||||||
|
|
||||||
|
(** {2 Iterator} *)
|
||||||
|
|
||||||
|
type 'a sequence = ('a -> unit) -> unit
|
||||||
|
|
||||||
|
let of_seq seq =
|
||||||
|
fun k ->
|
||||||
|
let decoder = mk_decoder () in
|
||||||
|
(* read a string *)
|
||||||
|
let rec read_chunk str =
|
||||||
|
match parse decoder str 0 (String.length str) with
|
||||||
|
| ParseOk v ->
|
||||||
|
k v; (* yield, and parse the rest of the string *)
|
||||||
|
resume ()
|
||||||
|
| ParseError e -> raise (Invalid_argument e)
|
||||||
|
| ParsePartial -> () (* wait for next chunk *)
|
||||||
|
and resume () = match parse_resume decoder with
|
||||||
|
| ParseOk v ->
|
||||||
|
k v;
|
||||||
|
resume ()
|
||||||
|
| ParseError e -> raise (Invalid_argument e)
|
||||||
|
| ParsePartial -> () (* wait for next chunk *)
|
||||||
|
in
|
||||||
|
seq read_chunk
|
||||||
|
|
||||||
|
let to_seq seq =
|
||||||
|
fun k -> seq (fun b -> k (to_string b))
|
||||||
|
|
||||||
|
|
|
||||||
15
bencode.mli
15
bencode.mli
|
|
@ -113,3 +113,18 @@ val parse_string : string -> parse_result
|
||||||
|
|
||||||
val of_string : string -> t
|
val of_string : string -> t
|
||||||
(** Parse the string. @raise Invalid_argument if it fails to parse. *)
|
(** Parse the string. @raise Invalid_argument if it fails to parse. *)
|
||||||
|
|
||||||
|
(** {2 Iterator} *)
|
||||||
|
|
||||||
|
type 'a sequence = ('a -> unit) -> unit
|
||||||
|
|
||||||
|
val of_seq : string sequence -> t sequence
|
||||||
|
(** Given a sequence of strings into Bencode values. Strings can be
|
||||||
|
the result of {!Unix.read}, for instance, they don't need to be
|
||||||
|
valid bencode individually; Only their concatenation should
|
||||||
|
be a valid stream of Bencode values.
|
||||||
|
|
||||||
|
@raise Invalid_argument if a parsing error occurs. *)
|
||||||
|
|
||||||
|
val to_seq : t sequence -> string sequence
|
||||||
|
(** Serialize each value in the sequence of Bencode values *)
|
||||||
|
|
|
||||||
|
|
@ -57,12 +57,11 @@ let open_out ?lock filename =
|
||||||
let close_out out =
|
let close_out out =
|
||||||
Unix.close out.file
|
Unix.close out.file
|
||||||
|
|
||||||
let write out b =
|
let write_string out s =
|
||||||
Unix.lockf out.lock_file Unix.F_LOCK 0;
|
Unix.lockf out.lock_file Unix.F_LOCK 0;
|
||||||
try
|
try
|
||||||
(* go to the end of the file *)
|
(* go to the end of the file *)
|
||||||
ignore (Unix.lseek out.file 0 Unix.SEEK_END);
|
ignore (Unix.lseek out.file 0 Unix.SEEK_END);
|
||||||
let s = Bencode.to_string b in
|
|
||||||
(* call write() until everything is written *)
|
(* call write() until everything is written *)
|
||||||
let rec write_all n =
|
let rec write_all n =
|
||||||
if n >= String.length s
|
if n >= String.length s
|
||||||
|
|
@ -78,6 +77,16 @@ let write out b =
|
||||||
Unix.lockf out.lock_file Unix.F_ULOCK 0;
|
Unix.lockf out.lock_file Unix.F_ULOCK 0;
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
|
let write out b =
|
||||||
|
let s = Bencode.to_string b in
|
||||||
|
write_string out s
|
||||||
|
|
||||||
|
let write_batch out l =
|
||||||
|
let buf = Buffer.create 255 in
|
||||||
|
List.iter (fun b -> Bencode.to_buf buf b) l;
|
||||||
|
let s = Buffer.contents buf in
|
||||||
|
write_string out s
|
||||||
|
|
||||||
type 'a result =
|
type 'a result =
|
||||||
| Ok of 'a
|
| Ok of 'a
|
||||||
| Error of string
|
| Error of string
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,9 @@ val close_out : t -> unit
|
||||||
val write : t -> Bencode.t -> unit
|
val write : t -> Bencode.t -> unit
|
||||||
(** Write "atomically" a value to the end of the file *)
|
(** Write "atomically" a value to the end of the file *)
|
||||||
|
|
||||||
|
val write_batch : t -> Bencode.t list -> unit
|
||||||
|
(** Write several values at once, at the end of the file *)
|
||||||
|
|
||||||
type 'a result =
|
type 'a result =
|
||||||
| Ok of 'a
|
| Ok of 'a
|
||||||
| Error of string
|
| Error of string
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue