1995-08-09 08:06:35 -07:00
|
|
|
(***********************************************************************)
|
|
|
|
(* *)
|
1996-04-30 07:53:58 -07:00
|
|
|
(* Objective Caml *)
|
1995-08-09 08:06:35 -07:00
|
|
|
(* *)
|
|
|
|
(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
|
|
|
|
(* *)
|
1996-04-30 07:53:58 -07:00
|
|
|
(* Copyright 1996 Institut National de Recherche en Informatique et *)
|
1999-11-17 10:59:06 -08:00
|
|
|
(* en Automatique. All rights reserved. This file is distributed *)
|
2001-12-07 05:41:02 -08:00
|
|
|
(* under the terms of the GNU Library General Public License, with *)
|
|
|
|
(* the special exception on linking described in file ../LICENSE. *)
|
1995-08-09 08:06:35 -07:00
|
|
|
(* *)
|
|
|
|
(***********************************************************************)
|
|
|
|
|
|
|
|
(* $Id$ *)
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
(* String operations *)
|
|
|
|
|
1995-07-10 02:48:27 -07:00
|
|
|
external length : string -> int = "%string_length"
|
|
|
|
external get : string -> int -> char = "%string_safe_get"
|
|
|
|
external set : string -> int -> char -> unit = "%string_safe_set"
|
2001-09-06 01:52:32 -07:00
|
|
|
external create : int -> string = "create_string"
|
1995-06-15 01:10:01 -07:00
|
|
|
external unsafe_get : string -> int -> char = "%string_unsafe_get"
|
|
|
|
external unsafe_set : string -> int -> char -> unit = "%string_unsafe_set"
|
1995-05-04 03:15:53 -07:00
|
|
|
external unsafe_blit : string -> int -> string -> int -> int -> unit
|
1995-07-25 04:39:02 -07:00
|
|
|
= "blit_string" "noalloc"
|
|
|
|
external unsafe_fill : string -> int -> int -> char -> unit
|
|
|
|
= "fill_string" "noalloc"
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
let make n c =
|
|
|
|
let s = create n in
|
|
|
|
unsafe_fill s 0 n c;
|
|
|
|
s
|
|
|
|
|
|
|
|
let copy s =
|
|
|
|
let len = length s in
|
|
|
|
let r = create len in
|
|
|
|
unsafe_blit s 0 r 0 len;
|
|
|
|
r
|
|
|
|
|
|
|
|
let sub s ofs len =
|
2000-12-28 05:07:42 -08:00
|
|
|
if ofs < 0 || len < 0 || ofs + len > length s
|
1995-05-04 03:15:53 -07:00
|
|
|
then invalid_arg "String.sub"
|
|
|
|
else begin
|
|
|
|
let r = create len in
|
|
|
|
unsafe_blit s ofs r 0 len;
|
|
|
|
r
|
|
|
|
end
|
|
|
|
|
|
|
|
let fill s ofs len c =
|
2000-12-28 05:07:42 -08:00
|
|
|
if ofs < 0 || len < 0 || ofs + len > length s
|
1995-05-04 03:15:53 -07:00
|
|
|
then invalid_arg "String.fill"
|
|
|
|
else unsafe_fill s ofs len c
|
|
|
|
|
|
|
|
let blit s1 ofs1 s2 ofs2 len =
|
2000-12-28 05:07:42 -08:00
|
|
|
if len < 0 || ofs1 < 0 || ofs1 + len > length s1
|
|
|
|
|| ofs2 < 0 || ofs2 + len > length s2
|
1995-05-04 03:15:53 -07:00
|
|
|
then invalid_arg "String.blit"
|
|
|
|
else unsafe_blit s1 ofs1 s2 ofs2 len
|
|
|
|
|
2001-09-06 01:52:32 -07:00
|
|
|
let iter f a =
|
|
|
|
for i = 0 to length a - 1 do f(unsafe_get a i) done
|
|
|
|
|
1995-05-05 03:05:18 -07:00
|
|
|
let concat sep l =
|
|
|
|
match l with
|
|
|
|
[] -> ""
|
|
|
|
| hd :: tl ->
|
|
|
|
let num = ref 0 and len = ref 0 in
|
|
|
|
List.iter (fun s -> incr num; len := !len + length s) l;
|
|
|
|
let r = create (!len + length sep * (!num - 1)) in
|
|
|
|
unsafe_blit hd 0 r 0 (length hd);
|
|
|
|
let pos = ref(length hd) in
|
|
|
|
List.iter
|
|
|
|
(fun s ->
|
|
|
|
unsafe_blit sep 0 r !pos (length sep);
|
|
|
|
pos := !pos + length sep;
|
|
|
|
unsafe_blit s 0 r !pos (length s);
|
|
|
|
pos := !pos + length s)
|
|
|
|
tl;
|
|
|
|
r
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
external is_printable: char -> bool = "is_printable"
|
1995-07-10 02:48:27 -07:00
|
|
|
external char_code: char -> int = "%identity"
|
|
|
|
external char_chr: int -> char = "%identity"
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
let escaped s =
|
|
|
|
let n = ref 0 in
|
|
|
|
for i = 0 to length s - 1 do
|
|
|
|
n := !n +
|
|
|
|
(match unsafe_get s i with
|
|
|
|
'"' | '\\' | '\n' | '\t' -> 2
|
|
|
|
| c -> if is_printable c then 1 else 4)
|
|
|
|
done;
|
|
|
|
if !n = length s then s else begin
|
|
|
|
let s' = create !n in
|
|
|
|
n := 0;
|
|
|
|
for i = 0 to length s - 1 do
|
|
|
|
begin
|
|
|
|
match unsafe_get s i with
|
|
|
|
('"' | '\\') as c ->
|
|
|
|
unsafe_set s' !n '\\'; incr n; unsafe_set s' !n c
|
|
|
|
| '\n' ->
|
|
|
|
unsafe_set s' !n '\\'; incr n; unsafe_set s' !n 'n'
|
|
|
|
| '\t' ->
|
|
|
|
unsafe_set s' !n '\\'; incr n; unsafe_set s' !n 't'
|
|
|
|
| c ->
|
|
|
|
if is_printable c then
|
|
|
|
unsafe_set s' !n c
|
|
|
|
else begin
|
1995-07-10 02:48:27 -07:00
|
|
|
let a = char_code c in
|
1995-05-04 03:15:53 -07:00
|
|
|
unsafe_set s' !n '\\';
|
|
|
|
incr n;
|
1995-07-10 02:48:27 -07:00
|
|
|
unsafe_set s' !n (char_chr (48 + a / 100));
|
1995-05-04 03:15:53 -07:00
|
|
|
incr n;
|
1995-07-10 02:48:27 -07:00
|
|
|
unsafe_set s' !n (char_chr (48 + (a / 10) mod 10));
|
1995-05-04 03:15:53 -07:00
|
|
|
incr n;
|
1995-07-10 02:48:27 -07:00
|
|
|
unsafe_set s' !n (char_chr (48 + a mod 10))
|
1995-05-04 03:15:53 -07:00
|
|
|
end
|
|
|
|
end;
|
|
|
|
incr n
|
|
|
|
done;
|
|
|
|
s'
|
|
|
|
end
|
1996-10-31 08:03:04 -08:00
|
|
|
|
|
|
|
let map f s =
|
|
|
|
let l = length s in
|
|
|
|
if l = 0 then s else begin
|
|
|
|
let r = create l in
|
|
|
|
for i = 0 to l - 1 do unsafe_set r i (f(unsafe_get s i)) done;
|
|
|
|
r
|
|
|
|
end
|
|
|
|
|
|
|
|
let uppercase s = map Char.uppercase s
|
1997-03-13 06:41:27 -08:00
|
|
|
let lowercase s = map Char.lowercase s
|
1996-10-31 08:03:04 -08:00
|
|
|
|
|
|
|
let apply1 f s =
|
|
|
|
if length s = 0 then s else begin
|
|
|
|
let r = copy s in
|
|
|
|
unsafe_set r 0 (f(unsafe_get s 0));
|
|
|
|
r
|
|
|
|
end
|
|
|
|
|
|
|
|
let capitalize s = apply1 Char.uppercase s
|
|
|
|
let uncapitalize s = apply1 Char.lowercase s
|
1997-10-24 08:54:07 -07:00
|
|
|
|
1999-02-12 00:08:57 -08:00
|
|
|
let rec index_rec s lim i c =
|
|
|
|
if i >= lim then raise Not_found else
|
|
|
|
if unsafe_get s i = c then i else index_rec s lim (i+1) c;;
|
1997-10-28 05:17:11 -08:00
|
|
|
|
1999-02-12 00:08:57 -08:00
|
|
|
let index s c = index_rec s (length s) 0 c;;
|
1997-10-28 05:17:11 -08:00
|
|
|
|
1997-12-09 01:12:05 -08:00
|
|
|
let index_from s i c =
|
1999-03-01 12:59:54 -08:00
|
|
|
if i < 0 || i > length s then invalid_arg "String.index_from" else
|
1999-02-12 00:08:57 -08:00
|
|
|
index_rec s (length s) i c;;
|
1997-12-09 01:12:05 -08:00
|
|
|
|
|
|
|
let rec rindex_rec s i c =
|
1999-02-12 00:08:57 -08:00
|
|
|
if i < 0 then raise Not_found else
|
|
|
|
if unsafe_get s i = c then i else rindex_rec s (i-1) c;;
|
1997-12-09 01:12:05 -08:00
|
|
|
|
1999-02-12 00:08:57 -08:00
|
|
|
let rindex s c = rindex_rec s (length s - 1) c;;
|
1997-12-09 01:12:05 -08:00
|
|
|
|
|
|
|
let rindex_from s i c =
|
2000-01-12 07:53:18 -08:00
|
|
|
if i < -1 || i >= length s then invalid_arg "String.rindex_from" else
|
1999-02-12 00:08:57 -08:00
|
|
|
rindex_rec s i c;;
|
1997-10-28 05:17:11 -08:00
|
|
|
|
1998-11-12 06:53:46 -08:00
|
|
|
let contains_from s i c =
|
1999-03-01 12:59:54 -08:00
|
|
|
if i < 0 || i > length s then invalid_arg "String.contains_from" else
|
1999-02-24 07:21:50 -08:00
|
|
|
try ignore(index_rec s (length s) i c); true with Not_found -> false;;
|
1998-11-12 06:53:46 -08:00
|
|
|
|
|
|
|
let rcontains_from s i c =
|
|
|
|
if i < 0 || i >= length s then invalid_arg "String.rcontains_from" else
|
1999-02-24 07:21:50 -08:00
|
|
|
try ignore(rindex_rec s i c); true with Not_found -> false;;
|
1998-11-12 06:53:46 -08:00
|
|
|
|
1999-03-01 12:59:54 -08:00
|
|
|
let contains s c = contains_from s 0 c;;
|