remove slice APIs in string and array

This commit is contained in:
Simon Cruanes 2020-04-24 20:23:26 -04:00
parent a767e4618d
commit d923795e1a
20 changed files with 123 additions and 1333 deletions

View file

@ -1,442 +0,0 @@
(* This file is free software, part of containers. See file "license" for more details. *)
(** {1 Array Slice} *)
open CCShims_
type 'a iter = ('a -> unit) -> unit
type 'a sequence = ('a -> unit) -> unit
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
type 'a gen = unit -> 'a option
type 'a equal = 'a -> 'a -> bool
type 'a ord = 'a -> 'a -> int
type 'a random_gen = Random.State.t -> 'a
type 'a printer = Format.formatter -> 'a -> unit
(*$inject
let (--) = CCArray.(--)
*)
type 'a t = {
arr : 'a array;
i : int; (** Start index (included) *)
j : int; (** Stop index (excluded) *)
}
let empty = {
arr = [||];
i = 0;
j = 0;
}
let make arr i ~len =
if i<0||i+len > Array.length arr then invalid_arg "CCArray_slice.make";
{ arr; i; j=i+len; }
let of_slice (arr,i,len) = make arr i ~len
let to_slice a = a.arr, a.i, a.j-a.i
let full arr = { arr; i=0; j=Array.length arr; }
let underlying a = a.arr
let length a = a.j - a.i
let copy a = Array.sub a.arr a.i (length a)
let sub a i len = make a.arr (a.i + i) ~len
(*$=
[ 3;4 ] \
(let a = make (0--10) 2 5 in sub a 1 2 |> to_list)
[ ] \
(let a = make (0--10) 2 5 in sub a 1 0 |> to_list)
[ 5 ] \
(let a = make (0--10) 1 9 in sub a 4 1 |> to_list)
*)
let rec _foldi f acc a i j =
if i = j then acc else _foldi f (f acc i a.(i)) a (i+1) j
let _reverse_in_place a i ~len =
if len=0 then ()
else
for k = 0 to (len-1)/2 do
let t = a.(i+k) in
a.(i+k) <- a.(i+len-1-k);
a.(i+len-1-k) <- t;
done
let rec _equal eq a1 i1 j1 a2 i2 j2 =
if i1 = j1
then (assert (i1=j1 && i2=j2); true)
else
eq a1.(i1) a2.(i2) && _equal eq a1 (i1+1) j1 a2 (i2+1) j2
let rec _compare cmp a1 i1 j1 a2 i2 j2 =
if i1 = j1
then if i2=j2 then 0 else -1
else if i2=j2
then 1
else
let c = cmp a1.(i1) a2.(i2) in
if c = 0
then _compare cmp a1 (i1+1) j1 a2 (i2+1) j2
else c
let equal eq a b =
length a = length b && _equal eq a.arr a.i a.j b.arr b.i b.j
let compare_int (a : int) b = Stdlib.compare a b
let compare cmp a b =
_compare cmp a.arr a.i a.j b.arr b.i b.j
let fold f acc a =
let rec _fold acc i j =
if i=j then acc
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 =
let rec fold_while_i f acc i =
if i < Array.length a.arr && i < a.j then
let acc, cont = f acc a.arr.(i) in
match cont with
| `Stop -> acc
| `Continue -> fold_while_i f acc (i+1)
else acc
in fold_while_i f acc a.i
let get a i =
let j = a.i + i in
if i<0 || j>=a.j then invalid_arg "CCArray_slice.get";
a.arr.(j)
let get_safe a i =
try Some (get a i)
with Invalid_argument _ -> None
(*$inject
let sub_a = make [|1;2;3;4;5|] 1 ~len:3
*)
(*$=
(Some 2) (get_safe sub_a 0)
(Some 3) (get_safe sub_a 1)
(Some 4) (get_safe sub_a 2)
None (get_safe sub_a 4)
None (get_safe sub_a max_int)
None (get_safe sub_a ~-1)
None (get_safe sub_a ~-42)
*)
let set a i x =
let j = a.i + i in
if i<0 || j>=a.j then invalid_arg "CCArray_slice.set";
a.arr.(j) <- x
let iter f a =
for k=a.i to a.j-1 do f a.arr.(k) done
let iteri f a =
for k=0 to length a-1 do f k a.arr.(a.i + k) done
let blit a i b j len =
if i+len>length a || j+len>length b then invalid_arg "CCArray_slice.blit";
Array.blit a.arr (a.i+i) b.arr (b.i+j) len
let rec _find f a i j =
if i = j then None
else match f i a.(i) with
| Some _ as res -> res
| None -> _find f a (i+1) j
let rec _lookup_rec ~cmp k a i j =
if i>j then raise Not_found
else if i=j
then if cmp k a.(i) = 0
then i
else raise Not_found
else
let middle = (j+i)/2 in
match cmp k a.(middle) with
| 0 -> middle
| n when n<0 -> _lookup_rec ~cmp k a i (middle-1)
| _ -> _lookup_rec ~cmp k a (middle+1) j
let _lookup_exn ~cmp k a i j =
if i>j then raise Not_found;
match cmp k a.(i) with
| 0 -> i
| n when n<0 -> raise Not_found (* too low *)
| _ when i=j -> raise Not_found (* too high *)
| _ ->
match cmp k a.(j) with
| 0 -> j
| n when n<0 -> _lookup_rec ~cmp k a (i+1) (j-1)
| _ -> raise Not_found (* too high *)
let bsearch_ ~cmp x arr i j =
let rec aux i j =
if i > j
then `Just_after j
else
let middle = i + (j - i) / 2 in (* avoid overflow *)
match cmp x arr.(middle) with
| 0 -> `At middle
| n when n<0 -> aux i (middle - 1)
| _ -> aux (middle + 1) j
in
if i>=j then `Empty
else match cmp arr.(i) x, cmp arr.(j) x with
| n, _ when n>0 -> `All_bigger
| _, n when n<0 -> `All_lower
| _ -> aux i j
let rec _for_all p a i j =
i = j || (p a.(i) && _for_all p a (i+1) j)
let rec _exists p a i j =
i <> j && (p a.(i) || _exists p a (i+1) j)
let rec _for_all2 p a1 a2 i1 i2 ~len =
len=0 || (p a1.(i1) a2.(i2) && _for_all2 p a1 a2 (i1+1) (i2+1) ~len:(len-1))
let rec _exists2 p a1 a2 i1 i2 ~len =
len>0 && (p a1.(i1) a2.(i2) || _exists2 p a1 a2 (i1+1) (i2+1) ~len:(len-1))
(* shuffle a[i...j[ using the given int random generator
See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle *)
let _shuffle _rand_int a i j =
for k = j-1 downto i+1 do
let l = _rand_int (k+1) in
let tmp = a.(l) in
a.(l) <- a.(k);
a.(k) <- tmp;
done
(*$T
let st = Random.State.make [||] in let a = 0--10000 in \
let b = Array.copy a in CCArray.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))
let _pp ~sep pp_item out a i j =
for k = i to j - 1 do
if k > i then (Format.pp_print_string out sep; Format.pp_print_cut out ());
pp_item out a.(k)
done
let _pp_i ~sep pp_item out a i j =
for k = i to j - 1 do
if k > i then (Format.pp_print_string out sep; Format.pp_print_cut out ());
pp_item k out a.(k)
done
let _to_gen a i j =
let k = ref i in
fun () ->
if !k < j
then (
let x = a.(!k) in
incr k;
Some x
) else None
let rec _to_std_seq a i j () =
if i=j then Seq.Nil else Seq.Cons (a.(i), _to_std_seq a (i+1) j)
let rec _to_klist a i j () =
if i=j then `Nil else `Cons (a.(i), _to_klist a (i+1) j)
let reverse_in_place a = _reverse_in_place a.arr a.i ~len:(length a)
(*$T
let a = 1--6 in let s = make a 2 ~len:3 in \
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 = make a 2 ~len:0 in \
sorted Stdlib.compare s)
[|2;3;4|] \
(let a = [|6;5;4;3;2;1|] in let s = make a 2 ~len:3 in \
sorted Stdlib.compare s)
*)
(*$Q
Q.(array int) (fun a -> \
Array.length a > 10 ==> ( Array.length a > 10 && \
let s = make a 5 ~len:5 in \
let b = Array.sub a 5 5 in \
Array.sort Stdlib.compare b; b = sorted Stdlib.compare s))
*)
let sort_ranking cmp a =
let idx = _sort_indices cmp a.arr a.i a.j in
let sort_indices cmp a = _sort_indices cmp a 0 (Array.length a) in
sort_indices compare_int idx
(*$= & ~cmp:(=) ~printer:Q.Print.(array int)
[||] \
(let a = 1--6 in let s = make a 2 ~len:0 in \
sort_ranking Stdlib.compare s)
[|2;1;3;0|] \
(let a = [|"d";"c";"b";"e";"a"|] in let s = make a 1 ~len:4 in \
sort_ranking Stdlib.compare s)
*)
(*$Q
Q.(array_of_size Gen.(0--50) printable_string) (fun a -> \
Array.length a > 10 ==> ( Array.length a > 10 && \
let s = make a 5 ~len:5 in \
let b = sort_indices String.compare s in \
sorted String.compare s = Array.map (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 = make a 2 ~len:0 in \
sort_indices Stdlib.compare s)
[|3;1;0;2|] \
(let a = [|"d";"c";"b";"e";"a"|] in let s = make a 1 ~len:4 in \
sort_indices Stdlib.compare s)
*)
(*$Q
Q.(array_of_size Gen.(0--60) printable_string) (fun a -> \
Array.length a > 10 ==> ( Array.length a > 10 && \
let s = make a 5 ~len:5 in \
let b = sort_ranking String.compare s in \
let a_sorted = sorted String.compare s in \
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-a.i,x) else None) a.arr a.i a.j
(*$=
(Some (1,"c")) (find_idx ((=) "c") (make [| "a"; "b"; "c" |] 1 2))
*)
let lookup_exn ~cmp k a =
_lookup_exn ~cmp k a.arr a.i (a.j-1) - a.i
let lookup ~cmp k a =
try Some (_lookup_exn ~cmp k a.arr a.i (a.j-1) - a.i)
with Not_found -> None
(*$=
(Some 1) (lookup ~cmp:CCString.compare "c" (make [| "a"; "b"; "c" |] 1 2))
*)
let bsearch ~cmp k a =
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
let exists p a = _exists p a.arr a.i a.j
let for_all2 p a b =
length a = length b && _for_all2 p a.arr b.arr a.i b.i ~len:(length a)
let exists2 p a b =
_exists2 p a.arr b.arr a.i b.i ~len:(min (length a) (length b))
(*$T
exists2 (=) (make [| 1;2;3;4 |] 1 ~len:2) (make [| 0;1;3;4 |] 1 ~len:3)
*)
let _iter2 f a b i j ~len =
for o = 0 to len-1 do
f (Array.get a (i+o)) (Array.get b (j+o))
done
let iter2 f a b =
if length a <> length b then invalid_arg "CCArray_slice_iter2";
_iter2 f a.arr b.arr a.i b.i ~len:(length a)
let _fold2 f acc a b i j ~len =
let rec aux acc o =
if o=len then acc
else
let acc = f acc (Array.get a (i+o)) (Array.get b (j+o)) in
aux acc (o+1)
in
aux acc 0
let fold2 f acc a b =
if length a <> length b then invalid_arg "CCArray_slice_fold2";
_fold2 f acc a.arr b.arr a.i b.i ~len:(length a)
let shuffle a =
_shuffle Random.int a.arr a.i a.j
let shuffle_with st a =
_shuffle (Random.State.int st) a.arr a.i a.j
let random_choose a st = _choose a.arr a.i a.j st
let pp ?(sep=", ") pp_item buf a = _pp ~sep pp_item buf a.arr a.i a.j
let pp_i ?(sep=", ") pp_item out a =
_pp_i ~sep (fun k out x -> pp_item (k-a.i) out x) out a.arr a.i a.j
let to_iter a k = iter k a
let to_seq = to_iter
let to_gen a = _to_gen a.arr a.i a.j
let to_std_seq a = _to_std_seq a.arr a.i a.j
let to_klist a = _to_klist a.arr a.i a.j
(* test consistency of interfaces *)
(*$inject
module type L = module type of CCArray_slice
module type LL = module type of CCArray_sliceLabels
*)
(*$R
ignore (module CCArray_sliceLabels : L)
*)
(*$R
ignore (module CCArray_slice : LL)
*)

View file

@ -1,286 +0,0 @@
(* AUTOGENERATED FROM CCArray_sliceLabels.mli *)
(* This file is free software, part of containers. See file "license" for more details. *)
(** {1 Array Slice} *)
(* TODO: remove for 3.0 *)
type 'a sequence = ('a -> unit) -> unit
(** @deprecated use ['a iter] instead *)
type 'a iter = ('a -> unit) -> unit
(** Fast internal iterator.
@since 2.8 *)
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
type 'a gen = unit -> 'a option
type 'a equal = 'a -> 'a -> bool
type 'a ord = 'a -> 'a -> int
type 'a random_gen = Random.State.t -> 'a
type 'a printer = Format.formatter -> 'a -> unit
type 'a t
(** The type for an array slice, containing elements of type ['a] *)
val empty : 'a t
(** [empty] is the empty array slice. *)
val equal : 'a equal -> 'a t equal
(** [equal eq as1 as2] is [true] if the lengths of [as1] and [as2] are the same
and if the corresponding elements test equal using [eq]. *)
val compare : 'a ord -> 'a t ord
(** [compare cmp as1 as2] compares the two slices [as1] and [as2] using
the comparison function [cmp], element by element. *)
val get : 'a t -> int -> 'a
(** [get as n] returns the element number [n] of slice [as].
The first element has number 0.
The last element has number [length as - 1].
You can also write [as.(n)] instead of [get as n].
Raise [Invalid_argument "index out of bounds"]
if [n] is outside the range 0 to [(length as - 1)]. *)
val get_safe : 'a t -> int -> 'a option
(** [get_safe as i] returns [Some as.(i)] if [i] is a valid index.
@since 0.18 *)
val make : 'a array -> int -> len:int -> 'a t
(** [make a i ~len] creates a slice from given offset [i] and length [len] of the given array [a].
@raise Invalid_argument if the slice isn't valid. *)
val of_slice : ('a array * int * int) -> 'a t
(** [of_slice (a, i, len)] makes a slice from a triple [(a, i, len)] where [a] is the array,
[i] the offset in [a], and [len] the number of elements of the slice.
@raise Invalid_argument if the slice isn't valid (See {!make}). *)
val to_slice : 'a t -> ('a array * int * int)
(** [to_slice as] converts the slice [as] into a triple [(a, i, len)] where [len] is the length of
the sub-array of [a] starting at offset [i]. *)
val to_list : 'a t -> 'a list
(** [to_list as] converts the slice [as] directly to a list.
@since 1.0 *)
val full : 'a array -> 'a t
(** [full a] creates a slice that covers the full array [a]. *)
val underlying : 'a t -> 'a array
(** [underlying as] returns the underlying array (shared). Modifying this array will modify
the slice [as]. *)
val copy : 'a t -> 'a array
(** [copy as] copies the slice [as] into a new array. *)
val sub : 'a t -> int -> int -> 'a t
(** [sub as i len] builds a new sub-slice that contains the given subrange specified
by the index [i] and the length [len]. *)
val set : 'a t -> int -> 'a -> unit
(** [set as n x] modifies the slice [as] in place, replacing
element number [n] with [x].
You can also write [as.(n) <- x] instead of [set as n x].
Raise [Invalid_argument "index out of bounds"]
if [n] is outside the range 0 to [length as - 1]. *)
val length : _ t -> int
(** [length as] returns the length (number of elements) of the given slice [as]. *)
val fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a
(** [fold f acc as] computes [f (... (f (f acc as.(0)) as.(1)) ...) as.(length as - 1)]. *)
val foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'a
(** [foldi f acc as] is just like {!fold} but it also passes in the index of each element
as the second argument to the folded function [f]. *)
val fold_while : ('a -> 'b -> 'a * [`Stop | `Continue]) -> 'a -> 'b t -> 'a
(** [fold_while f acc as] folds left on slice [as] until a stop condition via [('a, `Stop)]
is indicated by the accumulator.
@since 0.8 *)
val iter : ('a -> unit) -> 'a t -> unit
(** [iter f as] applies function [f] in turn to all elements of [as].
It is equivalent to [f as.(0); f as.(1); ...; f as.(length as - 1); ()]. *)
val iteri : (int -> 'a -> unit) -> 'a t -> unit
(** [iteri f as] is like {!iter}, but the function [f] is applied with the index of the element
as first argument, and the element itself as second argument. *)
val blit : 'a t -> int -> 'a t -> int -> int -> unit
(** [blit as1 o1 as2 o2 len] copies [len] elements
from slice [as1], starting at element number [o1], to slice [as2],
starting at element number [o2]. It works correctly even if
[as1] and [as2] are the same slice, and the source and
destination chunks overlap.
Raise [Invalid_argument "CCArray_slice.blit"] if [o1] and [len] do not
designate a valid subarray of [as1], or if [o2] and [len] do not
designate a valid subarray of [as2]. *)
val reverse_in_place : 'a t -> unit
(** [reverse_in_place as] reverses the slice [as] in place. *)
val sorted : ('a -> 'a -> int) -> 'a t -> 'a array
(** [sorted cmp as] makes a copy of [as] and sorts it with [cmp].
@since 1.0 *)
val sort_indices : ('a -> 'a -> int) -> 'a t -> int array
(** [sort_indices cmp as] returns a new array [b], with the same length as [as],
such that [b.(i)] is the index at which the [i]-th element of [sorted cmp as]
appears in [as]. [as] is not modified.
In other words, [map (fun i -> as.(i)) (sort_indices cmp as) = sorted cmp as].
[sort_indices] yields the inverse permutation of {!sort_ranking}.
@since 1.0 *)
val sort_ranking : ('a -> 'a -> int) -> 'a t -> int array
(** [sort_ranking cmp as] returns a new array [b], with the same length as [as],
such that [b.(i)] is the index at which the [i]-th element of [as] appears
in [sorted cmp as]. [as] is not modified.
In other words, [map (fun i -> (sorted cmp as).(i)) (sort_ranking cmp as) = as].
[sort_ranking] yields the inverse permutation of {!sort_indices}.
In the absence of duplicate elements in [as], we also have
[lookup_exn as.(i) (sorted as) = (sorted_ranking as).(i)].
@since 1.0 *)
val find : ('a -> 'b option) -> 'a t -> 'b option
(** [find f as] returns [Some y] if there is an element [x] such
that [f x = Some y]. Otherwise returns [None]. *)
val findi : (int -> 'a -> 'b option) -> 'a t -> 'b option
(** [findi f as] is like {!find}, but the index of the element is also passed
to the predicate function [f].
@since 0.3.4 *)
val find_idx : ('a -> bool) -> 'a t -> (int * 'a) option
(** [find_idx p as] returns [Some (i,x)] where [x] is the [i]-th element of [as],
and [p x] holds. Otherwise returns [None].
@since 0.3.4 *)
val lookup : cmp:('a ord) -> 'a -> 'a t -> int option
(** [lookup ~cmp x as] lookups the index [i] of some key [x] in the slice [as], provided [as] is
sorted using [cmp].
@return [None] if the key [x] is not present, or
[Some i] ([i] the index of the key) otherwise. *)
val lookup_exn : cmp:('a ord) -> 'a -> 'a t -> int
(** [lookup_exn ~cmp x as] is like {!lookup}, but
@raise Not_found if the key [x] is not present. *)
val bsearch : cmp:('a -> 'a -> int) -> 'a -> 'a t ->
[ `All_lower | `All_bigger | `Just_after of int | `Empty | `At of int ]
(** [bsearch ~cmp x as] finds the index of the object [x] in the slice [as],
provided [as] is {b sorted} using [cmp]. If the slice is not sorted,
the result is not specified (may raise Invalid_argument).
Complexity: [O(log n)] where n is the length of the slice [as]
(dichotomic search).
@return
- [`At i] if [cmp as.(i) x = 0] (for some i).
- [`All_lower] if all elements of [as] are lower than [x].
- [`All_bigger] if all elements of [as] are bigger than [x].
- [`Just_after i] if [as.(i) < x < as.(i+1)].
- [`Empty] if the slice [as] is empty.
@raise Invalid_argument if the slice is found to be unsorted w.r.t [cmp].
@since 0.13 *)
val for_all : ('a -> bool) -> 'a t -> bool
(** [for_all p [|as1; ...; asn|]] checks if all elements of the slice
satisfy the predicate [p]. That is, it returns
[(p as1) && (p as2) && ... && (p asn)]. *)
val for_all2 : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool
(** [for_all2 p [|as1; ...; asn|] [|bs1; ...; bsn|]] is [true] if each pair of elements [asi bsi]
satisfies the predicate [p].
That is, it returns [(p as1 bs1) && (p as2 bs2) && ... && (p asn bsn)].
@raise Invalid_argument if slices have distinct lengths.
Allow different types.
@since 0.20 *)
val exists : ('a -> bool) -> 'a t -> bool
(** [exists p [|as1; ...; asn|]] is [true] if at least one element of
the slice satisfies the predicate [p]. That is, it returns
[(p as1) || (p as2) || ... || (p asn)]. *)
val exists2 : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool
(** [exists2 p [|as1; ...; asn|] [|bs1; ...; bsn|]] is [true] if any pair of elements [asi bsi]
satisfies the predicate [p].
That is, it returns [(p as1 bs1) || (p as2 bs2) || ... || (p asn bsn)].
@raise Invalid_argument if slices have distinct lengths.
Allow different types.
@since 0.20 *)
val fold2 : ('acc -> 'a -> 'b -> 'acc) -> 'acc -> 'a t -> 'b t -> 'acc
(** [fold2 f acc as bs] fold on two slices [as] and [bs] stepwise.
It computes [f (... (f acc as1 bs1)...) asn bsn].
@raise Invalid_argument if slices have distinct lengths.
@since 0.20 *)
val iter2 : ('a -> 'b -> unit) -> 'a t -> 'b t -> unit
(** [iter2 f as bs] iterates on the two slices [as] and [bs] stepwise.
It is equivalent to [f as0 bs0; ...; f as.(length as - 1) bs.(length bs - 1); ()].
@raise Invalid_argument if slices have distinct lengths.
@since 0.20 *)
val shuffle : 'a t -> unit
(** [shuffle as] randomly shuffles the slice [as], in place. *)
val shuffle_with : Random.State.t -> 'a t -> unit
(** [shuffle_with rs as] randomly shuffles the slice [as] (like {!shuffle}) but a specialized random
state [rs] is used to control the random numbers being produced during shuffling (for reproducibility). *)
val random_choose : 'a t -> 'a random_gen
(** [random_choose as rs] randomly chooses an element of [as].
@raise Not_found if the array/slice is empty. *)
val to_iter : 'a t -> 'a iter
(** [to_iter a] returns an [iter] of the elements of a slice [a].
The input array [a] is shared with the sequence and modification of it will result
in modification of the iterator.
@since 2.8 *)
val to_std_seq : 'a t -> 'a Seq.t
(** [to_std_seq a] returns a [Seq.t] of the elements of a slice [a].
The input array [a] is shared with the sequence and modification of it will result
in modification of the sequence.
@since 2.8
*)
val to_seq : 'a t -> 'a sequence
(** [to_seq as] returns a [sequence] of the elements of a slice [as].
The input slice [as] is shared with the sequence and modification of it will result
in modification of the sequence.
@deprecated use {!to_iter} instead *)
[@@ocaml.deprecated "use to_iter or to_std_seq"]
val to_gen : 'a t -> 'a gen
(** [to_gen as] returns a [gen] of the elements of a slice [as]. *)
val to_klist : 'a t -> 'a klist
(** [to_klist as] returns a [klist] of the elements of a slice [as].
@deprecated use {!to_std_seq} *)
[@@ocaml.deprecated "use to_std_seq"]
(** {2 IO} *)
val pp: ?sep:string -> 'a printer -> 'a t printer
(** [pp ~sep pp_item ppf as] formats the slice [as] on [ppf].
Each element is formatted with [pp_item] and elements are separated
by [sep] (defaults to ", "). *)
val pp_i: ?sep:string -> (int -> 'a printer) -> 'a t printer
(** [pp_i ~sep pp_item ppf as] prints the slice [as] on [ppf].
The printing function [pp_item] is giving both index and element.
Elements are separated by [sep] (defaults to ", "). *)

View file

@ -1,4 +0,0 @@
(* This file is free software, part of containers. See file "license" for more details. *)
include CCArray_slice

View file

@ -1,283 +0,0 @@
(* This file is free software, part of containers. See file "license" for more details. *)
(** {1 Array Slice} *)
(* TODO: remove for 3.0 *)
type 'a sequence = ('a -> unit) -> unit
(** @deprecated use ['a iter] instead *)
type 'a iter = ('a -> unit) -> unit
(** Fast internal iterator.
@since 2.8 *)
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
type 'a gen = unit -> 'a option
type 'a equal = 'a -> 'a -> bool
type 'a ord = 'a -> 'a -> int
type 'a random_gen = Random.State.t -> 'a
type 'a printer = Format.formatter -> 'a -> unit
type 'a t
(** The type for an array slice, containing elements of type ['a] *)
val empty : 'a t
(** [empty] is the empty array slice. *)
val equal : 'a equal -> 'a t equal
(** [equal eq as1 as2] is [true] if the lengths of [as1] and [as2] are the same
and if the corresponding elements test equal using [eq]. *)
val compare : 'a ord -> 'a t ord
(** [compare cmp as1 as2] compares the two slices [as1] and [as2] using
the comparison function [cmp], element by element. *)
val get : 'a t -> int -> 'a
(** [get as n] returns the element number [n] of slice [as].
The first element has number 0.
The last element has number [length as - 1].
You can also write [as.(n)] instead of [get as n].
Raise [Invalid_argument "index out of bounds"]
if [n] is outside the range 0 to [(length as - 1)]. *)
val get_safe : 'a t -> int -> 'a option
(** [get_safe as i] returns [Some as.(i)] if [i] is a valid index.
@since 0.18 *)
val make : 'a array -> int -> len:(int [@keep_label]) -> 'a t
(** [make a i ~len] creates a slice from given offset [i] and length [len] of the given array [a].
@raise Invalid_argument if the slice isn't valid. *)
val of_slice : ('a array * int * int) -> 'a t
(** [of_slice (a, i, len)] makes a slice from a triple [(a, i, len)] where [a] is the array,
[i] the offset in [a], and [len] the number of elements of the slice.
@raise Invalid_argument if the slice isn't valid (See {!make}). *)
val to_slice : 'a t -> ('a array * int * int)
(** [to_slice as] converts the slice [as] into a triple [(a, i, len)] where [len] is the length of
the sub-array of [a] starting at offset [i]. *)
val to_list : 'a t -> 'a list
(** [to_list as] converts the slice [as] directly to a list.
@since 1.0 *)
val full : 'a array -> 'a t
(** [full a] creates a slice that covers the full array [a]. *)
val underlying : 'a t -> 'a array
(** [underlying as] returns the underlying array (shared). Modifying this array will modify
the slice [as]. *)
val copy : 'a t -> 'a array
(** [copy as] copies the slice [as] into a new array. *)
val sub : 'a t -> int -> int -> 'a t
(** [sub as i len] builds a new sub-slice that contains the given subrange specified
by the index [i] and the length [len]. *)
val set : 'a t -> int -> 'a -> unit
(** [set as n x] modifies the slice [as] in place, replacing
element number [n] with [x].
You can also write [as.(n) <- x] instead of [set as n x].
Raise [Invalid_argument "index out of bounds"]
if [n] is outside the range 0 to [length as - 1]. *)
val length : _ t -> int
(** [length as] returns the length (number of elements) of the given slice [as]. *)
val fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a
(** [fold f acc as] computes [f (... (f (f acc as.(0)) as.(1)) ...) as.(length as - 1)]. *)
val foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'a
(** [foldi f acc as] is just like {!fold} but it also passes in the index of each element
as the second argument to the folded function [f]. *)
val fold_while : ('a -> 'b -> 'a * [`Stop | `Continue]) -> 'a -> 'b t -> 'a
(** [fold_while f acc as] folds left on slice [as] until a stop condition via [('a, `Stop)]
is indicated by the accumulator.
@since 0.8 *)
val iter : ('a -> unit) -> 'a t -> unit
(** [iter f as] applies function [f] in turn to all elements of [as].
It is equivalent to [f as.(0); f as.(1); ...; f as.(length as - 1); ()]. *)
val iteri : (int -> 'a -> unit) -> 'a t -> unit
(** [iteri f as] is like {!iter}, but the function [f] is applied with the index of the element
as first argument, and the element itself as second argument. *)
val blit : 'a t -> int -> 'a t -> int -> int -> unit
(** [blit as1 o1 as2 o2 len] copies [len] elements
from slice [as1], starting at element number [o1], to slice [as2],
starting at element number [o2]. It works correctly even if
[as1] and [as2] are the same slice, and the source and
destination chunks overlap.
Raise [Invalid_argument "CCArray_slice.blit"] if [o1] and [len] do not
designate a valid subarray of [as1], or if [o2] and [len] do not
designate a valid subarray of [as2]. *)
val reverse_in_place : 'a t -> unit
(** [reverse_in_place as] reverses the slice [as] in place. *)
val sorted : ('a -> 'a -> int) -> 'a t -> 'a array
(** [sorted cmp as] makes a copy of [as] and sorts it with [cmp].
@since 1.0 *)
val sort_indices : ('a -> 'a -> int) -> 'a t -> int array
(** [sort_indices cmp as] returns a new array [b], with the same length as [as],
such that [b.(i)] is the index at which the [i]-th element of [sorted cmp as]
appears in [as]. [as] is not modified.
In other words, [map (fun i -> as.(i)) (sort_indices cmp as) = sorted cmp as].
[sort_indices] yields the inverse permutation of {!sort_ranking}.
@since 1.0 *)
val sort_ranking : ('a -> 'a -> int) -> 'a t -> int array
(** [sort_ranking cmp as] returns a new array [b], with the same length as [as],
such that [b.(i)] is the index at which the [i]-th element of [as] appears
in [sorted cmp as]. [as] is not modified.
In other words, [map (fun i -> (sorted cmp as).(i)) (sort_ranking cmp as) = as].
[sort_ranking] yields the inverse permutation of {!sort_indices}.
In the absence of duplicate elements in [as], we also have
[lookup_exn as.(i) (sorted as) = (sorted_ranking as).(i)].
@since 1.0 *)
val find : ('a -> 'b option) -> 'a t -> 'b option
(** [find f as] returns [Some y] if there is an element [x] such
that [f x = Some y]. Otherwise returns [None]. *)
val findi : (int -> 'a -> 'b option) -> 'a t -> 'b option
(** [findi f as] is like {!find}, but the index of the element is also passed
to the predicate function [f].
@since 0.3.4 *)
val find_idx : ('a -> bool) -> 'a t -> (int * 'a) option
(** [find_idx p as] returns [Some (i,x)] where [x] is the [i]-th element of [as],
and [p x] holds. Otherwise returns [None].
@since 0.3.4 *)
val lookup : cmp:(('a ord) [@keep_label]) -> 'a -> 'a t -> int option
(** [lookup ~cmp x as] lookups the index [i] of some key [x] in the slice [as], provided [as] is
sorted using [cmp].
@return [None] if the key [x] is not present, or
[Some i] ([i] the index of the key) otherwise. *)
val lookup_exn : cmp:(('a ord) [@keep_label]) -> 'a -> 'a t -> int
(** [lookup_exn ~cmp x as] is like {!lookup}, but
@raise Not_found if the key [x] is not present. *)
val bsearch : cmp:(('a -> 'a -> int) [@keep_label]) -> 'a -> 'a t ->
[ `All_lower | `All_bigger | `Just_after of int | `Empty | `At of int ]
(** [bsearch ~cmp x as] finds the index of the object [x] in the slice [as],
provided [as] is {b sorted} using [cmp]. If the slice is not sorted,
the result is not specified (may raise Invalid_argument).
Complexity: [O(log n)] where n is the length of the slice [as]
(dichotomic search).
@return
- [`At i] if [cmp as.(i) x = 0] (for some i).
- [`All_lower] if all elements of [as] are lower than [x].
- [`All_bigger] if all elements of [as] are bigger than [x].
- [`Just_after i] if [as.(i) < x < as.(i+1)].
- [`Empty] if the slice [as] is empty.
@raise Invalid_argument if the slice is found to be unsorted w.r.t [cmp].
@since 0.13 *)
val for_all : ('a -> bool) -> 'a t -> bool
(** [for_all p [|as1; ...; asn|]] checks if all elements of the slice
satisfy the predicate [p]. That is, it returns
[(p as1) && (p as2) && ... && (p asn)]. *)
val for_all2 : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool
(** [for_all2 p [|as1; ...; asn|] [|bs1; ...; bsn|]] is [true] if each pair of elements [asi bsi]
satisfies the predicate [p].
That is, it returns [(p as1 bs1) && (p as2 bs2) && ... && (p asn bsn)].
@raise Invalid_argument if slices have distinct lengths.
Allow different types.
@since 0.20 *)
val exists : ('a -> bool) -> 'a t -> bool
(** [exists p [|as1; ...; asn|]] is [true] if at least one element of
the slice satisfies the predicate [p]. That is, it returns
[(p as1) || (p as2) || ... || (p asn)]. *)
val exists2 : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool
(** [exists2 p [|as1; ...; asn|] [|bs1; ...; bsn|]] is [true] if any pair of elements [asi bsi]
satisfies the predicate [p].
That is, it returns [(p as1 bs1) || (p as2 bs2) || ... || (p asn bsn)].
@raise Invalid_argument if slices have distinct lengths.
Allow different types.
@since 0.20 *)
val fold2 : ('acc -> 'a -> 'b -> 'acc) -> 'acc -> 'a t -> 'b t -> 'acc
(** [fold2 f acc as bs] fold on two slices [as] and [bs] stepwise.
It computes [f (... (f acc as1 bs1)...) asn bsn].
@raise Invalid_argument if slices have distinct lengths.
@since 0.20 *)
val iter2 : ('a -> 'b -> unit) -> 'a t -> 'b t -> unit
(** [iter2 f as bs] iterates on the two slices [as] and [bs] stepwise.
It is equivalent to [f as0 bs0; ...; f as.(length as - 1) bs.(length bs - 1); ()].
@raise Invalid_argument if slices have distinct lengths.
@since 0.20 *)
val shuffle : 'a t -> unit
(** [shuffle as] randomly shuffles the slice [as], in place. *)
val shuffle_with : Random.State.t -> 'a t -> unit
(** [shuffle_with rs as] randomly shuffles the slice [as] (like {!shuffle}) but a specialized random
state [rs] is used to control the random numbers being produced during shuffling (for reproducibility). *)
val random_choose : 'a t -> 'a random_gen
(** [random_choose as rs] randomly chooses an element of [as].
@raise Not_found if the array/slice is empty. *)
val to_iter : 'a t -> 'a iter
(** [to_iter a] returns an [iter] of the elements of a slice [a].
The input array [a] is shared with the sequence and modification of it will result
in modification of the iterator.
@since 2.8 *)
val to_std_seq : 'a t -> 'a Seq.t
(** [to_std_seq a] returns a [Seq.t] of the elements of a slice [a].
The input array [a] is shared with the sequence and modification of it will result
in modification of the sequence.
@since 2.8
*)
val to_seq : 'a t -> 'a sequence
(** [to_seq as] returns a [sequence] of the elements of a slice [as].
The input slice [as] is shared with the sequence and modification of it will result
in modification of the sequence.
@deprecated use {!to_iter} instead *)
[@@ocaml.deprecated "use to_iter or to_std_seq"]
val to_gen : 'a t -> 'a gen
(** [to_gen as] returns a [gen] of the elements of a slice [as]. *)
val to_klist : 'a t -> 'a klist
(** [to_klist as] returns a [klist] of the elements of a slice [as].
@deprecated use {!to_std_seq} *)
[@@ocaml.deprecated "use to_std_seq"]
(** {2 IO} *)
val pp: ?sep:string -> 'a printer -> 'a t printer
(** [pp ~sep pp_item ppf as] formats the slice [as] on [ppf].
Each element is formatted with [pp_item] and elements are separated
by [sep] (defaults to ", "). *)
val pp_i: ?sep:string -> (int -> 'a printer) -> 'a t printer
(** [pp_i ~sep pp_item ppf as] prints the slice [as] on [ppf].
The printing function [pp_item] is giving both index and element.
Elements are separated by [sep] (defaults to ", "). *)

View file

@ -3,7 +3,7 @@
(** {1 Helpers for Format} *)
type 'a sequence = ('a -> unit) -> unit
type 'a iter = ('a -> unit) -> unit
include Format
@ -77,6 +77,14 @@ let arrayi ?(sep=return ",@ ") pp fmt a =
done
let seq ?(sep=return ",@ ") pp fmt seq =
let first = ref true in
CCSeq.iter
(fun x ->
if !first then first := false else sep fmt ();
pp fmt x)
seq
let iter ?(sep=return ",@ ") pp fmt seq =
let first = ref true in
seq
(fun x ->

View file

@ -5,7 +5,7 @@
@since 0.8 *)
type 'a sequence = ('a -> unit) -> unit
type 'a iter = ('a -> unit) -> unit
(* include Format, and alias all its types.
see https://discuss.ocaml.org/t/extend-existing-module/1389/4
@ -69,7 +69,8 @@ val string_quoted : string printer
val list : ?sep:unit printer -> 'a printer -> 'a list printer
val array : ?sep:unit printer -> 'a printer -> 'a array printer
val arrayi : ?sep:unit printer -> (int * 'a) printer -> 'a array printer
val seq : ?sep:unit printer -> 'a printer -> 'a sequence printer
val seq : ?sep:unit printer -> 'a printer -> 'a Seq.t printer
val iter : ?sep:unit printer -> 'a printer -> 'a iter printer
val opt : 'a printer -> 'a option printer
(** [opt pp] prints options as follows:

View file

@ -7,7 +7,7 @@ type hash = int
type 'a t = 'a -> hash
type 'a sequence = ('a -> unit) -> unit
type 'a iter = ('a -> unit) -> unit
type 'a gen = unit -> 'a option
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
@ -72,11 +72,16 @@ let list_comm f l =
let a = Array.of_list l in
array_comm f a
let seq f seq =
let iter f seq =
let h = ref 0x43 in
seq (fun x -> h := combine f !h x);
!h
let seq f seq =
let h = ref 0x43 in
Seq.iter (fun x -> h := combine f !h x) seq;
!h
let gen f g =
let rec aux s = match g () with
| None -> s

View file

@ -72,10 +72,11 @@ val combine6 : hash -> hash -> hash -> hash -> hash -> hash -> hash
(** {2 Iterators} *)
type 'a sequence = ('a -> unit) -> unit
type 'a iter = ('a -> unit) -> unit
type 'a gen = unit -> 'a option
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
val seq : 'a t -> 'a sequence t
val seq : 'a t -> 'a Seq.t t
val iter : 'a t -> 'a iter t
val gen : 'a t -> 'a gen t
val klist : 'a t -> 'a klist t

View file

@ -4,7 +4,6 @@
(** {1 Leftist Heaps} *)
type 'a iter = ('a -> unit) -> unit
type 'a sequence = ('a -> unit) -> unit
type 'a gen = unit -> 'a option
type 'a printer = Format.formatter -> 'a -> unit
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]

View file

@ -5,11 +5,6 @@
Implementation following Okasaki's book. *)
(* TODO: remove for 3.0 *)
type 'a sequence = ('a -> unit) -> unit
(** @deprecated use ['a iter] instead *)
type 'a iter = ('a -> unit) -> unit
(** Fast internal iterator.
@since 2.8 *)

View file

@ -4,7 +4,7 @@
open CCShims_
type t = int
type 'a sequence = ('a -> unit) -> unit
type 'a iter = ('a -> unit) -> unit
let equal (a:int) b = Stdlib.(=) a b
@ -80,8 +80,8 @@ module Infix : sig
val (>) : t -> t -> bool
val (<=) : t -> t -> bool
val (>=) : t -> t -> bool
val (--) : t -> t -> t sequence
val (--^) : t -> t -> t sequence
val (--) : t -> t -> t iter
val (--^) : t -> t -> t iter
val (+) : t -> t -> t
val (-) : t -> t -> t
val (~-) : t -> t

View file

@ -38,7 +38,7 @@ val rem : t -> t -> t
type 'a printer = Format.formatter -> 'a -> unit
type 'a random_gen = Random.State.t -> 'a
type 'a sequence = ('a -> unit) -> unit
type 'a iter = ('a -> unit) -> unit
val random : int -> t random_gen
val random_small : t random_gen
@ -77,19 +77,19 @@ val max : t -> t -> t
(** The maximum of two integers.
@since 0.17 *)
val range_by : step:t -> t -> t -> t sequence
val range_by : step:t -> t -> t -> t iter
(** [range_by ~step i j] iterates on integers from [i] to [j] included,
where the difference between successive elements is [step].
Use a negative [step] for a decreasing list.
@raise Invalid_argument if [step=0].
@since 1.2 *)
val range : t -> t -> t sequence
val range : t -> t -> t iter
(** [range i j] iterates on integers from [i] to [j] included . It works
both for decreasing and increasing ranges.
@since 1.2 *)
val range' : t -> t -> t sequence
val range' : t -> t -> t iter
(** Like {!range} but the second bound is excluded.
For instance [range' 0 5 = Iter.of_list [0;1;2;3;4]].
@since 1.2 *)
@ -117,11 +117,11 @@ module Infix : sig
val (>=) : t -> t -> bool
(** @since 0.17 *)
val (--) : t -> t -> t sequence
val (--) : t -> t -> t iter
(** Alias to {!range}.
@since 1.2 *)
val (--^) : t -> t -> t sequence
val (--^) : t -> t -> t iter
(** Alias to {!range'}.
@since 1.2 *)

View file

@ -5,7 +5,7 @@
open CCShims_
type 'a or_error = ('a, string) result
type 'a sequence = ('a -> unit) -> unit
type 'a iter = ('a -> unit) -> unit
type 'a gen = unit -> 'a option
module type SEXP = CCSexp_intf.SEXP
@ -118,13 +118,13 @@ module Make(Sexp : SEXP) = struct
pp fmt t;
Format.pp_print_flush fmt ()
let to_file_seq filename seq =
let to_file_iter filename seq =
_with_out filename
(fun oc ->
seq (fun t -> to_chan oc t; output_char oc '\n')
)
let to_file filename t = to_file_seq filename (fun k -> k t)
let to_file filename t = to_file_iter filename (fun k -> k t)
(** {2 Parsing} *)

View file

@ -6,7 +6,6 @@
*)
type 'a or_error = ('a, string) result
type 'a sequence = ('a -> unit) -> unit
type 'a gen = unit -> 'a option
(** {2 Abstract representation of S-expressions}

View file

@ -1,6 +1,6 @@
type 'a or_error = ('a, string) result
type 'a sequence = ('a -> unit) -> unit
type 'a iter = ('a -> unit) -> unit
type 'a gen = unit -> 'a option
(** {2 Abstract representation of S-expressions}
@ -73,8 +73,8 @@ module type S = sig
val to_file : string -> t -> unit
val to_file_seq : string -> t sequence -> unit
(** Print the given sequence of expressions to a file. *)
val to_file_iter : string -> t iter -> unit
(** Print the given iter of expressions to a file. *)
val to_chan : out_channel -> t -> unit

View file

@ -13,55 +13,6 @@ type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
include String
module type S = sig
type t
val length : t -> int
(** Return the length (number of characters) of the given string. *)
val blit : t -> int -> Bytes.t -> int -> int -> unit
(** Like {!String.blit}.
Compatible with the [-safe-string] option.
@raise Invalid_argument if indices are not valid. *)
(*
val blit_immut : t -> int -> t -> int -> int -> string
(** Immutable version of {!blit}, returning a new string.
[blit a i b j len] is the same as [b], but in which
the range [j, ..., j+len] is replaced by [a.[i], ..., a.[i + len]].
@raise Invalid_argument if indices are not valid. *)
*)
val fold : ('a -> char -> 'a) -> 'a -> t -> 'a
(** Fold on chars by increasing index.
@since 0.7 *)
(** {2 Conversions} *)
val to_gen : t -> char gen
(** Return the [gen] of characters contained in the string. *)
val to_iter : t -> char iter
(** Return the [iter] of characters contained in the string.
@since 2.8 *)
val to_std_seq : t -> char Seq.t
(** [to_std_seq s] returns a [Seq.t] of the bytes in [s].
@since 2.8
*)
val to_list : t -> char list
(** Return the list of characters contained in the string. *)
val pp_buf : Buffer.t -> t -> unit
(** Renamed from [pp] since 2.0. *)
val pp : Format.formatter -> t -> unit
(** Print the string within quotes.
Renamed from [print] since 2.0. *)
end
let compare_int (a : int) b = Stdlib.compare a b
let compare = String.compare
@ -1109,86 +1060,6 @@ let pp_buf buf s =
let pp fmt s =
Format.fprintf fmt "\"%s\"" s
module Sub = struct
type t = string * int * int
let make s i ~len =
if i<0||len<0||i+len > String.length s then invalid_arg "CCString.Sub.make";
s,i,len
let full s = s, 0, String.length s
let copy (s,i,len) = String.sub s i len
let underlying (s,_,_) = s
let sub (s,i,len) i' len' =
if i+i' + len' > i+len then invalid_arg "CCString.Sub.sub";
(s, i+i',len')
let length (_,_,l) = l
let get (s,i,l) j =
if j<0 || j>= l then invalid_arg "CCString.Sub.get";
String.unsafe_get s (i+j)
let blit (a1,i1,len1) o1 a2 o2 len =
if o1+len>len1 then invalid_arg "CCString.Sub.blit";
blit a1 (i1+o1) a2 o2 len
let fold f acc (s,i,len) =
let rec fold_rec f acc s i j =
if i = j then acc
else fold_rec f (f acc s.[i]) s (i+1) j
in fold_rec f acc s i (i+len)
(*$T
let s = Sub.make "abcde" 1 3 in \
Sub.fold (fun acc x -> x::acc) [] s = ['d'; 'c'; 'b']
Sub.make "abcde" 1 3 |> Sub.copy = "bcd"
Sub.full "abcde" |> Sub.copy = "abcde"
*)
(*$T
let sub = Sub.make " abc " 1 ~len:3 in \
"\"abc\"" = (CCFormat.to_string Sub.pp sub)
*)
(*$= & ~printer:(String.make 1)
'b' Sub.(get (make "abc" 1 ~len:2) 0)
'c' Sub.(get (make "abc" 1 ~len:2) 1)
*)
(*$QR
Q.(printable_string_of_size Gen.(3--10)) (fun s ->
let open Iter.Infix in
begin
(0 -- (length s-2)
>|= fun i -> i, Sub.make s i ~len:(length s-i))
>>= fun (i,sub) ->
(0 -- (Sub.length sub-1) >|= fun j -> i,j,sub)
end
|> Iter.for_all
(fun (i,j,sub) -> Sub.get sub j = s.[i+j]))
*)
let to_gen (s,i,len) = _to_gen s i len
let to_iter (s,i,len) k = for i=i to i+len-1 do k s.[i] done
let to_std_seq (s,i,len) = _to_std_seq s i len
let to_seq = to_iter
let to_klist (s,i,len) = _to_klist s i len
let to_list (s,i,len) = _to_list s [] i len
let pp_buf buf (s,i,len) =
Buffer.add_char buf '"';
Buffer.add_substring buf s i len;
Buffer.add_char buf '"'
let pp fmt s =
Format.fprintf fmt "\"%s\"" (copy s)
end
(* test consistency of interfaces *)
(*$inject
module type L = module type of CCString

View file

@ -12,60 +12,52 @@ type 'a iter = ('a -> unit) -> unit
type 'a gen = unit -> 'a option
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
(** {2 Common Signature} *)
include module type of struct include String end
module type S = sig
type t
val length : t -> int
(** Return the length (number of characters) of the given string. *)
val length : t -> int
(** Return the length (number of characters) of the given string. *)
val blit : t -> int -> Bytes.t -> int -> int -> unit
(** Like {!String.blit}.
val blit : t -> int -> Bytes.t -> int -> int -> unit
(** Like {!String.blit}.
Compatible with the [-safe-string] option.
@raise Invalid_argument if indices are not valid. *)
(*
val blit_immut : t -> int -> t -> int -> int -> string
(** Immutable version of {!blit}, returning a new string.
(*
val blit_immut : t -> int -> t -> int -> int -> string
(** Immutable version of {!blit}, returning a new string.
[blit a i b j len] is the same as [b], but in which
the range [j, ..., j+len] is replaced by [a.[i], ..., a.[i + len]].
@raise Invalid_argument if indices are not valid. *)
*)
val fold : ('a -> char -> 'a) -> 'a -> t -> 'a
(** Fold on chars by increasing index.
val fold : ('a -> char -> 'a) -> 'a -> t -> 'a
(** Fold on chars by increasing index.
@since 0.7 *)
(** {2 Conversions} *)
(** {2 Conversions} *)
val to_gen : t -> char gen
(** Return the [gen] of characters contained in the string. *)
val to_gen : t -> char gen
(** Return the [gen] of characters contained in the string. *)
val to_iter : t -> char iter
(** Return the [iter] of characters contained in the string.
val to_iter : t -> char iter
(** Return the [iter] of characters contained in the string.
@since 2.8 *)
val to_std_seq : t -> char Seq.t
(** [to_std_seq s] returns a [Seq.t] of the bytes in [s].
val to_std_seq : t -> char Seq.t
(** [to_std_seq s] returns a [Seq.t] of the bytes in [s].
@since 2.8
*)
*)
val to_list : t -> char list
(** Return the list of characters contained in the string. *)
val to_list : t -> char list
(** Return the list of characters contained in the string. *)
val pp_buf : Buffer.t -> t -> unit
(** Renamed from [pp] since 2.0. *)
val pp_buf : Buffer.t -> t -> unit
(** Renamed from [pp] since 2.0. *)
val pp : Format.formatter -> t -> unit
(** Print the string within quotes.
val pp : Format.formatter -> t -> unit
(** Print the string within quotes.
Renamed from [print] since 2.0. *)
end
(** {2 Strings} *)
include module type of struct include String end
val compare : string -> string -> int
@ -235,8 +227,6 @@ val exists : (char -> bool) -> string -> bool
(** True for some char?
@since 0.12 *)
include S with type t := string
val drop_while : (char -> bool) -> t -> t
(** [drop_while f s] discards any characters starting from the left,
up to the first character [c] not satisfying [f c].
@ -419,33 +409,3 @@ val edit_distance : string -> string -> int
(** Edition distance between two strings. This satisfies the classical
distance axioms: it is always positive, symmetric, and satisfies
the formula [distance a b + distance b c >= distance a c]. *)
(** {2 Slices}
A contiguous part of a string *)
module Sub : sig
type t = string * int * int
(** A string, an offset, and the length of the slice. *)
val make : string -> int -> len:int -> t
val full : string -> t
(** Full string. *)
val copy : t -> string
(** Make a copy of the substring. *)
val underlying : t -> string
val sub : t -> int -> int -> t
(** Sub-slice. *)
val get : t -> int -> char
(** [get s i] gets the [i]-th element, or fails.
@raise Invalid_argument if the index is not within [0 ... length - 1].
@since 1.2 *)
include S with type t := t
end

View file

@ -10,61 +10,55 @@ type 'a iter = ('a -> unit) -> unit
type 'a gen = unit -> 'a option
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
(** {2 Common Signature} *)
include module type of struct include StringLabels end
module type S = sig
type t
val length : t -> int
(** Return the length (number of characters) of the given string. *)
val length : t -> int
(** Return the length (number of characters) of the given string. *)
val blit : src:t -> src_pos:int -> dst:Bytes.t -> dst_pos:int -> len:int -> unit
(** Like {!String.blit}.
val blit : src:t -> src_pos:int -> dst:Bytes.t -> dst_pos:int -> len:int -> unit
(** Like {!String.blit}.
Compatible with the [-safe-string] option.
@raise Invalid_argument if indices are not valid. *)
(*
val blit_immut : t -> int -> t -> int -> int -> string
(** Immutable version of {!blit}, returning a new string.
(*
val blit_immut : t -> int -> t -> int -> int -> string
(** Immutable version of {!blit}, returning a new string.
[blit a i b j len] is the same as [b], but in which
the range [j, ..., j+len] is replaced by [a.[i], ..., a.[i + len]].
@raise Invalid_argument if indices are not valid. *)
*)
val fold : f:('a -> char -> 'a) -> init:'a -> t -> 'a
(** Fold on chars by increasing index.
val fold : f:('a -> char -> 'a) -> init:'a -> t -> 'a
(** Fold on chars by increasing index.
@since 0.7 *)
(** {2 Conversions} *)
(** {2 Conversions} *)
val to_gen : t -> char gen
(** Return the [gen] of characters contained in the string. *)
val to_gen : t -> char gen
(** Return the [gen] of characters contained in the string. *)
val to_iter : t -> char iter
(** Return the [iter] of characters contained in the string.
val to_iter : t -> char iter
(** Return the [iter] of characters contained in the string.
@since 2.8 *)
val to_std_seq : t -> char Seq.t
(** [to_std_seq s] returns a [Seq.t] of the bytes in [s].
val to_std_seq : t -> char Seq.t
(** [to_std_seq s] returns a [Seq.t] of the bytes in [s].
@since 2.8
*)
*)
val to_list : t -> char list
(** Return the list of characters contained in the string. *)
val to_list : t -> char list
(** Return the list of characters contained in the string. *)
val pp_buf : Buffer.t -> t -> unit
(** Renamed from [pp] since 2.0. *)
val pp_buf : Buffer.t -> t -> unit
(** Renamed from [pp] since 2.0. *)
val pp : Format.formatter -> t -> unit
(** Print the string within quotes.
val pp : Format.formatter -> t -> unit
(** Print the string within quotes.
Renamed from [print] since 2.0. *)
end
(** {2 Strings} *)
include module type of struct include StringLabels end
val equal : string -> string -> bool
(** Equality function on strings. *)
@ -236,8 +230,6 @@ val exists : f:(char -> bool) -> string -> bool
(** True for some char?
@since 0.12 *)
include S with type t := string
val drop_while : f:(char -> bool) -> t -> t
(** [drop_while f s] discards any characters starting from the left,
up to the first character [c] not satisfying [f c].
@ -436,33 +428,3 @@ val edit_distance : string -> string -> int
(** Edition distance between two strings. This satisfies the classical
distance axioms: it is always positive, symmetric, and satisfies
the formula [distance a b + distance b c >= distance a c]. *)
(** {2 Slices}
A contiguous part of a string *)
module Sub : sig
type t = string * int * int
(** A string, an offset, and the length of the slice. *)
val make : string -> pos:int -> len:(int [@keep_label]) -> t
val full : string -> t
(** Full string. *)
val copy : t -> string
(** Make a copy of the substring. *)
val underlying : t -> string
val sub : t -> int -> int -> t
(** Sub-slice. *)
val get : t -> int -> char
(** [get s i] gets the [i]-th element, or fails.
@raise Invalid_argument if the index is not within [0 ... length - 1].
@since 1.2 *)
include S with type t := t
end

View file

@ -4,7 +4,6 @@
(** {1 Drop-In replacement to Stdlib} *)
module Array = CCArray
module Array_slice = CCArray_slice
module Bool = CCBool
module Char = CCChar
module Equal = CCEqual

View file

@ -4,9 +4,8 @@
(** {1 Drop-In replacement to Stdlib} *)
module Array = CCArrayLabels
module Array_slice = CCArray_sliceLabels
module Bool = CCBool
module Char = Char
module Char = CCChar
module Equal = CCEqualLabels
module Float = CCFloat
module Format = CCFormat
@ -39,10 +38,16 @@ module Parse = CCParse
module Random = CCRandom
module Ref = CCRef
module Result = CCResult
module Seq = CCSeq
module Set = CCSet
module String = CCStringLabels
module Vector = CCVector
module Monomorphic = CCMonomorphic
module Utf8_string = CCUtf8_string
module Sexp = CCSexp
module Sexp_intf = CCSexp_intf
module Stdlib = CCShims_.Stdlib
include Monomorphic