remove the Obj.magic from the string.ml implementation
It is important not to assume that String.t and Bytes.t will always share the same representation. Using Obj.magic to convert between functions would give a very bad example to users considering a migration, which are very quick to imitate any moral turpitude found in the standard library. An unfortunate consequence of the change is the duplication of String.concat code; other designs would be possible to share more implementation details between Bytes and String (eg. defined factorized operations on both in a shared internal module), but if we consider that String representation may evolve in the future this coincidence of implementation is really a temporary coindence rather than an definitive duplication. I checked that all the small functions introduced are marked as inlinable. In the case of coercions like this, we could even have the compiler recognize eta-expansions of the identity function and turn them into simple rebindings. git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@15060 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02master
parent
b7dd6d2c91
commit
2c4b259f60
|
@ -26,18 +26,48 @@ external unsafe_fill : bytes -> int -> int -> char -> unit
|
||||||
|
|
||||||
module B = Bytes
|
module B = Bytes
|
||||||
|
|
||||||
let make = (Obj.magic B.make : int -> char -> string)
|
let bts = B.unsafe_to_string
|
||||||
let init = (Obj.magic B.init : int -> (int -> char) -> string)
|
let bos = B.unsafe_of_string
|
||||||
let copy = (Obj.magic B.copy : string -> string)
|
|
||||||
let sub = (Obj.magic B.sub : string -> int -> int -> string)
|
let make n c =
|
||||||
let fill = B.fill
|
B.make n c |> bts
|
||||||
let blit =
|
let init n f =
|
||||||
(Obj.magic B.blit : string -> int -> bytes -> int -> int -> unit)
|
B.init n f |> bts
|
||||||
let concat = (Obj.magic B.concat : string -> string list -> string)
|
let copy s =
|
||||||
let iter = (Obj.magic B.iter : (char -> unit) -> string -> unit)
|
B.copy (bos s) |> bts
|
||||||
let iteri = (Obj.magic B.iteri : (int -> char -> unit) -> string -> unit)
|
let sub s ofs len =
|
||||||
let map = (Obj.magic B.map : (char -> char) -> string -> string)
|
B.sub (bos s) ofs len |> bts
|
||||||
let mapi = (Obj.magic B.mapi : (int -> char -> char) -> string -> string)
|
let fill =
|
||||||
|
B.fill
|
||||||
|
let blit s1 ofs1 s2 ofs2 len =
|
||||||
|
B.blit (bos s1) ofs1 s2 ofs2 len
|
||||||
|
|
||||||
|
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 = B.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;
|
||||||
|
Bytes.unsafe_to_string r
|
||||||
|
|
||||||
|
let iter f s =
|
||||||
|
B.iter f (bos s)
|
||||||
|
let iteri f s =
|
||||||
|
B.iteri f (bos s)
|
||||||
|
let map f s =
|
||||||
|
B.map f (bos s) |> bts
|
||||||
|
let mapi f s =
|
||||||
|
B.mapi f (bos s) |> bts
|
||||||
|
|
||||||
(* Beware: we cannot use B.trim or B.escape because they always make a
|
(* Beware: we cannot use B.trim or B.escape because they always make a
|
||||||
copy, but String.mli spells out some cases where we are not allowed
|
copy, but String.mli spells out some cases where we are not allowed
|
||||||
|
@ -52,7 +82,7 @@ let is_space = function
|
||||||
let trim s =
|
let trim s =
|
||||||
if s = "" then s
|
if s = "" then s
|
||||||
else if is_space (unsafe_get s 0) || is_space (unsafe_get s (length s - 1))
|
else if is_space (unsafe_get s 0) || is_space (unsafe_get s (length s - 1))
|
||||||
then B.unsafe_to_string (B.trim (B.unsafe_of_string s))
|
then bts (B.trim (bos s))
|
||||||
else s
|
else s
|
||||||
|
|
||||||
let escaped s =
|
let escaped s =
|
||||||
|
@ -64,22 +94,32 @@ let escaped s =
|
||||||
| _ -> true
|
| _ -> true
|
||||||
in
|
in
|
||||||
if needs_escape 0 then
|
if needs_escape 0 then
|
||||||
B.unsafe_to_string (B.escaped (B.unsafe_of_string s))
|
bts (B.escaped (bos s))
|
||||||
else
|
else
|
||||||
s
|
s
|
||||||
|
|
||||||
let index = (Obj.magic B.index : string -> char -> int)
|
let index s c =
|
||||||
let rindex = (Obj.magic B.rindex : string -> char -> int)
|
B.index (bos s) c
|
||||||
let index_from = (Obj.magic B.index_from : string -> int -> char -> int)
|
let rindex s c =
|
||||||
let rindex_from = (Obj.magic B.rindex_from : string -> int -> char -> int)
|
B.rindex (bos s) c
|
||||||
let contains = (Obj.magic B.contains : string -> char -> bool)
|
let index_from s i c=
|
||||||
let contains_from = (Obj.magic B.contains_from : string -> int -> char -> bool)
|
B.index_from (bos s) i c
|
||||||
let rcontains_from =
|
let rindex_from s i c =
|
||||||
(Obj.magic B.rcontains_from : string -> int -> char -> bool)
|
B.rindex_from (bos s) i c
|
||||||
let uppercase = (Obj.magic B.uppercase : string -> string)
|
let contains s c =
|
||||||
let lowercase = (Obj.magic B.lowercase : string -> string)
|
B.contains (bos s) c
|
||||||
let capitalize = (Obj.magic B.capitalize : string -> string)
|
let contains_from s i c =
|
||||||
let uncapitalize = (Obj.magic B.uncapitalize : string -> string)
|
B.contains_from (bos s) i c
|
||||||
|
let rcontains_from s i c =
|
||||||
|
B.rcontains_from (bos s) i c
|
||||||
|
let uppercase s =
|
||||||
|
B.uppercase (bos s) |> bts
|
||||||
|
let lowercase s =
|
||||||
|
B.lowercase (bos s) |> bts
|
||||||
|
let capitalize s =
|
||||||
|
B.capitalize (bos s) |> bts
|
||||||
|
let uncapitalize s =
|
||||||
|
B.uncapitalize (bos s) |> bts
|
||||||
|
|
||||||
type t = string
|
type t = string
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue