lejp.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  1. /*
  2. * Lightweight Embedded JSON Parser
  3. *
  4. * Copyright (C) 2013-2017 Andy Green <[email protected]>
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation:
  9. * version 2.1 of the License.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  19. * MA 02110-1301 USA
  20. */
  21. #include <libwebsockets.h>
  22. #include "core/private.h"
  23. #include <string.h>
  24. #include <stdio.h>
  25. /**
  26. * lejp_construct - prepare a struct lejp_ctx for use
  27. *
  28. * \param ctx: pointer to your struct lejp_ctx
  29. * \param callback: your user callback which will received parsed tokens
  30. * \param user: optional user data pointer untouched by lejp
  31. * \param paths: your array of name elements you are interested in
  32. * \param count_paths: LWS_ARRAY_SIZE() of @paths
  33. *
  34. * Prepares your context struct for use with lejp
  35. */
  36. void
  37. lejp_construct(struct lejp_ctx *ctx,
  38. signed char (*callback)(struct lejp_ctx *ctx, char reason), void *user,
  39. const char * const *paths, unsigned char count_paths)
  40. {
  41. ctx->st[0].s = 0;
  42. ctx->st[0].p = 0;
  43. ctx->st[0].i = 0;
  44. ctx->st[0].b = 0;
  45. ctx->sp = 0;
  46. ctx->ipos = 0;
  47. ctx->ppos = 0;
  48. ctx->path_match = 0;
  49. ctx->path[0] = '\0';
  50. ctx->callback = callback;
  51. ctx->user = user;
  52. ctx->paths = paths;
  53. ctx->count_paths = count_paths;
  54. ctx->line = 1;
  55. ctx->callback(ctx, LEJPCB_CONSTRUCTED);
  56. }
  57. /**
  58. * lejp_destruct - retire a previously constructed struct lejp_ctx
  59. *
  60. * \param ctx: pointer to your struct lejp_ctx
  61. *
  62. * lejp does not perform any allocations, but since your user code might, this
  63. * provides a one-time LEJPCB_DESTRUCTED callback at destruction time where
  64. * you can clean up in your callback.
  65. */
  66. void
  67. lejp_destruct(struct lejp_ctx *ctx)
  68. {
  69. /* no allocations... just let callback know what it happening */
  70. ctx->callback(ctx, LEJPCB_DESTRUCTED);
  71. }
  72. /**
  73. * lejp_change_callback - switch to a different callback from now on
  74. *
  75. * \param ctx: pointer to your struct lejp_ctx
  76. * \param callback: your user callback which will received parsed tokens
  77. *
  78. * This tells the old callback it was destroyed, in case you want to take any
  79. * action because that callback "lost focus", then changes to the new
  80. * callback and tells it first that it was constructed, and then started.
  81. *
  82. * Changing callback is a cheap and powerful trick to split out handlers
  83. * according to information earlier in the parse. For example you may have
  84. * a JSON pair "schema" whose value defines what can be expected for the rest
  85. * of the JSON. Rather than having one huge callback for all cases, you can
  86. * have an initial one looking for "schema" which then calls
  87. * lejp_change_callback() to a handler specific for the schema.
  88. *
  89. * Notice that afterwards, you need to construct the context again anyway to
  90. * parse another JSON object, and the callback is reset then to the main,
  91. * schema-interpreting one. The construction action is very lightweight.
  92. */
  93. void
  94. lejp_change_callback(struct lejp_ctx *ctx,
  95. signed char (*callback)(struct lejp_ctx *ctx, char reason))
  96. {
  97. ctx->callback(ctx, LEJPCB_DESTRUCTED);
  98. ctx->callback = callback;
  99. ctx->callback(ctx, LEJPCB_CONSTRUCTED);
  100. ctx->callback(ctx, LEJPCB_START);
  101. }
  102. static void
  103. lejp_check_path_match(struct lejp_ctx *ctx)
  104. {
  105. const char *p, *q;
  106. int n;
  107. /* we only need to check if a match is not active */
  108. for (n = 0; !ctx->path_match && n < ctx->count_paths; n++) {
  109. ctx->wildcount = 0;
  110. p = ctx->path;
  111. q = ctx->paths[n];
  112. while (*p && *q) {
  113. if (*q != '*') {
  114. if (*p != *q)
  115. break;
  116. p++;
  117. q++;
  118. continue;
  119. }
  120. ctx->wild[ctx->wildcount++] = lws_ptr_diff(p, ctx->path);
  121. q++;
  122. /*
  123. * if * has something after it, match to .
  124. * if ends with *, eat everything.
  125. * This implies match sequences must be ordered like
  126. * x.*.*
  127. * x.*
  128. * if both options are possible
  129. */
  130. while (*p && (*p != '.' || !*q))
  131. p++;
  132. }
  133. if (*p || *q)
  134. continue;
  135. ctx->path_match = n + 1;
  136. ctx->path_match_len = ctx->ppos;
  137. return;
  138. }
  139. if (!ctx->path_match)
  140. ctx->wildcount = 0;
  141. }
  142. int
  143. lejp_get_wildcard(struct lejp_ctx *ctx, int wildcard, char *dest, int len)
  144. {
  145. int n;
  146. if (wildcard >= ctx->wildcount || !len)
  147. return 0;
  148. n = ctx->wild[wildcard];
  149. while (--len && n < ctx->ppos &&
  150. (n == ctx->wild[wildcard] || ctx->path[n] != '.'))
  151. *dest++ = ctx->path[n++];
  152. *dest = '\0';
  153. n++;
  154. return n - ctx->wild[wildcard];
  155. }
  156. /**
  157. * lejp_parse - interpret some more incoming data incrementally
  158. *
  159. * \param ctx: previously constructed parsing context
  160. * \param json: char buffer with the new data to interpret
  161. * \param len: amount of data in the buffer
  162. *
  163. * Because lejp is a stream parser, it incrementally parses as new data
  164. * becomes available, maintaining all state in the context struct. So an
  165. * incomplete JSON is a normal situation, getting you a LEJP_CONTINUE
  166. * return, signalling there's no error but to call again with more data when
  167. * it comes to complete the parsing. Successful parsing completes with a
  168. * 0 or positive integer indicating how much of the last input buffer was
  169. * unused.
  170. */
  171. int
  172. lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len)
  173. {
  174. unsigned char c, n, s, ret = LEJP_REJECT_UNKNOWN;
  175. static const char esc_char[] = "\"\\/bfnrt";
  176. static const char esc_tran[] = "\"\\/\b\f\n\r\t";
  177. static const char tokens[] = "rue alse ull ";
  178. if (!ctx->sp && !ctx->ppos)
  179. ctx->callback(ctx, LEJPCB_START);
  180. while (len--) {
  181. c = *json++;
  182. s = ctx->st[ctx->sp].s;
  183. /* skip whitespace unless we should care */
  184. if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '#') {
  185. if (c == '\n') {
  186. ctx->line++;
  187. ctx->st[ctx->sp].s &= ~LEJP_FLAG_WS_COMMENTLINE;
  188. }
  189. if (!(s & LEJP_FLAG_WS_KEEP)) {
  190. if (c == '#')
  191. ctx->st[ctx->sp].s |=
  192. LEJP_FLAG_WS_COMMENTLINE;
  193. continue;
  194. }
  195. }
  196. if (ctx->st[ctx->sp].s & LEJP_FLAG_WS_COMMENTLINE)
  197. continue;
  198. switch (s) {
  199. case LEJP_IDLE:
  200. if (c != '{') {
  201. ret = LEJP_REJECT_IDLE_NO_BRACE;
  202. goto reject;
  203. }
  204. if (ctx->callback(ctx, LEJPCB_OBJECT_START)) {
  205. ret = LEJP_REJECT_CALLBACK;
  206. goto reject;
  207. }
  208. ctx->st[ctx->sp].s = LEJP_MEMBERS;
  209. break;
  210. case LEJP_MEMBERS:
  211. if (c == '}') {
  212. ctx->st[ctx->sp].s = LEJP_IDLE;
  213. ret = LEJP_REJECT_MEMBERS_NO_CLOSE;
  214. goto reject;
  215. }
  216. ctx->st[ctx->sp].s = LEJP_M_P;
  217. goto redo_character;
  218. case LEJP_M_P:
  219. if (c != '\"') {
  220. ret = LEJP_REJECT_MP_NO_OPEN_QUOTE;
  221. goto reject;
  222. }
  223. /* push */
  224. ctx->st[ctx->sp].s = LEJP_MP_DELIM;
  225. c = LEJP_MP_STRING;
  226. goto add_stack_level;
  227. case LEJP_MP_STRING:
  228. if (c == '\"') {
  229. if (!ctx->sp) { /* JSON can't end on quote */
  230. ret = LEJP_REJECT_MP_STRING_UNDERRUN;
  231. goto reject;
  232. }
  233. if (ctx->st[ctx->sp - 1].s != LEJP_MP_DELIM) {
  234. ctx->buf[ctx->npos] = '\0';
  235. if (ctx->callback(ctx,
  236. LEJPCB_VAL_STR_END) < 0) {
  237. ret = LEJP_REJECT_CALLBACK;
  238. goto reject;
  239. }
  240. }
  241. /* pop */
  242. ctx->sp--;
  243. break;
  244. }
  245. if (c == '\\') {
  246. ctx->st[ctx->sp].s = LEJP_MP_STRING_ESC;
  247. break;
  248. }
  249. if (c < ' ') {/* "control characters" not allowed */
  250. ret = LEJP_REJECT_MP_ILLEGAL_CTRL;
  251. goto reject;
  252. }
  253. goto emit_string_char;
  254. case LEJP_MP_STRING_ESC:
  255. if (c == 'u') {
  256. ctx->st[ctx->sp].s = LEJP_MP_STRING_ESC_U1;
  257. ctx->uni = 0;
  258. break;
  259. }
  260. for (n = 0; n < sizeof(esc_char); n++) {
  261. if (c != esc_char[n])
  262. continue;
  263. /* found it */
  264. c = esc_tran[n];
  265. ctx->st[ctx->sp].s = LEJP_MP_STRING;
  266. goto emit_string_char;
  267. }
  268. ret = LEJP_REJECT_MP_STRING_ESC_ILLEGAL_ESC;
  269. /* illegal escape char */
  270. goto reject;
  271. case LEJP_MP_STRING_ESC_U1:
  272. case LEJP_MP_STRING_ESC_U2:
  273. case LEJP_MP_STRING_ESC_U3:
  274. case LEJP_MP_STRING_ESC_U4:
  275. ctx->uni <<= 4;
  276. if (c >= '0' && c <= '9')
  277. ctx->uni |= c - '0';
  278. else
  279. if (c >= 'a' && c <= 'f')
  280. ctx->uni = c - 'a' + 10;
  281. else
  282. if (c >= 'A' && c <= 'F')
  283. ctx->uni = c - 'A' + 10;
  284. else {
  285. ret = LEJP_REJECT_ILLEGAL_HEX;
  286. goto reject;
  287. }
  288. ctx->st[ctx->sp].s++;
  289. switch (s) {
  290. case LEJP_MP_STRING_ESC_U2:
  291. if (ctx->uni < 0x08)
  292. break;
  293. /*
  294. * 0x08-0xff (0x0800 - 0xffff)
  295. * emit 3-byte UTF-8
  296. */
  297. c = 0xe0 | ((ctx->uni >> 4) & 0xf);
  298. goto emit_string_char;
  299. case LEJP_MP_STRING_ESC_U3:
  300. if (ctx->uni >= 0x080) {
  301. /*
  302. * 0x080 - 0xfff (0x0800 - 0xffff)
  303. * middle 3-byte seq
  304. * send ....XXXXXX..
  305. */
  306. c = 0x80 | ((ctx->uni >> 2) & 0x3f);
  307. goto emit_string_char;
  308. }
  309. if (ctx->uni < 0x008)
  310. break;
  311. /*
  312. * 0x008 - 0x7f (0x0080 - 0x07ff)
  313. * start 2-byte seq
  314. */
  315. c = 0xc0 | (ctx->uni >> 2);
  316. goto emit_string_char;
  317. case LEJP_MP_STRING_ESC_U4:
  318. if (ctx->uni >= 0x0080)
  319. /* end of 2 or 3-byte seq */
  320. c = 0x80 | (ctx->uni & 0x3f);
  321. else
  322. /* literal */
  323. c = (unsigned char)ctx->uni;
  324. ctx->st[ctx->sp].s = LEJP_MP_STRING;
  325. goto emit_string_char;
  326. default:
  327. break;
  328. }
  329. break;
  330. case LEJP_MP_DELIM:
  331. if (c != ':') {
  332. ret = LEJP_REJECT_MP_DELIM_MISSING_COLON;
  333. goto reject;
  334. }
  335. ctx->st[ctx->sp].s = LEJP_MP_VALUE;
  336. ctx->path[ctx->ppos] = '\0';
  337. lejp_check_path_match(ctx);
  338. if (ctx->callback(ctx, LEJPCB_PAIR_NAME)) {
  339. ret = LEJP_REJECT_CALLBACK;
  340. goto reject;
  341. }
  342. break;
  343. case LEJP_MP_VALUE:
  344. if (c >= '0' && c <= '9') {
  345. ctx->npos = 0;
  346. ctx->dcount = 0;
  347. ctx->f = 0;
  348. ctx->st[ctx->sp].s = LEJP_MP_VALUE_NUM_INT;
  349. goto redo_character;
  350. }
  351. switch (c) {
  352. case'\"':
  353. /* push */
  354. ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END;
  355. c = LEJP_MP_STRING;
  356. ctx->npos = 0;
  357. ctx->buf[0] = '\0';
  358. if (ctx->callback(ctx, LEJPCB_VAL_STR_START)) {
  359. ret = LEJP_REJECT_CALLBACK;
  360. goto reject;
  361. }
  362. goto add_stack_level;
  363. case '{':
  364. /* push */
  365. ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END;
  366. c = LEJP_MEMBERS;
  367. lejp_check_path_match(ctx);
  368. if (ctx->callback(ctx, LEJPCB_OBJECT_START)) {
  369. ret = LEJP_REJECT_CALLBACK;
  370. goto reject;
  371. }
  372. ctx->path_match = 0;
  373. goto add_stack_level;
  374. case '[':
  375. /* push */
  376. ctx->st[ctx->sp].s = LEJP_MP_ARRAY_END;
  377. c = LEJP_MP_VALUE;
  378. ctx->path[ctx->ppos++] = '[';
  379. ctx->path[ctx->ppos++] = ']';
  380. ctx->path[ctx->ppos] = '\0';
  381. if (ctx->callback(ctx, LEJPCB_ARRAY_START)) {
  382. ret = LEJP_REJECT_CALLBACK;
  383. goto reject;
  384. }
  385. ctx->i[ctx->ipos++] = 0;
  386. if (ctx->ipos > LWS_ARRAY_SIZE(ctx->i)) {
  387. ret = LEJP_REJECT_MP_DELIM_ISTACK;
  388. goto reject;
  389. }
  390. goto add_stack_level;
  391. case ']':
  392. /* pop */
  393. if (!ctx->sp) { /* JSON can't end on ] */
  394. ret = LEJP_REJECT_MP_C_OR_E_UNDERF;
  395. goto reject;
  396. }
  397. ctx->sp--;
  398. if (ctx->st[ctx->sp].s != LEJP_MP_ARRAY_END) {
  399. ret = LEJP_REJECT_MP_C_OR_E_NOTARRAY;
  400. goto reject;
  401. }
  402. /* drop the path [n] bit */
  403. if (ctx->sp) {
  404. ctx->ppos = ctx->st[ctx->sp - 1].p;
  405. ctx->ipos = ctx->st[ctx->sp - 1].i;
  406. }
  407. ctx->path[ctx->ppos] = '\0';
  408. if (ctx->path_match &&
  409. ctx->ppos <= ctx->path_match_len)
  410. /*
  411. * we shrank the path to be
  412. * smaller than the matching point
  413. */
  414. ctx->path_match = 0;
  415. goto array_end;
  416. case 't': /* true */
  417. ctx->uni = 0;
  418. ctx->st[ctx->sp].s = LEJP_MP_VALUE_TOK;
  419. break;
  420. case 'f':
  421. ctx->uni = 4;
  422. ctx->st[ctx->sp].s = LEJP_MP_VALUE_TOK;
  423. break;
  424. case 'n':
  425. ctx->uni = 4 + 5;
  426. ctx->st[ctx->sp].s = LEJP_MP_VALUE_TOK;
  427. break;
  428. default:
  429. ret = LEJP_REJECT_MP_DELIM_BAD_VALUE_START;
  430. goto reject;
  431. }
  432. break;
  433. case LEJP_MP_VALUE_NUM_INT:
  434. if (!ctx->npos && c == '-') {
  435. ctx->f |= LEJP_SEEN_MINUS;
  436. goto append_npos;
  437. }
  438. if (ctx->dcount < 10 && c >= '0' && c <= '9') {
  439. if (ctx->f & LEJP_SEEN_POINT)
  440. ctx->f |= LEJP_SEEN_POST_POINT;
  441. ctx->dcount++;
  442. goto append_npos;
  443. }
  444. if (c == '.') {
  445. if (!ctx->dcount || (ctx->f & LEJP_SEEN_POINT)) {
  446. ret = LEJP_REJECT_MP_VAL_NUM_FORMAT;
  447. goto reject;
  448. }
  449. ctx->f |= LEJP_SEEN_POINT;
  450. goto append_npos;
  451. }
  452. /*
  453. * before exponent, if we had . we must have had at
  454. * least one more digit
  455. */
  456. if ((ctx->f &
  457. (LEJP_SEEN_POINT | LEJP_SEEN_POST_POINT)) ==
  458. LEJP_SEEN_POINT) {
  459. ret = LEJP_REJECT_MP_VAL_NUM_INT_NO_FRAC;
  460. goto reject;
  461. }
  462. if (c == 'e' || c == 'E') {
  463. if (ctx->f & LEJP_SEEN_EXP) {
  464. ret = LEJP_REJECT_MP_VAL_NUM_FORMAT;
  465. goto reject;
  466. }
  467. ctx->f |= LEJP_SEEN_EXP;
  468. ctx->st[ctx->sp].s = LEJP_MP_VALUE_NUM_EXP;
  469. goto append_npos;
  470. }
  471. /* if none of the above, did we even have a number? */
  472. if (!ctx->dcount) {
  473. ret = LEJP_REJECT_MP_VAL_NUM_FORMAT;
  474. goto reject;
  475. }
  476. ctx->buf[ctx->npos] = '\0';
  477. if (ctx->f & LEJP_SEEN_POINT) {
  478. if (ctx->callback(ctx, LEJPCB_VAL_NUM_FLOAT)) {
  479. ret = LEJP_REJECT_CALLBACK;
  480. goto reject;
  481. }
  482. } else {
  483. if (ctx->callback(ctx, LEJPCB_VAL_NUM_INT)) {
  484. ret = LEJP_REJECT_CALLBACK;
  485. goto reject;
  486. }
  487. }
  488. /* then this is the post-number character, loop */
  489. ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END;
  490. goto redo_character;
  491. case LEJP_MP_VALUE_NUM_EXP:
  492. ctx->st[ctx->sp].s = LEJP_MP_VALUE_NUM_INT;
  493. if (c >= '0' && c <= '9')
  494. goto redo_character;
  495. if (c == '+' || c == '-')
  496. goto append_npos;
  497. ret = LEJP_REJECT_MP_VAL_NUM_EXP_BAD_EXP;
  498. goto reject;
  499. case LEJP_MP_VALUE_TOK: /* true, false, null */
  500. if (c != tokens[ctx->uni]) {
  501. ret = LEJP_REJECT_MP_VAL_TOK_UNKNOWN;
  502. goto reject;
  503. }
  504. ctx->uni++;
  505. if (tokens[ctx->uni] != ' ')
  506. break;
  507. switch (ctx->uni) {
  508. case 3:
  509. ctx->buf[0] = '1';
  510. ctx->buf[1] = '\0';
  511. if (ctx->callback(ctx, LEJPCB_VAL_TRUE)) {
  512. ret = LEJP_REJECT_CALLBACK;
  513. goto reject;
  514. }
  515. break;
  516. case 8:
  517. ctx->buf[0] = '0';
  518. ctx->buf[1] = '\0';
  519. if (ctx->callback(ctx, LEJPCB_VAL_FALSE)) {
  520. ret = LEJP_REJECT_CALLBACK;
  521. goto reject;
  522. }
  523. break;
  524. case 12:
  525. ctx->buf[0] = '\0';
  526. if (ctx->callback(ctx, LEJPCB_VAL_NULL)) {
  527. ret = LEJP_REJECT_CALLBACK;
  528. goto reject;
  529. }
  530. break;
  531. }
  532. ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END;
  533. break;
  534. case LEJP_MP_COMMA_OR_END:
  535. ctx->path[ctx->ppos] = '\0';
  536. if (c == ',') {
  537. /* increment this stack level's index */
  538. ctx->st[ctx->sp].s = LEJP_M_P;
  539. if (!ctx->sp) {
  540. ctx->ppos = 0;
  541. /*
  542. * since we came back to root level,
  543. * no path can still match
  544. */
  545. ctx->path_match = 0;
  546. break;
  547. }
  548. ctx->ppos = ctx->st[ctx->sp - 1].p;
  549. ctx->path[ctx->ppos] = '\0';
  550. if (ctx->path_match &&
  551. ctx->ppos <= ctx->path_match_len)
  552. /*
  553. * we shrank the path to be
  554. * smaller than the matching point
  555. */
  556. ctx->path_match = 0;
  557. if (ctx->st[ctx->sp - 1].s != LEJP_MP_ARRAY_END)
  558. break;
  559. /* top level is definitely an array... */
  560. if (ctx->ipos)
  561. ctx->i[ctx->ipos - 1]++;
  562. ctx->st[ctx->sp].s = LEJP_MP_VALUE;
  563. break;
  564. }
  565. if (c == ']') {
  566. if (!ctx->sp) { /* JSON can't end on ] */
  567. ret = LEJP_REJECT_MP_C_OR_E_UNDERF;
  568. goto reject;
  569. }
  570. /* pop */
  571. ctx->sp--;
  572. if (ctx->st[ctx->sp].s != LEJP_MP_ARRAY_END) {
  573. ret = LEJP_REJECT_MP_C_OR_E_NOTARRAY;
  574. goto reject;
  575. }
  576. /* drop the path [n] bit */
  577. if (ctx->sp) {
  578. ctx->ppos = ctx->st[ctx->sp - 1].p;
  579. ctx->ipos = ctx->st[ctx->sp - 1].i;
  580. }
  581. ctx->path[ctx->ppos] = '\0';
  582. if (ctx->path_match &&
  583. ctx->ppos <= ctx->path_match_len)
  584. /*
  585. * we shrank the path to be
  586. * smaller than the matching point
  587. */
  588. ctx->path_match = 0;
  589. /* do LEJP_MP_ARRAY_END processing */
  590. goto redo_character;
  591. }
  592. if (c == '}') {
  593. if (!ctx->sp) {
  594. lejp_check_path_match(ctx);
  595. if (ctx->callback(ctx, LEJPCB_OBJECT_END)) {
  596. ret = LEJP_REJECT_CALLBACK;
  597. goto reject;
  598. }
  599. ctx->callback(ctx, LEJPCB_COMPLETE);
  600. /* done, return unused amount */
  601. return len;
  602. }
  603. /* pop */
  604. ctx->sp--;
  605. if (ctx->sp) {
  606. ctx->ppos = ctx->st[ctx->sp - 1].p;
  607. ctx->ipos = ctx->st[ctx->sp - 1].i;
  608. }
  609. ctx->path[ctx->ppos] = '\0';
  610. if (ctx->path_match &&
  611. ctx->ppos <= ctx->path_match_len)
  612. /*
  613. * we shrank the path to be
  614. * smaller than the matching point
  615. */
  616. ctx->path_match = 0;
  617. lejp_check_path_match(ctx);
  618. if (ctx->callback(ctx, LEJPCB_OBJECT_END)) {
  619. ret = LEJP_REJECT_CALLBACK;
  620. goto reject;
  621. }
  622. break;
  623. }
  624. ret = LEJP_REJECT_MP_C_OR_E_NEITHER;
  625. goto reject;
  626. case LEJP_MP_ARRAY_END:
  627. array_end:
  628. ctx->path[ctx->ppos] = '\0';
  629. if (c == ',') {
  630. /* increment this stack level's index */
  631. if (ctx->ipos)
  632. ctx->i[ctx->ipos - 1]++;
  633. ctx->st[ctx->sp].s = LEJP_MP_VALUE;
  634. if (ctx->sp)
  635. ctx->ppos = ctx->st[ctx->sp - 1].p;
  636. ctx->path[ctx->ppos] = '\0';
  637. break;
  638. }
  639. if (c != ']') {
  640. ret = LEJP_REJECT_MP_ARRAY_END_MISSING;
  641. goto reject;
  642. }
  643. ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END;
  644. ctx->callback(ctx, LEJPCB_ARRAY_END);
  645. break;
  646. }
  647. continue;
  648. emit_string_char:
  649. if (!ctx->sp || ctx->st[ctx->sp - 1].s != LEJP_MP_DELIM) {
  650. /* assemble the string value into chunks */
  651. ctx->buf[ctx->npos++] = c;
  652. if (ctx->npos == sizeof(ctx->buf) - 1) {
  653. if (ctx->callback(ctx, LEJPCB_VAL_STR_CHUNK)) {
  654. ret = LEJP_REJECT_CALLBACK;
  655. goto reject;
  656. }
  657. ctx->npos = 0;
  658. }
  659. continue;
  660. }
  661. /* name part of name:value pair */
  662. ctx->path[ctx->ppos++] = c;
  663. continue;
  664. add_stack_level:
  665. /* push on to the object stack */
  666. if (ctx->ppos && ctx->st[ctx->sp].s != LEJP_MP_COMMA_OR_END &&
  667. ctx->st[ctx->sp].s != LEJP_MP_ARRAY_END)
  668. ctx->path[ctx->ppos++] = '.';
  669. ctx->st[ctx->sp].p = ctx->ppos;
  670. ctx->st[ctx->sp].i = ctx->ipos;
  671. if (++ctx->sp == LWS_ARRAY_SIZE(ctx->st)) {
  672. ret = LEJP_REJECT_STACK_OVERFLOW;
  673. goto reject;
  674. }
  675. ctx->path[ctx->ppos] = '\0';
  676. ctx->st[ctx->sp].s = c;
  677. ctx->st[ctx->sp].b = 0;
  678. continue;
  679. append_npos:
  680. if (ctx->npos >= sizeof(ctx->buf)) {
  681. ret = LEJP_REJECT_NUM_TOO_LONG;
  682. goto reject;
  683. }
  684. ctx->buf[ctx->npos++] = c;
  685. continue;
  686. redo_character:
  687. json--;
  688. len++;
  689. }
  690. return LEJP_CONTINUE;
  691. reject:
  692. ctx->callback(ctx, LEJPCB_FAILED);
  693. return ret;
  694. }