2 * Copyright (c) 2015, Facebook, Inc.
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the "hack" directory of this source tree. An additional grant
7 * of patent rights can be found in the PATENTS file in the same directory.
11 let soi = string_of_int
12 let string_of_char = String.make
1
14 let string_before s n
= String.sub s
0 n
15 let string_after s n
= String.sub s n
(String.length s
- n
)
17 let string_starts_with long short
=
19 let long = String.sub
long 0 (String.length short
) in
21 with Invalid_argument _
->
24 let string_ends_with long short
=
26 let len = String.length short
in
27 let long = String.sub
long (String.length
long - len) len in
29 with Invalid_argument _
->
32 (* Returns the index of the first occurrence of string `needle` in string
33 `haystack`. If not found, returns -1.
35 An implementation of the Knuth-Morris-Pratt (KMP) algorithm. *)
36 let substring_index needle
=
37 (* see Wikipedia pseudocode *)
38 let needle_len = String.length needle
in
39 if needle_len = 0 then raise
(Invalid_argument needle
);
40 let table = Array.make
needle_len 0 in
42 let pos = ref 2 and cnd
= ref 0 in
43 while !pos < needle_len do
44 if needle
.[!pos - 1] = needle
.[!cnd
] then
45 (table.(!pos) <- !cnd
+ 1; incr
pos; incr cnd
)
49 (table.(!pos) <- 0; incr
pos)
52 let len = String.length haystack
in
55 while !p < len && !q < needle_len do
56 if haystack
.[!p] = needle
.[!q] then (incr
p; incr
q)
57 else if !q = 0 then incr
p
60 if !q >= needle_len then !p - needle_len
63 let is_substring needle
=
64 let substring_index_memo = substring_index needle
in
65 fun haystack
-> (substring_index_memo haystack
) >= 0
67 (* Return a copy of the string with prefixing string removed.
68 * The function is a no-op if it s does not start with prefix.
69 * Modeled after Python's string.lstrip.
72 let prefix_length = String.length prefix
in
73 if string_starts_with s prefix
74 then String.sub s
prefix_length (String.length s
- prefix_length)
78 let sep_idx = String.rindex s c
in
79 let first = String.sub s
0 sep_idx in
81 String.sub s
(sep_idx + 1) (String.length s
- sep_idx - 1) in
84 let is_lowercase_char =
85 let a_code, z_code
= Char.code 'a'
, Char.code 'z'
in
87 let code = Char.code chr
in
88 a_code <= code && code <= z_code
90 let rec is_not_lowercase str i j
=
91 if is_lowercase_char str
.[i
] then false
92 else if i
= j
then true
93 else is_not_lowercase str
(i
+ 1) j