1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
open EzCompat
open String
let for_all f s =
let res = ref true in
for i = 0 to length s - 1 do
res := !res && f s.[i]
done;
!res
let exists f s =
let res = ref false in
for i = 0 to length s - 1 do
res := !res || f s.[i]
done;
!res
let before s pos =
sub s 0 pos
let after s pos =
sub s (pos + 1) (length s - pos - 1)
let rec strneql s1 s2 len =
len = 0 || (
let len = len - 1 in
s1.[len] = s2.[len] && strneql s1 s2 len)
let starts_with s ~prefix =
let len1 = length s in
let len2 = length prefix in
len2 <= len1 && strneql s prefix len2
let ends_with s ~suffix =
let rec aux offset len =
len = 0 || (
let len = len - 1 in
s.[offset+len] = suffix.[len] && aux offset len) in
let len1 = length s in
let len2 = length suffix in
len2 <= len1 && aux (len1 - len2) len2
let cut s pos =
try
before s pos, after s pos
with _ -> s, ""
let cut_at s c =
try
let pos = index s c in
cut s pos
with _ -> s, ""
let rcut_at s c =
try
let pos = rindex s c in
cut s pos
with _ -> s, ""
let split s c =
let len = String.length s in
match String.index s c with
| exception Not_found ->
if len = 0 then [] else [ s ]
| pos ->
let rec iter pos to_rev =
match String.index_from s pos c with
| exception Not_found ->
List.rev ( String.sub s pos ( len - pos ) :: to_rev )
| pos2 ->
iter ( pos2 + 1 )
( String.sub s pos ( pos2 - pos ) :: to_rev )
in
iter (pos+1) [ String.sub s 0 pos ]
let _ =
assert (split "" 'o' = []);
assert (split "o" 'o' = [""; ""]);
assert (split "toto" 'o' = ["t"; "t"; ""]);
assert (split "ototo" 'o' = [""; "t"; "t"; ""]);
assert (split "tot" 'o' = ["t"; "t"]);
()
let split_simplify s c =
let len = String.length s in
let rec iter pos to_rev =
if pos = len then List.rev to_rev else
match try
Some ( String.index_from s pos c )
with Not_found -> None
with
Some pos2 ->
if pos2 = pos then iter (pos+1) to_rev else
iter (pos2+1) ((String.sub s pos (pos2-pos)) :: to_rev)
| None -> List.rev ( String.sub s pos (len-pos) :: to_rev )
in
iter 0 []
let _ =
assert (split_simplify "" 'o' = []);
assert (split_simplify "toto" 'o' = ["t"; "t"]);
assert (split_simplify "ototo" 'o' = ["t"; "t"]);
assert (split_simplify "tot" 'o' = ["t"; "t"]);
()
let chop_prefix s ~prefix =
if starts_with s ~prefix then
let prefix_len = String.length prefix in
let len = String.length s in
Some ( String.sub s prefix_len (len - prefix_len) )
else
None
let chop_suffix s ~suffix =
if ends_with s ~suffix then
let suffix_len = String.length suffix in
let len = String.length s in
Some ( String.sub s 0 (len - suffix_len) )
else
None