yajl_tree.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. /*
  2. * Copyright (c) 2010-2011 Florian Forster <ff at octo.it>
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <errno.h>
  20. #include <assert.h>
  21. #include "api/yajl_tree.h"
  22. #include "api/yajl_parse.h"
  23. #include "yajl_parser.h"
  24. #ifdef WIN32
  25. #define snprintf sprintf_s
  26. #endif
  27. #define STATUS_CONTINUE 1
  28. #define STATUS_ABORT 0
  29. struct stack_elem_s;
  30. typedef struct stack_elem_s stack_elem_t;
  31. struct stack_elem_s
  32. {
  33. char * key;
  34. yajl_val value;
  35. stack_elem_t *next;
  36. };
  37. struct context_s
  38. {
  39. stack_elem_t *stack;
  40. yajl_val root;
  41. char *errbuf;
  42. size_t errbuf_size;
  43. };
  44. typedef struct context_s context_t;
  45. #define RETURN_ERROR(ctx,retval,...) { \
  46. if ((ctx)->errbuf != NULL) \
  47. snprintf ((ctx)->errbuf, (ctx)->errbuf_size, __VA_ARGS__); \
  48. return (retval); \
  49. }
  50. static yajl_val value_alloc (yajl_type type)
  51. {
  52. yajl_val v;
  53. v = malloc (sizeof (*v));
  54. if (v == NULL) return (NULL);
  55. memset (v, 0, sizeof (*v));
  56. v->type = type;
  57. return (v);
  58. }
  59. static void yajl_object_free (yajl_val v)
  60. {
  61. size_t i;
  62. if (!YAJL_IS_OBJECT(v)) return;
  63. for (i = 0; i < v->u.object.len; i++)
  64. {
  65. free((char *) v->u.object.keys[i]);
  66. v->u.object.keys[i] = NULL;
  67. yajl_tree_free (v->u.object.values[i]);
  68. v->u.object.values[i] = NULL;
  69. }
  70. free((void*) v->u.object.keys);
  71. free(v->u.object.values);
  72. free(v);
  73. }
  74. static void yajl_array_free (yajl_val v)
  75. {
  76. size_t i;
  77. if (!YAJL_IS_ARRAY(v)) return;
  78. for (i = 0; i < v->u.array.len; i++)
  79. {
  80. yajl_tree_free (v->u.array.values[i]);
  81. v->u.array.values[i] = NULL;
  82. }
  83. free(v->u.array.values);
  84. free(v);
  85. }
  86. /*
  87. * Parsing nested objects and arrays is implemented using a stack. When a new
  88. * object or array starts (a curly or a square opening bracket is read), an
  89. * appropriate value is pushed on the stack. When the end of the object is
  90. * reached (an appropriate closing bracket has been read), the value is popped
  91. * off the stack and added to the enclosing object using "context_add_value".
  92. */
  93. static int context_push(context_t *ctx, yajl_val v)
  94. {
  95. stack_elem_t *stack;
  96. stack = malloc (sizeof (*stack));
  97. if (stack == NULL)
  98. RETURN_ERROR (ctx, ENOMEM, "Out of memory");
  99. memset (stack, 0, sizeof (*stack));
  100. assert ((ctx->stack == NULL)
  101. || YAJL_IS_OBJECT (v)
  102. || YAJL_IS_ARRAY (v));
  103. stack->value = v;
  104. stack->next = ctx->stack;
  105. ctx->stack = stack;
  106. return (0);
  107. }
  108. static yajl_val context_pop(context_t *ctx)
  109. {
  110. stack_elem_t *stack;
  111. yajl_val v;
  112. if (ctx->stack == NULL)
  113. RETURN_ERROR (ctx, NULL, "context_pop: "
  114. "Bottom of stack reached prematurely");
  115. stack = ctx->stack;
  116. ctx->stack = stack->next;
  117. v = stack->value;
  118. free (stack);
  119. return (v);
  120. }
  121. static int object_add_keyval(context_t *ctx,
  122. yajl_val obj, char *key, yajl_val value)
  123. {
  124. const char **tmpk;
  125. yajl_val *tmpv;
  126. /* We're checking for NULL in "context_add_value" or its callers. */
  127. assert (ctx != NULL);
  128. assert (obj != NULL);
  129. assert (key != NULL);
  130. assert (value != NULL);
  131. /* We're assuring that "obj" is an object in "context_add_value". */
  132. assert(YAJL_IS_OBJECT(obj));
  133. tmpk = realloc((void *) obj->u.object.keys, sizeof(*(obj->u.object.keys)) * (obj->u.object.len + 1));
  134. if (tmpk == NULL)
  135. RETURN_ERROR(ctx, ENOMEM, "Out of memory");
  136. obj->u.object.keys = tmpk;
  137. tmpv = realloc(obj->u.object.values, sizeof (*obj->u.object.values) * (obj->u.object.len + 1));
  138. if (tmpv == NULL)
  139. RETURN_ERROR(ctx, ENOMEM, "Out of memory");
  140. obj->u.object.values = tmpv;
  141. obj->u.object.keys[obj->u.object.len] = key;
  142. obj->u.object.values[obj->u.object.len] = value;
  143. obj->u.object.len++;
  144. return (0);
  145. }
  146. static int array_add_value (context_t *ctx,
  147. yajl_val array, yajl_val value)
  148. {
  149. yajl_val *tmp;
  150. /* We're checking for NULL pointers in "context_add_value" or its
  151. * callers. */
  152. assert (ctx != NULL);
  153. assert (array != NULL);
  154. assert (value != NULL);
  155. /* "context_add_value" will only call us with array values. */
  156. assert(YAJL_IS_ARRAY(array));
  157. tmp = realloc(array->u.array.values,
  158. sizeof(*(array->u.array.values)) * (array->u.array.len + 1));
  159. if (tmp == NULL)
  160. RETURN_ERROR(ctx, ENOMEM, "Out of memory");
  161. array->u.array.values = tmp;
  162. array->u.array.values[array->u.array.len] = value;
  163. array->u.array.len++;
  164. return 0;
  165. }
  166. /*
  167. * Add a value to the value on top of the stack or the "root" member in the
  168. * context if the end of the parsing process is reached.
  169. */
  170. static int context_add_value (context_t *ctx, yajl_val v)
  171. {
  172. /* We're checking for NULL values in all the calling functions. */
  173. assert (ctx != NULL);
  174. assert (v != NULL);
  175. /*
  176. * There are three valid states in which this function may be called:
  177. * - There is no value on the stack => This is the only value. This is the
  178. * last step done when parsing a document. We assign the value to the
  179. * "root" member and return.
  180. * - The value on the stack is an object. In this case store the key on the
  181. * stack or, if the key has already been read, add key and value to the
  182. * object.
  183. * - The value on the stack is an array. In this case simply add the value
  184. * and return.
  185. */
  186. if (ctx->stack == NULL)
  187. {
  188. assert (ctx->root == NULL);
  189. ctx->root = v;
  190. return (0);
  191. }
  192. else if (YAJL_IS_OBJECT (ctx->stack->value))
  193. {
  194. if (ctx->stack->key == NULL)
  195. {
  196. if (!YAJL_IS_STRING (v))
  197. RETURN_ERROR (ctx, EINVAL, "context_add_value: "
  198. "Object key is not a string (%#04x)",
  199. v->type);
  200. ctx->stack->key = v->u.string;
  201. v->u.string = NULL;
  202. free(v);
  203. return (0);
  204. }
  205. else /* if (ctx->key != NULL) */
  206. {
  207. char * key;
  208. key = ctx->stack->key;
  209. ctx->stack->key = NULL;
  210. return (object_add_keyval (ctx, ctx->stack->value, key, v));
  211. }
  212. }
  213. else if (YAJL_IS_ARRAY (ctx->stack->value))
  214. {
  215. return (array_add_value (ctx, ctx->stack->value, v));
  216. }
  217. else
  218. {
  219. RETURN_ERROR (ctx, EINVAL, "context_add_value: Cannot add value to "
  220. "a value of type %#04x (not a composite type)",
  221. ctx->stack->value->type);
  222. }
  223. }
  224. static int handle_string (void *ctx,
  225. const unsigned char *string, size_t string_length)
  226. {
  227. yajl_val v;
  228. v = value_alloc (yajl_t_string);
  229. if (v == NULL)
  230. RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory");
  231. v->u.string = malloc (string_length + 1);
  232. if (v->u.string == NULL)
  233. {
  234. free (v);
  235. RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory");
  236. }
  237. memcpy(v->u.string, string, string_length);
  238. v->u.string[string_length] = 0;
  239. return ((context_add_value (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT);
  240. }
  241. static int handle_number (void *ctx, const char *string, size_t string_length)
  242. {
  243. yajl_val v;
  244. char *endptr;
  245. v = value_alloc(yajl_t_number);
  246. if (v == NULL)
  247. RETURN_ERROR((context_t *) ctx, STATUS_ABORT, "Out of memory");
  248. v->u.number.r = malloc(string_length + 1);
  249. if (v->u.number.r == NULL)
  250. {
  251. free(v);
  252. RETURN_ERROR((context_t *) ctx, STATUS_ABORT, "Out of memory");
  253. }
  254. memcpy(v->u.number.r, string, string_length);
  255. v->u.number.r[string_length] = 0;
  256. v->u.number.flags = 0;
  257. endptr = NULL;
  258. errno = 0;
  259. v->u.number.i = yajl_parse_integer((const unsigned char *) v->u.number.r,
  260. strlen(v->u.number.r));
  261. if ((errno == 0) && (endptr != NULL) && (*endptr == 0))
  262. v->u.number.flags |= YAJL_NUMBER_INT_VALID;
  263. endptr = NULL;
  264. errno = 0;
  265. v->u.number.ui = yajl_parse_unsigned_integer((const unsigned char *) v->u.number.r,
  266. strlen(v->u.number.r));
  267. if ((errno == 0) && (endptr != NULL) && (*endptr == 0))
  268. v->u.number.flags |= YAJL_NUMBER_UINT_VALID;
  269. endptr = NULL;
  270. errno = 0;
  271. v->u.number.d = strtod(v->u.number.r, &endptr);
  272. if ((errno == 0) && (endptr != NULL) && (*endptr == 0))
  273. v->u.number.flags |= YAJL_NUMBER_DOUBLE_VALID;
  274. return ((context_add_value(ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT);
  275. }
  276. static int handle_start_map (void *ctx)
  277. {
  278. yajl_val v;
  279. v = value_alloc(yajl_t_object);
  280. if (v == NULL)
  281. RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory");
  282. v->u.object.keys = NULL;
  283. v->u.object.values = NULL;
  284. v->u.object.len = 0;
  285. return ((context_push (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT);
  286. }
  287. static int handle_end_map (void *ctx)
  288. {
  289. yajl_val v;
  290. v = context_pop (ctx);
  291. if (v == NULL)
  292. return (STATUS_ABORT);
  293. return ((context_add_value (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT);
  294. }
  295. static int handle_start_array (void *ctx)
  296. {
  297. yajl_val v;
  298. v = value_alloc(yajl_t_array);
  299. if (v == NULL)
  300. RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory");
  301. v->u.array.values = NULL;
  302. v->u.array.len = 0;
  303. return ((context_push (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT);
  304. }
  305. static int handle_end_array (void *ctx)
  306. {
  307. yajl_val v;
  308. v = context_pop (ctx);
  309. if (v == NULL)
  310. return (STATUS_ABORT);
  311. return ((context_add_value (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT);
  312. }
  313. static int handle_boolean (void *ctx, int boolean_value)
  314. {
  315. yajl_val v;
  316. v = value_alloc (boolean_value ? yajl_t_true : yajl_t_false);
  317. if (v == NULL)
  318. RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory");
  319. return ((context_add_value (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT);
  320. }
  321. static int handle_null (void *ctx)
  322. {
  323. yajl_val v;
  324. v = value_alloc (yajl_t_null);
  325. if (v == NULL)
  326. RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory");
  327. return ((context_add_value (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT);
  328. }
  329. /*
  330. * Public functions
  331. */
  332. yajl_val yajl_tree_parse (const char *input,
  333. char *error_buffer, size_t error_buffer_size)
  334. {
  335. static const yajl_callbacks callbacks =
  336. {
  337. /* null = */ handle_null,
  338. /* boolean = */ handle_boolean,
  339. /* integer = */ NULL,
  340. /* unsigned integer = */ NULL,
  341. /* double = */ NULL,
  342. /* number = */ handle_number,
  343. /* string = */ handle_string,
  344. /* start map = */ handle_start_map,
  345. /* map key = */ handle_string,
  346. /* end map = */ handle_end_map,
  347. /* start array = */ handle_start_array,
  348. /* end array = */ handle_end_array
  349. };
  350. yajl_handle handle;
  351. yajl_status status;
  352. context_t ctx = { NULL, NULL, NULL, 0 };
  353. ctx.errbuf = error_buffer;
  354. ctx.errbuf_size = error_buffer_size;
  355. if (error_buffer != NULL)
  356. memset (error_buffer, 0, error_buffer_size);
  357. handle = yajl_alloc (&callbacks, NULL, &ctx);
  358. yajl_config(handle, yajl_allow_comments, 1);
  359. status = yajl_parse(handle,
  360. (unsigned char *) input,
  361. strlen (input));
  362. status = yajl_complete_parse (handle);
  363. if (status != yajl_status_ok) {
  364. if (error_buffer != NULL && error_buffer_size > 0) {
  365. snprintf(
  366. error_buffer, error_buffer_size, "%s",
  367. (char *) yajl_get_error(handle, 1,
  368. (const unsigned char *) input,
  369. strlen(input)));
  370. }
  371. yajl_free (handle);
  372. return NULL;
  373. }
  374. yajl_free (handle);
  375. return (ctx.root);
  376. }
  377. yajl_val yajl_tree_get(yajl_val n, const char ** path, yajl_type type)
  378. {
  379. if (!path) return NULL;
  380. while (n && *path) {
  381. unsigned int i;
  382. if (n->type != yajl_t_object) return NULL;
  383. for (i = 0; i < n->u.object.len; i++) {
  384. if (!strcmp(*path, n->u.object.keys[i])) {
  385. n = n->u.object.values[i];
  386. break;
  387. }
  388. }
  389. if (i == n->u.object.len) return NULL;
  390. path++;
  391. }
  392. if (n && type != yajl_t_any && type != n->type) n = NULL;
  393. return n;
  394. }
  395. void yajl_tree_free (yajl_val v)
  396. {
  397. if (v == NULL) return;
  398. if (YAJL_IS_STRING(v))
  399. {
  400. free(v->u.string);
  401. free(v);
  402. }
  403. else if (YAJL_IS_NUMBER(v))
  404. {
  405. free(v->u.number.r);
  406. free(v);
  407. }
  408. else if (YAJL_GET_OBJECT(v))
  409. {
  410. yajl_object_free(v);
  411. }
  412. else if (YAJL_GET_ARRAY(v))
  413. {
  414. yajl_array_free(v);
  415. }
  416. else /* if (yajl_t_true or yajl_t_false or yajl_t_null) */
  417. {
  418. free(v);
  419. }
  420. }