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
|
#include "json.h"
#include "common.h"
struct JsonBuilder {
StrBuilder buf;
// not supported by ducc for now
// bool has_output_element[256];
bool* has_output_element;
int depth;
};
JsonBuilder* jsonbuilder_new() {
JsonBuilder* b = calloc(1, sizeof(JsonBuilder));
strbuilder_init(&b->buf);
b->has_output_element = calloc(256, sizeof(bool));
return b;
}
const char* jsonbuilder_get_output(JsonBuilder* b) {
return b->buf.buf;
}
static void emit_comma_if_needed(JsonBuilder* b) {
if (b->has_output_element[b->depth - 1]) {
strbuilder_append_char(&b->buf, ',');
}
}
void jsonbuilder_object_start(JsonBuilder* b) {
strbuilder_append_char(&b->buf, '{');
b->has_output_element[b->depth++] = false;
}
void jsonbuilder_object_end(JsonBuilder* b) {
b->depth--;
strbuilder_append_char(&b->buf, '}');
}
void jsonbuilder_object_member_start(JsonBuilder* b, const char* key) {
emit_comma_if_needed(b);
jsonbuilder_string(b, key);
strbuilder_append_char(&b->buf, ':');
}
void jsonbuilder_object_member_end(JsonBuilder* b) {
b->has_output_element[b->depth - 1] = true;
}
void jsonbuilder_array_start(JsonBuilder* b) {
strbuilder_append_char(&b->buf, '[');
b->has_output_element[b->depth++] = false;
}
void jsonbuilder_array_end(JsonBuilder* b) {
b->depth--;
strbuilder_append_char(&b->buf, ']');
}
void jsonbuilder_array_element_start(JsonBuilder* b) {
emit_comma_if_needed(b);
}
void jsonbuilder_array_element_end(JsonBuilder* b) {
b->has_output_element[b->depth - 1] = true;
}
void jsonbuilder_null(JsonBuilder* b) {
strbuilder_append_string(&b->buf, "null");
}
void jsonbuilder_boolean(JsonBuilder* b, bool value) {
strbuilder_append_string(&b->buf, value ? "true" : "false");
}
void jsonbuilder_integer(JsonBuilder* b, int value) {
char buf[32];
sprintf(buf, "%d", value);
strbuilder_append_string(&b->buf, buf);
}
void jsonbuilder_string(JsonBuilder* b, const char* value) {
if (!value) {
jsonbuilder_null(b);
return;
}
strbuilder_append_char(&b->buf, '"');
for (const char* p = value; *p; p++) {
if (*p == '"') {
strbuilder_append_string(&b->buf, "\\\"");
} else if (*p == '\\') {
strbuilder_append_string(&b->buf, "\\\\");
} else if (*p == '\b') {
strbuilder_append_string(&b->buf, "\\b");
} else if (*p == '\f') {
strbuilder_append_string(&b->buf, "\\f");
} else if (*p == '\n') {
strbuilder_append_string(&b->buf, "\\n");
} else if (*p == '\r') {
strbuilder_append_string(&b->buf, "\\r");
} else if (*p == '\t') {
strbuilder_append_string(&b->buf, "\\t");
} else {
strbuilder_append_char(&b->buf, *p);
}
}
strbuilder_append_char(&b->buf, '"');
}
|