package containers
A modular, clean and powerful extension of the OCaml standard library
Install
Dune Dependency
Authors
Maintainers
Sources
containers-3.15.tbz
sha256=92143ceb4785ae5f8a07f3ab4ab9f6f32d31ead0536e9be4fdb818dd3c677e58
sha512=5fa80189d0e177af2302b48e72b70299d51fc36ac2019e1cbf389ff6a7f4705b10089405b5a719b3e4845b0d1349a47a967f865dc2e4e3f0d5a0167ef6c31431
doc/src/containers/CCIO.ml.html
Source file CCIO.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
(* This file is free software, part of containers. See file "license" for more details. *) (** {1 IO Utils} *) type 'a iter = ('a -> unit) -> unit type 'a or_error = ('a, string) result type 'a gen = unit -> 'a option let gen_empty () = None let gen_singleton x = let done_ = ref false in fun () -> if !done_ then None else ( done_ := true; Some x ) let gen_filter_map f gen = (* tailrec *) let rec next () = match gen () with | None -> None | Some x -> (match f x with | None -> next () | Some _ as res -> res) in next let gen_of_array arr = let r = ref 0 in fun () -> if !r = Array.length arr then None else ( let x = arr.(!r) in incr r; Some x ) let rec gen_iter f g = match g () with | None -> () | Some x -> f x; gen_iter f g let gen_flat_map f next_elem = let state = ref `Init in let rec next () = match !state with | `Init -> get_next_gen () | `Run gen -> (match gen () with | None -> get_next_gen () | Some _ as x -> x) | `Stop -> None and get_next_gen () = match next_elem () with | None -> state := `Stop; None | Some x -> (try state := `Run (f x); next () with e -> state := `Stop; raise e) 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 -> (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) in consume (ref (Of_gen_thunk g)) let finally_ f x ~h = try let res = f x in h x; res with e -> h x; raise e let with_in ?(mode = 0o644) ?(flags = [ Open_text ]) filename f = let ic = open_in_gen (Open_rdonly :: flags) mode filename in finally_ f ic ~h:close_in let read_chunks_gen ?(size = 1024) ic = let buf = Bytes.create size in let next () = let n = input ic buf 0 size in if n = 0 then None else Some (Bytes.sub_string buf 0 n) in next let read_chunks_iter ?size ic = let g = read_chunks_gen ?size ic in fun yield -> gen_iter yield g 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 let read_lines_gen ic = let stop = ref false in fun () -> if !stop then None else ( try Some (input_line ic) with End_of_file -> stop := true; None ) let read_lines_seq ic = seq_of_gen_ (read_lines_gen ic) let read_lines_iter ic = let g = read_lines_gen ic in fun yield -> gen_iter yield g let read_lines_l ic = let l = ref [] in try while true do l := input_line ic :: !l done; assert false with End_of_file -> List.rev !l (* thanks to nicoo for this trick *) type _ ret_type = | Ret_string : string ret_type | Ret_bytes : Bytes.t ret_type let read_all_ : type a. op:a ret_type -> size:int -> in_channel -> a = fun ~op ~size ic -> let buf = ref (Bytes.create size) in let len = ref 0 in try while true do (* resize *) if !len = Bytes.length !buf then buf := Bytes.extend !buf 0 !len; assert (Bytes.length !buf > !len); let n = input ic !buf !len (Bytes.length !buf - !len) in len := !len + n; if n = 0 then raise Exit (* exhausted *) done; assert false (* never reached*) with Exit -> (match op with | Ret_string -> Bytes.sub_string !buf 0 !len | Ret_bytes -> Bytes.sub !buf 0 !len) let read_all_bytes ?(size = 1024) ic = read_all_ ~op:Ret_bytes ~size ic let read_all ?(size = 1024) ic = read_all_ ~op:Ret_string ~size ic let with_out ?(mode = 0o644) ?(flags = [ Open_creat; Open_trunc; Open_text ]) filename f = let oc = open_out_gen (Open_wronly :: flags) mode filename in finally_ f oc ~h:close_out let with_out_a ?mode ?(flags = []) filename f = with_out ?mode ~flags:(Open_wronly :: Open_creat :: Open_append :: flags) filename f let write_line oc s = output_string oc s; output_char oc '\n' let write_gen ?(sep = "") oc g = let rec recurse g = match g () with | None -> () | Some s -> output_string oc sep; output_string oc s; recurse g in match g () with | None -> () | Some s -> output_string oc s; 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 -> () | Some l -> write_line oc l; write_lines oc g let write_lines_seq oc seq = Seq.iter (write_line oc) seq let write_lines_iter oc i = i (write_line oc) let write_lines_l oc l = List.iter (write_line oc) l (* test {read,write}_lines. Need to concatenate the lists because some strings in the random input might contain '\n' themselves *) let with_in_out ?(mode = 0o644) ?(flags = [ Open_creat ]) filename f = let ic = open_in_gen (Open_rdonly :: flags) mode filename in let oc = open_out_gen (Open_wronly :: flags) mode filename in try let x = f ic oc in close_out oc; (* must be first?! *) close_in ic; x with e -> close_out_noerr oc; close_in_noerr ic; raise e let copy_into ?(bufsize = 4_096) ic oc : unit = let buf = Bytes.create bufsize in let cont = ref true in while !cont do let n = input ic buf 0 bufsize in if n > 0 then output oc buf 0 n else cont := false done let tee funs g () = match g () with | None -> None | Some x as res -> List.iter (fun f -> f x) funs; res (* TODO: lines/unlines: string gen -> string gen *) (* TODO: words: string gen -> string gen, with a state machine that goes: - 0: read input chunk - switch to "search for ' '", and yield word - goto 0 if no ' ' found - yield leftover when g returns Stop *) module File = struct type t = string let to_string f = f let make f = if Filename.is_relative f then Filename.concat (Sys.getcwd ()) f else f let exists f = Sys.file_exists f let is_directory f = Sys.is_directory f let remove_exn f = Sys.remove f let remove f = try Ok (Sys.remove f) with exn -> Error (Printexc.to_string exn) let read_exn f = with_in f (read_all_ ~op:Ret_string ~size:4096) let read f = try Ok (read_exn f) with e -> Error (Printexc.to_string e) let append_exn f x = with_out ~flags:[ Open_append; Open_creat; Open_text ] f (fun oc -> output_string oc x; flush oc) let append f x = try Ok (append_exn f x) with e -> Error (Printexc.to_string e) let write_exn f x = with_out f (fun oc -> output_string oc x; flush oc) let write f x = try Ok (write_exn f x) with e -> Error (Printexc.to_string e) let remove_noerr f = try Sys.remove f with _ -> () let read_dir_base d = if Sys.is_directory d then ( let arr = Sys.readdir d in gen_of_array arr ) else fun () -> None let cons_ x tl = let first = ref true in fun () -> if !first then ( first := false; Some x ) else tl () let rec walk d = if not (Sys.file_exists d) then gen_empty else if Sys.is_directory d then ( (* try to list the directory *) let arr = try Sys.readdir d with Sys_error _ -> [||] in let tail = gen_of_array arr in let tail = gen_flat_map (fun s -> walk (Filename.concat d s)) tail in cons_ (`Dir, d) tail ) else gen_singleton (`File, d) let walk_seq d = seq_of_gen_ (walk d) let walk_iter d yield = gen_iter yield (walk d) let walk_l d = let l = ref [] in let g = walk d in let rec aux () = match g () with | None -> !l | Some x -> l := x :: !l; aux () in aux () type walk_item = [ `File | `Dir ] * t let read_dir ?(recurse = false) d = if recurse then gen_filter_map (function | `File, f -> Some f | `Dir, _ -> None) (walk d) else read_dir_base d let show_walk_item ((i, f) : walk_item) = (match i with | `File -> "file:" | `Dir -> "dir:") ^ f let with_temp ?temp_dir ~prefix ~suffix f = let name = Filename.temp_file ?temp_dir prefix suffix in finally_ f name ~h:remove_noerr end
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>