-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjson.c
144 lines (123 loc) · 3.95 KB
/
json.c
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
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <ctype.h>
#include "json.h"
#include "n_buf.h"
static size_t json_string_format(struct n_buf *nb, const char *s, void *data)
{
static char esc[] = {
['\0'] = '0',
['\a'] = 'a',
['\b'] = 'b',
['\t'] = 't',
['\n'] = 'n',
['\v'] = 'v',
['\f'] = 'f',
['\r'] = 'r',
['\"'] = '\"',
['\\'] = '\\',
};
/* This is probably broken for UNICODE. */
size_t len = 0;
len += n_buf_putc(nb, '\"');
for (; *s != 0; s++) {
int c = *(const unsigned char *) s;
if (!isascii(c)) {
len += n_buf_printf(nb, "\\u%04x", (unsigned int) c);
} else if (c < sizeof(esc) && esc[c] != 0) {
len += n_buf_putc(nb, '\\');
len += n_buf_putc(nb, esc[c]);
} else {
len += n_buf_putc(nb, c);
}
}
len += n_buf_putc(nb, '\"');
return len;
}
static size_t json_bool_format(struct n_buf *nb, int v, void *data)
{
return n_buf_printf(nb, v ? "true" : "false");
}
static size_t json_format_r(struct n_buf *nb, struct json **j,
void *data, int in_object, int in_array);
static size_t json_value_format(struct n_buf *nb, struct json *j,
void *data)
{
return json_format_r(nb, &j, data, 0, 0);
}
static size_t json_format_1(struct n_buf *nb, struct json *j, void *data)
{
switch (j->j_type & ~3) {
#define X(type, c_type, fmt, func) \
case J_ ## type ## _V: { \
typeof(c_type) cv; \
switch (j->j_type & 3) { \
case 0: \
cv = (j->j_u.u_ ## type ## _V); \
break; \
case 1: \
cv = *(j->j_u.u_ ## type ## _P); \
break; \
case 2: \
cv = (*(j->j_u.u_ ## type ## _F))(); \
break; \
case 3: \
cv = (*(j->j_u.u_ ## type ## _D))(data); \
break; \
} \
if ((func) != NULL) \
return ((size_t (*)(struct n_buf *, c_type, void *)) \
(func))(nb, cv, data); \
else \
return n_buf_printf(nb, fmt, cv); \
}
JSON_TYPES
#undef X
}
return 0;
}
static size_t json_format_r(struct n_buf *nb, struct json **j,
void *data, int in_object, int in_array)
{
size_t len = 0;
int i;
for (i = 0; (*j)->j_type != J_end_V; (*j)++) {
if (i > 0) {
if (in_array)
len += n_buf_putc(nb, ',');
else if (in_object)
len += n_buf_putc(nb, i % 2 ? ':' : ',');
else
break;
}
switch ((*j)->j_type) {
case J_init_V:
((*j)->j_u.u_init_V)();
break;
case J_array_V:
(*j)++;
len += n_buf_putc(nb, '[');
len += json_format_r(nb, j, data, 0, 1);
len += n_buf_putc(nb, ']');
break;
case J_object_V:
(*j)++;
len += n_buf_putc(nb, '{');
len += json_format_r(nb, j, data, 1, 0);
len += n_buf_putc(nb, '}');
break;
default:
len += json_format_1(nb, *j, data);
break;
}
i += ((*j)->j_type != J_init_V);
}
return len;
}
ssize_t json_format(struct n_buf *nb, struct json *j, void *data)
{
size_t len = json_format_r(nb, &j, data, 0, 0);
n_buf_put0(nb);
return len;
}