|
rpm-build |
0f2925 |
(*
|
|
rpm-build |
0f2925 |
* ExtString - Additional functions for string manipulations.
|
|
rpm-build |
0f2925 |
* Copyright (C) 2003 Nicolas Cannasse
|
|
rpm-build |
0f2925 |
*
|
|
rpm-build |
0f2925 |
* This library is free software; you can redistribute it and/or
|
|
rpm-build |
0f2925 |
* modify it under the terms of the GNU Lesser General Public
|
|
rpm-build |
0f2925 |
* License as published by the Free Software Foundation; either
|
|
rpm-build |
0f2925 |
* version 2.1 of the License, or (at your option) any later version,
|
|
rpm-build |
0f2925 |
* with the special exception on linking described in file LICENSE.
|
|
rpm-build |
0f2925 |
*
|
|
rpm-build |
0f2925 |
* This library is distributed in the hope that it will be useful,
|
|
rpm-build |
0f2925 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
rpm-build |
0f2925 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
rpm-build |
0f2925 |
* Lesser General Public License for more details.
|
|
rpm-build |
0f2925 |
*
|
|
rpm-build |
0f2925 |
* You should have received a copy of the GNU Lesser General Public
|
|
rpm-build |
0f2925 |
* License along with this library; if not, write to the Free Software
|
|
rpm-build |
0f2925 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
rpm-build |
0f2925 |
*)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
exception Invalid_string
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
open ExtBytes
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
module String = struct
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
include String
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
#if OCAML < 402
|
|
rpm-build |
0f2925 |
let init len f =
|
|
rpm-build |
0f2925 |
let s = Bytes.create len in
|
|
rpm-build |
0f2925 |
for i = 0 to len - 1 do
|
|
rpm-build |
0f2925 |
Bytes.unsafe_set s i (f i)
|
|
rpm-build |
0f2925 |
done;
|
|
rpm-build |
0f2925 |
(* 's' doesn't escape and will never be mutated again *)
|
|
rpm-build |
0f2925 |
Bytes.unsafe_to_string s
|
|
rpm-build |
0f2925 |
#endif
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let starts_with str p =
|
|
rpm-build |
0f2925 |
if length str < length p then
|
|
rpm-build |
0f2925 |
false
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
let rec loop str p i =
|
|
rpm-build |
0f2925 |
if i = length p then true else
|
|
rpm-build |
0f2925 |
if unsafe_get str i <> unsafe_get p i then false
|
|
rpm-build |
0f2925 |
else loop str p (i+1)
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
loop str p 0
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let ends_with s e =
|
|
rpm-build |
0f2925 |
if length s < length e then
|
|
rpm-build |
0f2925 |
false
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
let rec loop s e i =
|
|
rpm-build |
0f2925 |
if i = length e then true else
|
|
rpm-build |
0f2925 |
if unsafe_get s (length s - length e + i) <> unsafe_get e i then false
|
|
rpm-build |
0f2925 |
else loop s e (i+1)
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
loop s e 0
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let find_from str pos sub =
|
|
rpm-build |
0f2925 |
let sublen = length sub in
|
|
rpm-build |
0f2925 |
if sublen = 0 then
|
|
rpm-build |
0f2925 |
0
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
let found = ref 0 in
|
|
rpm-build |
0f2925 |
let len = length str in
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
for i = pos to len - sublen do
|
|
rpm-build |
0f2925 |
let j = ref 0 in
|
|
rpm-build |
0f2925 |
while unsafe_get str (i + !j) = unsafe_get sub !j do
|
|
rpm-build |
0f2925 |
incr j;
|
|
rpm-build |
0f2925 |
if !j = sublen then begin found := i; raise Exit; end;
|
|
rpm-build |
0f2925 |
done;
|
|
rpm-build |
0f2925 |
done;
|
|
rpm-build |
0f2925 |
raise Invalid_string
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
Exit -> !found
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let find str sub = find_from str 0 sub
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let exists str sub =
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
ignore(find str sub);
|
|
rpm-build |
0f2925 |
true
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
Invalid_string -> false
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let strip ?(chars=" \t\r\n") s =
|
|
rpm-build |
0f2925 |
let p = ref 0 in
|
|
rpm-build |
0f2925 |
let l = length s in
|
|
rpm-build |
0f2925 |
while !p < l && contains chars (unsafe_get s !p) do
|
|
rpm-build |
0f2925 |
incr p;
|
|
rpm-build |
0f2925 |
done;
|
|
rpm-build |
0f2925 |
let p = !p in
|
|
rpm-build |
0f2925 |
let l = ref (l - 1) in
|
|
rpm-build |
0f2925 |
while !l >= p && contains chars (unsafe_get s !l) do
|
|
rpm-build |
0f2925 |
decr l;
|
|
rpm-build |
0f2925 |
done;
|
|
rpm-build |
0f2925 |
sub s p (!l - p + 1)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
#if OCAML < 400
|
|
rpm-build |
0f2925 |
let trim s = strip ~chars:" \t\r\n\012" s
|
|
rpm-build |
0f2925 |
#endif
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let split str sep =
|
|
rpm-build |
0f2925 |
let p = find str sep in
|
|
rpm-build |
0f2925 |
let len = length sep in
|
|
rpm-build |
0f2925 |
let slen = length str in
|
|
rpm-build |
0f2925 |
sub str 0 p, sub str (p + len) (slen - p - len)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let nsplit str sep =
|
|
rpm-build |
0f2925 |
if str = "" then []
|
|
rpm-build |
0f2925 |
else if sep = "" then raise Invalid_string
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
let rec loop acc pos =
|
|
rpm-build |
0f2925 |
if pos > String.length str then
|
|
rpm-build |
0f2925 |
List.rev acc
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
let i = try find_from str pos sep with Invalid_string -> String.length str in
|
|
rpm-build |
0f2925 |
loop (String.sub str pos (i - pos) :: acc) (i + String.length sep)
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
loop [] 0
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let join = concat
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let slice =
|
|
rpm-build |
0f2925 |
let clip max x = if x > max then max else if x < 0 then 0 else x in
|
|
rpm-build |
0f2925 |
fun ?(first=0) ?(last=Sys.max_string_length) s ->
|
|
rpm-build |
0f2925 |
let len = String.length s in
|
|
rpm-build |
0f2925 |
let i = if first = 0 then 0 else clip len (if first < 0 then len + first else first) in
|
|
rpm-build |
0f2925 |
let j = if last = Sys.max_string_length then len else clip len (if last < 0 then len + last else last) in
|
|
rpm-build |
0f2925 |
if i>=j || i=len then
|
|
rpm-build |
0f2925 |
make 0 ' '
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
sub s i (j-i)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let lchop s =
|
|
rpm-build |
0f2925 |
if s = "" then "" else sub s 1 (length s - 1)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let rchop s =
|
|
rpm-build |
0f2925 |
if s = "" then "" else sub s 0 (length s - 1)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let of_int = string_of_int
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let of_float = string_of_float
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let of_char = make 1
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let to_int s =
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
int_of_string s
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
_ -> raise Invalid_string
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let to_float s =
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
float_of_string s
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
_ -> raise Invalid_string
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let enum s =
|
|
rpm-build |
0f2925 |
let l = length s in
|
|
rpm-build |
0f2925 |
let rec make i =
|
|
rpm-build |
0f2925 |
Enum.make
|
|
rpm-build |
0f2925 |
~next:(fun () ->
|
|
rpm-build |
0f2925 |
if !i = l then
|
|
rpm-build |
0f2925 |
raise Enum.No_more_elements
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
let p = !i in
|
|
rpm-build |
0f2925 |
incr i;
|
|
rpm-build |
0f2925 |
unsafe_get s p
|
|
rpm-build |
0f2925 |
)
|
|
rpm-build |
0f2925 |
~count:(fun () -> l - !i)
|
|
rpm-build |
0f2925 |
~clone:(fun () -> make (ref !i))
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
make (ref 0)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let of_enum e =
|
|
rpm-build |
0f2925 |
let l = Enum.count e in
|
|
rpm-build |
0f2925 |
let s = Bytes.create l in
|
|
rpm-build |
0f2925 |
let i = ref 0 in
|
|
rpm-build |
0f2925 |
Enum.iter (fun c -> Bytes.unsafe_set s !i c; incr i) e;
|
|
rpm-build |
0f2925 |
(* 's' doesn't escape and will never be mutated again *)
|
|
rpm-build |
0f2925 |
Bytes.unsafe_to_string s
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
#if OCAML < 400
|
|
rpm-build |
0f2925 |
let map f s =
|
|
rpm-build |
0f2925 |
let len = length s in
|
|
rpm-build |
0f2925 |
let sc = Bytes.create len in
|
|
rpm-build |
0f2925 |
for i = 0 to len - 1 do
|
|
rpm-build |
0f2925 |
Bytes.unsafe_set sc i (f (unsafe_get s i))
|
|
rpm-build |
0f2925 |
done;
|
|
rpm-build |
0f2925 |
(* 'sc' doesn't escape and will never be mutated again *)
|
|
rpm-build |
0f2925 |
Bytes.unsafe_to_string sc
|
|
rpm-build |
0f2925 |
#endif
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
#if OCAML < 402
|
|
rpm-build |
0f2925 |
let mapi f s =
|
|
rpm-build |
0f2925 |
let len = length s in
|
|
rpm-build |
0f2925 |
let sc = Bytes.create len in
|
|
rpm-build |
0f2925 |
for i = 0 to len - 1 do
|
|
rpm-build |
0f2925 |
Bytes.unsafe_set sc i (f i (unsafe_get s i))
|
|
rpm-build |
0f2925 |
done;
|
|
rpm-build |
0f2925 |
(* 'sc' doesn't escape and will never be mutated again *)
|
|
rpm-build |
0f2925 |
Bytes.unsafe_to_string sc
|
|
rpm-build |
0f2925 |
#endif
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
#if OCAML < 400
|
|
rpm-build |
0f2925 |
let iteri f s =
|
|
rpm-build |
0f2925 |
for i = 0 to length s - 1 do
|
|
rpm-build |
0f2925 |
let () = f i (unsafe_get s i) in ()
|
|
rpm-build |
0f2925 |
done
|
|
rpm-build |
0f2925 |
#endif
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
(* fold_left and fold_right by Eric C. Cooper *)
|
|
rpm-build |
0f2925 |
let fold_left f init str =
|
|
rpm-build |
0f2925 |
let n = String.length str in
|
|
rpm-build |
0f2925 |
let rec loop i result =
|
|
rpm-build |
0f2925 |
if i = n then result
|
|
rpm-build |
0f2925 |
else loop (i + 1) (f result str.[i])
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
loop 0 init
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let fold_right f str init =
|
|
rpm-build |
0f2925 |
let n = String.length str in
|
|
rpm-build |
0f2925 |
let rec loop i result =
|
|
rpm-build |
0f2925 |
if i = 0 then result
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
let i' = i - 1 in
|
|
rpm-build |
0f2925 |
loop i' (f str.[i'] result)
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
loop n init
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
(* explode and implode from the OCaml Expert FAQ. *)
|
|
rpm-build |
0f2925 |
let explode s =
|
|
rpm-build |
0f2925 |
let rec exp i l =
|
|
rpm-build |
0f2925 |
if i < 0 then l else exp (i - 1) (s.[i] :: l) in
|
|
rpm-build |
0f2925 |
exp (String.length s - 1) []
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let implode l =
|
|
rpm-build |
0f2925 |
let res = Bytes.create (List.length l) in
|
|
rpm-build |
0f2925 |
let rec imp i = function
|
|
rpm-build |
0f2925 |
| [] -> res
|
|
rpm-build |
0f2925 |
| c :: l -> Bytes.set res i c; imp (i + 1) l in
|
|
rpm-build |
0f2925 |
let s = imp 0 l in
|
|
rpm-build |
0f2925 |
(* 's' doesn't escape and will never be mutated again *)
|
|
rpm-build |
0f2925 |
Bytes.unsafe_to_string s
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let replace_chars f s =
|
|
rpm-build |
0f2925 |
let len = String.length s in
|
|
rpm-build |
0f2925 |
let tlen = ref 0 in
|
|
rpm-build |
0f2925 |
let rec loop i acc =
|
|
rpm-build |
0f2925 |
if i = len then
|
|
rpm-build |
0f2925 |
acc
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
let s = f (unsafe_get s i) in
|
|
rpm-build |
0f2925 |
tlen := !tlen + length s;
|
|
rpm-build |
0f2925 |
loop (i+1) (s :: acc)
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let strs = loop 0 [] in
|
|
rpm-build |
0f2925 |
let sbuf = Bytes.create !tlen in
|
|
rpm-build |
0f2925 |
let pos = ref !tlen in
|
|
rpm-build |
0f2925 |
let rec loop2 = function
|
|
rpm-build |
0f2925 |
| [] -> ()
|
|
rpm-build |
0f2925 |
| s :: acc ->
|
|
rpm-build |
0f2925 |
let len = length s in
|
|
rpm-build |
0f2925 |
pos := !pos - len;
|
|
rpm-build |
0f2925 |
blit s 0 sbuf !pos len;
|
|
rpm-build |
0f2925 |
loop2 acc
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
loop2 strs;
|
|
rpm-build |
0f2925 |
(* 'sbuf' doesn't escape and will never be mutated again *)
|
|
rpm-build |
0f2925 |
Bytes.unsafe_to_string sbuf
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let replace ~str ~sub ~by =
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
let i = find str sub in
|
|
rpm-build |
0f2925 |
(true, (slice ~last:i str) ^ by ^
|
|
rpm-build |
0f2925 |
(slice ~first:(i+(String.length sub)) str))
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
Invalid_string -> (false, String.sub str 0 (String.length str))
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
#if OCAML < 403
|
|
rpm-build |
0f2925 |
let uppercase_ascii = uppercase
|
|
rpm-build |
0f2925 |
let lowercase_ascii = lowercase
|
|
rpm-build |
0f2925 |
let capitalize_ascii = capitalize
|
|
rpm-build |
0f2925 |
let uncapitalize_ascii = uncapitalize
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let equal = (=)
|
|
rpm-build |
0f2925 |
#endif
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
#if OCAML < 404
|
|
rpm-build |
0f2925 |
let split_on_char sep s =
|
|
rpm-build |
0f2925 |
let r = ref [] in
|
|
rpm-build |
0f2925 |
let j = ref (length s) in
|
|
rpm-build |
0f2925 |
for i = length s - 1 downto 0 do
|
|
rpm-build |
0f2925 |
if unsafe_get s i = sep then begin
|
|
rpm-build |
0f2925 |
r := sub s (i + 1) (!j - i - 1) :: !r;
|
|
rpm-build |
0f2925 |
j := i
|
|
rpm-build |
0f2925 |
end
|
|
rpm-build |
0f2925 |
done;
|
|
rpm-build |
0f2925 |
sub s 0 !j :: !r
|
|
rpm-build |
0f2925 |
#endif
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
#if OCAML < 405
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let rec index_rec_opt s lim i c =
|
|
rpm-build |
0f2925 |
if i >= lim then None else
|
|
rpm-build |
0f2925 |
if unsafe_get s i = c then Some i else index_rec_opt s lim (i + 1) c
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let index_opt s c = index_rec_opt s (length s) 0 c
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let index_from_opt s i c =
|
|
rpm-build |
0f2925 |
let l = length s in
|
|
rpm-build |
0f2925 |
if i < 0 || i > l then invalid_arg "ExtString.index_from_opt" else
|
|
rpm-build |
0f2925 |
index_rec_opt s l i c
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let rec rindex_rec_opt s i c =
|
|
rpm-build |
0f2925 |
if i < 0 then None else
|
|
rpm-build |
0f2925 |
if unsafe_get s i = c then Some i else rindex_rec_opt s (i - 1) c
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let rindex_opt s c = rindex_rec_opt s (length s - 1) c
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let rindex_from_opt s i c =
|
|
rpm-build |
0f2925 |
if i < -1 || i >= length s then
|
|
rpm-build |
0f2925 |
invalid_arg "ExtString.rindex_from_opt"
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
rindex_rec_opt s i c
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
#endif
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
end
|