Merge pull request #9533 from bschommer/string-suffix-prefix

String suffix and prefix functions.
master
Nicolás Ojeda Bär 2020-06-24 17:39:32 +02:00 committed by GitHub
commit 34dbc549b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 53 additions and 4 deletions

View File

@ -111,6 +111,10 @@ Working version
and more generally all other data that is not a well-formed OCaml value
(Xavier Leroy, review by Damien Doligez and Gabriel Scherer)
- #9533: Added String.starts_with and String.ends_with.
(Bernhard Schommer, review by Daniel Bünzli, Gabriel Scherer and
Alain Frisch)
### Other libraries:
* #9206, #9419: update documentation of the threads library;

View File

@ -100,9 +100,7 @@ module Unix : SYSDEPS = struct
&& (String.length n < 2 || String.sub n 0 2 <> "./")
&& (String.length n < 3 || String.sub n 0 3 <> "../")
let check_suffix name suff =
String.length name >= String.length suff &&
String.sub name (String.length name - String.length suff)
(String.length suff) = suff
String.ends_with ~suffix:suff name
let chop_suffix_opt ~suffix filename =
let len_s = String.length suffix and len_f = String.length filename in

View File

@ -231,3 +231,22 @@ let to_seq s = bos s |> B.to_seq
let to_seqi s = bos s |> B.to_seqi
let of_seq g = B.of_seq g |> bts
let starts_with ~prefix s =
let len_s = length s
and len_pre = length prefix in
let rec aux i =
if i = len_pre then true
else if unsafe_get s i <> unsafe_get prefix i then false
else aux (i + 1)
in len_s >= len_pre && aux 0
let ends_with ~suffix s =
let len_s = length s
and len_suf = length suffix in
let diff = len_s - len_suf in
let rec aux i =
if i = len_suf then true
else if unsafe_get s (diff + i) <> unsafe_get suffix i then false
else aux (i + 1)
in diff >= 0 && aux 0

View File

@ -316,6 +316,14 @@ val equal: t -> t -> bool
(** The equal function for strings.
@since 4.03.0 *)
val starts_with : prefix:t -> t -> bool
(** [String.starts_with prefix s] tests if [s] starts with [prefix]
@since 4.12.0 *)
val ends_with : suffix:t -> t -> bool
(** [String.ends_with suffix s] tests if [s] ends with [suffix]
@since 4.12.0 *)
val split_on_char: char -> string -> string list
(** [String.split_on_char sep s] returns the list of all (possibly empty)
substrings of [s] that are delimited by the [sep] character.

View File

@ -282,6 +282,14 @@ val equal: t -> t -> bool
(** The equal function for strings.
@since 4.05.0 *)
val starts_with : prefix:t -> t -> bool
(** [String.starts_with prefix s] tests if [s] starts with [prefix]
@since 4.12.0 *)
val ends_with : suffix:t -> t -> bool
(** [String.ends_with suffix s] tests if [s] ends with [suffix]
@since 4.12.0 *)
val split_on_char: sep:char -> string -> string list
(** [String.split_on_char sep s] returns the list of all (possibly empty)
substrings of [s] that are delimited by the [sep] character.

View File

@ -51,5 +51,17 @@ let () =
while !sz >= 0 do push big l; sz += Sys.max_string_length done;
while !sz <= 0 do push big l; sz += Sys.max_string_length done;
try ignore (String.concat "" !l); assert false
with Invalid_argument _ -> ()
with Invalid_argument _ -> ();
assert(String.starts_with ~prefix:"foob" "foobarbaz");
assert(String.starts_with ~prefix:"" "foobarbaz");
assert(String.starts_with ~prefix:"" "");
assert(not (String.starts_with ~prefix:"foobar" "bar"));
assert(not (String.starts_with ~prefix:"foo" ""));
assert(not (String.starts_with ~prefix:"fool" "foobar"));
assert(String.ends_with ~suffix:"baz" "foobarbaz");
assert(String.ends_with ~suffix:"" "foobarbaz");
assert(String.ends_with ~suffix:"" "");
assert(not (String.ends_with ~suffix:"foobar" "bar"));
assert(not (String.ends_with ~suffix:"foo" ""));
assert(not (String.ends_with ~suffix:"obaz" "foobar"));
end