Source file writer_string.ml
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
module type Intf = sig
val json_to_string : 'a Json_internal.constrained -> (string, string) result
val json_to_string_exn : 'a Json_internal.constrained -> string
val to_string : 'a Json_internal.constrained -> string
val json_to_string_hum : 'a Json_internal.constrained -> (string, string) result
val json_to_string_hum_exn : 'a Json_internal.constrained -> string
val to_string_hum : 'a Json_internal.constrained -> string
val json_to_buffer : Buffer.t -> 'a Json_internal.constrained -> (unit, string) result
val json_to_buffer_exn : Buffer.t -> 'a Json_internal.constrained -> unit
val json_to_buffer_hum : Buffer.t -> 'a Json_internal.constrained -> (unit, string) result
val json_to_buffer_hum_exn : Buffer.t -> 'a Json_internal.constrained -> unit
val to_buffer : Buffer.t -> 'a Json_internal.constrained -> unit
val to_buffer_hum : Buffer.t -> 'a Json_internal.constrained -> unit
val stream_to_string : 'a Json_internal.constrained Stream.t -> string
val stream_to_buffer : Buffer.t -> 'a Json_internal.constrained Stream.t -> unit
end
module Make (Compliance : Compliance.S) : Intf = struct
let nibble_to_hex i = char_of_int (if i > 9 then 65 + i - 10 else 48 + i)
let add_hex_byte buf i =
Buffer.add_char buf (nibble_to_hex ((i lsr 4) land 0x0f));
Buffer.add_char buf (nibble_to_hex (i land 0x0f))
let escape buf s =
let add_char = Buffer.add_char buf in
let add_string = Buffer.add_string buf in
let l = String.length s in
for i = 0 to l - 1 do
match s.[i] with
| '"' -> add_string "\\\""
| '\\' -> add_string "\\\\"
| '\b' -> add_string "\\b"
| '\012' -> add_string "\\f"
| '\n' -> add_string "\\n"
| '\r' -> add_string "\\r"
| '\t' -> add_string "\\t"
| '\x00'..'\x1F'
| '\x7F' as c ->
add_string "\\u00"; add_hex_byte buf (int_of_char c)
| _ -> add_char s.[i]
done
let json_to_buffer' buf json =
let add_char = Buffer.add_char buf in
let add_string = Buffer.add_string buf in
let add_quote_string s = add_char '"'; escape buf s; add_char '"' in
let add_int i = add_string (string_of_int i) in
let add_float f = add_string (Compliance.number_to_string f) in
let rec fmt value =
match value with
| `Assoc o -> add_char '{'; json_assoc o; add_char '}'
| `List l -> add_char '['; json_list l; add_char ']'
| `Null -> add_string "null"
| `Bool b -> add_string (string_of_bool b)
| `Int i -> add_int i
| `Intlit s -> add_string s
| `Float f -> add_float f
| `Floatlit s -> add_string s
| `String s -> add_quote_string s
| `Stringlit s -> add_string s
| `Tuple t -> add_char '('; json_list t; add_char ')'
| `Variant v -> add_char '<'; variant v; add_char '>'
and json_assoc o =
let sep = ref "" in List.iter (fun v -> add_string !sep; sep := ","; pair v ) o
and pair (k, v) = add_quote_string k; add_char ':'; fmt v
and json_list l =
let sep = ref "" in List.iter (fun v -> add_string !sep; sep := ","; fmt v ) l
and variant (k, j) =
add_quote_string k;
match j with
| Some j -> add_char ':'; fmt j
| None -> ()
in
fmt json
let json_to_buffer_hum' buf json =
let add_char = Buffer.add_char buf in
let add_string = Buffer.add_string buf in
let add_quote_string s = add_char '"'; escape buf s; add_char '"' in
let add_int i = add_string (string_of_int i) in
let add_float f = add_string (Compliance.number_to_string f) in
let rec fmt ldr value =
match value with
| `Assoc o ->
add_string "{\n"; json_assoc (ldr ^ " ") o;
add_char '\n'; add_string ldr; add_char '}'
| `List l ->
add_string "[\n"; json_list (ldr ^ " ") l;
add_char '\n'; add_string ldr; add_char ']'
| `Null -> add_string "null"
| `Bool b -> add_string (string_of_bool b)
| `Int i -> add_int i
| `Intlit s -> add_string s
| `Float f -> add_float f
| `Floatlit s -> add_string s
| `String s -> add_quote_string s
| `Stringlit s -> add_string s
| `Tuple t ->
add_string "(\n"; json_list (ldr ^ " ") t;
add_char '\n'; add_string ldr; add_char ')'
| `Variant v ->
add_string "<"; variant (ldr ^ " ") v;
add_char '\n'; add_string ldr; add_char '>'
and json_assoc ldr o =
let sep = ref ldr in
let newsep = ",\n" ^ ldr in
List.iter (fun v -> add_string !sep; sep := newsep; pair ldr v ) o
and pair ldr (k, v) = add_quote_string k; add_string ": "; fmt ldr v
and json_list ldr l =
let sep = ref ldr in
let newsep = ",\n" ^ ldr in
List.iter (fun v -> add_string !sep; sep := newsep; fmt ldr v ) l
and variant ldr (k, j) =
add_quote_string k;
match j with
| Some j -> add_string ": "; fmt (ldr ^ " ") j
| None -> ()
in
fmt "" json;
add_char '\n'
let json_to_string' json =
let buf = Buffer.create 100 in
json_to_buffer' buf json;
Buffer.contents buf
let json_to_string json =
try Ok (json_to_string' json) with
| Failure err -> Error err
let json_to_buffer buf json =
try Ok (json_to_buffer' buf json) with
| Failure err -> Error err
let json_to_string_exn = json_to_string'
let to_string = json_to_string'
let json_to_buffer_exn = json_to_buffer'
let to_buffer = json_to_buffer'
let json_to_string_hum' json =
let buf = Buffer.create 100 in
json_to_buffer_hum' buf json;
Buffer.contents buf
let json_to_string_hum json =
try Ok (json_to_string_hum' json) with
| Failure err -> Error err
let json_to_buffer_hum buf json =
try Ok (json_to_buffer' buf json) with
| Failure err -> Error err
let json_to_string_hum_exn = json_to_string_hum'
let to_string_hum = json_to_string_hum'
let json_to_buffer_hum_exn = json_to_buffer_hum'
let to_buffer_hum = json_to_buffer_hum'
let stream_to_string stream =
let buf = Buffer.create 100 in
let () = Stream.iter (fun json -> to_buffer buf json; Buffer.add_char buf '\n') stream in
Buffer.contents buf
let stream_to_buffer buf stream =
Stream.iter (fun json -> to_buffer buf json; Buffer.add_char buf '\n') stream
end