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
|
(**************************************************************************)
(* Copyright © 2009-2013 Stéphane Glondu <steph@glondu.net> *)
(* © 2010-2013 Mehdi Dogguy <mehdi@dogguy.org> *)
(* *)
(* This program is free software: you can redistribute it and/or modify *)
(* it under the terms of the GNU Affero General Public License as *)
(* published by the Free Software Foundation, either version 3 of the *)
(* License, or (at your option) any later version, with the additional *)
(* exemption that compiling, linking, and/or using OpenSSL is allowed. *)
(* *)
(* This program is distributed in the hope that it will be useful, but *)
(* WITHOUT ANY WARRANTY; without even the implied warranty of *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *)
(* Affero General Public License for more details. *)
(* *)
(* You should have received a copy of the GNU Affero General Public *)
(* License along with this program. If not, see *)
(* <http://www.gnu.org/licenses/>. *)
(**************************************************************************)
module StringMap = struct
include Map.Make(String)
let from_list =
List.fold_left
(fun map (key, value) -> add key value map)
empty
let fusion m1 m2 =
let smerge _ v1 v2 = match v1, v2 with
| Some v1, Some _ -> Some v1
| Some v1, None -> Some v1
| None , Some v2 -> Some v2
| _ -> None
in
merge smerge m1 m2
end
module StringSet = struct
include Set.Make(String)
let from_list =
List.fold_left
(fun set elt -> add elt set)
empty
end
module IntMap = Map.Make(struct
type t = int
let compare : t -> t -> int = compare
end)
let with_in_channel chan f =
try
let res = f chan in
close_in chan; res
with e -> close_in chan; raise e
let with_in_file file f =
let chan = open_in_bin file in
try
let res = f chan in
close_in chan; res
with e -> close_in chan; raise e
let with_out_file file f =
let chan = open_out_bin file in
try
let res = f chan in
close_out chan; res
with e -> close_out chan; raise e
let escape_for_shell str =
let buf = Buffer.create (2 * String.length str) in
Buffer.add_char buf '\'';
String.iter
(function
| '\'' -> Buffer.add_string buf "'\\''"
| c -> Buffer.add_char buf c)
str;
Buffer.add_char buf '\'';
Buffer.contents buf
let get_rfc2822_date () =
let chan = Unix.open_process_in "date -R" in
let r = input_line chan in
match Unix.close_process_in chan with
| Unix.WEXITED 0 -> r
| _ -> failwith "unexpected return of date"
let list_rev_mapi f xs =
let rec aux i accu = function
| [] -> accu
| x::xs -> aux (i+1) ((f i x)::accu) xs
in aux 0 [] xs
let rec uniq = function
| [] -> []
| h::l ->
if List.mem h l
then uniq l
else h :: (uniq l)
let simple_split delim str =
let n = String.length str in
let rec aux i accu =
if i < n then
let j = try String.index_from str i delim with Not_found -> n in
aux (j+1) (String.sub str i (j-i) :: accu)
else List.rev accu
in aux 0 []
let capitalize ?(sep = '-') s =
let l = simple_split sep s in
let l = List.map String.capitalize_ascii l in
String.concat (String.make 1 sep) l
let starts_with str x =
let n = String.length str and p = String.length x in
n > p && String.sub str 0 p = x
let ends_with str x =
let n = String.length str and p = String.length x in
n > p && String.sub str (n-p) p = x
|