let fold_file f init fname =
let inchan = open_in fname in
- let rec fold_lines' value =
- try
- let line = input_line inchan in
- fold_lines' (f value line)
- with End_of_file -> value
+ let res =
+ try
+ Zack.fold_in f init inchan
+ with e -> close_in inchan; raise e
in
- let res = (try fold_lines' init with e -> (close_in inchan; raise e)) in
close_in inchan;
res
+
let iter_file f = fold_file (fun _ line -> f line) ()
let hashtbl_sorted_fold f tbl init =
Some (Http_client.Convenience.http_get url)
with Http_client.Http_error (code, _) -> None
+ (** apply a transformation "string list -> string list" to file lines *)
+let mangle_file ~fname f =
+ let ic = open_in fname in
+ let lines = Zack.input_lines ic in
+ close_in ic;
+ let oc = open_out fname in
+ Zack.output_lines (f lines) oc;
+ close_out oc
+;;
+
+let add_line ~fname ?position line =
+ mangle_file ~fname
+ (fun lines ->
+ match position with
+ | None -> lines @ [line]
+ | Some i ->
+ assert (i >= 0);
+ let rec add_after i = function
+ | (acc, []) -> acc @ [line] (* eof *)
+ | (acc, ((hd::tl) as l)) ->
+ if i = 0 then
+ acc @ [line] @ l
+ else
+ add_after (i-1) (acc @ [hd], tl)
+ in
+ add_after i ([], lines))
+;;
+
+let remove_line ~fname position =
+ mangle_file ~fname
+ (fun lines ->
+ assert (position >= 0);
+ let rec remove i = function
+ | (acc, []) -> acc (* eof *)
+ | (acc, ((hd::tl) as l)) ->
+ if i = 0 then
+ acc @ tl
+ else
+ remove (i-1) (acc @ [hd], tl)
+ in
+ remove position ([], lines))
+;;
+
remote resources fetched via HTTP GET requests *)
val http_get_iter_buf: callback:(string -> unit) -> string -> unit
+ (** add a line to a file (specified by name) _after_ a given line (defaults to
+ last line). *)
+val add_line: fname:string -> ?position:int -> string -> unit
+ (** remove a line, if any, from a file specified by line number (0 based, i.e.
+ first line of file is line 0) *)
+val remove_line: fname:string -> int -> unit
+