pack_unpack.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. /*
  2. * Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org>
  3. * Copyright (c) 2011-2012 Graeme Smecher <graeme.smecher@mail.mcgill.ca>
  4. *
  5. * Jansson is free software; you can redistribute it and/or modify
  6. * it under the terms of the MIT license. See LICENSE for details.
  7. */
  8. #include <string.h>
  9. #include "jansson.h"
  10. #include "jansson_private.h"
  11. #include "utf.h"
  12. typedef struct {
  13. const char *start;
  14. const char *fmt;
  15. char token;
  16. json_error_t *error;
  17. size_t flags;
  18. int line;
  19. int column;
  20. } scanner_t;
  21. static const char *type_names[] = {
  22. "object",
  23. "array",
  24. "string",
  25. "integer",
  26. "real",
  27. "true",
  28. "false",
  29. "null"
  30. };
  31. #define type_name(x) type_names[json_typeof(x)]
  32. static const char *unpack_value_starters = "{[siIbfFOon";
  33. static void scanner_init(scanner_t *s, json_error_t *error,
  34. size_t flags, const char *fmt)
  35. {
  36. s->error = error;
  37. s->flags = flags;
  38. s->fmt = s->start = fmt;
  39. s->line = 1;
  40. s->column = 0;
  41. }
  42. static void next_token(scanner_t *s)
  43. {
  44. const char *t = s->fmt;
  45. s->column++;
  46. /* skip space and ignored chars */
  47. while(*t == ' ' || *t == '\t' || *t == '\n' || *t == ',' || *t == ':') {
  48. if(*t == '\n') {
  49. s->line++;
  50. s->column = 1;
  51. }
  52. else
  53. s->column++;
  54. t++;
  55. }
  56. s->token = *t;
  57. t++;
  58. s->fmt = t;
  59. }
  60. static void set_error(scanner_t *s, const char *source, const char *fmt, ...)
  61. {
  62. va_list ap;
  63. size_t pos;
  64. va_start(ap, fmt);
  65. pos = (size_t)(s->fmt - s->start);
  66. jsonp_error_vset(s->error, s->line, s->column, pos, fmt, ap);
  67. jsonp_error_set_source(s->error, source);
  68. va_end(ap);
  69. }
  70. static json_t *pack(scanner_t *s, va_list *ap);
  71. static json_t *pack_object(scanner_t *s, va_list *ap)
  72. {
  73. json_t *object = json_object();
  74. next_token(s);
  75. while(s->token != '}') {
  76. const char *key;
  77. json_t *value;
  78. if(!s->token) {
  79. set_error(s, "<format>", "Unexpected end of format string");
  80. goto error;
  81. }
  82. if(s->token != 's') {
  83. set_error(s, "<format>", "Expected format 's', got '%c'", s->token);
  84. goto error;
  85. }
  86. key = va_arg(*ap, const char *);
  87. if(!key) {
  88. set_error(s, "<args>", "NULL object key");
  89. goto error;
  90. }
  91. if(!utf8_check_string(key, -1)) {
  92. set_error(s, "<args>", "Invalid UTF-8 in object key");
  93. goto error;
  94. }
  95. next_token(s);
  96. value = pack(s, ap);
  97. if(!value)
  98. goto error;
  99. if(json_object_set_new_nocheck(object, key, value)) {
  100. set_error(s, "<internal>", "Unable to add key \"%s\"", key);
  101. goto error;
  102. }
  103. next_token(s);
  104. }
  105. return object;
  106. error:
  107. json_decref(object);
  108. return NULL;
  109. }
  110. static json_t *pack_array(scanner_t *s, va_list *ap)
  111. {
  112. json_t *array = json_array();
  113. next_token(s);
  114. while(s->token != ']') {
  115. json_t *value;
  116. if(!s->token) {
  117. set_error(s, "<format>", "Unexpected end of format string");
  118. goto error;
  119. }
  120. value = pack(s, ap);
  121. if(!value)
  122. goto error;
  123. if(json_array_append_new(array, value)) {
  124. set_error(s, "<internal>", "Unable to append to array");
  125. goto error;
  126. }
  127. next_token(s);
  128. }
  129. return array;
  130. error:
  131. json_decref(array);
  132. return NULL;
  133. }
  134. static json_t *pack(scanner_t *s, va_list *ap)
  135. {
  136. switch(s->token) {
  137. case '{':
  138. return pack_object(s, ap);
  139. case '[':
  140. return pack_array(s, ap);
  141. case 's': /* string */
  142. {
  143. const char *str = va_arg(*ap, const char *);
  144. if(!str) {
  145. set_error(s, "<args>", "NULL string argument");
  146. return NULL;
  147. }
  148. if(!utf8_check_string(str, -1)) {
  149. set_error(s, "<args>", "Invalid UTF-8 string");
  150. return NULL;
  151. }
  152. return json_string_nocheck(str);
  153. }
  154. case 'n': /* null */
  155. return json_null();
  156. case 'b': /* boolean */
  157. return va_arg(*ap, int) ? json_true() : json_false();
  158. case 'i': /* integer from int */
  159. return json_integer(va_arg(*ap, int));
  160. case 'I': /* integer from json_int_t */
  161. return json_integer(va_arg(*ap, json_int_t));
  162. case 'f': /* real */
  163. return json_real(va_arg(*ap, double));
  164. case 'O': /* a json_t object; increments refcount */
  165. return json_incref(va_arg(*ap, json_t *));
  166. case 'o': /* a json_t object; doesn't increment refcount */
  167. return va_arg(*ap, json_t *);
  168. default:
  169. set_error(s, "<format>", "Unexpected format character '%c'",
  170. s->token);
  171. return NULL;
  172. }
  173. }
  174. static int unpack(scanner_t *s, json_t *root, va_list *ap);
  175. static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
  176. {
  177. int ret = -1;
  178. int strict = 0;
  179. /* Use a set (emulated by a hashtable) to check that all object
  180. keys are accessed. Checking that the correct number of keys
  181. were accessed is not enough, as the same key can be unpacked
  182. multiple times.
  183. */
  184. hashtable_t key_set;
  185. if(hashtable_init(&key_set)) {
  186. set_error(s, "<internal>", "Out of memory");
  187. return -1;
  188. }
  189. if(root && !json_is_object(root)) {
  190. set_error(s, "<validation>", "Expected object, got %s",
  191. type_name(root));
  192. goto out;
  193. }
  194. next_token(s);
  195. while(s->token != '}') {
  196. const char *key;
  197. json_t *value;
  198. int opt = 0;
  199. if(strict != 0) {
  200. set_error(s, "<format>", "Expected '}' after '%c', got '%c'",
  201. (strict == 1 ? '!' : '*'), s->token);
  202. goto out;
  203. }
  204. if(!s->token) {
  205. set_error(s, "<format>", "Unexpected end of format string");
  206. goto out;
  207. }
  208. if(s->token == '!' || s->token == '*') {
  209. strict = (s->token == '!' ? 1 : -1);
  210. next_token(s);
  211. continue;
  212. }
  213. if(s->token != 's') {
  214. set_error(s, "<format>", "Expected format 's', got '%c'", s->token);
  215. goto out;
  216. }
  217. key = va_arg(*ap, const char *);
  218. if(!key) {
  219. set_error(s, "<args>", "NULL object key");
  220. goto out;
  221. }
  222. next_token(s);
  223. if(s->token == '?') {
  224. opt = 1;
  225. next_token(s);
  226. }
  227. if(!root) {
  228. /* skipping */
  229. value = NULL;
  230. }
  231. else {
  232. value = json_object_get(root, key);
  233. if(!value && !opt) {
  234. set_error(s, "<validation>", "Object item not found: %s", key);
  235. goto out;
  236. }
  237. }
  238. if(unpack(s, value, ap))
  239. goto out;
  240. hashtable_set(&key_set, key, 0, json_null());
  241. next_token(s);
  242. }
  243. if(strict == 0 && (s->flags & JSON_STRICT))
  244. strict = 1;
  245. if(root && strict == 1 && key_set.size != json_object_size(root)) {
  246. long diff = (long)json_object_size(root) - (long)key_set.size;
  247. set_error(s, "<validation>", "%li object item(s) left unpacked", diff);
  248. goto out;
  249. }
  250. ret = 0;
  251. out:
  252. hashtable_close(&key_set);
  253. return ret;
  254. }
  255. static int unpack_array(scanner_t *s, json_t *root, va_list *ap)
  256. {
  257. size_t i = 0;
  258. int strict = 0;
  259. if(root && !json_is_array(root)) {
  260. set_error(s, "<validation>", "Expected array, got %s", type_name(root));
  261. return -1;
  262. }
  263. next_token(s);
  264. while(s->token != ']') {
  265. json_t *value;
  266. if(strict != 0) {
  267. set_error(s, "<format>", "Expected ']' after '%c', got '%c'",
  268. (strict == 1 ? '!' : '*'),
  269. s->token);
  270. return -1;
  271. }
  272. if(!s->token) {
  273. set_error(s, "<format>", "Unexpected end of format string");
  274. return -1;
  275. }
  276. if(s->token == '!' || s->token == '*') {
  277. strict = (s->token == '!' ? 1 : -1);
  278. next_token(s);
  279. continue;
  280. }
  281. if(!strchr(unpack_value_starters, s->token)) {
  282. set_error(s, "<format>", "Unexpected format character '%c'",
  283. s->token);
  284. return -1;
  285. }
  286. if(!root) {
  287. /* skipping */
  288. value = NULL;
  289. }
  290. else {
  291. value = json_array_get(root, i);
  292. if(!value) {
  293. set_error(s, "<validation>", "Array index %lu out of range",
  294. (unsigned long)i);
  295. return -1;
  296. }
  297. }
  298. if(unpack(s, value, ap))
  299. return -1;
  300. next_token(s);
  301. i++;
  302. }
  303. if(strict == 0 && (s->flags & JSON_STRICT))
  304. strict = 1;
  305. if(root && strict == 1 && i != json_array_size(root)) {
  306. long diff = (long)json_array_size(root) - (long)i;
  307. set_error(s, "<validation>", "%li array item(s) left unpacked", diff);
  308. return -1;
  309. }
  310. return 0;
  311. }
  312. static int unpack(scanner_t *s, json_t *root, va_list *ap)
  313. {
  314. switch(s->token)
  315. {
  316. case '{':
  317. return unpack_object(s, root, ap);
  318. case '[':
  319. return unpack_array(s, root, ap);
  320. case 's':
  321. if(root && !json_is_string(root)) {
  322. set_error(s, "<validation>", "Expected string, got %s",
  323. type_name(root));
  324. return -1;
  325. }
  326. if(!(s->flags & JSON_VALIDATE_ONLY)) {
  327. const char **target;
  328. target = va_arg(*ap, const char **);
  329. if(!target) {
  330. set_error(s, "<args>", "NULL string argument");
  331. return -1;
  332. }
  333. if(root)
  334. *target = json_string_value(root);
  335. }
  336. return 0;
  337. case 'i':
  338. if(root && !json_is_integer(root)) {
  339. set_error(s, "<validation>", "Expected integer, got %s",
  340. type_name(root));
  341. return -1;
  342. }
  343. if(!(s->flags & JSON_VALIDATE_ONLY)) {
  344. int *target = va_arg(*ap, int*);
  345. if(root)
  346. *target = (int)json_integer_value(root);
  347. }
  348. return 0;
  349. case 'I':
  350. if(root && !json_is_integer(root)) {
  351. set_error(s, "<validation>", "Expected integer, got %s",
  352. type_name(root));
  353. return -1;
  354. }
  355. if(!(s->flags & JSON_VALIDATE_ONLY)) {
  356. json_int_t *target = va_arg(*ap, json_int_t*);
  357. if(root)
  358. *target = json_integer_value(root);
  359. }
  360. return 0;
  361. case 'b':
  362. if(root && !json_is_boolean(root)) {
  363. set_error(s, "<validation>", "Expected true or false, got %s",
  364. type_name(root));
  365. return -1;
  366. }
  367. if(!(s->flags & JSON_VALIDATE_ONLY)) {
  368. int *target = va_arg(*ap, int*);
  369. if(root)
  370. *target = json_is_true(root);
  371. }
  372. return 0;
  373. case 'f':
  374. if(root && !json_is_real(root)) {
  375. set_error(s, "<validation>", "Expected real, got %s",
  376. type_name(root));
  377. return -1;
  378. }
  379. if(!(s->flags & JSON_VALIDATE_ONLY)) {
  380. double *target = va_arg(*ap, double*);
  381. if(root)
  382. *target = json_real_value(root);
  383. }
  384. return 0;
  385. case 'F':
  386. if(root && !json_is_number(root)) {
  387. set_error(s, "<validation>", "Expected real or integer, got %s",
  388. type_name(root));
  389. return -1;
  390. }
  391. if(!(s->flags & JSON_VALIDATE_ONLY)) {
  392. double *target = va_arg(*ap, double*);
  393. if(root)
  394. *target = json_number_value(root);
  395. }
  396. return 0;
  397. case 'O':
  398. if(root && !(s->flags & JSON_VALIDATE_ONLY))
  399. json_incref(root);
  400. /* Fall through */
  401. case 'o':
  402. if(!(s->flags & JSON_VALIDATE_ONLY)) {
  403. json_t **target = va_arg(*ap, json_t**);
  404. if(root)
  405. *target = root;
  406. }
  407. return 0;
  408. case 'n':
  409. /* Never assign, just validate */
  410. if(root && !json_is_null(root)) {
  411. set_error(s, "<validation>", "Expected null, got %s",
  412. type_name(root));
  413. return -1;
  414. }
  415. return 0;
  416. default:
  417. set_error(s, "<format>", "Unexpected format character '%c'",
  418. s->token);
  419. return -1;
  420. }
  421. }
  422. json_t *json_vpack_ex(json_error_t *error, size_t flags,
  423. const char *fmt, va_list ap)
  424. {
  425. scanner_t s;
  426. va_list ap_copy;
  427. json_t *value;
  428. if(!fmt || !*fmt) {
  429. jsonp_error_init(error, "<format>");
  430. jsonp_error_set(error, -1, -1, 0, "NULL or empty format string");
  431. return NULL;
  432. }
  433. jsonp_error_init(error, NULL);
  434. scanner_init(&s, error, flags, fmt);
  435. next_token(&s);
  436. va_copy(ap_copy, ap);
  437. value = pack(&s, &ap_copy);
  438. va_end(ap_copy);
  439. if(!value)
  440. return NULL;
  441. next_token(&s);
  442. if(s.token) {
  443. json_decref(value);
  444. set_error(&s, "<format>", "Garbage after format string");
  445. return NULL;
  446. }
  447. return value;
  448. }
  449. json_t *json_pack_ex(json_error_t *error, size_t flags, const char *fmt, ...)
  450. {
  451. json_t *value;
  452. va_list ap;
  453. va_start(ap, fmt);
  454. value = json_vpack_ex(error, flags, fmt, ap);
  455. va_end(ap);
  456. return value;
  457. }
  458. json_t *json_pack(const char *fmt, ...)
  459. {
  460. json_t *value;
  461. va_list ap;
  462. va_start(ap, fmt);
  463. value = json_vpack_ex(NULL, 0, fmt, ap);
  464. va_end(ap);
  465. return value;
  466. }
  467. int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags,
  468. const char *fmt, va_list ap)
  469. {
  470. scanner_t s;
  471. va_list ap_copy;
  472. if(!root) {
  473. jsonp_error_init(error, "<root>");
  474. jsonp_error_set(error, -1, -1, 0, "NULL root value");
  475. return -1;
  476. }
  477. if(!fmt || !*fmt) {
  478. jsonp_error_init(error, "<format>");
  479. jsonp_error_set(error, -1, -1, 0, "NULL or empty format string");
  480. return -1;
  481. }
  482. jsonp_error_init(error, NULL);
  483. scanner_init(&s, error, flags, fmt);
  484. next_token(&s);
  485. va_copy(ap_copy, ap);
  486. if(unpack(&s, root, &ap_copy)) {
  487. va_end(ap_copy);
  488. return -1;
  489. }
  490. va_end(ap_copy);
  491. next_token(&s);
  492. if(s.token) {
  493. set_error(&s, "<format>", "Garbage after format string");
  494. return -1;
  495. }
  496. return 0;
  497. }
  498. int json_unpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, ...)
  499. {
  500. int ret;
  501. va_list ap;
  502. va_start(ap, fmt);
  503. ret = json_vunpack_ex(root, error, flags, fmt, ap);
  504. va_end(ap);
  505. return ret;
  506. }
  507. int json_unpack(json_t *root, const char *fmt, ...)
  508. {
  509. int ret;
  510. va_list ap;
  511. va_start(ap, fmt);
  512. ret = json_vunpack_ex(root, NULL, 0, fmt, ap);
  513. va_end(ap);
  514. return ret;
  515. }