xref: /aosp_15_r20/external/jemalloc_new/test/unit/stats_print.c (revision 1208bc7e437ced7eb82efac44ba17e3beba411da)
1*1208bc7eSAndroid Build Coastguard Worker #include "test/jemalloc_test.h"
2*1208bc7eSAndroid Build Coastguard Worker 
3*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/util.h"
4*1208bc7eSAndroid Build Coastguard Worker 
5*1208bc7eSAndroid Build Coastguard Worker typedef enum {
6*1208bc7eSAndroid Build Coastguard Worker 	TOKEN_TYPE_NONE,
7*1208bc7eSAndroid Build Coastguard Worker 	TOKEN_TYPE_ERROR,
8*1208bc7eSAndroid Build Coastguard Worker 	TOKEN_TYPE_EOI,
9*1208bc7eSAndroid Build Coastguard Worker 	TOKEN_TYPE_NULL,
10*1208bc7eSAndroid Build Coastguard Worker 	TOKEN_TYPE_FALSE,
11*1208bc7eSAndroid Build Coastguard Worker 	TOKEN_TYPE_TRUE,
12*1208bc7eSAndroid Build Coastguard Worker 	TOKEN_TYPE_LBRACKET,
13*1208bc7eSAndroid Build Coastguard Worker 	TOKEN_TYPE_RBRACKET,
14*1208bc7eSAndroid Build Coastguard Worker 	TOKEN_TYPE_LBRACE,
15*1208bc7eSAndroid Build Coastguard Worker 	TOKEN_TYPE_RBRACE,
16*1208bc7eSAndroid Build Coastguard Worker 	TOKEN_TYPE_COLON,
17*1208bc7eSAndroid Build Coastguard Worker 	TOKEN_TYPE_COMMA,
18*1208bc7eSAndroid Build Coastguard Worker 	TOKEN_TYPE_STRING,
19*1208bc7eSAndroid Build Coastguard Worker 	TOKEN_TYPE_NUMBER
20*1208bc7eSAndroid Build Coastguard Worker } token_type_t;
21*1208bc7eSAndroid Build Coastguard Worker 
22*1208bc7eSAndroid Build Coastguard Worker typedef struct parser_s parser_t;
23*1208bc7eSAndroid Build Coastguard Worker typedef struct {
24*1208bc7eSAndroid Build Coastguard Worker 	parser_t	*parser;
25*1208bc7eSAndroid Build Coastguard Worker 	token_type_t	token_type;
26*1208bc7eSAndroid Build Coastguard Worker 	size_t		pos;
27*1208bc7eSAndroid Build Coastguard Worker 	size_t		len;
28*1208bc7eSAndroid Build Coastguard Worker 	size_t		line;
29*1208bc7eSAndroid Build Coastguard Worker 	size_t		col;
30*1208bc7eSAndroid Build Coastguard Worker } token_t;
31*1208bc7eSAndroid Build Coastguard Worker 
32*1208bc7eSAndroid Build Coastguard Worker struct parser_s {
33*1208bc7eSAndroid Build Coastguard Worker 	bool verbose;
34*1208bc7eSAndroid Build Coastguard Worker 	char	*buf; /* '\0'-terminated. */
35*1208bc7eSAndroid Build Coastguard Worker 	size_t	len; /* Number of characters preceding '\0' in buf. */
36*1208bc7eSAndroid Build Coastguard Worker 	size_t	pos;
37*1208bc7eSAndroid Build Coastguard Worker 	size_t	line;
38*1208bc7eSAndroid Build Coastguard Worker 	size_t	col;
39*1208bc7eSAndroid Build Coastguard Worker 	token_t	token;
40*1208bc7eSAndroid Build Coastguard Worker };
41*1208bc7eSAndroid Build Coastguard Worker 
42*1208bc7eSAndroid Build Coastguard Worker static void
token_init(token_t * token,parser_t * parser,token_type_t token_type,size_t pos,size_t len,size_t line,size_t col)43*1208bc7eSAndroid Build Coastguard Worker token_init(token_t *token, parser_t *parser, token_type_t token_type,
44*1208bc7eSAndroid Build Coastguard Worker     size_t pos, size_t len, size_t line, size_t col) {
45*1208bc7eSAndroid Build Coastguard Worker 	token->parser = parser;
46*1208bc7eSAndroid Build Coastguard Worker 	token->token_type = token_type;
47*1208bc7eSAndroid Build Coastguard Worker 	token->pos = pos;
48*1208bc7eSAndroid Build Coastguard Worker 	token->len = len;
49*1208bc7eSAndroid Build Coastguard Worker 	token->line = line;
50*1208bc7eSAndroid Build Coastguard Worker 	token->col = col;
51*1208bc7eSAndroid Build Coastguard Worker }
52*1208bc7eSAndroid Build Coastguard Worker 
53*1208bc7eSAndroid Build Coastguard Worker static void
token_error(token_t * token)54*1208bc7eSAndroid Build Coastguard Worker token_error(token_t *token) {
55*1208bc7eSAndroid Build Coastguard Worker 	if (!token->parser->verbose) {
56*1208bc7eSAndroid Build Coastguard Worker 		return;
57*1208bc7eSAndroid Build Coastguard Worker 	}
58*1208bc7eSAndroid Build Coastguard Worker 	switch (token->token_type) {
59*1208bc7eSAndroid Build Coastguard Worker 	case TOKEN_TYPE_NONE:
60*1208bc7eSAndroid Build Coastguard Worker 		not_reached();
61*1208bc7eSAndroid Build Coastguard Worker 	case TOKEN_TYPE_ERROR:
62*1208bc7eSAndroid Build Coastguard Worker 		malloc_printf("%zu:%zu: Unexpected character in token: ",
63*1208bc7eSAndroid Build Coastguard Worker 		    token->line, token->col);
64*1208bc7eSAndroid Build Coastguard Worker 		break;
65*1208bc7eSAndroid Build Coastguard Worker 	default:
66*1208bc7eSAndroid Build Coastguard Worker 		malloc_printf("%zu:%zu: Unexpected token: ", token->line,
67*1208bc7eSAndroid Build Coastguard Worker 		    token->col);
68*1208bc7eSAndroid Build Coastguard Worker 		break;
69*1208bc7eSAndroid Build Coastguard Worker 	}
70*1208bc7eSAndroid Build Coastguard Worker 	UNUSED ssize_t err = malloc_write_fd(STDERR_FILENO,
71*1208bc7eSAndroid Build Coastguard Worker 	    &token->parser->buf[token->pos], token->len);
72*1208bc7eSAndroid Build Coastguard Worker 	malloc_printf("\n");
73*1208bc7eSAndroid Build Coastguard Worker }
74*1208bc7eSAndroid Build Coastguard Worker 
75*1208bc7eSAndroid Build Coastguard Worker static void
parser_init(parser_t * parser,bool verbose)76*1208bc7eSAndroid Build Coastguard Worker parser_init(parser_t *parser, bool verbose) {
77*1208bc7eSAndroid Build Coastguard Worker 	parser->verbose = verbose;
78*1208bc7eSAndroid Build Coastguard Worker 	parser->buf = NULL;
79*1208bc7eSAndroid Build Coastguard Worker 	parser->len = 0;
80*1208bc7eSAndroid Build Coastguard Worker 	parser->pos = 0;
81*1208bc7eSAndroid Build Coastguard Worker 	parser->line = 1;
82*1208bc7eSAndroid Build Coastguard Worker 	parser->col = 0;
83*1208bc7eSAndroid Build Coastguard Worker }
84*1208bc7eSAndroid Build Coastguard Worker 
85*1208bc7eSAndroid Build Coastguard Worker static void
parser_fini(parser_t * parser)86*1208bc7eSAndroid Build Coastguard Worker parser_fini(parser_t *parser) {
87*1208bc7eSAndroid Build Coastguard Worker 	if (parser->buf != NULL) {
88*1208bc7eSAndroid Build Coastguard Worker 		dallocx(parser->buf, MALLOCX_TCACHE_NONE);
89*1208bc7eSAndroid Build Coastguard Worker 	}
90*1208bc7eSAndroid Build Coastguard Worker }
91*1208bc7eSAndroid Build Coastguard Worker 
92*1208bc7eSAndroid Build Coastguard Worker static bool
parser_append(parser_t * parser,const char * str)93*1208bc7eSAndroid Build Coastguard Worker parser_append(parser_t *parser, const char *str) {
94*1208bc7eSAndroid Build Coastguard Worker 	size_t len = strlen(str);
95*1208bc7eSAndroid Build Coastguard Worker 	char *buf = (parser->buf == NULL) ? mallocx(len + 1,
96*1208bc7eSAndroid Build Coastguard Worker 	    MALLOCX_TCACHE_NONE) : rallocx(parser->buf, parser->len + len + 1,
97*1208bc7eSAndroid Build Coastguard Worker 	    MALLOCX_TCACHE_NONE);
98*1208bc7eSAndroid Build Coastguard Worker 	if (buf == NULL) {
99*1208bc7eSAndroid Build Coastguard Worker 		return true;
100*1208bc7eSAndroid Build Coastguard Worker 	}
101*1208bc7eSAndroid Build Coastguard Worker 	memcpy(&buf[parser->len], str, len + 1);
102*1208bc7eSAndroid Build Coastguard Worker 	parser->buf = buf;
103*1208bc7eSAndroid Build Coastguard Worker 	parser->len += len;
104*1208bc7eSAndroid Build Coastguard Worker 	return false;
105*1208bc7eSAndroid Build Coastguard Worker }
106*1208bc7eSAndroid Build Coastguard Worker 
107*1208bc7eSAndroid Build Coastguard Worker static bool
parser_tokenize(parser_t * parser)108*1208bc7eSAndroid Build Coastguard Worker parser_tokenize(parser_t *parser) {
109*1208bc7eSAndroid Build Coastguard Worker 	enum {
110*1208bc7eSAndroid Build Coastguard Worker 		STATE_START,
111*1208bc7eSAndroid Build Coastguard Worker 		STATE_EOI,
112*1208bc7eSAndroid Build Coastguard Worker 		STATE_N, STATE_NU, STATE_NUL, STATE_NULL,
113*1208bc7eSAndroid Build Coastguard Worker 		STATE_F, STATE_FA, STATE_FAL, STATE_FALS, STATE_FALSE,
114*1208bc7eSAndroid Build Coastguard Worker 		STATE_T, STATE_TR, STATE_TRU, STATE_TRUE,
115*1208bc7eSAndroid Build Coastguard Worker 		STATE_LBRACKET,
116*1208bc7eSAndroid Build Coastguard Worker 		STATE_RBRACKET,
117*1208bc7eSAndroid Build Coastguard Worker 		STATE_LBRACE,
118*1208bc7eSAndroid Build Coastguard Worker 		STATE_RBRACE,
119*1208bc7eSAndroid Build Coastguard Worker 		STATE_COLON,
120*1208bc7eSAndroid Build Coastguard Worker 		STATE_COMMA,
121*1208bc7eSAndroid Build Coastguard Worker 		STATE_CHARS,
122*1208bc7eSAndroid Build Coastguard Worker 		STATE_CHAR_ESCAPE,
123*1208bc7eSAndroid Build Coastguard Worker 		STATE_CHAR_U, STATE_CHAR_UD, STATE_CHAR_UDD, STATE_CHAR_UDDD,
124*1208bc7eSAndroid Build Coastguard Worker 		STATE_STRING,
125*1208bc7eSAndroid Build Coastguard Worker 		STATE_MINUS,
126*1208bc7eSAndroid Build Coastguard Worker 		STATE_LEADING_ZERO,
127*1208bc7eSAndroid Build Coastguard Worker 		STATE_DIGITS,
128*1208bc7eSAndroid Build Coastguard Worker 		STATE_DECIMAL,
129*1208bc7eSAndroid Build Coastguard Worker 		STATE_FRAC_DIGITS,
130*1208bc7eSAndroid Build Coastguard Worker 		STATE_EXP,
131*1208bc7eSAndroid Build Coastguard Worker 		STATE_EXP_SIGN,
132*1208bc7eSAndroid Build Coastguard Worker 		STATE_EXP_DIGITS,
133*1208bc7eSAndroid Build Coastguard Worker 		STATE_ACCEPT
134*1208bc7eSAndroid Build Coastguard Worker 	} state = STATE_START;
135*1208bc7eSAndroid Build Coastguard Worker 	size_t token_pos JEMALLOC_CC_SILENCE_INIT(0);
136*1208bc7eSAndroid Build Coastguard Worker 	size_t token_line JEMALLOC_CC_SILENCE_INIT(1);
137*1208bc7eSAndroid Build Coastguard Worker 	size_t token_col JEMALLOC_CC_SILENCE_INIT(0);
138*1208bc7eSAndroid Build Coastguard Worker 
139*1208bc7eSAndroid Build Coastguard Worker 	assert_zu_le(parser->pos, parser->len,
140*1208bc7eSAndroid Build Coastguard Worker 	    "Position is past end of buffer");
141*1208bc7eSAndroid Build Coastguard Worker 
142*1208bc7eSAndroid Build Coastguard Worker 	while (state != STATE_ACCEPT) {
143*1208bc7eSAndroid Build Coastguard Worker 		char c = parser->buf[parser->pos];
144*1208bc7eSAndroid Build Coastguard Worker 
145*1208bc7eSAndroid Build Coastguard Worker 		switch (state) {
146*1208bc7eSAndroid Build Coastguard Worker 		case STATE_START:
147*1208bc7eSAndroid Build Coastguard Worker 			token_pos = parser->pos;
148*1208bc7eSAndroid Build Coastguard Worker 			token_line = parser->line;
149*1208bc7eSAndroid Build Coastguard Worker 			token_col = parser->col;
150*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
151*1208bc7eSAndroid Build Coastguard Worker 			case ' ': case '\b': case '\n': case '\r': case '\t':
152*1208bc7eSAndroid Build Coastguard Worker 				break;
153*1208bc7eSAndroid Build Coastguard Worker 			case '\0':
154*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_EOI;
155*1208bc7eSAndroid Build Coastguard Worker 				break;
156*1208bc7eSAndroid Build Coastguard Worker 			case 'n':
157*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_N;
158*1208bc7eSAndroid Build Coastguard Worker 				break;
159*1208bc7eSAndroid Build Coastguard Worker 			case 'f':
160*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_F;
161*1208bc7eSAndroid Build Coastguard Worker 				break;
162*1208bc7eSAndroid Build Coastguard Worker 			case 't':
163*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_T;
164*1208bc7eSAndroid Build Coastguard Worker 				break;
165*1208bc7eSAndroid Build Coastguard Worker 			case '[':
166*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_LBRACKET;
167*1208bc7eSAndroid Build Coastguard Worker 				break;
168*1208bc7eSAndroid Build Coastguard Worker 			case ']':
169*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_RBRACKET;
170*1208bc7eSAndroid Build Coastguard Worker 				break;
171*1208bc7eSAndroid Build Coastguard Worker 			case '{':
172*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_LBRACE;
173*1208bc7eSAndroid Build Coastguard Worker 				break;
174*1208bc7eSAndroid Build Coastguard Worker 			case '}':
175*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_RBRACE;
176*1208bc7eSAndroid Build Coastguard Worker 				break;
177*1208bc7eSAndroid Build Coastguard Worker 			case ':':
178*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_COLON;
179*1208bc7eSAndroid Build Coastguard Worker 				break;
180*1208bc7eSAndroid Build Coastguard Worker 			case ',':
181*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_COMMA;
182*1208bc7eSAndroid Build Coastguard Worker 				break;
183*1208bc7eSAndroid Build Coastguard Worker 			case '"':
184*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_CHARS;
185*1208bc7eSAndroid Build Coastguard Worker 				break;
186*1208bc7eSAndroid Build Coastguard Worker 			case '-':
187*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_MINUS;
188*1208bc7eSAndroid Build Coastguard Worker 				break;
189*1208bc7eSAndroid Build Coastguard Worker 			case '0':
190*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_LEADING_ZERO;
191*1208bc7eSAndroid Build Coastguard Worker 				break;
192*1208bc7eSAndroid Build Coastguard Worker 			case '1': case '2': case '3': case '4':
193*1208bc7eSAndroid Build Coastguard Worker 			case '5': case '6': case '7': case '8': case '9':
194*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_DIGITS;
195*1208bc7eSAndroid Build Coastguard Worker 				break;
196*1208bc7eSAndroid Build Coastguard Worker 			default:
197*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
198*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
199*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
200*1208bc7eSAndroid Build Coastguard Worker 				return true;
201*1208bc7eSAndroid Build Coastguard Worker 			}
202*1208bc7eSAndroid Build Coastguard Worker 			break;
203*1208bc7eSAndroid Build Coastguard Worker 		case STATE_EOI:
204*1208bc7eSAndroid Build Coastguard Worker 			token_init(&parser->token, parser,
205*1208bc7eSAndroid Build Coastguard Worker 			    TOKEN_TYPE_EOI, token_pos, parser->pos -
206*1208bc7eSAndroid Build Coastguard Worker 			    token_pos, token_line, token_col);
207*1208bc7eSAndroid Build Coastguard Worker 			state = STATE_ACCEPT;
208*1208bc7eSAndroid Build Coastguard Worker 			break;
209*1208bc7eSAndroid Build Coastguard Worker 		case STATE_N:
210*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
211*1208bc7eSAndroid Build Coastguard Worker 			case 'u':
212*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_NU;
213*1208bc7eSAndroid Build Coastguard Worker 				break;
214*1208bc7eSAndroid Build Coastguard Worker 			default:
215*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
216*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
217*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
218*1208bc7eSAndroid Build Coastguard Worker 				return true;
219*1208bc7eSAndroid Build Coastguard Worker 			}
220*1208bc7eSAndroid Build Coastguard Worker 			break;
221*1208bc7eSAndroid Build Coastguard Worker 		case STATE_NU:
222*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
223*1208bc7eSAndroid Build Coastguard Worker 			case 'l':
224*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_NUL;
225*1208bc7eSAndroid Build Coastguard Worker 				break;
226*1208bc7eSAndroid Build Coastguard Worker 			default:
227*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
228*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
229*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
230*1208bc7eSAndroid Build Coastguard Worker 				return true;
231*1208bc7eSAndroid Build Coastguard Worker 			}
232*1208bc7eSAndroid Build Coastguard Worker 			break;
233*1208bc7eSAndroid Build Coastguard Worker 		case STATE_NUL:
234*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
235*1208bc7eSAndroid Build Coastguard Worker 			case 'l':
236*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_NULL;
237*1208bc7eSAndroid Build Coastguard Worker 				break;
238*1208bc7eSAndroid Build Coastguard Worker 			default:
239*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
240*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
241*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
242*1208bc7eSAndroid Build Coastguard Worker 				return true;
243*1208bc7eSAndroid Build Coastguard Worker 			}
244*1208bc7eSAndroid Build Coastguard Worker 			break;
245*1208bc7eSAndroid Build Coastguard Worker 		case STATE_NULL:
246*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
247*1208bc7eSAndroid Build Coastguard Worker 			case ' ': case '\b': case '\n': case '\r': case '\t':
248*1208bc7eSAndroid Build Coastguard Worker 			case '\0':
249*1208bc7eSAndroid Build Coastguard Worker 			case '[': case ']': case '{': case '}': case ':':
250*1208bc7eSAndroid Build Coastguard Worker 			case ',':
251*1208bc7eSAndroid Build Coastguard Worker 				break;
252*1208bc7eSAndroid Build Coastguard Worker 			default:
253*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
254*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
255*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
256*1208bc7eSAndroid Build Coastguard Worker 				return true;
257*1208bc7eSAndroid Build Coastguard Worker 			}
258*1208bc7eSAndroid Build Coastguard Worker 			token_init(&parser->token, parser, TOKEN_TYPE_NULL,
259*1208bc7eSAndroid Build Coastguard Worker 			    token_pos, parser->pos - token_pos, token_line,
260*1208bc7eSAndroid Build Coastguard Worker 			    token_col);
261*1208bc7eSAndroid Build Coastguard Worker 			state = STATE_ACCEPT;
262*1208bc7eSAndroid Build Coastguard Worker 			break;
263*1208bc7eSAndroid Build Coastguard Worker 		case STATE_F:
264*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
265*1208bc7eSAndroid Build Coastguard Worker 			case 'a':
266*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_FA;
267*1208bc7eSAndroid Build Coastguard Worker 				break;
268*1208bc7eSAndroid Build Coastguard Worker 			default:
269*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
270*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
271*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
272*1208bc7eSAndroid Build Coastguard Worker 				return true;
273*1208bc7eSAndroid Build Coastguard Worker 			}
274*1208bc7eSAndroid Build Coastguard Worker 			break;
275*1208bc7eSAndroid Build Coastguard Worker 		case STATE_FA:
276*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
277*1208bc7eSAndroid Build Coastguard Worker 			case 'l':
278*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_FAL;
279*1208bc7eSAndroid Build Coastguard Worker 				break;
280*1208bc7eSAndroid Build Coastguard Worker 			default:
281*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
282*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
283*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
284*1208bc7eSAndroid Build Coastguard Worker 				return true;
285*1208bc7eSAndroid Build Coastguard Worker 			}
286*1208bc7eSAndroid Build Coastguard Worker 			break;
287*1208bc7eSAndroid Build Coastguard Worker 		case STATE_FAL:
288*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
289*1208bc7eSAndroid Build Coastguard Worker 			case 's':
290*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_FALS;
291*1208bc7eSAndroid Build Coastguard Worker 				break;
292*1208bc7eSAndroid Build Coastguard Worker 			default:
293*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
294*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
295*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
296*1208bc7eSAndroid Build Coastguard Worker 				return true;
297*1208bc7eSAndroid Build Coastguard Worker 			}
298*1208bc7eSAndroid Build Coastguard Worker 			break;
299*1208bc7eSAndroid Build Coastguard Worker 		case STATE_FALS:
300*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
301*1208bc7eSAndroid Build Coastguard Worker 			case 'e':
302*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_FALSE;
303*1208bc7eSAndroid Build Coastguard Worker 				break;
304*1208bc7eSAndroid Build Coastguard Worker 			default:
305*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
306*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
307*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
308*1208bc7eSAndroid Build Coastguard Worker 				return true;
309*1208bc7eSAndroid Build Coastguard Worker 			}
310*1208bc7eSAndroid Build Coastguard Worker 			break;
311*1208bc7eSAndroid Build Coastguard Worker 		case STATE_FALSE:
312*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
313*1208bc7eSAndroid Build Coastguard Worker 			case ' ': case '\b': case '\n': case '\r': case '\t':
314*1208bc7eSAndroid Build Coastguard Worker 			case '\0':
315*1208bc7eSAndroid Build Coastguard Worker 			case '[': case ']': case '{': case '}': case ':':
316*1208bc7eSAndroid Build Coastguard Worker 			case ',':
317*1208bc7eSAndroid Build Coastguard Worker 				break;
318*1208bc7eSAndroid Build Coastguard Worker 			default:
319*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
320*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
321*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
322*1208bc7eSAndroid Build Coastguard Worker 				return true;
323*1208bc7eSAndroid Build Coastguard Worker 			}
324*1208bc7eSAndroid Build Coastguard Worker 			token_init(&parser->token, parser,
325*1208bc7eSAndroid Build Coastguard Worker 			    TOKEN_TYPE_FALSE, token_pos, parser->pos -
326*1208bc7eSAndroid Build Coastguard Worker 			    token_pos, token_line, token_col);
327*1208bc7eSAndroid Build Coastguard Worker 			state = STATE_ACCEPT;
328*1208bc7eSAndroid Build Coastguard Worker 			break;
329*1208bc7eSAndroid Build Coastguard Worker 		case STATE_T:
330*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
331*1208bc7eSAndroid Build Coastguard Worker 			case 'r':
332*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_TR;
333*1208bc7eSAndroid Build Coastguard Worker 				break;
334*1208bc7eSAndroid Build Coastguard Worker 			default:
335*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
336*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
337*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
338*1208bc7eSAndroid Build Coastguard Worker 				return true;
339*1208bc7eSAndroid Build Coastguard Worker 			}
340*1208bc7eSAndroid Build Coastguard Worker 			break;
341*1208bc7eSAndroid Build Coastguard Worker 		case STATE_TR:
342*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
343*1208bc7eSAndroid Build Coastguard Worker 			case 'u':
344*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_TRU;
345*1208bc7eSAndroid Build Coastguard Worker 				break;
346*1208bc7eSAndroid Build Coastguard Worker 			default:
347*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
348*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
349*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
350*1208bc7eSAndroid Build Coastguard Worker 				return true;
351*1208bc7eSAndroid Build Coastguard Worker 			}
352*1208bc7eSAndroid Build Coastguard Worker 			break;
353*1208bc7eSAndroid Build Coastguard Worker 		case STATE_TRU:
354*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
355*1208bc7eSAndroid Build Coastguard Worker 			case 'e':
356*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_TRUE;
357*1208bc7eSAndroid Build Coastguard Worker 				break;
358*1208bc7eSAndroid Build Coastguard Worker 			default:
359*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
360*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
361*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
362*1208bc7eSAndroid Build Coastguard Worker 				return true;
363*1208bc7eSAndroid Build Coastguard Worker 			}
364*1208bc7eSAndroid Build Coastguard Worker 			break;
365*1208bc7eSAndroid Build Coastguard Worker 		case STATE_TRUE:
366*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
367*1208bc7eSAndroid Build Coastguard Worker 			case ' ': case '\b': case '\n': case '\r': case '\t':
368*1208bc7eSAndroid Build Coastguard Worker 			case '\0':
369*1208bc7eSAndroid Build Coastguard Worker 			case '[': case ']': case '{': case '}': case ':':
370*1208bc7eSAndroid Build Coastguard Worker 			case ',':
371*1208bc7eSAndroid Build Coastguard Worker 				break;
372*1208bc7eSAndroid Build Coastguard Worker 			default:
373*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
374*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
375*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
376*1208bc7eSAndroid Build Coastguard Worker 				return true;
377*1208bc7eSAndroid Build Coastguard Worker 			}
378*1208bc7eSAndroid Build Coastguard Worker 			token_init(&parser->token, parser, TOKEN_TYPE_TRUE,
379*1208bc7eSAndroid Build Coastguard Worker 			    token_pos, parser->pos - token_pos, token_line,
380*1208bc7eSAndroid Build Coastguard Worker 			    token_col);
381*1208bc7eSAndroid Build Coastguard Worker 			state = STATE_ACCEPT;
382*1208bc7eSAndroid Build Coastguard Worker 			break;
383*1208bc7eSAndroid Build Coastguard Worker 		case STATE_LBRACKET:
384*1208bc7eSAndroid Build Coastguard Worker 			token_init(&parser->token, parser, TOKEN_TYPE_LBRACKET,
385*1208bc7eSAndroid Build Coastguard Worker 			    token_pos, parser->pos - token_pos, token_line,
386*1208bc7eSAndroid Build Coastguard Worker 			    token_col);
387*1208bc7eSAndroid Build Coastguard Worker 			state = STATE_ACCEPT;
388*1208bc7eSAndroid Build Coastguard Worker 			break;
389*1208bc7eSAndroid Build Coastguard Worker 		case STATE_RBRACKET:
390*1208bc7eSAndroid Build Coastguard Worker 			token_init(&parser->token, parser, TOKEN_TYPE_RBRACKET,
391*1208bc7eSAndroid Build Coastguard Worker 			    token_pos, parser->pos - token_pos, token_line,
392*1208bc7eSAndroid Build Coastguard Worker 			    token_col);
393*1208bc7eSAndroid Build Coastguard Worker 			state = STATE_ACCEPT;
394*1208bc7eSAndroid Build Coastguard Worker 			break;
395*1208bc7eSAndroid Build Coastguard Worker 		case STATE_LBRACE:
396*1208bc7eSAndroid Build Coastguard Worker 			token_init(&parser->token, parser, TOKEN_TYPE_LBRACE,
397*1208bc7eSAndroid Build Coastguard Worker 			    token_pos, parser->pos - token_pos, token_line,
398*1208bc7eSAndroid Build Coastguard Worker 			    token_col);
399*1208bc7eSAndroid Build Coastguard Worker 			state = STATE_ACCEPT;
400*1208bc7eSAndroid Build Coastguard Worker 			break;
401*1208bc7eSAndroid Build Coastguard Worker 		case STATE_RBRACE:
402*1208bc7eSAndroid Build Coastguard Worker 			token_init(&parser->token, parser, TOKEN_TYPE_RBRACE,
403*1208bc7eSAndroid Build Coastguard Worker 			    token_pos, parser->pos - token_pos, token_line,
404*1208bc7eSAndroid Build Coastguard Worker 			    token_col);
405*1208bc7eSAndroid Build Coastguard Worker 			state = STATE_ACCEPT;
406*1208bc7eSAndroid Build Coastguard Worker 			break;
407*1208bc7eSAndroid Build Coastguard Worker 		case STATE_COLON:
408*1208bc7eSAndroid Build Coastguard Worker 			token_init(&parser->token, parser, TOKEN_TYPE_COLON,
409*1208bc7eSAndroid Build Coastguard Worker 			    token_pos, parser->pos - token_pos, token_line,
410*1208bc7eSAndroid Build Coastguard Worker 			    token_col);
411*1208bc7eSAndroid Build Coastguard Worker 			state = STATE_ACCEPT;
412*1208bc7eSAndroid Build Coastguard Worker 			break;
413*1208bc7eSAndroid Build Coastguard Worker 		case STATE_COMMA:
414*1208bc7eSAndroid Build Coastguard Worker 			token_init(&parser->token, parser, TOKEN_TYPE_COMMA,
415*1208bc7eSAndroid Build Coastguard Worker 			    token_pos, parser->pos - token_pos, token_line,
416*1208bc7eSAndroid Build Coastguard Worker 			    token_col);
417*1208bc7eSAndroid Build Coastguard Worker 			state = STATE_ACCEPT;
418*1208bc7eSAndroid Build Coastguard Worker 			break;
419*1208bc7eSAndroid Build Coastguard Worker 		case STATE_CHARS:
420*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
421*1208bc7eSAndroid Build Coastguard Worker 			case '\\':
422*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_CHAR_ESCAPE;
423*1208bc7eSAndroid Build Coastguard Worker 				break;
424*1208bc7eSAndroid Build Coastguard Worker 			case '"':
425*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_STRING;
426*1208bc7eSAndroid Build Coastguard Worker 				break;
427*1208bc7eSAndroid Build Coastguard Worker 			case 0x00: case 0x01: case 0x02: case 0x03: case 0x04:
428*1208bc7eSAndroid Build Coastguard Worker 			case 0x05: case 0x06: case 0x07: case 0x08: case 0x09:
429*1208bc7eSAndroid Build Coastguard Worker 			case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e:
430*1208bc7eSAndroid Build Coastguard Worker 			case 0x0f: case 0x10: case 0x11: case 0x12: case 0x13:
431*1208bc7eSAndroid Build Coastguard Worker 			case 0x14: case 0x15: case 0x16: case 0x17: case 0x18:
432*1208bc7eSAndroid Build Coastguard Worker 			case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d:
433*1208bc7eSAndroid Build Coastguard Worker 			case 0x1e: case 0x1f:
434*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
435*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
436*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
437*1208bc7eSAndroid Build Coastguard Worker 				return true;
438*1208bc7eSAndroid Build Coastguard Worker 			default:
439*1208bc7eSAndroid Build Coastguard Worker 				break;
440*1208bc7eSAndroid Build Coastguard Worker 			}
441*1208bc7eSAndroid Build Coastguard Worker 			break;
442*1208bc7eSAndroid Build Coastguard Worker 		case STATE_CHAR_ESCAPE:
443*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
444*1208bc7eSAndroid Build Coastguard Worker 			case '"': case '\\': case '/': case 'b': case 'n':
445*1208bc7eSAndroid Build Coastguard Worker 			case 'r': case 't':
446*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_CHARS;
447*1208bc7eSAndroid Build Coastguard Worker 				break;
448*1208bc7eSAndroid Build Coastguard Worker 			case 'u':
449*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_CHAR_U;
450*1208bc7eSAndroid Build Coastguard Worker 				break;
451*1208bc7eSAndroid Build Coastguard Worker 			default:
452*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
453*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
454*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
455*1208bc7eSAndroid Build Coastguard Worker 				return true;
456*1208bc7eSAndroid Build Coastguard Worker 			}
457*1208bc7eSAndroid Build Coastguard Worker 			break;
458*1208bc7eSAndroid Build Coastguard Worker 		case STATE_CHAR_U:
459*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
460*1208bc7eSAndroid Build Coastguard Worker 			case '0': case '1': case '2': case '3': case '4':
461*1208bc7eSAndroid Build Coastguard Worker 			case '5': case '6': case '7': case '8': case '9':
462*1208bc7eSAndroid Build Coastguard Worker 			case 'a': case 'b': case 'c': case 'd': case 'e':
463*1208bc7eSAndroid Build Coastguard Worker 			case 'f':
464*1208bc7eSAndroid Build Coastguard Worker 			case 'A': case 'B': case 'C': case 'D': case 'E':
465*1208bc7eSAndroid Build Coastguard Worker 			case 'F':
466*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_CHAR_UD;
467*1208bc7eSAndroid Build Coastguard Worker 				break;
468*1208bc7eSAndroid Build Coastguard Worker 			default:
469*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
470*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
471*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
472*1208bc7eSAndroid Build Coastguard Worker 				return true;
473*1208bc7eSAndroid Build Coastguard Worker 			}
474*1208bc7eSAndroid Build Coastguard Worker 			break;
475*1208bc7eSAndroid Build Coastguard Worker 		case STATE_CHAR_UD:
476*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
477*1208bc7eSAndroid Build Coastguard Worker 			case '0': case '1': case '2': case '3': case '4':
478*1208bc7eSAndroid Build Coastguard Worker 			case '5': case '6': case '7': case '8': case '9':
479*1208bc7eSAndroid Build Coastguard Worker 			case 'a': case 'b': case 'c': case 'd': case 'e':
480*1208bc7eSAndroid Build Coastguard Worker 			case 'f':
481*1208bc7eSAndroid Build Coastguard Worker 			case 'A': case 'B': case 'C': case 'D': case 'E':
482*1208bc7eSAndroid Build Coastguard Worker 			case 'F':
483*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_CHAR_UDD;
484*1208bc7eSAndroid Build Coastguard Worker 				break;
485*1208bc7eSAndroid Build Coastguard Worker 			default:
486*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
487*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
488*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
489*1208bc7eSAndroid Build Coastguard Worker 				return true;
490*1208bc7eSAndroid Build Coastguard Worker 			}
491*1208bc7eSAndroid Build Coastguard Worker 			break;
492*1208bc7eSAndroid Build Coastguard Worker 		case STATE_CHAR_UDD:
493*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
494*1208bc7eSAndroid Build Coastguard Worker 			case '0': case '1': case '2': case '3': case '4':
495*1208bc7eSAndroid Build Coastguard Worker 			case '5': case '6': case '7': case '8': case '9':
496*1208bc7eSAndroid Build Coastguard Worker 			case 'a': case 'b': case 'c': case 'd': case 'e':
497*1208bc7eSAndroid Build Coastguard Worker 			case 'f':
498*1208bc7eSAndroid Build Coastguard Worker 			case 'A': case 'B': case 'C': case 'D': case 'E':
499*1208bc7eSAndroid Build Coastguard Worker 			case 'F':
500*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_CHAR_UDDD;
501*1208bc7eSAndroid Build Coastguard Worker 				break;
502*1208bc7eSAndroid Build Coastguard Worker 			default:
503*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
504*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
505*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
506*1208bc7eSAndroid Build Coastguard Worker 				return true;
507*1208bc7eSAndroid Build Coastguard Worker 			}
508*1208bc7eSAndroid Build Coastguard Worker 			break;
509*1208bc7eSAndroid Build Coastguard Worker 		case STATE_CHAR_UDDD:
510*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
511*1208bc7eSAndroid Build Coastguard Worker 			case '0': case '1': case '2': case '3': case '4':
512*1208bc7eSAndroid Build Coastguard Worker 			case '5': case '6': case '7': case '8': case '9':
513*1208bc7eSAndroid Build Coastguard Worker 			case 'a': case 'b': case 'c': case 'd': case 'e':
514*1208bc7eSAndroid Build Coastguard Worker 			case 'f':
515*1208bc7eSAndroid Build Coastguard Worker 			case 'A': case 'B': case 'C': case 'D': case 'E':
516*1208bc7eSAndroid Build Coastguard Worker 			case 'F':
517*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_CHARS;
518*1208bc7eSAndroid Build Coastguard Worker 				break;
519*1208bc7eSAndroid Build Coastguard Worker 			default:
520*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
521*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
522*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
523*1208bc7eSAndroid Build Coastguard Worker 				return true;
524*1208bc7eSAndroid Build Coastguard Worker 			}
525*1208bc7eSAndroid Build Coastguard Worker 			break;
526*1208bc7eSAndroid Build Coastguard Worker 		case STATE_STRING:
527*1208bc7eSAndroid Build Coastguard Worker 			token_init(&parser->token, parser, TOKEN_TYPE_STRING,
528*1208bc7eSAndroid Build Coastguard Worker 			    token_pos, parser->pos - token_pos, token_line,
529*1208bc7eSAndroid Build Coastguard Worker 			    token_col);
530*1208bc7eSAndroid Build Coastguard Worker 			state = STATE_ACCEPT;
531*1208bc7eSAndroid Build Coastguard Worker 			break;
532*1208bc7eSAndroid Build Coastguard Worker 		case STATE_MINUS:
533*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
534*1208bc7eSAndroid Build Coastguard Worker 			case '0':
535*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_LEADING_ZERO;
536*1208bc7eSAndroid Build Coastguard Worker 				break;
537*1208bc7eSAndroid Build Coastguard Worker 			case '1': case '2': case '3': case '4':
538*1208bc7eSAndroid Build Coastguard Worker 			case '5': case '6': case '7': case '8': case '9':
539*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_DIGITS;
540*1208bc7eSAndroid Build Coastguard Worker 				break;
541*1208bc7eSAndroid Build Coastguard Worker 			default:
542*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
543*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
544*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
545*1208bc7eSAndroid Build Coastguard Worker 				return true;
546*1208bc7eSAndroid Build Coastguard Worker 			}
547*1208bc7eSAndroid Build Coastguard Worker 			break;
548*1208bc7eSAndroid Build Coastguard Worker 		case STATE_LEADING_ZERO:
549*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
550*1208bc7eSAndroid Build Coastguard Worker 			case '.':
551*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_DECIMAL;
552*1208bc7eSAndroid Build Coastguard Worker 				break;
553*1208bc7eSAndroid Build Coastguard Worker 			default:
554*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
555*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_NUMBER, token_pos, parser->pos -
556*1208bc7eSAndroid Build Coastguard Worker 				    token_pos, token_line, token_col);
557*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_ACCEPT;
558*1208bc7eSAndroid Build Coastguard Worker 				break;
559*1208bc7eSAndroid Build Coastguard Worker 			}
560*1208bc7eSAndroid Build Coastguard Worker 			break;
561*1208bc7eSAndroid Build Coastguard Worker 		case STATE_DIGITS:
562*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
563*1208bc7eSAndroid Build Coastguard Worker 			case '0': case '1': case '2': case '3': case '4':
564*1208bc7eSAndroid Build Coastguard Worker 			case '5': case '6': case '7': case '8': case '9':
565*1208bc7eSAndroid Build Coastguard Worker 				break;
566*1208bc7eSAndroid Build Coastguard Worker 			case '.':
567*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_DECIMAL;
568*1208bc7eSAndroid Build Coastguard Worker 				break;
569*1208bc7eSAndroid Build Coastguard Worker 			default:
570*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
571*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_NUMBER, token_pos, parser->pos -
572*1208bc7eSAndroid Build Coastguard Worker 				    token_pos, token_line, token_col);
573*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_ACCEPT;
574*1208bc7eSAndroid Build Coastguard Worker 				break;
575*1208bc7eSAndroid Build Coastguard Worker 			}
576*1208bc7eSAndroid Build Coastguard Worker 			break;
577*1208bc7eSAndroid Build Coastguard Worker 		case STATE_DECIMAL:
578*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
579*1208bc7eSAndroid Build Coastguard Worker 			case '0': case '1': case '2': case '3': case '4':
580*1208bc7eSAndroid Build Coastguard Worker 			case '5': case '6': case '7': case '8': case '9':
581*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_FRAC_DIGITS;
582*1208bc7eSAndroid Build Coastguard Worker 				break;
583*1208bc7eSAndroid Build Coastguard Worker 			default:
584*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
585*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
586*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
587*1208bc7eSAndroid Build Coastguard Worker 				return true;
588*1208bc7eSAndroid Build Coastguard Worker 			}
589*1208bc7eSAndroid Build Coastguard Worker 			break;
590*1208bc7eSAndroid Build Coastguard Worker 		case STATE_FRAC_DIGITS:
591*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
592*1208bc7eSAndroid Build Coastguard Worker 			case '0': case '1': case '2': case '3': case '4':
593*1208bc7eSAndroid Build Coastguard Worker 			case '5': case '6': case '7': case '8': case '9':
594*1208bc7eSAndroid Build Coastguard Worker 				break;
595*1208bc7eSAndroid Build Coastguard Worker 			case 'e': case 'E':
596*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_EXP;
597*1208bc7eSAndroid Build Coastguard Worker 				break;
598*1208bc7eSAndroid Build Coastguard Worker 			default:
599*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
600*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_NUMBER, token_pos, parser->pos -
601*1208bc7eSAndroid Build Coastguard Worker 				    token_pos, token_line, token_col);
602*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_ACCEPT;
603*1208bc7eSAndroid Build Coastguard Worker 				break;
604*1208bc7eSAndroid Build Coastguard Worker 			}
605*1208bc7eSAndroid Build Coastguard Worker 			break;
606*1208bc7eSAndroid Build Coastguard Worker 		case STATE_EXP:
607*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
608*1208bc7eSAndroid Build Coastguard Worker 			case '-': case '+':
609*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_EXP_SIGN;
610*1208bc7eSAndroid Build Coastguard Worker 				break;
611*1208bc7eSAndroid Build Coastguard Worker 			case '0': case '1': case '2': case '3': case '4':
612*1208bc7eSAndroid Build Coastguard Worker 			case '5': case '6': case '7': case '8': case '9':
613*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_EXP_DIGITS;
614*1208bc7eSAndroid Build Coastguard Worker 				break;
615*1208bc7eSAndroid Build Coastguard Worker 			default:
616*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
617*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
618*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
619*1208bc7eSAndroid Build Coastguard Worker 				return true;
620*1208bc7eSAndroid Build Coastguard Worker 			}
621*1208bc7eSAndroid Build Coastguard Worker 			break;
622*1208bc7eSAndroid Build Coastguard Worker 		case STATE_EXP_SIGN:
623*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
624*1208bc7eSAndroid Build Coastguard Worker 			case '0': case '1': case '2': case '3': case '4':
625*1208bc7eSAndroid Build Coastguard Worker 			case '5': case '6': case '7': case '8': case '9':
626*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_EXP_DIGITS;
627*1208bc7eSAndroid Build Coastguard Worker 				break;
628*1208bc7eSAndroid Build Coastguard Worker 			default:
629*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
630*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
631*1208bc7eSAndroid Build Coastguard Worker 				    - token_pos, token_line, token_col);
632*1208bc7eSAndroid Build Coastguard Worker 				return true;
633*1208bc7eSAndroid Build Coastguard Worker 			}
634*1208bc7eSAndroid Build Coastguard Worker 			break;
635*1208bc7eSAndroid Build Coastguard Worker 		case STATE_EXP_DIGITS:
636*1208bc7eSAndroid Build Coastguard Worker 			switch (c) {
637*1208bc7eSAndroid Build Coastguard Worker 			case '0': case '1': case '2': case '3': case '4':
638*1208bc7eSAndroid Build Coastguard Worker 			case '5': case '6': case '7': case '8': case '9':
639*1208bc7eSAndroid Build Coastguard Worker 				break;
640*1208bc7eSAndroid Build Coastguard Worker 			default:
641*1208bc7eSAndroid Build Coastguard Worker 				token_init(&parser->token, parser,
642*1208bc7eSAndroid Build Coastguard Worker 				    TOKEN_TYPE_NUMBER, token_pos, parser->pos -
643*1208bc7eSAndroid Build Coastguard Worker 				    token_pos, token_line, token_col);
644*1208bc7eSAndroid Build Coastguard Worker 				state = STATE_ACCEPT;
645*1208bc7eSAndroid Build Coastguard Worker 				break;
646*1208bc7eSAndroid Build Coastguard Worker 			}
647*1208bc7eSAndroid Build Coastguard Worker 			break;
648*1208bc7eSAndroid Build Coastguard Worker 		default:
649*1208bc7eSAndroid Build Coastguard Worker 			not_reached();
650*1208bc7eSAndroid Build Coastguard Worker 		}
651*1208bc7eSAndroid Build Coastguard Worker 
652*1208bc7eSAndroid Build Coastguard Worker 		if (state != STATE_ACCEPT) {
653*1208bc7eSAndroid Build Coastguard Worker 			if (c == '\n') {
654*1208bc7eSAndroid Build Coastguard Worker 				parser->line++;
655*1208bc7eSAndroid Build Coastguard Worker 				parser->col = 0;
656*1208bc7eSAndroid Build Coastguard Worker 			} else {
657*1208bc7eSAndroid Build Coastguard Worker 				parser->col++;
658*1208bc7eSAndroid Build Coastguard Worker 			}
659*1208bc7eSAndroid Build Coastguard Worker 			parser->pos++;
660*1208bc7eSAndroid Build Coastguard Worker 		}
661*1208bc7eSAndroid Build Coastguard Worker 	}
662*1208bc7eSAndroid Build Coastguard Worker 	return false;
663*1208bc7eSAndroid Build Coastguard Worker }
664*1208bc7eSAndroid Build Coastguard Worker 
665*1208bc7eSAndroid Build Coastguard Worker static bool	parser_parse_array(parser_t *parser);
666*1208bc7eSAndroid Build Coastguard Worker static bool	parser_parse_object(parser_t *parser);
667*1208bc7eSAndroid Build Coastguard Worker 
668*1208bc7eSAndroid Build Coastguard Worker static bool
parser_parse_value(parser_t * parser)669*1208bc7eSAndroid Build Coastguard Worker parser_parse_value(parser_t *parser) {
670*1208bc7eSAndroid Build Coastguard Worker 	switch (parser->token.token_type) {
671*1208bc7eSAndroid Build Coastguard Worker 	case TOKEN_TYPE_NULL:
672*1208bc7eSAndroid Build Coastguard Worker 	case TOKEN_TYPE_FALSE:
673*1208bc7eSAndroid Build Coastguard Worker 	case TOKEN_TYPE_TRUE:
674*1208bc7eSAndroid Build Coastguard Worker 	case TOKEN_TYPE_STRING:
675*1208bc7eSAndroid Build Coastguard Worker 	case TOKEN_TYPE_NUMBER:
676*1208bc7eSAndroid Build Coastguard Worker 		return false;
677*1208bc7eSAndroid Build Coastguard Worker 	case TOKEN_TYPE_LBRACE:
678*1208bc7eSAndroid Build Coastguard Worker 		return parser_parse_object(parser);
679*1208bc7eSAndroid Build Coastguard Worker 	case TOKEN_TYPE_LBRACKET:
680*1208bc7eSAndroid Build Coastguard Worker 		return parser_parse_array(parser);
681*1208bc7eSAndroid Build Coastguard Worker 	default:
682*1208bc7eSAndroid Build Coastguard Worker 		return true;
683*1208bc7eSAndroid Build Coastguard Worker 	}
684*1208bc7eSAndroid Build Coastguard Worker 	not_reached();
685*1208bc7eSAndroid Build Coastguard Worker }
686*1208bc7eSAndroid Build Coastguard Worker 
687*1208bc7eSAndroid Build Coastguard Worker static bool
parser_parse_pair(parser_t * parser)688*1208bc7eSAndroid Build Coastguard Worker parser_parse_pair(parser_t *parser) {
689*1208bc7eSAndroid Build Coastguard Worker 	assert_d_eq(parser->token.token_type, TOKEN_TYPE_STRING,
690*1208bc7eSAndroid Build Coastguard Worker 	    "Pair should start with string");
691*1208bc7eSAndroid Build Coastguard Worker 	if (parser_tokenize(parser)) {
692*1208bc7eSAndroid Build Coastguard Worker 		return true;
693*1208bc7eSAndroid Build Coastguard Worker 	}
694*1208bc7eSAndroid Build Coastguard Worker 	switch (parser->token.token_type) {
695*1208bc7eSAndroid Build Coastguard Worker 	case TOKEN_TYPE_COLON:
696*1208bc7eSAndroid Build Coastguard Worker 		if (parser_tokenize(parser)) {
697*1208bc7eSAndroid Build Coastguard Worker 			return true;
698*1208bc7eSAndroid Build Coastguard Worker 		}
699*1208bc7eSAndroid Build Coastguard Worker 		return parser_parse_value(parser);
700*1208bc7eSAndroid Build Coastguard Worker 	default:
701*1208bc7eSAndroid Build Coastguard Worker 		return true;
702*1208bc7eSAndroid Build Coastguard Worker 	}
703*1208bc7eSAndroid Build Coastguard Worker }
704*1208bc7eSAndroid Build Coastguard Worker 
705*1208bc7eSAndroid Build Coastguard Worker static bool
parser_parse_values(parser_t * parser)706*1208bc7eSAndroid Build Coastguard Worker parser_parse_values(parser_t *parser) {
707*1208bc7eSAndroid Build Coastguard Worker 	if (parser_parse_value(parser)) {
708*1208bc7eSAndroid Build Coastguard Worker 		return true;
709*1208bc7eSAndroid Build Coastguard Worker 	}
710*1208bc7eSAndroid Build Coastguard Worker 
711*1208bc7eSAndroid Build Coastguard Worker 	while (true) {
712*1208bc7eSAndroid Build Coastguard Worker 		if (parser_tokenize(parser)) {
713*1208bc7eSAndroid Build Coastguard Worker 			return true;
714*1208bc7eSAndroid Build Coastguard Worker 		}
715*1208bc7eSAndroid Build Coastguard Worker 		switch (parser->token.token_type) {
716*1208bc7eSAndroid Build Coastguard Worker 		case TOKEN_TYPE_COMMA:
717*1208bc7eSAndroid Build Coastguard Worker 			if (parser_tokenize(parser)) {
718*1208bc7eSAndroid Build Coastguard Worker 				return true;
719*1208bc7eSAndroid Build Coastguard Worker 			}
720*1208bc7eSAndroid Build Coastguard Worker 			if (parser_parse_value(parser)) {
721*1208bc7eSAndroid Build Coastguard Worker 				return true;
722*1208bc7eSAndroid Build Coastguard Worker 			}
723*1208bc7eSAndroid Build Coastguard Worker 			break;
724*1208bc7eSAndroid Build Coastguard Worker 		case TOKEN_TYPE_RBRACKET:
725*1208bc7eSAndroid Build Coastguard Worker 			return false;
726*1208bc7eSAndroid Build Coastguard Worker 		default:
727*1208bc7eSAndroid Build Coastguard Worker 			return true;
728*1208bc7eSAndroid Build Coastguard Worker 		}
729*1208bc7eSAndroid Build Coastguard Worker 	}
730*1208bc7eSAndroid Build Coastguard Worker }
731*1208bc7eSAndroid Build Coastguard Worker 
732*1208bc7eSAndroid Build Coastguard Worker static bool
parser_parse_array(parser_t * parser)733*1208bc7eSAndroid Build Coastguard Worker parser_parse_array(parser_t *parser) {
734*1208bc7eSAndroid Build Coastguard Worker 	assert_d_eq(parser->token.token_type, TOKEN_TYPE_LBRACKET,
735*1208bc7eSAndroid Build Coastguard Worker 	    "Array should start with [");
736*1208bc7eSAndroid Build Coastguard Worker 	if (parser_tokenize(parser)) {
737*1208bc7eSAndroid Build Coastguard Worker 		return true;
738*1208bc7eSAndroid Build Coastguard Worker 	}
739*1208bc7eSAndroid Build Coastguard Worker 	switch (parser->token.token_type) {
740*1208bc7eSAndroid Build Coastguard Worker 	case TOKEN_TYPE_RBRACKET:
741*1208bc7eSAndroid Build Coastguard Worker 		return false;
742*1208bc7eSAndroid Build Coastguard Worker 	default:
743*1208bc7eSAndroid Build Coastguard Worker 		return parser_parse_values(parser);
744*1208bc7eSAndroid Build Coastguard Worker 	}
745*1208bc7eSAndroid Build Coastguard Worker 	not_reached();
746*1208bc7eSAndroid Build Coastguard Worker }
747*1208bc7eSAndroid Build Coastguard Worker 
748*1208bc7eSAndroid Build Coastguard Worker static bool
parser_parse_pairs(parser_t * parser)749*1208bc7eSAndroid Build Coastguard Worker parser_parse_pairs(parser_t *parser) {
750*1208bc7eSAndroid Build Coastguard Worker 	assert_d_eq(parser->token.token_type, TOKEN_TYPE_STRING,
751*1208bc7eSAndroid Build Coastguard Worker 	    "Object should start with string");
752*1208bc7eSAndroid Build Coastguard Worker 	if (parser_parse_pair(parser)) {
753*1208bc7eSAndroid Build Coastguard Worker 		return true;
754*1208bc7eSAndroid Build Coastguard Worker 	}
755*1208bc7eSAndroid Build Coastguard Worker 
756*1208bc7eSAndroid Build Coastguard Worker 	while (true) {
757*1208bc7eSAndroid Build Coastguard Worker 		if (parser_tokenize(parser)) {
758*1208bc7eSAndroid Build Coastguard Worker 			return true;
759*1208bc7eSAndroid Build Coastguard Worker 		}
760*1208bc7eSAndroid Build Coastguard Worker 		switch (parser->token.token_type) {
761*1208bc7eSAndroid Build Coastguard Worker 		case TOKEN_TYPE_COMMA:
762*1208bc7eSAndroid Build Coastguard Worker 			if (parser_tokenize(parser)) {
763*1208bc7eSAndroid Build Coastguard Worker 				return true;
764*1208bc7eSAndroid Build Coastguard Worker 			}
765*1208bc7eSAndroid Build Coastguard Worker 			switch (parser->token.token_type) {
766*1208bc7eSAndroid Build Coastguard Worker 			case TOKEN_TYPE_STRING:
767*1208bc7eSAndroid Build Coastguard Worker 				if (parser_parse_pair(parser)) {
768*1208bc7eSAndroid Build Coastguard Worker 					return true;
769*1208bc7eSAndroid Build Coastguard Worker 				}
770*1208bc7eSAndroid Build Coastguard Worker 				break;
771*1208bc7eSAndroid Build Coastguard Worker 			default:
772*1208bc7eSAndroid Build Coastguard Worker 				return true;
773*1208bc7eSAndroid Build Coastguard Worker 			}
774*1208bc7eSAndroid Build Coastguard Worker 			break;
775*1208bc7eSAndroid Build Coastguard Worker 		case TOKEN_TYPE_RBRACE:
776*1208bc7eSAndroid Build Coastguard Worker 			return false;
777*1208bc7eSAndroid Build Coastguard Worker 		default:
778*1208bc7eSAndroid Build Coastguard Worker 			return true;
779*1208bc7eSAndroid Build Coastguard Worker 		}
780*1208bc7eSAndroid Build Coastguard Worker 	}
781*1208bc7eSAndroid Build Coastguard Worker }
782*1208bc7eSAndroid Build Coastguard Worker 
783*1208bc7eSAndroid Build Coastguard Worker static bool
parser_parse_object(parser_t * parser)784*1208bc7eSAndroid Build Coastguard Worker parser_parse_object(parser_t *parser) {
785*1208bc7eSAndroid Build Coastguard Worker 	assert_d_eq(parser->token.token_type, TOKEN_TYPE_LBRACE,
786*1208bc7eSAndroid Build Coastguard Worker 	    "Object should start with {");
787*1208bc7eSAndroid Build Coastguard Worker 	if (parser_tokenize(parser)) {
788*1208bc7eSAndroid Build Coastguard Worker 		return true;
789*1208bc7eSAndroid Build Coastguard Worker 	}
790*1208bc7eSAndroid Build Coastguard Worker 	switch (parser->token.token_type) {
791*1208bc7eSAndroid Build Coastguard Worker 	case TOKEN_TYPE_STRING:
792*1208bc7eSAndroid Build Coastguard Worker 		return parser_parse_pairs(parser);
793*1208bc7eSAndroid Build Coastguard Worker 	case TOKEN_TYPE_RBRACE:
794*1208bc7eSAndroid Build Coastguard Worker 		return false;
795*1208bc7eSAndroid Build Coastguard Worker 	default:
796*1208bc7eSAndroid Build Coastguard Worker 		return true;
797*1208bc7eSAndroid Build Coastguard Worker 	}
798*1208bc7eSAndroid Build Coastguard Worker 	not_reached();
799*1208bc7eSAndroid Build Coastguard Worker }
800*1208bc7eSAndroid Build Coastguard Worker 
801*1208bc7eSAndroid Build Coastguard Worker static bool
parser_parse(parser_t * parser)802*1208bc7eSAndroid Build Coastguard Worker parser_parse(parser_t *parser) {
803*1208bc7eSAndroid Build Coastguard Worker 	if (parser_tokenize(parser)) {
804*1208bc7eSAndroid Build Coastguard Worker 		goto label_error;
805*1208bc7eSAndroid Build Coastguard Worker 	}
806*1208bc7eSAndroid Build Coastguard Worker 	if (parser_parse_value(parser)) {
807*1208bc7eSAndroid Build Coastguard Worker 		goto label_error;
808*1208bc7eSAndroid Build Coastguard Worker 	}
809*1208bc7eSAndroid Build Coastguard Worker 
810*1208bc7eSAndroid Build Coastguard Worker 	if (parser_tokenize(parser)) {
811*1208bc7eSAndroid Build Coastguard Worker 		goto label_error;
812*1208bc7eSAndroid Build Coastguard Worker 	}
813*1208bc7eSAndroid Build Coastguard Worker 	switch (parser->token.token_type) {
814*1208bc7eSAndroid Build Coastguard Worker 	case TOKEN_TYPE_EOI:
815*1208bc7eSAndroid Build Coastguard Worker 		return false;
816*1208bc7eSAndroid Build Coastguard Worker 	default:
817*1208bc7eSAndroid Build Coastguard Worker 		goto label_error;
818*1208bc7eSAndroid Build Coastguard Worker 	}
819*1208bc7eSAndroid Build Coastguard Worker 	not_reached();
820*1208bc7eSAndroid Build Coastguard Worker 
821*1208bc7eSAndroid Build Coastguard Worker label_error:
822*1208bc7eSAndroid Build Coastguard Worker 	token_error(&parser->token);
823*1208bc7eSAndroid Build Coastguard Worker 	return true;
824*1208bc7eSAndroid Build Coastguard Worker }
825*1208bc7eSAndroid Build Coastguard Worker 
TEST_BEGIN(test_json_parser)826*1208bc7eSAndroid Build Coastguard Worker TEST_BEGIN(test_json_parser) {
827*1208bc7eSAndroid Build Coastguard Worker 	size_t i;
828*1208bc7eSAndroid Build Coastguard Worker 	const char *invalid_inputs[] = {
829*1208bc7eSAndroid Build Coastguard Worker 		/* Tokenizer error case tests. */
830*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": X }",
831*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": nXll }",
832*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": nuXl }",
833*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": nulX }",
834*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": nullX }",
835*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": fXlse }",
836*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": faXse }",
837*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": falXe }",
838*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": falsX }",
839*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": falseX }",
840*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": tXue }",
841*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": trXe }",
842*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": truX }",
843*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": trueX }",
844*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": \"\n\" }",
845*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": \"\\z\" }",
846*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": \"\\uX000\" }",
847*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": \"\\u0X00\" }",
848*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": \"\\u00X0\" }",
849*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": \"\\u000X\" }",
850*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": -X }",
851*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": 0.X }",
852*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": 0.0eX }",
853*1208bc7eSAndroid Build Coastguard Worker 		"{ \"string\": 0.0e+X }",
854*1208bc7eSAndroid Build Coastguard Worker 
855*1208bc7eSAndroid Build Coastguard Worker 		/* Parser error test cases. */
856*1208bc7eSAndroid Build Coastguard Worker 		"{\"string\": }",
857*1208bc7eSAndroid Build Coastguard Worker 		"{\"string\" }",
858*1208bc7eSAndroid Build Coastguard Worker 		"{\"string\": [ 0 }",
859*1208bc7eSAndroid Build Coastguard Worker 		"{\"string\": {\"a\":0, 1 } }",
860*1208bc7eSAndroid Build Coastguard Worker 		"{\"string\": {\"a\":0: } }",
861*1208bc7eSAndroid Build Coastguard Worker 		"{",
862*1208bc7eSAndroid Build Coastguard Worker 		"{}{",
863*1208bc7eSAndroid Build Coastguard Worker 	};
864*1208bc7eSAndroid Build Coastguard Worker 	const char *valid_inputs[] = {
865*1208bc7eSAndroid Build Coastguard Worker 		/* Token tests. */
866*1208bc7eSAndroid Build Coastguard Worker 		"null",
867*1208bc7eSAndroid Build Coastguard Worker 		"false",
868*1208bc7eSAndroid Build Coastguard Worker 		"true",
869*1208bc7eSAndroid Build Coastguard Worker 		"{}",
870*1208bc7eSAndroid Build Coastguard Worker 		"{\"a\": 0}",
871*1208bc7eSAndroid Build Coastguard Worker 		"[]",
872*1208bc7eSAndroid Build Coastguard Worker 		"[0, 1]",
873*1208bc7eSAndroid Build Coastguard Worker 		"0",
874*1208bc7eSAndroid Build Coastguard Worker 		"1",
875*1208bc7eSAndroid Build Coastguard Worker 		"10",
876*1208bc7eSAndroid Build Coastguard Worker 		"-10",
877*1208bc7eSAndroid Build Coastguard Worker 		"10.23",
878*1208bc7eSAndroid Build Coastguard Worker 		"10.23e4",
879*1208bc7eSAndroid Build Coastguard Worker 		"10.23e-4",
880*1208bc7eSAndroid Build Coastguard Worker 		"10.23e+4",
881*1208bc7eSAndroid Build Coastguard Worker 		"10.23E4",
882*1208bc7eSAndroid Build Coastguard Worker 		"10.23E-4",
883*1208bc7eSAndroid Build Coastguard Worker 		"10.23E+4",
884*1208bc7eSAndroid Build Coastguard Worker 		"-10.23",
885*1208bc7eSAndroid Build Coastguard Worker 		"-10.23e4",
886*1208bc7eSAndroid Build Coastguard Worker 		"-10.23e-4",
887*1208bc7eSAndroid Build Coastguard Worker 		"-10.23e+4",
888*1208bc7eSAndroid Build Coastguard Worker 		"-10.23E4",
889*1208bc7eSAndroid Build Coastguard Worker 		"-10.23E-4",
890*1208bc7eSAndroid Build Coastguard Worker 		"-10.23E+4",
891*1208bc7eSAndroid Build Coastguard Worker 		"\"value\"",
892*1208bc7eSAndroid Build Coastguard Worker 		"\" \\\" \\/ \\b \\n \\r \\t \\u0abc \\u1DEF \"",
893*1208bc7eSAndroid Build Coastguard Worker 
894*1208bc7eSAndroid Build Coastguard Worker 		/* Parser test with various nesting. */
895*1208bc7eSAndroid Build Coastguard Worker 		"{\"a\":null, \"b\":[1,[{\"c\":2},3]], \"d\":{\"e\":true}}",
896*1208bc7eSAndroid Build Coastguard Worker 	};
897*1208bc7eSAndroid Build Coastguard Worker 
898*1208bc7eSAndroid Build Coastguard Worker 	for (i = 0; i < sizeof(invalid_inputs)/sizeof(const char *); i++) {
899*1208bc7eSAndroid Build Coastguard Worker 		const char *input = invalid_inputs[i];
900*1208bc7eSAndroid Build Coastguard Worker 		parser_t parser;
901*1208bc7eSAndroid Build Coastguard Worker 		parser_init(&parser, false);
902*1208bc7eSAndroid Build Coastguard Worker 		assert_false(parser_append(&parser, input),
903*1208bc7eSAndroid Build Coastguard Worker 		    "Unexpected input appending failure");
904*1208bc7eSAndroid Build Coastguard Worker 		assert_true(parser_parse(&parser),
905*1208bc7eSAndroid Build Coastguard Worker 		    "Unexpected parse success for input: %s", input);
906*1208bc7eSAndroid Build Coastguard Worker 		parser_fini(&parser);
907*1208bc7eSAndroid Build Coastguard Worker 	}
908*1208bc7eSAndroid Build Coastguard Worker 
909*1208bc7eSAndroid Build Coastguard Worker 	for (i = 0; i < sizeof(valid_inputs)/sizeof(const char *); i++) {
910*1208bc7eSAndroid Build Coastguard Worker 		const char *input = valid_inputs[i];
911*1208bc7eSAndroid Build Coastguard Worker 		parser_t parser;
912*1208bc7eSAndroid Build Coastguard Worker 		parser_init(&parser, true);
913*1208bc7eSAndroid Build Coastguard Worker 		assert_false(parser_append(&parser, input),
914*1208bc7eSAndroid Build Coastguard Worker 		    "Unexpected input appending failure");
915*1208bc7eSAndroid Build Coastguard Worker 		assert_false(parser_parse(&parser),
916*1208bc7eSAndroid Build Coastguard Worker 		    "Unexpected parse error for input: %s", input);
917*1208bc7eSAndroid Build Coastguard Worker 		parser_fini(&parser);
918*1208bc7eSAndroid Build Coastguard Worker 	}
919*1208bc7eSAndroid Build Coastguard Worker }
920*1208bc7eSAndroid Build Coastguard Worker TEST_END
921*1208bc7eSAndroid Build Coastguard Worker 
922*1208bc7eSAndroid Build Coastguard Worker void
write_cb(void * opaque,const char * str)923*1208bc7eSAndroid Build Coastguard Worker write_cb(void *opaque, const char *str) {
924*1208bc7eSAndroid Build Coastguard Worker 	parser_t *parser = (parser_t *)opaque;
925*1208bc7eSAndroid Build Coastguard Worker 	if (parser_append(parser, str)) {
926*1208bc7eSAndroid Build Coastguard Worker 		test_fail("Unexpected input appending failure");
927*1208bc7eSAndroid Build Coastguard Worker 	}
928*1208bc7eSAndroid Build Coastguard Worker }
929*1208bc7eSAndroid Build Coastguard Worker 
TEST_BEGIN(test_stats_print_json)930*1208bc7eSAndroid Build Coastguard Worker TEST_BEGIN(test_stats_print_json) {
931*1208bc7eSAndroid Build Coastguard Worker 	const char *opts[] = {
932*1208bc7eSAndroid Build Coastguard Worker 		"J",
933*1208bc7eSAndroid Build Coastguard Worker 		"Jg",
934*1208bc7eSAndroid Build Coastguard Worker 		"Jm",
935*1208bc7eSAndroid Build Coastguard Worker 		"Jd",
936*1208bc7eSAndroid Build Coastguard Worker 		"Jmd",
937*1208bc7eSAndroid Build Coastguard Worker 		"Jgd",
938*1208bc7eSAndroid Build Coastguard Worker 		"Jgm",
939*1208bc7eSAndroid Build Coastguard Worker 		"Jgmd",
940*1208bc7eSAndroid Build Coastguard Worker 		"Ja",
941*1208bc7eSAndroid Build Coastguard Worker 		"Jb",
942*1208bc7eSAndroid Build Coastguard Worker 		"Jl",
943*1208bc7eSAndroid Build Coastguard Worker 		"Jx",
944*1208bc7eSAndroid Build Coastguard Worker 		"Jbl",
945*1208bc7eSAndroid Build Coastguard Worker 		"Jal",
946*1208bc7eSAndroid Build Coastguard Worker 		"Jab",
947*1208bc7eSAndroid Build Coastguard Worker 		"Jabl",
948*1208bc7eSAndroid Build Coastguard Worker 		"Jax",
949*1208bc7eSAndroid Build Coastguard Worker 		"Jbx",
950*1208bc7eSAndroid Build Coastguard Worker 		"Jlx",
951*1208bc7eSAndroid Build Coastguard Worker 		"Jablx",
952*1208bc7eSAndroid Build Coastguard Worker 		"Jgmdablx",
953*1208bc7eSAndroid Build Coastguard Worker 	};
954*1208bc7eSAndroid Build Coastguard Worker 	unsigned arena_ind, i;
955*1208bc7eSAndroid Build Coastguard Worker 
956*1208bc7eSAndroid Build Coastguard Worker 	for (i = 0; i < 3; i++) {
957*1208bc7eSAndroid Build Coastguard Worker 		unsigned j;
958*1208bc7eSAndroid Build Coastguard Worker 
959*1208bc7eSAndroid Build Coastguard Worker 		switch (i) {
960*1208bc7eSAndroid Build Coastguard Worker 		case 0:
961*1208bc7eSAndroid Build Coastguard Worker 			break;
962*1208bc7eSAndroid Build Coastguard Worker 		case 1: {
963*1208bc7eSAndroid Build Coastguard Worker 			size_t sz = sizeof(arena_ind);
964*1208bc7eSAndroid Build Coastguard Worker 			assert_d_eq(mallctl("arenas.create", (void *)&arena_ind,
965*1208bc7eSAndroid Build Coastguard Worker 			    &sz, NULL, 0), 0, "Unexpected mallctl failure");
966*1208bc7eSAndroid Build Coastguard Worker 			break;
967*1208bc7eSAndroid Build Coastguard Worker 		} case 2: {
968*1208bc7eSAndroid Build Coastguard Worker 			size_t mib[3];
969*1208bc7eSAndroid Build Coastguard Worker 			size_t miblen = sizeof(mib)/sizeof(size_t);
970*1208bc7eSAndroid Build Coastguard Worker 			assert_d_eq(mallctlnametomib("arena.0.destroy",
971*1208bc7eSAndroid Build Coastguard Worker 			    mib, &miblen), 0,
972*1208bc7eSAndroid Build Coastguard Worker 			    "Unexpected mallctlnametomib failure");
973*1208bc7eSAndroid Build Coastguard Worker 			mib[1] = arena_ind;
974*1208bc7eSAndroid Build Coastguard Worker 			assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL,
975*1208bc7eSAndroid Build Coastguard Worker 			    0), 0, "Unexpected mallctlbymib failure");
976*1208bc7eSAndroid Build Coastguard Worker 			break;
977*1208bc7eSAndroid Build Coastguard Worker 		} default:
978*1208bc7eSAndroid Build Coastguard Worker 			not_reached();
979*1208bc7eSAndroid Build Coastguard Worker 		}
980*1208bc7eSAndroid Build Coastguard Worker 
981*1208bc7eSAndroid Build Coastguard Worker 		for (j = 0; j < sizeof(opts)/sizeof(const char *); j++) {
982*1208bc7eSAndroid Build Coastguard Worker 			parser_t parser;
983*1208bc7eSAndroid Build Coastguard Worker 
984*1208bc7eSAndroid Build Coastguard Worker 			parser_init(&parser, true);
985*1208bc7eSAndroid Build Coastguard Worker 			malloc_stats_print(write_cb, (void *)&parser, opts[j]);
986*1208bc7eSAndroid Build Coastguard Worker 			assert_false(parser_parse(&parser),
987*1208bc7eSAndroid Build Coastguard Worker 			    "Unexpected parse error, opts=\"%s\"", opts[j]);
988*1208bc7eSAndroid Build Coastguard Worker 			parser_fini(&parser);
989*1208bc7eSAndroid Build Coastguard Worker 		}
990*1208bc7eSAndroid Build Coastguard Worker 	}
991*1208bc7eSAndroid Build Coastguard Worker }
992*1208bc7eSAndroid Build Coastguard Worker TEST_END
993*1208bc7eSAndroid Build Coastguard Worker 
994*1208bc7eSAndroid Build Coastguard Worker int
main(void)995*1208bc7eSAndroid Build Coastguard Worker main(void) {
996*1208bc7eSAndroid Build Coastguard Worker 	return test(
997*1208bc7eSAndroid Build Coastguard Worker 	    test_json_parser,
998*1208bc7eSAndroid Build Coastguard Worker 	    test_stats_print_json);
999*1208bc7eSAndroid Build Coastguard Worker }
1000