diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 506ae9df..a70fd23e 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,5 +1,20 @@ = Changelog +== 0.21 + +- (breaking) make default `start`/`stop` arguments empty in printers (#82) + +- add `CCFormat.{with_color_sf,fprintf_dyn_color,sprintf_dyn_color}` +- add `CCFormat.Dump` for easy debugging (see #82) +- add `CCArray.Sub.to_list` +- add `CCArray.{sorted,sort_indices,sort_ranking}` (closes #81) + +- handle '\r` in CCSexpM (fixes #83) +- add alias `Containers.IO` +- bugfixes in `CCArray.Sub` +- bugfix + tests for `CCArray.Sub.sub` +- disable parallel build to support cygwin + == 0.20 - bugfix in `CCArray.equal` diff --git a/_oasis b/_oasis index 1fbf5c55..ba273d42 100644 --- a/_oasis +++ b/_oasis @@ -1,6 +1,6 @@ OASISFormat: 0.4 Name: containers -Version: 0.20 +Version: 0.21 Homepage: https://github.com/c-cube/ocaml-containers Authors: Simon Cruanes License: BSD-2-clause @@ -10,7 +10,8 @@ OCamlVersion: >= 4.00.1 BuildTools: ocamlbuild AlphaFeatures: ocamlbuild_more_args -XOCamlbuildExtraArgs: "-j 0" +# cygwin fails with anything else +XOCamlbuildExtraArgs: "-j 1" Synopsis: A modular standard library focused on data structures. Description: diff --git a/opam b/opam index 566581e8..d1bb2e04 100644 --- a/opam +++ b/opam @@ -1,6 +1,6 @@ opam-version: "1.2" name: "containers" -version: "0.20" +version: "0.21" author: "Simon Cruanes" maintainer: "simon.cruanes@inria.fr" build: [ diff --git a/setup.ml b/setup.ml index 7db329de..657cf17a 100644 --- a/setup.ml +++ b/setup.ml @@ -1,7 +1,7 @@ (* setup.ml generated for the first time by OASIS v0.4.4 *) (* OASIS_START *) -(* DO NOT EDIT (digest: 1ed8a841a820b1830b239987cd022aa8) *) +(* DO NOT EDIT (digest: 5a4456e803f365ce3410624a599bc76f) *) (* Regenerated by OASIS v0.4.7 Visit http://oasis.forge.ocamlcore.org for more information and @@ -6980,7 +6980,7 @@ open OASISTypes;; let setup_t = { BaseSetup.configure = InternalConfigurePlugin.configure; - build = OCamlbuildPlugin.build ["-use-ocamlfind"; "-j 0"]; + build = OCamlbuildPlugin.build ["-use-ocamlfind"; "-j 1"]; test = [ ("all", @@ -7049,7 +7049,7 @@ let setup_t = { oasis_version = "0.4"; ocaml_version = Some (OASISVersion.VGreaterEqual "4.00.1"); - version = "0.20"; + version = "0.21"; license = OASISLicense.DEP5License (OASISLicense.DEP5Unit @@ -9689,7 +9689,7 @@ let setup_t = }; oasis_fn = Some "_oasis"; oasis_version = "0.4.7"; - oasis_digest = Some "\223\133\236\175X\030c\221\172i#\201\\\181\1865"; + oasis_digest = Some "v\210\236\240,\180C\195X\143\011\\\217Y\180\206"; oasis_exec = None; oasis_setup_args = []; setup_update = false diff --git a/src/core/CCArray.ml b/src/core/CCArray.ml index cc7b622f..f881489e 100644 --- a/src/core/CCArray.ml +++ b/src/core/CCArray.ml @@ -51,6 +51,29 @@ module type S = sig val reverse_in_place : 'a t -> unit (** Reverse the array in place *) + val sorted : ('a -> 'a -> int) -> 'a t -> 'a array + (** [sorted cmp a] makes a copy of [a] and sorts it with [cmp]. + @since 0.21 *) + + val sort_indices : ('a -> 'a -> int) -> 'a t -> int array + (** [sort_indices cmp a] returns a new array [b], with the same length as [a], + such that [b.(i)] is the index of the [i]-th element of [a] in [sort cmp a]. + In other words, [map (fun i -> a.(i)) (sort_indices a) = sorted cmp a]. + [a] is not modified. + @since 0.21 *) + + val sort_ranking : ('a -> 'a -> int) -> 'a t -> int array + (** [sort_ranking cmp a] returns a new array [b], with the same length as [a], + such that [b.(i)] is the position in [sorted cmp a] of the [i]-th + element of [a]. + [a] is not modified. + + In other words, [map (fun i -> (sorted cmp a).(i)) (sort_ranking cmp a) = a]. + + Without duplicates, we also have + [lookup_exn a.(i) (sorted a) = (sorted_ranking a).(i)] + @since 0.21 *) + val find : ('a -> 'b option) -> 'a t -> 'b option (** [find f a] returns [Some y] if there is an element [x] such that [f x = Some y], else it returns [None] *) @@ -260,6 +283,18 @@ let _shuffle _rand_int a i j = let b = Array.copy a in shuffle_with st a; a <> b *) +let _sort_indices cmp a i j = + let len = j-i in + let b = Array.init len (fun k->k) in + Array.sort (fun k1 k2 -> cmp a.(k1+i) a.(k2+i)) b; + b + +let _sorted cmp a i j = + let len = j-i in + let b = Array.sub a i len in + Array.sort cmp b; + b + let _choose a i j st = if i>=j then raise Not_found; a.(i+Random.State.int st (j-i)) @@ -366,6 +401,48 @@ let reverse_in_place a = a = [| 6;5;4;3;2;1 |] *) +let sorted cmp a = _sorted cmp a 0 (Array.length a) + +(*$= & ~cmp:(=) ~printer:Q.Print.(array int) + [||] (sorted Pervasives.compare [||]) + [|0;1;2;3;4|] (sorted Pervasives.compare [|3;2;1;4;0|]) + *) + +(*$Q + Q.(array int) (fun a -> \ + let b = Array.copy a in \ + Array.sort Pervasives.compare b; b = sorted Pervasives.compare a) +*) + +let sort_indices cmp a = _sort_indices cmp a 0 (Array.length a) + +(*$= & ~cmp:(=) ~printer:Q.Print.(array int) + [||] (sort_indices Pervasives.compare [||]) + [|4;2;1;0;3|] (sort_indices Pervasives.compare [|"d";"c";"b";"e";"a"|]) +*) + +(*$Q + Q.(array printable_string) (fun a -> \ + let b = sort_indices String.compare a in \ + sorted String.compare a = Array.map (Array.get a) b) +*) + +let sort_ranking cmp a = + let cmp_int : int -> int -> int = Pervasives.compare in + sort_indices cmp_int (sort_indices cmp a) + +(*$= & ~cmp:(=) ~printer:Q.Print.(array int) + [||] (sort_ranking Pervasives.compare [||]) + [|3;2;1;4;0|] (sort_ranking Pervasives.compare [|"d";"c";"b";"e";"a"|]) +*) + +(*$Q + Q.(array printable_string) (fun a -> \ + let b = sort_ranking String.compare a in \ + let a_sorted = sorted String.compare a in \ + a = Array.map (Array.get a_sorted) b) +*) + let rev a = let b = Array.copy a in reverse_in_place b; @@ -618,7 +695,15 @@ module Sub = struct let copy a = Array.sub a.arr a.i (length a) - let sub a i len = make a.arr ~len:(a.i + i) len + let sub a i len = make a.arr (a.i + i) ~len + (*$= + [ 3;4 ] \ + (let a = Sub.make (0--10) 2 5 in Sub.sub a 1 2 |> Sub.to_list) + [ ] \ + (let a = Sub.make (0--10) 2 5 in Sub.sub a 1 0 |> Sub.to_list) + [ 5 ] \ + (let a = Sub.make (0--10) 1 9 in Sub.sub a 4 1 |> Sub.to_list) + *) let equal eq a b = length a = length b && _equal eq a.arr a.i a.j b.arr b.i b.j @@ -632,6 +717,10 @@ module Sub = struct else _fold (f acc a.arr.(i)) (i+1) j in _fold acc a.i a.j + let to_list a = + let l = fold (fun l x -> x::l) [] a in + List.rev l + let foldi f acc a = _foldi f acc a.arr a.i a.j let fold_while f acc a = @@ -689,22 +778,95 @@ module Sub = struct Sub.reverse_in_place s; a = [| 1; 2; 5; 4; 3; 6 |] *) + let sorted cmp a = _sorted cmp a.arr a.i a.j + + (*$= & ~cmp:(=) ~printer:Q.Print.(array int) + [||] \ + (let a = 1--6 in let s = Sub.make a 2 ~len:0 in \ + Sub.sorted Pervasives.compare s) + [|2;3;4|] \ + (let a = [|6;5;4;3;2;1|] in let s = Sub.make a 2 ~len:3 in \ + Sub.sorted Pervasives.compare s) + *) + + (*$Q + Q.(array int) (fun a -> \ + Array.length a > 10 ==> ( Array.length a > 10 && \ + let s = Sub.make a 5 ~len:5 in \ + let b = Array.sub a 5 5 in \ + Array.sort Pervasives.compare b; b = Sub.sorted Pervasives.compare s)) + *) + + let sort_ranking cmp a = + let idx = _sort_indices cmp a.arr a.i a.j in + let cmp_int : int -> int -> int = Pervasives.compare in + sort_indices cmp_int idx + + (*$= & ~cmp:(=) ~printer:Q.Print.(array int) + [||] \ + (let a = 1--6 in let s = Sub.make a 2 ~len:0 in \ + Sub.sort_ranking Pervasives.compare s) + [|2;1;3;0|] \ + (let a = [|"d";"c";"b";"e";"a"|] in let s = Sub.make a 1 ~len:4 in \ + Sub.sort_ranking Pervasives.compare s) + *) + + (*$Q + Q.(array printable_string) (fun a -> \ + Array.length a > 10 ==> ( Array.length a > 10 && \ + let s = Sub.make a 5 ~len:5 in \ + let b = Sub.sort_indices String.compare s in \ + Sub.sorted String.compare s = Array.map (Sub.get s) b)) + *) + + let sort_indices cmp a = _sort_indices cmp a.arr a.i a.j + + (*$= & ~cmp:(=) ~printer:Q.Print.(array int) + [||] \ + (let a = 1--6 in let s = Sub.make a 2 ~len:0 in \ + Sub.sort_indices Pervasives.compare s) + [|3;1;0;2|] \ + (let a = [|"d";"c";"b";"e";"a"|] in let s = Sub.make a 1 ~len:4 in \ + Sub.sort_indices Pervasives.compare s) + *) + + (*$Q + Q.(array printable_string) (fun a -> \ + Array.length a > 10 ==> ( Array.length a > 10 && \ + let s = Sub.make a 5 ~len:5 in \ + let b = Sub.sort_ranking String.compare s in \ + let a_sorted = Sub.sorted String.compare s in \ + Sub.copy s = Array.map (Array.get a_sorted) b)) + *) + + let find f a = _find (fun _ -> f) a.arr a.i a.j let findi f a = _find (fun i -> f (i-a.i)) a.arr a.i a.j let find_idx p a = - _find (fun i x -> if p x then Some (i,x) else None) a.arr a.i a.j + _find (fun i x -> if p x then Some (i-a.i,x) else None) a.arr a.i a.j + + (*$= + (Some (1,"c")) (Sub.find_idx ((=) "c") (Sub.make [| "a"; "b"; "c" |] 1 2)) + *) let lookup_exn ?(cmp=Pervasives.compare) k a = - _lookup_exn ~cmp k a.arr a.i (a.j-1) + _lookup_exn ~cmp k a.arr a.i (a.j-1) - a.i let lookup ?(cmp=Pervasives.compare) k a = - try Some (_lookup_exn ~cmp k a.arr a.i (a.j-1)) + try Some (_lookup_exn ~cmp k a.arr a.i (a.j-1) - a.i) with Not_found -> None + (*$= + (Some 1) (Sub.lookup "c" (Sub.make [| "a"; "b"; "c" |] 1 2)) + *) + let bsearch ?(cmp=Pervasives.compare) k a = - bsearch_ ~cmp k a.arr a.i (a.j - 1) + match bsearch_ ~cmp k a.arr a.i (a.j - 1) with + | `At m -> `At (m - a.i) + | `Just_after m -> `Just_after (m - a.i) + | res -> res let for_all p a = _for_all p a.arr a.i a.j @@ -738,7 +900,8 @@ module Sub = struct let pp ?(sep=", ") pp_item buf a = _pp ~sep pp_item buf a.arr a.i a.j - let pp_i ?(sep=", ") pp_item buf a = _pp_i ~sep pp_item buf a.arr a.i a.j + let pp_i ?(sep=", ") pp_item buf a = + _pp_i ~sep (fun out k x -> pp_item out (k-a.i) x) buf a.arr a.i a.j let print ?(sep=", ") pp_item fmt a = _print ~sep pp_item fmt a.arr a.i a.j diff --git a/src/core/CCArray.mli b/src/core/CCArray.mli index 8206d2cb..11be5ebd 100644 --- a/src/core/CCArray.mli +++ b/src/core/CCArray.mli @@ -53,6 +53,29 @@ module type S = sig val reverse_in_place : 'a t -> unit (** Reverse the array in place *) + val sorted : ('a -> 'a -> int) -> 'a t -> 'a array + (** [sorted cmp a] makes a copy of [a] and sorts it with [cmp]. + @since 0.21 *) + + val sort_indices : ('a -> 'a -> int) -> 'a t -> int array + (** [sort_indices cmp a] returns a new array [b], with the same length as [a], + such that [b.(i)] is the index of the [i]-th element of [a] in [sort cmp a]. + In other words, [map (fun i -> a.(i)) (sort_indices a) = sorted cmp a]. + [a] is not modified. + @since 0.21 *) + + val sort_ranking : ('a -> 'a -> int) -> 'a t -> int array + (** [sort_ranking cmp a] returns a new array [b], with the same length as [a], + such that [b.(i)] is the position in [sorted cmp a] of the [i]-th + element of [a]. + [a] is not modified. + + In other words, [map (fun i -> (sorted cmp a).(i)) (sort_ranking cmp a) = a]. + + Without duplicates, we also have + [lookup_exn a.(i) (sorted a) = (sorted_ranking a).(i)] + @since 0.21 *) + val find : ('a -> 'b option) -> 'a t -> 'b option (** [find f a] returns [Some y] if there is an element [x] such that [f x = Some y], else it returns [None] *) @@ -224,6 +247,10 @@ module Sub : sig (** Convert into a triple [(arr, i, len)] where [len] is the length of the subarray of [arr] starting at offset [i] *) + val to_list : 'a t -> 'a list + (** Convert directly to a list + @since 0.21 *) + val full : 'a array -> 'a t (** Slice that covers the full array *) diff --git a/src/core/CCFormat.ml b/src/core/CCFormat.ml index c7b82288..a02f6b23 100644 --- a/src/core/CCFormat.ml +++ b/src/core/CCFormat.ml @@ -25,7 +25,7 @@ let int64 fmt n = Format.fprintf fmt "%Ld" n let nativeint fmt n = Format.fprintf fmt "%nd" n let string_quoted fmt s = Format.fprintf fmt "\"%s\"" s -let list ?(start="[") ?(stop="]") ?(sep=", ") pp fmt l = +let list ?(start="") ?(stop="") ?(sep=", ") pp fmt l = let rec pp_list l = match l with | x::((_::_) as l) -> pp fmt x; @@ -39,7 +39,7 @@ let list ?(start="[") ?(stop="]") ?(sep=", ") pp fmt l = pp_list l; Format.pp_print_string fmt stop -let array ?(start="[") ?(stop="]") ?(sep=", ") pp fmt a = +let array ?(start="") ?(stop="") ?(sep=", ") pp fmt a = Format.pp_print_string fmt start; for i = 0 to Array.length a - 1 do if i > 0 then ( @@ -50,7 +50,7 @@ let array ?(start="[") ?(stop="]") ?(sep=", ") pp fmt a = done; Format.pp_print_string fmt stop -let arrayi ?(start="[") ?(stop="]") ?(sep=", ") pp fmt a = +let arrayi ?(start="") ?(stop="") ?(sep=", ") pp fmt a = Format.pp_print_string fmt start; for i = 0 to Array.length a - 1 do if i > 0 then ( @@ -61,7 +61,7 @@ let arrayi ?(start="[") ?(stop="]") ?(sep=", ") pp fmt a = done; Format.pp_print_string fmt stop -let seq ?(start="[") ?(stop="]") ?(sep=", ") pp fmt seq = +let seq ?(start="") ?(stop="") ?(sep=", ") pp fmt seq = Format.pp_print_string fmt start; let first = ref true in seq (fun x -> @@ -279,8 +279,28 @@ let sprintf_ c format = fmt format +let with_color_sf s fmt = + let buf = Buffer.create 64 in + let out = Format.formatter_of_buffer buf in + if !color_enabled then set_color_tag_handling out; + Format.pp_open_tag out s; + Format.kfprintf + (fun out -> + Format.pp_close_tag out (); + Format.pp_print_flush out (); + Buffer.contents buf) + out fmt + let sprintf fmt = sprintf_ true fmt let sprintf_no_color fmt = sprintf_ false fmt +let sprintf_dyn_color ~colors fmt = sprintf_ colors fmt + +let fprintf_dyn_color ~colors out fmt = + let old_tags = Format.pp_get_mark_tags out () in + Format.pp_set_mark_tags out colors; (* enable/disable tags *) + Format.kfprintf + (fun out -> Format.pp_set_mark_tags out old_tags) + out fmt (*$T sprintf "yolo %s %d" "a b" 42 = "yolo a b 42" @@ -301,3 +321,31 @@ let ksprintf ~f fmt = Format.kfprintf (fun _ -> Format.pp_print_flush out (); f (Buffer.contents buf)) out fmt + + +module Dump = struct + type 'a t = 'a printer + let unit = unit + let int = int + let string = string_quoted + let bool = bool + let float = float + let char = char + let int32 = int32 + let int64 = int64 + let nativeint = nativeint + let list pp = within "[" "]" (hovbox (list ~sep:";" pp)) + let array pp = within "[|" "|]" (hovbox (array ~sep:";" pp)) + let option pp out x = match x with + | None -> Format.pp_print_string out "None" + | Some x -> Format.fprintf out "Some %a" pp x + let pair p1 p2 = pair p1 p2 + let triple p1 p2 p3 = triple p1 p2 p3 + let quad p1 p2 p3 p4 = quad p1 p2 p3 p4 +end + +(*$= & ~printer:(fun s->s) + "[1;2;3]" (to_string Dump.(list int) [1;2;3]) + "Some 1" (to_string Dump.(option int) (Some 1)) + "[None;Some \"a b\"]" (to_string Dump.(list (option string)) [None; Some "a b"]) +*) diff --git a/src/core/CCFormat.mli b/src/core/CCFormat.mli index 7d2fd22b..98ddcc46 100644 --- a/src/core/CCFormat.mli +++ b/src/core/CCFormat.mli @@ -137,6 +137,16 @@ val with_colorf : string -> t -> ('a, t, unit, unit) format4 -> 'a {b status: experimental} @since 0.16 *) +val with_color_sf : string -> ('a, t, unit, string) format4 -> 'a +(** [with_color_sf "Blue" out "%s %d" "yolo" 42] will behave like + {!sprintf}, but wrapping the content with the given style + Example: + {[ + CCFormat.with_color_sf "red" "%a" CCFormat.Dump.(list int) [1;2;3] |> print_endline;; + ]} + {b status: experimental} + @since 0.21 *) + (** {2 IO} *) val output : t -> 'a printer -> 'a -> unit @@ -153,10 +163,28 @@ val sprintf_no_color : ('a, t, unit, string) format4 -> 'a (** Similar to {!sprintf} but never prints colors @since 0.16 *) +val sprintf_dyn_color : colors:bool -> ('a, t, unit, string) format4 -> 'a +(** Similar to {!sprintf} but enable/disable colors depending on [colors]. + Example: + {[ + (* with colors *) + CCFormat.sprintf_dyn_color ~colors:true "@{%a@}" + CCFormat.Dump.(list int) [1;2;3] |> print_endline;; + + (* without colors *) + CCFormat.sprintf_dyn_color ~colors:false "@{%a@}" + CCFormat.Dump.(list int) [1;2;3] |> print_endline;; + ]} + @since 0.21 *) + val fprintf : t -> ('a, t, unit ) format -> 'a (** Alias to {!Format.fprintf} @since 0.14 *) +val fprintf_dyn_color : colors:bool -> t -> ('a, t, unit ) format -> 'a +(** Similar to {!fprintf} but enable/disable colors depending on [colors] + @since 0.21 *) + val ksprintf : f:(string -> 'b) -> ('a, Format.formatter, unit, 'b) format4 -> @@ -172,3 +200,39 @@ val ksprintf : val to_file : string -> ('a, t, unit, unit) format4 -> 'a (** Print to the given file *) + +(** {2 Dump} + + Print structures as OCaml values, so that they can be parsed back + by OCaml (typically, in the toplevel, for debugging). + + Example: + {[ + Format.printf "%a@." CCFormat.Dump.(list int) CCList.(1 -- 200);; + + Format.printf "%a@." CCFormat.Dump.(array (list (pair int bool))) + [| [1, true; 2, false]; []; [42, false] |];; + ]} + + @since 0.21 *) + +module Dump : sig + type 'a t = 'a printer + val unit : unit t + val int : int t + val string : string t + val bool : bool t + val float : float t + val char : char t + val int32 : int32 t + val int64 : int64 t + val nativeint : nativeint t + val list : 'a t -> 'a list t + val array : 'a t -> 'a array t + val option : 'a t -> 'a option t + val pair : 'a t -> 'b t -> ('a * 'b) t + val triple : 'a t -> 'b t -> 'c t -> ('a * 'b * 'c) t + val quad : + 'a t -> 'b t -> 'c t -> 'd t -> + ('a * 'b * 'c * 'd) t +end diff --git a/src/core/CCList.ml b/src/core/CCList.ml index 17a29a04..f09ea9fc 100644 --- a/src/core/CCList.ml +++ b/src/core/CCList.ml @@ -1221,7 +1221,7 @@ end (** {2 IO} *) -let pp ?(start="[") ?(stop="]") ?(sep=", ") pp_item buf l = +let pp ?(start="") ?(stop="") ?(sep=", ") pp_item buf l = let rec print l = match l with | x::((_::_) as l) -> pp_item buf x; @@ -1232,10 +1232,10 @@ let pp ?(start="[") ?(stop="]") ?(sep=", ") pp_item buf l = in Buffer.add_string buf start; print l; Buffer.add_string buf stop (*$T - CCPrint.to_string (pp CCPrint.int) [1;2;3] = "[1, 2, 3]" + CCPrint.to_string (pp ~start:"[" ~stop:"]" CCPrint.int) [1;2;3] = "[1, 2, 3]" *) -let print ?(start="[") ?(stop="]") ?(sep=", ") pp_item fmt l = +let print ?(start="") ?(stop="") ?(sep=", ") pp_item fmt l = let rec print fmt l = match l with | x::((_::_) as l) -> pp_item fmt x; diff --git a/src/core/CCMap.ml b/src/core/CCMap.ml index 6dad0ad1..ee7c5f66 100644 --- a/src/core/CCMap.ml +++ b/src/core/CCMap.ml @@ -113,7 +113,7 @@ module Make(O : Map.OrderedType) = struct let to_list m = fold (fun k v acc -> (k,v)::acc) m [] - let pp ?(start="{") ?(stop="}") ?(arrow="->") ?(sep=", ") pp_k pp_v buf m = + let pp ?(start="") ?(stop="") ?(arrow="->") ?(sep=", ") pp_k pp_v buf m = let first = ref true in Buffer.add_string buf start; iter @@ -125,7 +125,7 @@ module Make(O : Map.OrderedType) = struct m; Buffer.add_string buf stop - let print ?(start="[") ?(stop="]") ?(arrow="->") ?(sep=", ") pp_k pp_v fmt m = + let print ?(start="") ?(stop="") ?(arrow="->") ?(sep=", ") pp_k pp_v fmt m = Format.pp_print_string fmt start; let first = ref true in iter diff --git a/src/core/CCPrint.ml b/src/core/CCPrint.ml index c0f1a4c7..3d1fd7b3 100644 --- a/src/core/CCPrint.ml +++ b/src/core/CCPrint.ml @@ -25,7 +25,7 @@ let float3 buf f = Printf.bprintf buf "%.3f" f let float buf f = Buffer.add_string buf (string_of_float f) let char buf c = Buffer.add_char buf c -let list ?(start="[") ?(stop="]") ?(sep=", ") pp buf l = +let list ?(start="") ?(stop="") ?(sep=", ") pp buf l = let rec pp_list l = match l with | x::((_::_) as l) -> pp buf x; @@ -38,7 +38,7 @@ let list ?(start="[") ?(stop="]") ?(sep=", ") pp buf l = pp_list l; Buffer.add_string buf stop -let array ?(start="[") ?(stop="]") ?(sep=", ") pp buf a = +let array ?(start="") ?(stop="") ?(sep=", ") pp buf a = Buffer.add_string buf start; for i = 0 to Array.length a - 1 do (if i > 0 then Buffer.add_string buf sep); @@ -46,7 +46,7 @@ let array ?(start="[") ?(stop="]") ?(sep=", ") pp buf a = done; Buffer.add_string buf stop -let arrayi ?(start="[") ?(stop="]") ?(sep=", ") pp buf a = +let arrayi ?(start="") ?(stop="") ?(sep=", ") pp buf a = Buffer.add_string buf start; for i = 0 to Array.length a - 1 do (if i > 0 then Buffer.add_string buf sep); @@ -54,7 +54,7 @@ let arrayi ?(start="[") ?(stop="]") ?(sep=", ") pp buf a = done; Buffer.add_string buf stop -let seq ?(start="[") ?(stop="]") ?(sep=", ") pp buf seq = +let seq ?(start="") ?(stop="") ?(sep=", ") pp buf seq = Buffer.add_string buf start; let first = ref true in seq (fun x -> diff --git a/src/core/CCSet.ml b/src/core/CCSet.ml index f11d1981..59815a2d 100644 --- a/src/core/CCSet.ml +++ b/src/core/CCSet.ml @@ -51,7 +51,7 @@ module Make(O : Map.OrderedType) = struct let to_list = elements - let pp ?(start="{") ?(stop="}") ?(sep=", ") pp_x buf m = + let pp ?(start="") ?(stop="") ?(sep=", ") pp_x buf m = let first = ref true in Buffer.add_string buf start; iter @@ -61,7 +61,7 @@ module Make(O : Map.OrderedType) = struct m; Buffer.add_string buf stop - let print ?(start="[") ?(stop="]") ?(sep=", ") pp_x fmt m = + let print ?(start="") ?(stop="") ?(sep=", ") pp_x fmt m = Format.pp_print_string fmt start; let first = ref true in iter diff --git a/src/core/CCVector.ml b/src/core/CCVector.ml index 240774fe..1c5362d0 100644 --- a/src/core/CCVector.ml +++ b/src/core/CCVector.ml @@ -737,7 +737,7 @@ let to_klist v = else `Cons (v.vec.(i), aux (i+1)) in aux 0 -let pp ?(start="[") ?(stop="]") ?(sep=", ") pp_item buf v = +let pp ?(start="") ?(stop="") ?(sep=", ") pp_item buf v = Buffer.add_string buf start; iteri (fun i x -> @@ -746,7 +746,7 @@ let pp ?(start="[") ?(stop="]") ?(sep=", ") pp_item buf v = ) v; Buffer.add_string buf stop -let print ?(start="[") ?(stop="]") ?(sep=", ") pp_item fmt v = +let print ?(start="") ?(stop="") ?(sep=", ") pp_item fmt v = Format.pp_print_string fmt start; iteri (fun i x -> diff --git a/src/core/META b/src/core/META index 121c5e09..5a4f08ce 100644 --- a/src/core/META +++ b/src/core/META @@ -1,6 +1,6 @@ # OASIS_START -# DO NOT EDIT (digest: 5fef39d6aa86c783d2d134baf25c1157) -version = "0.20" +# DO NOT EDIT (digest: 2366633cbce20e67d6074e01f20927dc) +version = "0.21" description = "A modular standard library focused on data structures." requires = "bytes result" archive(byte) = "containers.cma" @@ -9,7 +9,7 @@ archive(native) = "containers.cmxa" archive(native, plugin) = "containers.cmxs" exists_if = "containers.cma" package "unix" ( - version = "0.20" + version = "0.21" description = "A modular standard library focused on data structures." requires = "bytes unix" archive(byte) = "containers_unix.cma" @@ -20,7 +20,7 @@ package "unix" ( ) package "top" ( - version = "0.20" + version = "0.21" description = "A modular standard library focused on data structures." requires = "compiler-libs.common containers containers.data containers.bigarray containers.string containers.unix containers.sexp containers.iter" @@ -32,7 +32,7 @@ package "top" ( ) package "thread" ( - version = "0.20" + version = "0.21" description = "A modular standard library focused on data structures." requires = "containers threads" archive(byte) = "containers_thread.cma" @@ -43,7 +43,7 @@ package "thread" ( ) package "string" ( - version = "0.20" + version = "0.21" description = "A modular standard library focused on data structures." requires = "bytes" archive(byte) = "containers_string.cma" @@ -54,7 +54,7 @@ package "string" ( ) package "sexp" ( - version = "0.20" + version = "0.21" description = "A modular standard library focused on data structures." requires = "bytes" archive(byte) = "containers_sexp.cma" @@ -65,7 +65,7 @@ package "sexp" ( ) package "iter" ( - version = "0.20" + version = "0.21" description = "A modular standard library focused on data structures." archive(byte) = "containers_iter.cma" archive(byte, plugin) = "containers_iter.cma" @@ -75,7 +75,7 @@ package "iter" ( ) package "io" ( - version = "0.20" + version = "0.21" description = "A modular standard library focused on data structures." requires = "bytes" archive(byte) = "containers_io.cma" @@ -86,7 +86,7 @@ package "io" ( ) package "data" ( - version = "0.20" + version = "0.21" description = "A modular standard library focused on data structures." requires = "bytes" archive(byte) = "containers_data.cma" @@ -97,7 +97,7 @@ package "data" ( ) package "bigarray" ( - version = "0.20" + version = "0.21" description = "A modular standard library focused on data structures." requires = "containers bigarray bytes" archive(byte) = "containers_bigarray.cma" @@ -108,7 +108,7 @@ package "bigarray" ( ) package "advanced" ( - version = "0.20" + version = "0.21" description = "A modular standard library focused on data structures." requires = "containers sequence" archive(byte) = "containers_advanced.cma" diff --git a/src/core/containers.ml b/src/core/containers.ml index b8271589..470bae8f 100644 --- a/src/core/containers.ml +++ b/src/core/containers.ml @@ -81,6 +81,9 @@ module Vector = CCVector module Int64 = CCInt64 (** @since 0.13 *) +module IO = CCIO +(** @since 0.21 *) + module Char = struct include Char include (CCChar : module type of CCChar with type t := t) diff --git a/src/data/CCImmutArray.ml b/src/data/CCImmutArray.ml index a775a586..e7e335c6 100644 --- a/src/data/CCImmutArray.ml +++ b/src/data/CCImmutArray.ml @@ -116,7 +116,7 @@ let to_gen a = type 'a printer = Format.formatter -> 'a -> unit -let print ?(start="[|") ?(stop="|]") ?(sep=";") pp_item out a = +let print ?(start="") ?(stop="") ?(sep=", ") pp_item out a = Format.pp_print_string out start; for k = 0 to Array.length a - 1 do if k > 0 then ( diff --git a/src/sexp/CCSexpM.ml b/src/sexp/CCSexpM.ml index d714924f..3ecaf953 100644 --- a/src/sexp/CCSexpM.ml +++ b/src/sexp/CCSexpM.ml @@ -41,7 +41,7 @@ let _must_escape s = for i = 0 to String.length s - 1 do let c = String.unsafe_get s i in match c with - | ' ' | ';' | ')' | '(' | '"' | '\\' | '\n' | '\t' -> raise Exit + | ' ' | ';' | ')' | '(' | '"' | '\\' | '\n' | '\t' | '\r' -> raise Exit | _ when Char.code c > 127 -> raise Exit (* non-ascii *) | _ -> () done; @@ -176,11 +176,11 @@ module MakeDecode(M : MONAD) = struct let rec expr k t = if t.i = t.len then _refill t (expr k) _error_eof else match _get t with - | ' ' | '\t' | '\n' -> expr k t + | ' ' | '\t' | '\r' | '\n' -> expr k t | c -> expr_starting_with c k t and expr_starting_with c k t = match c with - | ' ' | '\t' | '\n' -> assert false + | ' ' | '\t' | '\r' | '\n' -> assert false | ';' -> skip_comment (fun _ () -> expr k t) t | '(' -> expr_list [] k t | ')' -> _error t "unexpected ')'" @@ -194,7 +194,7 @@ module MakeDecode(M : MONAD) = struct and expr_list acc k t = if t.i = t.len then _refill t (expr_list acc k) _error_eof else match _get t with - | ' ' | '\t' | '\n' -> expr_list acc k t + | ' ' | '\t' | '\r' | '\n' -> expr_list acc k t | ')' -> k None (`List (List.rev acc)) | c -> expr_starting_with c @@ -216,7 +216,7 @@ module MakeDecode(M : MONAD) = struct else match _get t with | '\\' -> _error t "unexpected '\\' in non-quoted string" | '"' -> _error t "unexpected '\"' in the middle of an atom" - | (' ' | '\n' | '\t' | '(' | ')') as c -> + | (' ' | '\r' | '\n' | '\t' | '(' | ')') as c -> _return_atom (Some c) k t | c -> Buffer.add_char t.atom c; @@ -277,7 +277,7 @@ module MakeDecode(M : MONAD) = struct if t.i = t.len then _refill t (expr_or_end k) (fun _ -> M.return `End) else match _get t with - | ' ' | '\t' | '\n' -> expr_or_end k t + | ' ' | '\t' | '\r' | '\n' -> expr_or_end k t | c -> expr_starting_with c k t (* entry point *) @@ -308,6 +308,8 @@ let parse_string s : t or_error = (*$T CCError.to_opt (parse_string "(abc d/e/f \"hello \\\" () world\" )") <> None CCError.to_opt (parse_string "(abc ( d e ffff ) \"hello/world\")") <> None + (parse_string "(abc\r\n ( d e \r\tffff ))") \ + = `Ok (`List [`Atom "abc"; `List [`Atom "d"; `Atom "e"; `Atom "ffff"]]) *) (*$inject