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
let assoc_keys xs = List.fold_left (fun acc (x, _) -> x :: acc) [] xs
let string_of_float f =
if f = (Float.round f) then int_of_float f |> string_of_int
else string_of_float f
let escape_string ?(exclude=[]) s =
let add_escaped_char buf c =
let add c = Buffer.add_string buf c in
if List.find_opt ((=) c) exclude |> Option.is_some then Buffer.add_char buf c else
match c with
| '\\' -> add "\\\\"
| '"' -> add "\\\""
| '\n' -> add "\\n"
| '\r' -> add "\\r"
| '\t' -> add "\\t"
| '\b' -> add "\\b"
| '\x00' .. '\x1F' | '\x7F' as c ->
let char_code = Char.code c in
let char_str =
if char_code > 0xFFFF then Printf.sprintf "\\u%08x" char_code
else Printf.sprintf "\\u%04x" char_code
in add char_str
| _ -> Buffer.add_char buf c
in
let buf = Buffer.create 4096 in
let () = String.iter (add_escaped_char buf) s in
Buffer.contents buf
let valid_bare_key s =
let good_for_bare_key c =
match c with
| 'a' .. 'z' | 'A' .. 'Z' | '-' | '_' -> true
| _ -> false
in
if s = "" then false else
String.to_seq s |> Seq.fold_left (fun acc c -> acc && (good_for_bare_key c)) true
let make_printable_key k =
if not (valid_bare_key k) then Printf.sprintf "\"%s\"" (escape_string k)
else k
let string_of_path ps =
List.map make_printable_key ps |> String.concat "."
let split_list xs =
let rec aux acc xs =
match xs with
| [] -> [], None
| x :: [] -> (List.rev acc), (Some x)
| x :: xs' -> aux (x :: acc) xs'
in aux [] xs