dump.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. /*
  2. * Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org>
  3. *
  4. * Jansson is free software; you can redistribute it and/or modify
  5. * it under the terms of the MIT license. See LICENSE for details.
  6. */
  7. #define _GNU_SOURCE
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <assert.h>
  12. #include "jansson.h"
  13. #include "jansson_private.h"
  14. #include "strbuffer.h"
  15. #include "utf.h"
  16. #define MAX_INTEGER_STR_LENGTH 100
  17. #define MAX_REAL_STR_LENGTH 100
  18. struct object_key {
  19. size_t serial;
  20. const char *key;
  21. };
  22. static int dump_to_strbuffer(const char *buffer, size_t size, void *data)
  23. {
  24. return strbuffer_append_bytes((strbuffer_t *)data, buffer, size);
  25. }
  26. static int dump_to_file(const char *buffer, size_t size, void *data)
  27. {
  28. FILE *dest = (FILE *)data;
  29. if(fwrite(buffer, size, 1, dest) != 1)
  30. return -1;
  31. return 0;
  32. }
  33. /* 32 spaces (the maximum indentation size) */
  34. static char whitespace[] = " ";
  35. static int dump_indent(size_t flags, int depth, int space, json_dump_callback_t dump, void *data)
  36. {
  37. if(JSON_INDENT(flags) > 0)
  38. {
  39. int i, ws_count = JSON_INDENT(flags);
  40. if(dump("\n", 1, data))
  41. return -1;
  42. for(i = 0; i < depth; i++)
  43. {
  44. if(dump(whitespace, ws_count, data))
  45. return -1;
  46. }
  47. }
  48. else if(space && !(flags & JSON_COMPACT))
  49. {
  50. return dump(" ", 1, data);
  51. }
  52. return 0;
  53. }
  54. static int dump_string(const char *str, json_dump_callback_t dump, void *data, size_t flags)
  55. {
  56. const char *pos, *end;
  57. int32_t codepoint;
  58. if(dump("\"", 1, data))
  59. return -1;
  60. end = pos = str;
  61. while(1)
  62. {
  63. const char *text;
  64. char seq[13];
  65. int length;
  66. while(*end)
  67. {
  68. end = utf8_iterate(pos, &codepoint);
  69. if(!end)
  70. return -1;
  71. /* mandatory escape or control char */
  72. if(codepoint == '\\' || codepoint == '"' || codepoint < 0x20)
  73. break;
  74. /* slash */
  75. if((flags & JSON_ESCAPE_SLASH) && codepoint == '/')
  76. break;
  77. /* non-ASCII */
  78. if((flags & JSON_ENSURE_ASCII) && codepoint > 0x7F)
  79. break;
  80. pos = end;
  81. }
  82. if(pos != str) {
  83. if(dump(str, pos - str, data))
  84. return -1;
  85. }
  86. if(end == pos)
  87. break;
  88. /* handle \, /, ", and control codes */
  89. length = 2;
  90. switch(codepoint)
  91. {
  92. case '\\': text = "\\\\"; break;
  93. case '\"': text = "\\\""; break;
  94. case '\b': text = "\\b"; break;
  95. case '\f': text = "\\f"; break;
  96. case '\n': text = "\\n"; break;
  97. case '\r': text = "\\r"; break;
  98. case '\t': text = "\\t"; break;
  99. case '/': text = "\\/"; break;
  100. default:
  101. {
  102. /* codepoint is in BMP */
  103. if(codepoint < 0x10000)
  104. {
  105. sprintf(seq, "\\u%04x", codepoint);
  106. length = 6;
  107. }
  108. /* not in BMP -> construct a UTF-16 surrogate pair */
  109. else
  110. {
  111. int32_t first, last;
  112. codepoint -= 0x10000;
  113. first = 0xD800 | ((codepoint & 0xffc00) >> 10);
  114. last = 0xDC00 | (codepoint & 0x003ff);
  115. sprintf(seq, "\\u%04x\\u%04x", first, last);
  116. length = 12;
  117. }
  118. text = seq;
  119. break;
  120. }
  121. }
  122. if(dump(text, length, data))
  123. return -1;
  124. str = pos = end;
  125. }
  126. return dump("\"", 1, data);
  127. }
  128. static int object_key_compare_keys(const void *key1, const void *key2)
  129. {
  130. return strcmp(((const struct object_key *)key1)->key,
  131. ((const struct object_key *)key2)->key);
  132. }
  133. static int object_key_compare_serials(const void *key1, const void *key2)
  134. {
  135. size_t a = ((const struct object_key *)key1)->serial;
  136. size_t b = ((const struct object_key *)key2)->serial;
  137. return a < b ? -1 : a == b ? 0 : 1;
  138. }
  139. static int do_dump(const json_t *json, size_t flags, int depth,
  140. json_dump_callback_t dump, void *data)
  141. {
  142. switch(json_typeof(json)) {
  143. case JSON_NULL:
  144. return dump("null", 4, data);
  145. case JSON_TRUE:
  146. return dump("true", 4, data);
  147. case JSON_FALSE:
  148. return dump("false", 5, data);
  149. case JSON_INTEGER:
  150. {
  151. char buffer[MAX_INTEGER_STR_LENGTH];
  152. int size;
  153. size = snprintf(buffer, MAX_INTEGER_STR_LENGTH,
  154. "%" JSON_INTEGER_FORMAT,
  155. json_integer_value(json));
  156. if(size < 0 || size >= MAX_INTEGER_STR_LENGTH)
  157. return -1;
  158. return dump(buffer, size, data);
  159. }
  160. case JSON_REAL:
  161. {
  162. char buffer[MAX_REAL_STR_LENGTH];
  163. int size;
  164. double value = json_real_value(json);
  165. size = jsonp_dtostr(buffer, MAX_REAL_STR_LENGTH, value);
  166. if(size < 0)
  167. return -1;
  168. return dump(buffer, size, data);
  169. }
  170. case JSON_STRING:
  171. return dump_string(json_string_value(json), dump, data, flags);
  172. case JSON_ARRAY:
  173. {
  174. int i;
  175. int n;
  176. json_array_t *array;
  177. /* detect circular references */
  178. array = json_to_array(json);
  179. if(array->visited)
  180. goto array_error;
  181. array->visited = 1;
  182. n = json_array_size(json);
  183. if(dump("[", 1, data))
  184. goto array_error;
  185. if(n == 0) {
  186. array->visited = 0;
  187. return dump("]", 1, data);
  188. }
  189. if(dump_indent(flags, depth + 1, 0, dump, data))
  190. goto array_error;
  191. for(i = 0; i < n; ++i) {
  192. if(do_dump(json_array_get(json, i), flags, depth + 1,
  193. dump, data))
  194. goto array_error;
  195. if(i < n - 1)
  196. {
  197. if(dump(",", 1, data) ||
  198. dump_indent(flags, depth + 1, 1, dump, data))
  199. goto array_error;
  200. }
  201. else
  202. {
  203. if(dump_indent(flags, depth, 0, dump, data))
  204. goto array_error;
  205. }
  206. }
  207. array->visited = 0;
  208. return dump("]", 1, data);
  209. array_error:
  210. array->visited = 0;
  211. return -1;
  212. }
  213. case JSON_OBJECT:
  214. {
  215. json_object_t *object;
  216. void *iter;
  217. const char *separator;
  218. int separator_length;
  219. if(flags & JSON_COMPACT) {
  220. separator = ":";
  221. separator_length = 1;
  222. }
  223. else {
  224. separator = ": ";
  225. separator_length = 2;
  226. }
  227. /* detect circular references */
  228. object = json_to_object(json);
  229. if(object->visited)
  230. goto object_error;
  231. object->visited = 1;
  232. iter = json_object_iter((json_t *)json);
  233. if(dump("{", 1, data))
  234. goto object_error;
  235. if(!iter) {
  236. object->visited = 0;
  237. return dump("}", 1, data);
  238. }
  239. if(dump_indent(flags, depth + 1, 0, dump, data))
  240. goto object_error;
  241. if(flags & JSON_SORT_KEYS || flags & JSON_PRESERVE_ORDER)
  242. {
  243. struct object_key *keys;
  244. size_t size, i;
  245. int (*cmp_func)(const void *, const void *);
  246. size = json_object_size(json);
  247. keys = jsonp_malloc(size * sizeof(struct object_key));
  248. if(!keys)
  249. goto object_error;
  250. i = 0;
  251. while(iter)
  252. {
  253. keys[i].serial = hashtable_iter_serial(iter);
  254. keys[i].key = json_object_iter_key(iter);
  255. iter = json_object_iter_next((json_t *)json, iter);
  256. i++;
  257. }
  258. assert(i == size);
  259. if(flags & JSON_SORT_KEYS)
  260. cmp_func = object_key_compare_keys;
  261. else
  262. cmp_func = object_key_compare_serials;
  263. qsort(keys, size, sizeof(struct object_key), cmp_func);
  264. for(i = 0; i < size; i++)
  265. {
  266. const char *key;
  267. json_t *value;
  268. key = keys[i].key;
  269. value = json_object_get(json, key);
  270. assert(value);
  271. dump_string(key, dump, data, flags);
  272. if(dump(separator, separator_length, data) ||
  273. do_dump(value, flags, depth + 1, dump, data))
  274. {
  275. jsonp_free(keys);
  276. goto object_error;
  277. }
  278. if(i < size - 1)
  279. {
  280. if(dump(",", 1, data) ||
  281. dump_indent(flags, depth + 1, 1, dump, data))
  282. {
  283. jsonp_free(keys);
  284. goto object_error;
  285. }
  286. }
  287. else
  288. {
  289. if(dump_indent(flags, depth, 0, dump, data))
  290. {
  291. jsonp_free(keys);
  292. goto object_error;
  293. }
  294. }
  295. }
  296. jsonp_free(keys);
  297. }
  298. else
  299. {
  300. /* Don't sort keys */
  301. while(iter)
  302. {
  303. void *next = json_object_iter_next((json_t *)json, iter);
  304. dump_string(json_object_iter_key(iter), dump, data, flags);
  305. if(dump(separator, separator_length, data) ||
  306. do_dump(json_object_iter_value(iter), flags, depth + 1,
  307. dump, data))
  308. goto object_error;
  309. if(next)
  310. {
  311. if(dump(",", 1, data) ||
  312. dump_indent(flags, depth + 1, 1, dump, data))
  313. goto object_error;
  314. }
  315. else
  316. {
  317. if(dump_indent(flags, depth, 0, dump, data))
  318. goto object_error;
  319. }
  320. iter = next;
  321. }
  322. }
  323. object->visited = 0;
  324. return dump("}", 1, data);
  325. object_error:
  326. object->visited = 0;
  327. return -1;
  328. }
  329. default:
  330. /* not reached */
  331. return -1;
  332. }
  333. }
  334. char *json_dumps(const json_t *json, size_t flags)
  335. {
  336. strbuffer_t strbuff;
  337. char *result;
  338. if(strbuffer_init(&strbuff))
  339. return NULL;
  340. if(json_dump_callback(json, dump_to_strbuffer, (void *)&strbuff, flags))
  341. result = NULL;
  342. else
  343. result = jsonp_strdup(strbuffer_value(&strbuff));
  344. strbuffer_close(&strbuff);
  345. return result;
  346. }
  347. int json_dumpf(const json_t *json, FILE *output, size_t flags)
  348. {
  349. return json_dump_callback(json, dump_to_file, (void *)output, flags);
  350. }
  351. int json_dump_file(const json_t *json, const char *path, size_t flags)
  352. {
  353. int result;
  354. FILE *output = fopen(path, "w");
  355. if(!output)
  356. return -1;
  357. result = json_dumpf(json, output, flags);
  358. fclose(output);
  359. return result;
  360. }
  361. int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags)
  362. {
  363. if(!(flags & JSON_ENCODE_ANY)) {
  364. if(!json_is_array(json) && !json_is_object(json))
  365. return -1;
  366. }
  367. return do_dump(json, flags, 0, callback, data);
  368. }