stats_print.c 23 KB

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