You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

json_tokener.c 13 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. /*
  2. * $Id: json_tokener.c,v 1.20 2006/07/25 03:24:50 mclark Exp $
  3. *
  4. * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
  5. * Michael Clark <michael@metaparadigm.com>
  6. *
  7. * This library is free software; you can redistribute it and/or modify
  8. * it under the terms of the MIT license. See COPYING for details.
  9. *
  10. */
  11. #include "config.h"
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <stddef.h>
  15. #include <ctype.h>
  16. #include <string.h>
  17. #include "bits.h"
  18. #include "debug.h"
  19. #include "printbuf.h"
  20. #include "arraylist.h"
  21. #include "json_object.h"
  22. #include "json_tokener.h"
  23. #if !HAVE_STRNCASECMP && defined(_MSC_VER)
  24. /* MSC has the version as _strnicmp */
  25. # define strncasecmp _strnicmp
  26. #elif !HAVE_STRNCASECMP
  27. # error You do not have strncasecmp on your system.
  28. #endif /* HAVE_STRNCASECMP */
  29. static const char* json_null_str = "null";
  30. static const char* json_true_str = "true";
  31. static const char* json_false_str = "false";
  32. const char* json_tokener_errors[] = {
  33. "success",
  34. "continue",
  35. "nesting to deep",
  36. "unexpected end of data",
  37. "unexpected character",
  38. "null expected",
  39. "boolean expected",
  40. "number expected",
  41. "array value separator ',' expected",
  42. "quoted object property name expected",
  43. "object property name separator ':' expected",
  44. "object value separator ',' expected",
  45. "invalid string sequence",
  46. "expected comment",
  47. };
  48. struct json_tokener* json_tokener_new()
  49. {
  50. struct json_tokener *tok = calloc(1, sizeof(struct json_tokener));
  51. tok->pb = printbuf_new();
  52. json_tokener_reset(tok);
  53. return tok;
  54. }
  55. void json_tokener_free(struct json_tokener *tok)
  56. {
  57. json_tokener_reset(tok);
  58. if(tok) printbuf_free(tok->pb);
  59. free(tok);
  60. }
  61. static void json_tokener_reset_level(struct json_tokener *tok, int depth)
  62. {
  63. tok->stack[depth].state = json_tokener_state_eatws;
  64. tok->stack[depth].saved_state = json_tokener_state_start;
  65. json_object_put(tok->stack[depth].current);
  66. tok->stack[depth].current = NULL;
  67. free(tok->stack[depth].obj_field_name);
  68. tok->stack[depth].obj_field_name = NULL;
  69. }
  70. void json_tokener_reset(struct json_tokener *tok)
  71. {
  72. int i;
  73. for(i = tok->depth; i >= 0; i--)
  74. json_tokener_reset_level(tok, i);
  75. tok->depth = 0;
  76. tok->err = json_tokener_success;
  77. }
  78. struct json_object* json_tokener_parse(char *str)
  79. {
  80. struct json_tokener* tok;
  81. struct json_object* obj;
  82. tok = json_tokener_new();
  83. obj = json_tokener_parse_ex(tok, str, -1);
  84. if(tok->err != json_tokener_success)
  85. obj = error_ptr(-tok->err);
  86. json_tokener_free(tok);
  87. return obj;
  88. }
  89. #if !HAVE_STRNDUP
  90. /* CAW: compliant version of strndup() */
  91. char* strndup(const char* str, size_t n)
  92. {
  93. if(str) {
  94. size_t len = strlen(str);
  95. size_t nn = min(len,n);
  96. char* s = (char*)malloc(sizeof(char) * (nn + 1));
  97. if(s) {
  98. memcpy(s, str, nn);
  99. s[nn] = '\0';
  100. }
  101. return s;
  102. }
  103. return NULL;
  104. }
  105. #endif
  106. #define state tok->stack[tok->depth].state
  107. #define saved_state tok->stack[tok->depth].saved_state
  108. #define current tok->stack[tok->depth].current
  109. #define obj_field_name tok->stack[tok->depth].obj_field_name
  110. struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
  111. char *str, int len)
  112. {
  113. struct json_object *obj = NULL;
  114. char c;
  115. tok->char_offset = 0;
  116. tok->err = json_tokener_success;
  117. do {
  118. if(tok->char_offset == len) {
  119. if(tok->depth == 0 && state == json_tokener_state_eatws &&
  120. saved_state == json_tokener_state_finish)
  121. tok->err = json_tokener_success;
  122. else
  123. tok->err = json_tokener_continue;
  124. goto out;
  125. }
  126. c = *str;
  127. redo_char:
  128. switch(state) {
  129. case json_tokener_state_eatws:
  130. if(isspace(c)) {
  131. /* okay */
  132. } else if(c == '/') {
  133. printbuf_reset(tok->pb);
  134. printbuf_memappend(tok->pb, &c, 1);
  135. state = json_tokener_state_comment_start;
  136. } else {
  137. state = saved_state;
  138. goto redo_char;
  139. }
  140. break;
  141. case json_tokener_state_start:
  142. switch(c) {
  143. case '{':
  144. state = json_tokener_state_eatws;
  145. saved_state = json_tokener_state_object_field_start;
  146. current = json_object_new_object();
  147. break;
  148. case '[':
  149. state = json_tokener_state_eatws;
  150. saved_state = json_tokener_state_array;
  151. current = json_object_new_array();
  152. break;
  153. case 'N':
  154. case 'n':
  155. state = json_tokener_state_null;
  156. printbuf_reset(tok->pb);
  157. tok->st_pos = 0;
  158. goto redo_char;
  159. case '"':
  160. case '\'':
  161. state = json_tokener_state_string;
  162. printbuf_reset(tok->pb);
  163. tok->quote_char = c;
  164. break;
  165. case 'T':
  166. case 't':
  167. case 'F':
  168. case 'f':
  169. state = json_tokener_state_boolean;
  170. printbuf_reset(tok->pb);
  171. tok->st_pos = 0;
  172. goto redo_char;
  173. #if defined(__GNUC__)
  174. case '0' ... '9':
  175. #else
  176. case '0':
  177. case '1':
  178. case '2':
  179. case '3':
  180. case '4':
  181. case '5':
  182. case '6':
  183. case '7':
  184. case '8':
  185. case '9':
  186. #endif
  187. case '-':
  188. state = json_tokener_state_number;
  189. printbuf_reset(tok->pb);
  190. tok->is_double = 0;
  191. goto redo_char;
  192. default:
  193. tok->err = json_tokener_error_parse_unexpected;
  194. goto out;
  195. }
  196. break;
  197. case json_tokener_state_finish:
  198. if(tok->depth == 0) goto out;
  199. obj = json_object_get(current);
  200. json_tokener_reset_level(tok, tok->depth);
  201. tok->depth--;
  202. goto redo_char;
  203. case json_tokener_state_null:
  204. printbuf_memappend(tok->pb, &c, 1);
  205. if(strncasecmp(json_null_str, tok->pb->buf,
  206. min(tok->st_pos+1, strlen(json_null_str))) == 0) {
  207. if(tok->st_pos == strlen(json_null_str)) {
  208. current = NULL;
  209. saved_state = json_tokener_state_finish;
  210. state = json_tokener_state_eatws;
  211. goto redo_char;
  212. }
  213. } else {
  214. tok->err = json_tokener_error_parse_null;
  215. goto out;
  216. }
  217. tok->st_pos++;
  218. break;
  219. case json_tokener_state_comment_start:
  220. if(c == '*') {
  221. state = json_tokener_state_comment;
  222. } else if(c == '/') {
  223. state = json_tokener_state_comment_eol;
  224. } else {
  225. tok->err = json_tokener_error_parse_comment;
  226. goto out;
  227. }
  228. printbuf_memappend(tok->pb, &c, 1);
  229. break;
  230. case json_tokener_state_comment:
  231. if(c == '*') state = json_tokener_state_comment_end;
  232. printbuf_memappend(tok->pb, &c, 1);
  233. break;
  234. case json_tokener_state_comment_eol:
  235. if(c == '\n') {
  236. MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
  237. state = json_tokener_state_eatws;
  238. } else {
  239. printbuf_memappend(tok->pb, &c, 1);
  240. }
  241. break;
  242. case json_tokener_state_comment_end:
  243. printbuf_memappend(tok->pb, &c, 1);
  244. if(c == '/') {
  245. MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
  246. state = json_tokener_state_eatws;
  247. } else {
  248. state = json_tokener_state_comment;
  249. }
  250. break;
  251. case json_tokener_state_string:
  252. if(c == tok->quote_char) {
  253. current = json_object_new_string(tok->pb->buf);
  254. saved_state = json_tokener_state_finish;
  255. state = json_tokener_state_eatws;
  256. } else if(c == '\\') {
  257. saved_state = json_tokener_state_string;
  258. state = json_tokener_state_string_escape;
  259. } else {
  260. printbuf_memappend(tok->pb, &c, 1);
  261. }
  262. break;
  263. case json_tokener_state_string_escape:
  264. switch(c) {
  265. case '"':
  266. case '\\':
  267. case '/':
  268. printbuf_memappend(tok->pb, &c, 1);
  269. state = saved_state;
  270. break;
  271. case 'b':
  272. case 'n':
  273. case 'r':
  274. case 't':
  275. if(c == 'b') printbuf_memappend(tok->pb, "\b", 1);
  276. else if(c == 'n') printbuf_memappend(tok->pb, "\n", 1);
  277. else if(c == 'r') printbuf_memappend(tok->pb, "\r", 1);
  278. else if(c == 't') printbuf_memappend(tok->pb, "\t", 1);
  279. state = saved_state;
  280. break;
  281. case 'u':
  282. tok->ucs_char = 0;
  283. tok->st_pos = 0;
  284. state = json_tokener_state_escape_unicode;
  285. break;
  286. default:
  287. tok->err = json_tokener_error_parse_string;
  288. goto out;
  289. }
  290. break;
  291. case json_tokener_state_escape_unicode:
  292. if(strchr(json_hex_chars, c)) {
  293. tok->ucs_char += ((unsigned int)hexdigit(c) << ((3-tok->st_pos++)*4));
  294. if(tok->st_pos == 4) {
  295. unsigned char utf_out[3];
  296. if (tok->ucs_char < 0x80) {
  297. utf_out[0] = tok->ucs_char;
  298. printbuf_memappend(tok->pb, (char*)utf_out, 1);
  299. } else if (tok->ucs_char < 0x800) {
  300. utf_out[0] = 0xc0 | (tok->ucs_char >> 6);
  301. utf_out[1] = 0x80 | (tok->ucs_char & 0x3f);
  302. printbuf_memappend(tok->pb, (char*)utf_out, 2);
  303. } else {
  304. utf_out[0] = 0xe0 | (tok->ucs_char >> 12);
  305. utf_out[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
  306. utf_out[2] = 0x80 | (tok->ucs_char & 0x3f);
  307. printbuf_memappend(tok->pb, (char*)utf_out, 3);
  308. }
  309. state = saved_state;
  310. }
  311. } else {
  312. tok->err = json_tokener_error_parse_string;
  313. goto out;
  314. }
  315. break;
  316. case json_tokener_state_boolean:
  317. printbuf_memappend(tok->pb, &c, 1);
  318. if(strncasecmp(json_true_str, tok->pb->buf,
  319. min(tok->st_pos+1, strlen(json_true_str))) == 0) {
  320. if(tok->st_pos == strlen(json_true_str)) {
  321. current = json_object_new_boolean(1);
  322. saved_state = json_tokener_state_finish;
  323. state = json_tokener_state_eatws;
  324. goto redo_char;
  325. }
  326. } else if(strncasecmp(json_false_str, tok->pb->buf,
  327. min(tok->st_pos+1, strlen(json_false_str))) == 0) {
  328. if(tok->st_pos == strlen(json_false_str)) {
  329. current = json_object_new_boolean(0);
  330. saved_state = json_tokener_state_finish;
  331. state = json_tokener_state_eatws;
  332. goto redo_char;
  333. }
  334. } else {
  335. tok->err = json_tokener_error_parse_boolean;
  336. goto out;
  337. }
  338. tok->st_pos++;
  339. break;
  340. case json_tokener_state_number:
  341. if(c && strchr(json_number_chars, c)) {
  342. printbuf_memappend(tok->pb, &c, 1);
  343. if(c == '.' || c == 'e' || c == 'E') tok->is_double = 1;
  344. } else {
  345. int numi;
  346. double numd;
  347. if(!tok->is_double && sscanf(tok->pb->buf, "%d", &numi) == 1) {
  348. current = json_object_new_int(numi);
  349. } else if(tok->is_double && sscanf(tok->pb->buf, "%lf", &numd) == 1) {
  350. current = json_object_new_double(numd);
  351. } else {
  352. tok->err = json_tokener_error_parse_number;
  353. goto out;
  354. }
  355. saved_state = json_tokener_state_finish;
  356. state = json_tokener_state_eatws;
  357. goto redo_char;
  358. }
  359. break;
  360. case json_tokener_state_array:
  361. if(c == ']') {
  362. saved_state = json_tokener_state_finish;
  363. state = json_tokener_state_eatws;
  364. } else {
  365. if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) {
  366. tok->err = json_tokener_error_depth;
  367. goto out;
  368. }
  369. state = json_tokener_state_array_add;
  370. tok->depth++;
  371. json_tokener_reset_level(tok, tok->depth);
  372. goto redo_char;
  373. }
  374. break;
  375. case json_tokener_state_array_add:
  376. json_object_array_add(current, obj);
  377. saved_state = json_tokener_state_array_sep;
  378. state = json_tokener_state_eatws;
  379. goto redo_char;
  380. case json_tokener_state_array_sep:
  381. if(c == ']') {
  382. saved_state = json_tokener_state_finish;
  383. state = json_tokener_state_eatws;
  384. } else if(c == ',') {
  385. saved_state = json_tokener_state_array;
  386. state = json_tokener_state_eatws;
  387. } else {
  388. tok->err = json_tokener_error_parse_array;
  389. goto out;
  390. }
  391. break;
  392. case json_tokener_state_object_field_start:
  393. if(c == '}') {
  394. saved_state = json_tokener_state_finish;
  395. state = json_tokener_state_eatws;
  396. } else if (c == '"' || c == '\'') {
  397. tok->quote_char = c;
  398. printbuf_reset(tok->pb);
  399. state = json_tokener_state_object_field;
  400. } else {
  401. tok->err = json_tokener_error_parse_object_key_name;
  402. goto out;
  403. }
  404. break;
  405. case json_tokener_state_object_field:
  406. if(c == tok->quote_char) {
  407. obj_field_name = strdup(tok->pb->buf);
  408. saved_state = json_tokener_state_object_field_end;
  409. state = json_tokener_state_eatws;
  410. } else if(c == '\\') {
  411. saved_state = json_tokener_state_object_field;
  412. state = json_tokener_state_string_escape;
  413. } else {
  414. printbuf_memappend(tok->pb, &c, 1);
  415. }
  416. break;
  417. case json_tokener_state_object_field_end:
  418. if(c == ':') {
  419. saved_state = json_tokener_state_object_value;
  420. state = json_tokener_state_eatws;
  421. } else {
  422. tok->err = json_tokener_error_parse_object_key_sep;
  423. goto out;
  424. }
  425. break;
  426. case json_tokener_state_object_value:
  427. if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) {
  428. tok->err = json_tokener_error_depth;
  429. goto out;
  430. }
  431. state = json_tokener_state_object_value_add;
  432. tok->depth++;
  433. json_tokener_reset_level(tok, tok->depth);
  434. goto redo_char;
  435. case json_tokener_state_object_value_add:
  436. json_object_object_add(current, obj_field_name, obj);
  437. free(obj_field_name);
  438. obj_field_name = NULL;
  439. saved_state = json_tokener_state_object_sep;
  440. state = json_tokener_state_eatws;
  441. goto redo_char;
  442. case json_tokener_state_object_sep:
  443. if(c == '}') {
  444. saved_state = json_tokener_state_finish;
  445. state = json_tokener_state_eatws;
  446. } else if(c == ',') {
  447. saved_state = json_tokener_state_object_field_start;
  448. state = json_tokener_state_eatws;
  449. } else {
  450. tok->err = json_tokener_error_parse_object_value_sep;
  451. goto out;
  452. }
  453. break;
  454. }
  455. str++;
  456. tok->char_offset++;
  457. } while(c);
  458. if(state != json_tokener_state_finish &&
  459. saved_state != json_tokener_state_finish)
  460. tok->err = json_tokener_error_parse_eof;
  461. out:
  462. if(tok->err == json_tokener_success) return json_object_get(current);
  463. MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n",
  464. json_tokener_errors[tok->err], tok->char_offset);
  465. return NULL;
  466. }

No Description

Contributors (1)