summaryrefslogtreecommitdiff
path: root/lib/render/emit_json.ml
blob: 272e4ca26ba811daf5597998260e24be60c42648 (plain) (blame)
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
(* emit_json.ml *)
module T = Template

let escape_string s =
  let b = Buffer.create (String.length s + 8) in
  Buffer.add_char b '"';
  String.iter
    (fun c ->
      match c with
      | '"' -> Buffer.add_string b "\\\""
      | '\\' -> Buffer.add_string b "\\\\"
      | '\n' -> Buffer.add_string b "\\n"
      | '\r' -> Buffer.add_string b "\\r"
      | '\t' -> Buffer.add_string b "\\t"
      | c when Char.code c < 0x20 -> Buffer.add_string b (Printf.sprintf "\\u%04x" (Char.code c))
      | c -> Buffer.add_char b c)
    s;
  Buffer.add_char b '"';
  Buffer.contents b

(* Emit the view tree directly. Bools stay bools; everything else is a string,
   an array or an object -- there are no numbers in the view, deliberately, so a
   consumer never has to guess whether "week" is 2 or "2". *)
let rec write b (v : T.value) =
  match v with
  | T.Str s -> Buffer.add_string b (escape_string s)
  | T.Bool x -> Buffer.add_string b (if x then "true" else "false")
  | T.List l ->
      Buffer.add_char b '[';
      List.iteri (fun i x -> if i > 0 then Buffer.add_char b ','; write b x) l;
      Buffer.add_char b ']'
  | T.Obj kvs ->
      Buffer.add_char b '{';
      List.iteri
        (fun i (k, x) ->
          if i > 0 then Buffer.add_char b ',';
          Buffer.add_string b (escape_string k);
          Buffer.add_char b ':';
          write b x)
        kvs;
      Buffer.add_char b '}'

let year v =
  let b = Buffer.create (64 * 1024) in
  write b v;
  Buffer.add_char b '\n';
  Buffer.contents b