• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  */
24 
25 #include "private-lib-core.h"
26 #include <string.h>
27 #include <stdio.h>
28 
29 static const char * const parser_errs[] = {
30 	"",
31 	"",
32 	"No opening '{'",
33 	"Expected closing '}'",
34 	"Expected '\"'",
35 	"String underrun",
36 	"Illegal unescaped control char",
37 	"Illegal escape format",
38 	"Illegal hex number",
39 	"Expected ':'",
40 	"Illegal value start",
41 	"Digit required after decimal point",
42 	"Bad number format",
43 	"Bad exponent format",
44 	"Unknown token",
45 	"Too many ']'",
46 	"Mismatched ']'",
47 	"Expected ']'",
48 	"JSON nesting limit exceeded",
49 	"Nesting tracking used up",
50 	"Number too long",
51 	"Comma or block end expected",
52 	"Unknown",
53 	"Parser callback errored (see earlier error)",
54 };
55 
56 /**
57  * lejp_construct - prepare a struct lejp_ctx for use
58  *
59  * \param ctx:	pointer to your struct lejp_ctx
60  * \param callback:	your user callback which will received parsed tokens
61  * \param user:	optional user data pointer untouched by lejp
62  * \param paths:	your array of name elements you are interested in
63  * \param count_paths:	LWS_ARRAY_SIZE() of @paths
64  *
65  * Prepares your context struct for use with lejp
66  */
67 
68 void
lejp_construct(struct lejp_ctx * ctx,signed char (* callback)(struct lejp_ctx * ctx,char reason),void * user,const char * const * paths,unsigned char count_paths)69 lejp_construct(struct lejp_ctx *ctx,
70 	signed char (*callback)(struct lejp_ctx *ctx, char reason), void *user,
71 			const char * const *paths, unsigned char count_paths)
72 {
73 	ctx->st[0].s = 0;
74 	ctx->st[0].p = 0;
75 	ctx->st[0].i = 0;
76 	ctx->st[0].b = 0;
77 	ctx->sp = 0;
78 	ctx->ipos = 0;
79 	ctx->outer_array = 0;
80 	ctx->path_match = 0;
81 	ctx->path_stride = 0;
82 	ctx->path[0] = '\0';
83 	ctx->user = user;
84 	ctx->line = 1;
85 
86 	ctx->pst_sp = 0;
87 	ctx->pst[0].callback = callback;
88 	ctx->pst[0].paths = paths;
89 	ctx->pst[0].count_paths = count_paths;
90 	ctx->pst[0].user = NULL;
91 	ctx->pst[0].ppos = 0;
92 
93 	ctx->pst[0].callback(ctx, LEJPCB_CONSTRUCTED);
94 }
95 
96 /**
97  * lejp_destruct - retire a previously constructed struct lejp_ctx
98  *
99  * \param ctx:	pointer to your struct lejp_ctx
100  *
101  * lejp does not perform any allocations, but since your user code might, this
102  * provides a one-time LEJPCB_DESTRUCTED callback at destruction time where
103  * you can clean up in your callback.
104  */
105 
106 void
lejp_destruct(struct lejp_ctx * ctx)107 lejp_destruct(struct lejp_ctx *ctx)
108 {
109 	/* no allocations... just let callback know what it happening */
110 	if (ctx && ctx->pst[0].callback)
111 		ctx->pst[0].callback(ctx, LEJPCB_DESTRUCTED);
112 }
113 
114 /**
115  * lejp_change_callback - switch to a different callback from now on
116  *
117  * \param ctx:	pointer to your struct lejp_ctx
118  * \param callback:	your user callback which will received parsed tokens
119  *
120  * This tells the old callback it was destroyed, in case you want to take any
121  * action because that callback "lost focus", then changes to the new
122  * callback and tells it first that it was constructed, and then started.
123  *
124  * Changing callback is a cheap and powerful trick to split out handlers
125  * according to information earlier in the parse.  For example you may have
126  * a JSON pair "schema" whose value defines what can be expected for the rest
127  * of the JSON.  Rather than having one huge callback for all cases, you can
128  * have an initial one looking for "schema" which then calls
129  * lejp_change_callback() to a handler specific for the schema.
130  *
131  * Notice that afterwards, you need to construct the context again anyway to
132  * parse another JSON object, and the callback is reset then to the main,
133  * schema-interpreting one.  The construction action is very lightweight.
134  */
135 
136 void
lejp_change_callback(struct lejp_ctx * ctx,signed char (* callback)(struct lejp_ctx * ctx,char reason))137 lejp_change_callback(struct lejp_ctx *ctx,
138 		     signed char (*callback)(struct lejp_ctx *ctx, char reason))
139 {
140 	ctx->pst[0].callback(ctx, LEJPCB_DESTRUCTED);
141 	ctx->pst[0].callback = callback;
142 	ctx->pst[0].callback(ctx, LEJPCB_CONSTRUCTED);
143 	ctx->pst[0].callback(ctx, LEJPCB_START);
144 }
145 
146 void
lejp_check_path_match(struct lejp_ctx * ctx)147 lejp_check_path_match(struct lejp_ctx *ctx)
148 {
149 	const char *p, *q;
150 	int n;
151 	size_t s = sizeof(char *);
152 
153 	if (ctx->path_stride)
154 		s = ctx->path_stride;
155 
156 	/* we only need to check if a match is not active */
157 	for (n = 0; !ctx->path_match &&
158 	     n < ctx->pst[ctx->pst_sp].count_paths; n++) {
159 		ctx->wildcount = 0;
160 		p = ctx->path;
161 
162 		q = *((char **)(((char *)ctx->pst[ctx->pst_sp].paths) + ((unsigned int)n * s)));
163 
164 		while (*p && *q) {
165 			if (*q != '*') {
166 				if (*p != *q)
167 					break;
168 				p++;
169 				q++;
170 				continue;
171 			}
172 			ctx->wild[ctx->wildcount++] = (uint16_t)lws_ptr_diff_size_t(p, ctx->path);
173 			q++;
174 			/*
175 			 * if * has something after it, match to .
176 			 * if ends with *, eat everything.
177 			 * This implies match sequences must be ordered like
178 			 *  x.*.*
179 			 *  x.*
180 			 * if both options are possible
181 			 */
182 			while (*p && (*p != '.' || !*q))
183 				p++;
184 		}
185 		if (*p || *q)
186 			continue;
187 
188 		ctx->path_match = (uint8_t)(n + 1);
189 		ctx->path_match_len = ctx->pst[ctx->pst_sp].ppos;
190 		return;
191 	}
192 
193 	if (!ctx->path_match)
194 		ctx->wildcount = 0;
195 }
196 
197 int
lejp_get_wildcard(struct lejp_ctx * ctx,int wildcard,char * dest,int len)198 lejp_get_wildcard(struct lejp_ctx *ctx, int wildcard, char *dest, int len)
199 {
200 	int n;
201 
202 	if (wildcard >= ctx->wildcount || !len)
203 		return 0;
204 
205 	n = ctx->wild[wildcard];
206 
207 	while (--len && n < ctx->pst[ctx->pst_sp].ppos &&
208 	       (n == ctx->wild[wildcard] || ctx->path[n] != '.'))
209 		*dest++ = ctx->path[n++];
210 
211 	*dest = '\0';
212 	n++;
213 
214 	return n - ctx->wild[wildcard];
215 }
216 
217 /**
218  * lejp_parse - interpret some more incoming data incrementally
219  *
220  * \param ctx:	previously constructed parsing context
221  * \param json:	char buffer with the new data to interpret
222  * \param len:	amount of data in the buffer
223  *
224  * Because lejp is a stream parser, it incrementally parses as new data
225  * becomes available, maintaining all state in the context struct.  So an
226  * incomplete JSON is a normal situation, getting you a LEJP_CONTINUE
227  * return, signalling there's no error but to call again with more data when
228  * it comes to complete the parsing.  Successful parsing completes with a
229  * 0 or positive integer indicating how much of the last input buffer was
230  * unused.
231  */
232 
233 static const char esc_char[] = "\"\\/bfnrt";
234 static const char esc_tran[] = "\"\\/\b\f\n\r\t";
235 static const char tokens[] = "rue alse ull ";
236 
237 int
lejp_parse(struct lejp_ctx * ctx,const unsigned char * json,int len)238 lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len)
239 {
240 	unsigned char c, n, s;
241 	int ret = LEJP_REJECT_UNKNOWN;
242 
243 	if (!ctx->sp && !ctx->pst[ctx->pst_sp].ppos)
244 		ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_START);
245 
246 	while (len--) {
247 		c = *json++;
248 		s = (unsigned char)ctx->st[ctx->sp].s;
249 
250 		/* skip whitespace unless we should care */
251 		if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '#') {
252 			if (c == '\n') {
253 				ctx->line++;
254 				ctx->st[ctx->sp].s &= (char)~LEJP_FLAG_WS_COMMENTLINE;
255 			}
256 			if (!(s & LEJP_FLAG_WS_KEEP)) {
257 				if (c == '#')
258 					ctx->st[ctx->sp].s |=
259 						LEJP_FLAG_WS_COMMENTLINE;
260 				continue;
261 			}
262 		}
263 
264 		if (ctx->st[ctx->sp].s & LEJP_FLAG_WS_COMMENTLINE)
265 			continue;
266 
267 		switch (s) {
268 		case LEJP_IDLE:
269 			if (!ctx->sp && c == '[') {
270 				/* push */
271 				ctx->outer_array = 1;
272 				ctx->st[ctx->sp].s = LEJP_MP_ARRAY_END;
273 				c = LEJP_MP_VALUE;
274 				ctx->path[ctx->pst[ctx->pst_sp].ppos++] = '[';
275 				ctx->path[ctx->pst[ctx->pst_sp].ppos++] = ']';
276 				ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0';
277 				if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_ARRAY_START))
278 					goto reject_callback;
279 				ctx->i[ctx->ipos++] = 0;
280 				if (ctx->ipos > LWS_ARRAY_SIZE(ctx->i)) {
281 					ret = LEJP_REJECT_MP_DELIM_ISTACK;
282 					goto reject;
283 				}
284 				goto add_stack_level;
285 			}
286 			if (c != '{') {
287 				ret = LEJP_REJECT_IDLE_NO_BRACE;
288 				goto reject;
289 			}
290 			if (ctx->pst[ctx->pst_sp].callback(ctx,
291 							   LEJPCB_OBJECT_START))
292 				goto reject_callback;
293 			ctx->st[ctx->sp].s = LEJP_MEMBERS;
294 			break;
295 		case LEJP_MEMBERS:
296 			if (c == '}') {
297 				if (ctx->sp >= 1)
298 					goto pop_level;
299 
300 				ctx->st[ctx->sp].s = LEJP_IDLE;
301 				ret = LEJP_REJECT_MEMBERS_NO_CLOSE;
302 				goto reject;
303 			}
304 			ctx->st[ctx->sp].s = LEJP_M_P;
305 			goto redo_character;
306 		case LEJP_M_P:
307 			if (c != '\"') {
308 				ret = LEJP_REJECT_MP_NO_OPEN_QUOTE;
309 				goto reject;
310 			}
311 			/* push */
312 			ctx->st[ctx->sp].s = LEJP_MP_DELIM;
313 			c = LEJP_MP_STRING;
314 			goto add_stack_level;
315 
316 		case LEJP_MP_STRING:
317 			if (c == '\"') {
318 				if (!ctx->sp) { /* JSON can't end on quote */
319 					ret = LEJP_REJECT_MP_STRING_UNDERRUN;
320 					goto reject;
321 				}
322 				if (ctx->st[ctx->sp - 1].s != LEJP_MP_DELIM) {
323 					ctx->buf[ctx->npos] = '\0';
324 					if (ctx->pst[ctx->pst_sp].callback(ctx,
325 						      LEJPCB_VAL_STR_END) < 0)
326 						goto reject_callback;
327 				}
328 				/* pop */
329 				ctx->sp--;
330 				break;
331 			}
332 			if (c == '\\') {
333 				ctx->st[ctx->sp].s = LEJP_MP_STRING_ESC;
334 				break;
335 			}
336 			if (c < ' ') {/* "control characters" not allowed */
337 				ret = LEJP_REJECT_MP_ILLEGAL_CTRL;
338 				goto reject;
339 			}
340 			goto emit_string_char;
341 
342 		case LEJP_MP_STRING_ESC:
343 			if (c == 'u') {
344 				ctx->st[ctx->sp].s = LEJP_MP_STRING_ESC_U1;
345 				ctx->uni = 0;
346 				break;
347 			}
348 			for (n = 0; n < sizeof(esc_char); n++) {
349 				if (c != esc_char[n])
350 					continue;
351 				/* found it */
352 				c = (unsigned char)esc_tran[n];
353 				ctx->st[ctx->sp].s = LEJP_MP_STRING;
354 				goto emit_string_char;
355 			}
356 			ret = LEJP_REJECT_MP_STRING_ESC_ILLEGAL_ESC;
357 			/* illegal escape char */
358 			goto reject;
359 
360 		case LEJP_MP_STRING_ESC_U1:
361 		case LEJP_MP_STRING_ESC_U2:
362 		case LEJP_MP_STRING_ESC_U3:
363 		case LEJP_MP_STRING_ESC_U4:
364 			ctx->uni = (uint16_t)(ctx->uni << 4);
365 			if (c >= '0' && c <= '9')
366 				ctx->uni |= (uint16_t)(c - '0');
367 			else
368 				if (c >= 'a' && c <= 'f')
369 					ctx->uni |= (uint16_t)(c - 'a' + 10);
370 				else
371 					if (c >= 'A' && c <= 'F')
372 						ctx->uni |= (uint16_t)(c - 'A' + 10);
373 					else {
374 						ret = LEJP_REJECT_ILLEGAL_HEX;
375 						goto reject;
376 					}
377 			ctx->st[ctx->sp].s++;
378 			switch (s) {
379 			case LEJP_MP_STRING_ESC_U2:
380 				if (ctx->uni < 0x08)
381 					break;
382 				/*
383 				 * 0x08-0xff (0x0800 - 0xffff)
384 				 * emit 3-byte UTF-8
385 				 */
386 				c = (unsigned char)(0xe0 | ((ctx->uni >> 4) & 0xf));
387 				goto emit_string_char;
388 
389 			case LEJP_MP_STRING_ESC_U3:
390 				if (ctx->uni >= 0x080) {
391 					/*
392 					 * 0x080 - 0xfff (0x0800 - 0xffff)
393 					 * middle 3-byte seq
394 					 * send ....XXXXXX..
395 					 */
396 					c = (unsigned char)(0x80 | ((ctx->uni >> 2) & 0x3f));
397 					goto emit_string_char;
398 				}
399 				if (ctx->uni < 0x008)
400 					break;
401 				/*
402 				 * 0x008 - 0x7f (0x0080 - 0x07ff)
403 				 * start 2-byte seq
404 				 */
405 				c = (unsigned char)(0xc0 | (ctx->uni >> 2));
406 				goto emit_string_char;
407 
408 			case LEJP_MP_STRING_ESC_U4:
409 				if (ctx->uni >= 0x0080)
410 					/* end of 2 or 3-byte seq */
411 					c = (unsigned char)(0x80 | (ctx->uni & 0x3f));
412 				else
413 					/* literal */
414 					c = (unsigned char)ctx->uni;
415 
416 				ctx->st[ctx->sp].s = LEJP_MP_STRING;
417 				goto emit_string_char;
418 			default:
419 				break;
420 			}
421 			break;
422 
423 		case LEJP_MP_DELIM:
424 			if (c != ':') {
425 				ret = LEJP_REJECT_MP_DELIM_MISSING_COLON;
426 				goto reject;
427 			}
428 			ctx->st[ctx->sp].s = LEJP_MP_VALUE;
429 			ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0';
430 
431 			lejp_check_path_match(ctx);
432 			if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_PAIR_NAME))
433 				goto reject_callback;
434 			break;
435 
436 		case LEJP_MP_VALUE:
437 			if (c == '-' || (c >= '0' && c <= '9')) {
438 				ctx->npos = 0;
439 				ctx->dcount = 0;
440 				ctx->f = 0;
441 				ctx->st[ctx->sp].s = LEJP_MP_VALUE_NUM_INT;
442 				goto redo_character;
443 			}
444 			switch (c) {
445 			case'\"':
446 				/* push */
447 				ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END;
448 				c = LEJP_MP_STRING;
449 				ctx->npos = 0;
450 				ctx->buf[0] = '\0';
451 				if (ctx->pst[ctx->pst_sp].callback(ctx,
452 							LEJPCB_VAL_STR_START))
453 					goto reject_callback;
454 				goto add_stack_level;
455 
456 			case '{':
457 				/* push */
458 				ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END;
459 				c = LEJP_MEMBERS;
460 				lejp_check_path_match(ctx);
461 				if (ctx->pst[ctx->pst_sp].callback(ctx,
462 							LEJPCB_OBJECT_START))
463 					goto reject_callback;
464 				ctx->path_match = 0;
465 				goto add_stack_level;
466 
467 			case '[':
468 				/* push */
469 				ctx->st[ctx->sp].s = LEJP_MP_ARRAY_END;
470 				c = LEJP_MP_VALUE;
471 				if (ctx->pst[ctx->pst_sp].ppos + 3u >=
472 							sizeof(ctx->path))
473 					goto reject;
474 				ctx->path[ctx->pst[ctx->pst_sp].ppos++] = '[';
475 				ctx->path[ctx->pst[ctx->pst_sp].ppos++] = ']';
476 				ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0';
477 				if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_ARRAY_START))
478 					goto reject_callback;
479 				ctx->i[ctx->ipos++] = 0;
480 				if (ctx->ipos > LWS_ARRAY_SIZE(ctx->i)) {
481 					ret = LEJP_REJECT_MP_DELIM_ISTACK;
482 					goto reject;
483 				}
484 				goto add_stack_level;
485 
486 			case ']':
487 				/* pop */
488 				if (!ctx->sp) { /* JSON can't end on ] */
489 					ret = LEJP_REJECT_MP_C_OR_E_UNDERF;
490 					goto reject;
491 				}
492 				ctx->sp--;
493 				if (ctx->st[ctx->sp].s != LEJP_MP_ARRAY_END) {
494 					ret = LEJP_REJECT_MP_C_OR_E_NOTARRAY;
495 					goto reject;
496 				}
497 				/* drop the path [n] bit */
498 				if (ctx->sp) {
499 					ctx->pst[ctx->pst_sp].ppos = (unsigned char)
500 							ctx->st[ctx->sp - 1].p;
501 					ctx->ipos = (unsigned char)ctx->st[ctx->sp - 1].i;
502 				}
503 				ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0';
504 				if (ctx->path_match &&
505 				    ctx->pst[ctx->pst_sp].ppos <= ctx->path_match_len)
506 					/*
507 					 * we shrank the path to be
508 					 * smaller than the matching point
509 					 */
510 					ctx->path_match = 0;
511 				if (ctx->outer_array && !ctx->sp) { /* ended on ] */
512 					n = LEJPCB_ARRAY_END;
513 					goto completed;
514 				}
515 				goto array_end;
516 
517 			case 't': /* true */
518 				ctx->uni = 0;
519 				ctx->st[ctx->sp].s = LEJP_MP_VALUE_TOK;
520 				break;
521 
522 			case 'f':
523 				ctx->uni = 4;
524 				ctx->st[ctx->sp].s = LEJP_MP_VALUE_TOK;
525 				break;
526 
527 			case 'n':
528 				ctx->uni = 4 + 5;
529 				ctx->st[ctx->sp].s = LEJP_MP_VALUE_TOK;
530 				break;
531 			default:
532 				ret = LEJP_REJECT_MP_DELIM_BAD_VALUE_START;
533 				goto reject;
534 			}
535 			break;
536 
537 		case LEJP_MP_VALUE_NUM_INT:
538 			if (!ctx->npos && c == '-') {
539 				ctx->f |= LEJP_SEEN_MINUS;
540 				goto append_npos;
541 			}
542 
543 			if (ctx->dcount < 20 && c >= '0' && c <= '9') {
544 				if (ctx->f & LEJP_SEEN_POINT)
545 					ctx->f |= LEJP_SEEN_POST_POINT;
546 				ctx->dcount++;
547 				goto append_npos;
548 			}
549 			if (c == '.') {
550 				if (!ctx->dcount || (ctx->f & LEJP_SEEN_POINT)) {
551 					ret = LEJP_REJECT_MP_VAL_NUM_FORMAT;
552 					goto reject;
553 				}
554 				ctx->f |= LEJP_SEEN_POINT;
555 				goto append_npos;
556 			}
557 			/*
558 			 * before exponent, if we had . we must have had at
559 			 * least one more digit
560 			 */
561 			if ((ctx->f &
562 				(LEJP_SEEN_POINT | LEJP_SEEN_POST_POINT)) ==
563 							      LEJP_SEEN_POINT) {
564 				ret = LEJP_REJECT_MP_VAL_NUM_INT_NO_FRAC;
565 				goto reject;
566 			}
567 			if (c == 'e' || c == 'E') {
568 				if (ctx->f & LEJP_SEEN_EXP) {
569 					ret = LEJP_REJECT_MP_VAL_NUM_FORMAT;
570 					goto reject;
571 				}
572 				ctx->f |= LEJP_SEEN_EXP;
573 				ctx->st[ctx->sp].s = LEJP_MP_VALUE_NUM_EXP;
574 				goto append_npos;
575 			}
576 			/* if none of the above, did we even have a number? */
577 			if (!ctx->dcount) {
578 				ret = LEJP_REJECT_MP_VAL_NUM_FORMAT;
579 				goto reject;
580 			}
581 
582 			ctx->buf[ctx->npos] = '\0';
583 			if (ctx->f & LEJP_SEEN_POINT) {
584 				if (ctx->pst[ctx->pst_sp].callback(ctx,
585 							LEJPCB_VAL_NUM_FLOAT))
586 					goto reject_callback;
587 			} else {
588 				if (ctx->pst[ctx->pst_sp].callback(ctx,
589 							LEJPCB_VAL_NUM_INT))
590 					goto reject_callback;
591 			}
592 
593 			/* then this is the post-number character, loop */
594 			ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END;
595 			goto redo_character;
596 
597 		case LEJP_MP_VALUE_NUM_EXP:
598 			ctx->st[ctx->sp].s = LEJP_MP_VALUE_NUM_INT;
599 			if (c >= '0' && c <= '9')
600 				goto redo_character;
601 			if (c == '+' || c == '-')
602 				goto append_npos;
603 			ret = LEJP_REJECT_MP_VAL_NUM_EXP_BAD_EXP;
604 			goto reject;
605 
606 		case LEJP_MP_VALUE_TOK: /* true, false, null */
607 			if (c != tokens[ctx->uni]) {
608 				ret = LEJP_REJECT_MP_VAL_TOK_UNKNOWN;
609 				goto reject;
610 			}
611 			ctx->uni++;
612 			if (tokens[ctx->uni] != ' ')
613 				break;
614 			switch (ctx->uni) {
615 			case 3:
616 				ctx->buf[0] = '1';
617 				ctx->buf[1] = '\0';
618 				if (ctx->pst[ctx->pst_sp].callback(ctx,
619 								LEJPCB_VAL_TRUE))
620 					goto reject_callback;
621 				break;
622 			case 8:
623 				ctx->buf[0] = '0';
624 				ctx->buf[1] = '\0';
625 				if (ctx->pst[ctx->pst_sp].callback(ctx,
626 								LEJPCB_VAL_FALSE))
627 					goto reject_callback;
628 				break;
629 			case 12:
630 				ctx->buf[0] = '\0';
631 				if (ctx->pst[ctx->pst_sp].callback(ctx,
632 								LEJPCB_VAL_NULL))
633 					goto reject_callback;
634 				break;
635 			}
636 			ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END;
637 			break;
638 
639 		case LEJP_MP_COMMA_OR_END:
640 			ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0';
641 			if (c == ',') {
642 				/* increment this stack level's index */
643 				ctx->st[ctx->sp].s = LEJP_M_P;
644 				if (!ctx->sp) {
645 					ctx->pst[ctx->pst_sp].ppos = 0;
646 					/*
647 					 * since we came back to root level,
648 					 * no path can still match
649 					 */
650 					ctx->path_match = 0;
651 					break;
652 				}
653 				ctx->pst[ctx->pst_sp].ppos = (unsigned char)ctx->st[ctx->sp - 1].p;
654 				ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0';
655 				if (ctx->path_match &&
656 				    ctx->pst[ctx->pst_sp].ppos <= ctx->path_match_len)
657 					/*
658 					 * we shrank the path to be
659 					 * smaller than the matching point
660 					 */
661 					ctx->path_match = 0;
662 
663 				if (ctx->st[ctx->sp - 1].s != LEJP_MP_ARRAY_END)
664 					break;
665 				/* top level is definitely an array... */
666 				if (ctx->ipos)
667 					ctx->i[ctx->ipos - 1]++;
668 				ctx->st[ctx->sp].s = LEJP_MP_VALUE;
669 				break;
670 			}
671 			if (c == ']') {
672 				if (!ctx->sp) {
673 					ret = LEJP_REJECT_MP_C_OR_E_UNDERF;
674 					goto reject;
675 				}
676 				/* pop */
677 				ctx->sp--;
678 				if (ctx->st[ctx->sp].s != LEJP_MP_ARRAY_END) {
679 					ret = LEJP_REJECT_MP_C_OR_E_NOTARRAY;
680 					goto reject;
681 				}
682 
683 				/* drop the path [n] bit */
684 				if (ctx->sp) {
685 					ctx->pst[ctx->pst_sp].ppos = (unsigned char)
686 							ctx->st[ctx->sp - 1].p;
687 					ctx->ipos = (unsigned char)ctx->st[ctx->sp - 1].i;
688 				}
689 				ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0';
690 				if (ctx->path_match &&
691 				    ctx->pst[ctx->pst_sp].ppos <= ctx->path_match_len)
692 					/*
693 					 * we shrank the path to be
694 					 * smaller than the matching point
695 					 */
696 					ctx->path_match = 0;
697 
698 				if (ctx->outer_array && !ctx->sp) { /* ended on ] */
699 					n = LEJPCB_ARRAY_END;
700 					goto completed;
701 				}
702 
703 				/* do LEJP_MP_ARRAY_END processing */
704 				goto redo_character;
705 			}
706 			if (c != '}') {
707 				ret = LEJP_REJECT_MP_C_OR_E_NEITHER;
708 				goto reject;
709 			}
710 			if (!ctx->sp) {
711 				n = LEJPCB_OBJECT_END;
712 completed:
713 				lejp_check_path_match(ctx);
714 				if (ctx->pst[ctx->pst_sp].callback(ctx, (char)n) ||
715 				    ctx->pst[ctx->pst_sp].callback(ctx,
716 							    LEJPCB_COMPLETE))
717 					goto reject_callback;
718 
719 				/* done, return unused amount */
720 				return len;
721 			}
722 
723 			/* pop */
724 pop_level:
725 			ctx->sp--;
726 			if (ctx->sp) {
727 				ctx->pst[ctx->pst_sp].ppos = (unsigned char)ctx->st[ctx->sp].p;
728 				ctx->ipos = (unsigned char)ctx->st[ctx->sp].i;
729 			}
730 			ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0';
731 			if (ctx->path_match &&
732 			    ctx->pst[ctx->pst_sp].ppos <= ctx->path_match_len)
733 				/*
734 				 * we shrank the path to be
735 				 * smaller than the matching point
736 				 */
737 				ctx->path_match = 0;
738 
739 			lejp_check_path_match(ctx);
740 			if (ctx->pst[ctx->pst_sp].callback(ctx,
741 							   LEJPCB_OBJECT_END))
742 				goto reject_callback;
743 			break;
744 
745 		case LEJP_MP_ARRAY_END:
746 array_end:
747 			ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0';
748 			if (c == ',') {
749 				/* increment this stack level's index */
750 				if (ctx->ipos)
751 					ctx->i[ctx->ipos - 1]++;
752 				ctx->st[ctx->sp].s = LEJP_MP_VALUE;
753 				if (ctx->sp)
754 					ctx->pst[ctx->pst_sp].ppos = (unsigned char)
755 							ctx->st[ctx->sp - 1].p;
756 				ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0';
757 				break;
758 			}
759 			if (c != ']') {
760 				ret = LEJP_REJECT_MP_ARRAY_END_MISSING;
761 				goto reject;
762 			}
763 
764 			ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END;
765 			ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_ARRAY_END);
766 			break;
767 		}
768 
769 		continue;
770 
771 emit_string_char:
772 		if (!ctx->sp || ctx->st[ctx->sp - 1].s != LEJP_MP_DELIM) {
773 			/* assemble the string value into chunks */
774 			ctx->buf[ctx->npos++] = (char)c;
775 			if (ctx->npos == sizeof(ctx->buf) - 1) {
776 				if (ctx->pst[ctx->pst_sp].callback(ctx,
777 							  LEJPCB_VAL_STR_CHUNK))
778 					goto reject_callback;
779 				ctx->npos = 0;
780 			}
781 			continue;
782 		}
783 		/* name part of name:value pair */
784 		ctx->path[ctx->pst[ctx->pst_sp].ppos++] = (char)c;
785 		continue;
786 
787 add_stack_level:
788 		/* push on to the object stack */
789 		if (ctx->pst[ctx->pst_sp].ppos &&
790 		    ctx->st[ctx->sp].s != LEJP_MP_COMMA_OR_END &&
791 		    ctx->st[ctx->sp].s != LEJP_MP_ARRAY_END)
792 			ctx->path[ctx->pst[ctx->pst_sp].ppos++] = '.';
793 
794 		ctx->st[ctx->sp].p = (char)ctx->pst[ctx->pst_sp].ppos;
795 		ctx->st[ctx->sp].i = (char)ctx->ipos;
796 		if (++ctx->sp == LWS_ARRAY_SIZE(ctx->st)) {
797 			ret = LEJP_REJECT_STACK_OVERFLOW;
798 			goto reject;
799 		}
800 		ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0';
801 		ctx->st[ctx->sp].s = (char)c;
802 		ctx->st[ctx->sp].b = 0;
803 		continue;
804 
805 append_npos:
806 		if (ctx->npos >= sizeof(ctx->buf)) {
807 			ret = LEJP_REJECT_NUM_TOO_LONG;
808 			goto reject;
809 		}
810 		ctx->buf[ctx->npos++] = (char)c;
811 		continue;
812 
813 redo_character:
814 		json--;
815 		len++;
816 	}
817 
818 	return LEJP_CONTINUE;
819 
820 
821 reject_callback:
822 	ret = LEJP_REJECT_CALLBACK;
823 
824 reject:
825 	ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_FAILED);
826 	return ret;
827 }
828 
829 int
830 lejp_parser_push(struct lejp_ctx *ctx, void *user, const char * const *paths,
831 		 unsigned char paths_count, lejp_callback lejp_cb)
832 {
833 	struct _lejp_parsing_stack *p;
834 
835 	if (ctx->pst_sp + 1 == LEJP_MAX_PARSING_STACK_DEPTH)
836 		return -1;
837 
838 	lejp_check_path_match(ctx);
839 
840 	ctx->pst[ctx->pst_sp].path_match = ctx->path_match;
841 	ctx->pst_sp++;
842 
843 	p = &ctx->pst[ctx->pst_sp];
844 	p->user = user;
845 	p->callback = lejp_cb;
846 	p->paths = paths;
847 	p->count_paths = paths_count;
848 	p->ppos = 0;
849 
850 	ctx->path_match = 0;
851 	lejp_check_path_match(ctx);
852 
853 	lwsl_debug("%s: pushed parser stack to %d (path %s)\n", __func__,
854 		   ctx->pst_sp, ctx->path);
855 
856 	return 0;
857 }
858 
859 int
860 lejp_parser_pop(struct lejp_ctx *ctx)
861 {
862 	if (!ctx->pst_sp)
863 		return -1;
864 
865 	ctx->pst_sp--;
866 	lwsl_debug("%s: popped parser stack to %d\n", __func__, ctx->pst_sp);
867 
868 	ctx->path_match = 0; /* force it to check */
869 	lejp_check_path_match(ctx);
870 
871 	return 0;
872 }
873 
874 const char *
875 lejp_error_to_string(int e)
876 {
877 	if (e > 0)
878 		e = 0;
879 	else
880 		e = -e;
881 
882 	if (e >= (int)LWS_ARRAY_SIZE(parser_errs))
883 		return "Unknown error";
884 
885 	return parser_errs[e];
886 }
887 
888