···11+# 1.6.0
22+33+* Port to dune and opam 2.0 metadata format
44+55+# 1.5.0 and earlier
66+77+No changelogs recorded.
+21
vendor/opam/stringext/LICENSE.md
···11+MIT License
22+33+Copyright (c) 2017 Rudi Grinberg
44+55+Permission is hereby granted, free of charge, to any person obtaining a copy
66+of this software and associated documentation files (the "Software"), to deal
77+in the Software without restriction, including without limitation the rights
88+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
99+copies of the Software, and to permit persons to whom the Software is
1010+furnished to do so, subject to the following conditions:
1111+1212+The above copyright notice and this permission notice shall be included in all
1313+copies or substantial portions of the Software.
1414+1515+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1616+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1717+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1818+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1919+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2020+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121+SOFTWARE.
+10
vendor/opam/stringext/Makefile
···11+.PHONY: all clean test
22+33+all:
44+ dune build
55+66+test:
77+ dune runtest
88+99+clean:
1010+ rm -rf _build *.install
+83
vendor/opam/stringext/README.md
···11+## Stringext -- Extra string functions fo OCaml
22+33+Extra string functions for OCaml. Mainly splitting. All functions are in the
44+`Stringext` module. Here's a snippet of most useful functions out of the mli:
55+66+## Api Documentation
77+88+```ocaml
99+(** string_after [s] [n] returns the substring of [s] that is after
1010+ character [n] *)
1111+val string_after : string -> int -> string
1212+1313+(** equivalent to [Str.quote] *)
1414+val quote : string -> string
1515+1616+(** split [?max] [s] [~on] splits [s] on every [on] occurence upto
1717+ [max] number of items if [max] is specified. [max] is assumed to
1818+ be a small number if specified. To not cause stack overflows *)
1919+val split : ?max:int -> string -> on:char -> string list
2020+2121+(** full_split [s] [~on] will split [s] on every occurence
2222+ of [on] but will add the separators between the tokens. Maintains
2323+ the invariant:
2424+2525+ String.concat (full_split s ~on) =s *)
2626+val full_split : string -> on:char -> string list
2727+2828+(** Trims spaces on the left of the string. In case no trimming is needed
2929+ the same string is returned without copying *)
3030+val trim_left : string -> string
3131+3232+(** split_strim_left [s] [~on] [~trim] splits [s] on every character
3333+ in [on]. Characters in [trim] are trimmed from the left of every
3434+ result element *)
3535+val split_trim_left : string -> on:string -> trim:string -> string list
3636+3737+val of_char : char -> string
3838+3939+val of_list : char list -> string
4040+4141+val to_list : string -> char list
4242+4343+val to_array : string -> char array
4444+4545+val of_array : char array -> string
4646+4747+val find_from : ?start:int -> string -> pattern:string -> int option
4848+4949+val replace_all : string -> pattern:string -> with_:string -> string
5050+5151+val replace_all_assoc : string -> (string * string) list -> string
5252+5353+val cut : string -> on:string -> (string * string) option
5454+(** [String.cut on s] is either the pair [Some (l,r)] of the two
5555+ (possibly empty) substrings of [s] that are delimited by the first
5656+ match of the non empty separator string [on] or [None] if [on]
5757+ can't be matched in [s]. Matching starts from the beginning of [s].
5858+5959+ The invariant [l ^ on ^ r = s] holds.
6060+6161+ @raise Invalid_argument if [on] is the empty string. *)
6262+6363+val rcut : string -> on:string -> (string * string) option
6464+(** [String.rcut on s] is like {!cut} but the matching is done backwards
6565+ starting from the end of [s].
6666+6767+ @raise Invalid_argument if [on] is the empty string. *)
6868+6969+val chop_prefix : string -> prefix:string -> string option
7070+7171+val drop : string -> int -> string
7272+7373+val take : string -> int -> string
7474+7575+(** [trim_left_sub s ~pos ~len ~chars] Trim all characters inside [chars]
7676+ from [s] starting from [pos] and up to [len] *)
7777+val trim_left_sub : string -> pos:int -> len:int -> chars:string -> string
7878+```
7979+8080+## Examples
8181+8282+See the directory `examples`. This is a separate dune workspace, so install
8383+Stringext first.
···11+# stringext
22+33+This example is for the stringext library
44+55+https://opam.ocaml.org/packages/stringext
66+77+# Source file
88+99+`bin/main.ml`
1010+1111+# Building and running
1212+1313+`dune exec bin/main.exe`
1414+1515+# Cleaning up
1616+1717+`dune clean`
···11+open String
22+33+let string_after s n = String.sub s n (String.length s - n)
44+55+let quote s =
66+ let len = String.length s in
77+ let buf = Buffer.create (2 * len) in
88+ for i = 0 to len - 1 do
99+ match s.[i] with
1010+ '[' | ']' | '*' | '.' | '\\' | '?' | '+' | '^' | '$' as c ->
1111+ Buffer.add_char buf '\\';
1212+ Buffer.add_char buf c
1313+ | c -> Buffer.add_char buf c
1414+ done;
1515+ Buffer.contents buf
1616+1717+1818+(* Not tail recursive for "performance", please choose low values for
1919+ [max]. The idea is that max is always small because it's hard
2020+ code *)
2121+let split_char_bounded str ~on ~max =
2222+ if str = "" then []
2323+ else if max = 1 then [str]
2424+ else
2525+ let rec loop offset tokens =
2626+ if tokens = max - 1
2727+ then [sub str offset (length str - offset)]
2828+ else
2929+ try
3030+ let index = index_from str offset on in
3131+ if index = offset then
3232+ ""::(loop (offset + 1) (tokens + 1))
3333+ else
3434+ let token = String.sub str offset (index - offset) in
3535+ token::(loop (index + 1) (tokens + 1))
3636+ with Not_found -> [sub str offset (length str - offset)]
3737+ in loop 0 0
3838+3939+let split_char_unbounded str ~on =
4040+ if str = "" then []
4141+ else
4242+ let rec loop acc offset =
4343+ try begin
4444+ let index = rindex_from str offset on in
4545+ if index = offset then
4646+ loop (""::acc) (index - 1)
4747+ else
4848+ let token = sub str (index + 1) (offset - index) in
4949+ loop (token::acc) (index - 1)
5050+ end
5151+ with Not_found -> (sub str 0 (offset + 1))::acc
5252+ in loop [] (length str - 1)
5353+5454+let of_char = String.make 1
5555+5656+let full_split str ~on =
5757+ if str = "" then []
5858+ else
5959+ let sep = of_char on in
6060+ let rec loop acc offset =
6161+ try begin
6262+ let index = rindex_from str offset on in
6363+ if index = offset then
6464+ loop (sep::acc) (index - 1)
6565+ else
6666+ let token = sub str (index + 1) (offset - index) in
6767+ loop (sep::token::acc) (index - 1)
6868+ end
6969+ with Not_found ->
7070+ if offset >= 0
7171+ then (sub str 0 (offset + 1))::acc
7272+ else acc
7373+ in loop [] (length str - 1)
7474+7575+(* copying core's convention for String.split but with an optional max
7676+ argument *)
7777+let split ?max s ~on =
7878+ match max with
7979+ | None -> split_char_unbounded s ~on
8080+ | Some max -> (* assert (max < 100); *)
8181+ split_char_bounded s ~on ~max
8282+8383+let rindex_from_on s ~offset ~on =
8484+ let rec loop i =
8585+ if i < 0 then raise Not_found
8686+ else if String.contains on s.[i] then i
8787+ else loop (i - 1)
8888+ in loop offset
8989+9090+let trim_left_sub s ~pos ~len ~chars =
9191+ let start_pos =
9292+ let final = pos + len in
9393+ let rec loop last_char i =
9494+ if i = final then last_char
9595+ else if String.contains chars s.[i] then loop (i + 1) (i + 1)
9696+ else last_char
9797+ in loop pos pos
9898+ in
9999+ let new_len = len - (start_pos - pos) in
100100+ String.sub s start_pos new_len
101101+102102+let split_trim_left str ~on ~trim =
103103+ if str = "" then []
104104+ else
105105+ let rec loop acc offset =
106106+ try begin
107107+ let index = rindex_from_on str ~offset ~on in
108108+ if index = offset then
109109+ loop (""::acc) (index - 1)
110110+ else
111111+ let token = trim_left_sub str ~pos:(index + 1)
112112+ ~len:(offset - index) ~chars:trim in
113113+ loop (token::acc) (index - 1)
114114+ end
115115+ with Not_found ->
116116+ (trim_left_sub str ~pos:0 ~len:(offset + 1) ~chars:trim)::acc
117117+ in loop [] (length str - 1)
118118+119119+exception Found_int of int
120120+121121+let first_char_ne s c =
122122+ String.length s > 0 && s.[0] <> c
123123+124124+let trim_left s =
125125+ if first_char_ne s ' ' then s
126126+ else
127127+ let len = String.length s in
128128+ try
129129+ for i=0 to len - 1 do
130130+ if s.[i] <> ' ' then raise (Found_int i)
131131+ done;
132132+ ""
133133+ with Found_int non_space ->
134134+ sub s non_space (len - non_space)
135135+136136+let substr_eq ?(start=0) s ~pattern =
137137+ try
138138+ for i = 0 to String.length pattern - 1 do
139139+ if s.[i + start] <> pattern.[i] then raise Exit
140140+ done;
141141+ true
142142+ with _ -> false
143143+144144+let find_from ?(start=0) str ~pattern =
145145+ try
146146+ for i = start to (String.length str) - (String.length pattern) do
147147+ if substr_eq ~start:i str ~pattern then
148148+ raise (Found_int i)
149149+ done;
150150+ None
151151+ with
152152+ | Found_int i -> Some i
153153+ | _ -> None
154154+155155+let find_min l ~f =
156156+ let rec loop x fx = function
157157+ | [] -> Some (x, fx)
158158+ | x'::xs ->
159159+ let fx' = f x' in
160160+ if fx' < fx then loop x' fx' xs
161161+ else loop x fx xs
162162+ in
163163+ match l with
164164+ | [] -> None
165165+ | x::xs -> loop x (f x) xs
166166+167167+let replace_all str ~pattern ~with_ =
168168+ let (slen, plen) = String.(length str, length pattern) in
169169+ let buf = Buffer.create slen in
170170+ let rec loop i =
171171+ match find_from ~start:i str ~pattern with
172172+ | None ->
173173+ Buffer.add_substring buf str i (slen - i);
174174+ Buffer.contents buf
175175+ | Some j ->
176176+ Buffer.add_substring buf str i (j - i);
177177+ Buffer.add_string buf with_;
178178+ loop (j + plen)
179179+ in loop 0
180180+181181+exception Found_replace of int * string * string
182182+183183+let replace_all_assoc str tbl =
184184+ let slen = String.length str in
185185+ let buf = Buffer.create slen in
186186+ let rec loop i =
187187+ if i >= slen then Buffer.contents buf
188188+ else
189189+ let r =
190190+ try
191191+ let found = ref false in
192192+ let e =
193193+ find_min tbl ~f:(fun (pattern, with_) ->
194194+ match find_from ~start:i str ~pattern with
195195+ | None -> max_int
196196+ | Some j when j = i -> raise (Found_replace (j, pattern, with_))
197197+ | Some j -> found := true; j)
198198+ in
199199+ match e with
200200+ | None -> None
201201+ | Some ((pattern, with_), j) when !found -> Some (j, pattern, with_)
202202+ | Some _ -> None
203203+ with Found_replace (j, pattern, with_) -> Some (j, pattern, with_)
204204+ in
205205+ match r with
206206+ | None ->
207207+ Buffer.add_substring buf str i (slen - i);
208208+ Buffer.contents buf
209209+ | Some (j, pattern, with_) ->
210210+ Buffer.add_substring buf str i (j - i);
211211+ Buffer.add_string buf with_;
212212+ loop (j + String.length pattern)
213213+ in loop 0
214214+215215+let iteri f l =
216216+ let rec loop i = function
217217+ | [] -> ()
218218+ | x::xs -> (f i x); loop (succ i) xs
219219+ in loop 0 l
220220+221221+let of_list xs =
222222+ let l = List.length xs in
223223+ let s = Bytes.create l in
224224+ iteri (fun i c -> Bytes.set s i c) xs;
225225+ Bytes.unsafe_to_string s
226226+227227+let to_list s =
228228+ let rec loop acc i =
229229+ if i = -1 then acc
230230+ else
231231+ loop (s.[i] :: acc) (pred i)
232232+ in loop [] (String.length s - 1)
233233+234234+let of_array a =
235235+ let len = Array.length a in
236236+ let bytes = Bytes.create len in
237237+ for i = 0 to len - 1 do
238238+ Bytes.set bytes i a.(i)
239239+ done;
240240+ Bytes.unsafe_to_string bytes
241241+242242+let to_array s = Array.init (String.length s) (String.get s)
243243+244244+(* ripped off from one of dbuenzli's libs *)
245245+let cut s ~on =
246246+ let sep_max = length on - 1 in
247247+ if sep_max < 0 then invalid_arg "Stringext.cut: empty separator" else
248248+ let s_max = length s - 1 in
249249+ if s_max < 0 then None else
250250+ let k = ref 0 in
251251+ let i = ref 0 in
252252+ (* We run from the start of [s] to end with [i] trying to match the
253253+ first character of [on] in [s]. If this matches, we verify that
254254+ the whole [on] is matched using [k]. If it doesn't match we
255255+ continue to look for [on] with [i]. If it matches we exit the
256256+ loop and extract a substring from the start of [s] to the
257257+ position before the [on] we found and another from the position
258258+ after the [on] we found to end of string. If [i] is such that no
259259+ separator can be found we exit the loop and return the no match
260260+ case. *)
261261+ try
262262+ while (!i + sep_max <= s_max) do
263263+ (* Check remaining [on] chars match, access to unsafe s (!i + !k) is
264264+ guaranteed by loop invariant. *)
265265+ if unsafe_get s !i <> unsafe_get on 0 then incr i else begin
266266+ k := 1;
267267+ while (!k <= sep_max && unsafe_get s (!i + !k) = unsafe_get on !k)
268268+ do incr k done;
269269+ if !k <= sep_max then (* no match *) incr i else raise Exit
270270+ end
271271+ done;
272272+ None (* no match in the whole string. *)
273273+ with
274274+ | Exit -> (* i is at the beginning of the separator *)
275275+ let left_end = !i - 1 in
276276+ let right_start = !i + sep_max + 1 in
277277+ Some (sub s 0 (left_end + 1),
278278+ sub s right_start (s_max - right_start + 1))
279279+280280+let rcut s ~on =
281281+ let sep_max = length on - 1 in
282282+ if sep_max < 0 then invalid_arg "Stringext.rcut: empty separator" else
283283+ let s_max = length s - 1 in
284284+ if s_max < 0 then None else
285285+ let k = ref 0 in
286286+ let i = ref s_max in
287287+ (* We run from the end of [s] to the beginning with [i] trying to
288288+ match the last character of [on] in [s]. If this matches, we
289289+ verify that the whole [on] is matched using [k] (we do that
290290+ backwards). If it doesn't match we continue to look for [on]
291291+ with [i]. If it matches we exit the loop and extract a
292292+ substring from the start of [s] to the position before the
293293+ [on] we found and another from the position after the [on] we
294294+ found to end of string. If [i] is such that no separator can
295295+ be found we exit the loop and return the no match case. *)
296296+ try
297297+ while (!i >= sep_max) do
298298+ if unsafe_get s !i <> unsafe_get on sep_max then decr i else begin
299299+ (* Check remaining [on] chars match, access to unsafe_get
300300+ s (sep_start + !k) is guaranteed by loop invariant. *)
301301+ let sep_start = !i - sep_max in
302302+ k := sep_max - 1;
303303+ while (!k >= 0 && unsafe_get s (sep_start + !k) = unsafe_get on !k)
304304+ do decr k done;
305305+ if !k >= 0 then (* no match *) decr i else raise Exit
306306+ end
307307+ done;
308308+ None (* no match in the whole string. *)
309309+ with
310310+ | Exit -> (* i is at the end of the separator *)
311311+ let left_end = !i - sep_max - 1 in
312312+ let right_start = !i + 1 in
313313+ Some (sub s 0 (left_end + 1),
314314+ sub s right_start (s_max - right_start + 1))
315315+316316+let chop_prefix s ~prefix =
317317+ let prefix_l = String.length prefix in
318318+ let string_l = String.length s in
319319+ if prefix_l > string_l then None
320320+ else
321321+ try
322322+ for i = 0 to prefix_l - 1 do
323323+ if s.[i] <> prefix.[i] then raise Exit;
324324+ done;
325325+ Some (String.sub s prefix_l (string_l - prefix_l))
326326+ with _ -> None
327327+328328+let drop s n =
329329+ let l = String.length s in
330330+ if n >= l
331331+ then ""
332332+ else String.sub s n (l - n)
333333+334334+let take s n =
335335+ if n >= String.length s
336336+ then s
337337+ else String.sub s 0 n
+72
vendor/opam/stringext/lib/stringext.mli
···11+(** Misc. string functions not found in the built in OCaml string
22+ module *)
33+44+(** string_after [s] [n] returns the substring of [s] that is after
55+ character [n] *)
66+val string_after : string -> int -> string
77+88+(** equivalent to [Str.quote] *)
99+val quote : string -> string
1010+1111+(** split [?max] [s] [~on] splits [s] on every [on] occurence upto
1212+ [max] number of items if [max] is specified. [max] is assumed to
1313+ be a small number if specified. To not cause stack overflows *)
1414+val split : ?max:int -> string -> on:char -> string list
1515+1616+(** full_split [s] [~on] will split [s] on every occurence
1717+ of [on] but will add the separators between the tokens. Maintains
1818+ the invariant:
1919+2020+ String.concat (full_split s ~on) =s *)
2121+val full_split : string -> on:char -> string list
2222+2323+(** Trims spaces on the left of the string. In case no trimming is needed
2424+ the same string is returned without copying *)
2525+val trim_left : string -> string
2626+2727+(** split_strim_left [s] [~on] [~trim] splits [s] on every character
2828+ in [on]. Characters in [trim] are trimmed from the left of every
2929+ result element *)
3030+val split_trim_left : string -> on:string -> trim:string -> string list
3131+3232+val of_char : char -> string
3333+3434+val of_list : char list -> string
3535+3636+val to_list : string -> char list
3737+3838+val to_array : string -> char array
3939+4040+val of_array : char array -> string
4141+4242+val find_from : ?start:int -> string -> pattern:string -> int option
4343+4444+val replace_all : string -> pattern:string -> with_:string -> string
4545+4646+val replace_all_assoc : string -> (string * string) list -> string
4747+4848+val cut : string -> on:string -> (string * string) option
4949+(** [String.cut on s] is either the pair [Some (l,r)] of the two
5050+ (possibly empty) substrings of [s] that are delimited by the first
5151+ match of the non empty separator string [on] or [None] if [on]
5252+ can't be matched in [s]. Matching starts from the beginning of [s].
5353+5454+ The invariant [l ^ on ^ r = s] holds.
5555+5656+ @raise Invalid_argument if [on] is the empty string. *)
5757+5858+val rcut : string -> on:string -> (string * string) option
5959+(** [String.rcut on s] is like {!cut} but the matching is done backwards
6060+ starting from the end of [s].
6161+6262+ @raise Invalid_argument if [on] is the empty string. *)
6363+6464+val chop_prefix : string -> prefix:string -> string option
6565+6666+val drop : string -> int -> string
6767+6868+val take : string -> int -> string
6969+7070+(** [trim_left_sub s ~pos ~len ~chars] Trim all characters inside [chars]
7171+ from [s] starting from [pos] and up to [len] *)
7272+val trim_left_sub : string -> pos:int -> len:int -> chars:string -> string