JSONPreparse.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. /*
  2. * JSONPreparse.cpp
  3. * TestSuite
  4. *
  5. * Created by Wallace on 4/13/11.
  6. * Copyright 2011 Streamwide. All rights reserved.
  7. *
  8. */
  9. #include "JSONPreparse.h"
  10. #if (defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY))
  11. #ifdef JSON_COMMENTS
  12. json_string extractComment(json_string::const_iterator & ptr, json_string::const_iterator & end);
  13. json_string extractComment(json_string::const_iterator & ptr, json_string::const_iterator & end){
  14. json_string::const_iterator start;
  15. json_string result;
  16. looplabel:
  17. if (json_unlikely(((ptr != end) && (*ptr == JSON_TEMP_COMMENT_IDENTIFIER)))){
  18. start = ++ptr;
  19. for(; (ptr != end) && (*(ptr) != JSON_TEMP_COMMENT_IDENTIFIER); ++ptr){}
  20. result += json_string(start, ptr);
  21. if (json_unlikely(ptr == end)) return result;
  22. ++ptr;
  23. if (json_unlikely(((ptr != end) && (*ptr == JSON_TEMP_COMMENT_IDENTIFIER)))){
  24. result += JSON_TEXT('\n');
  25. goto looplabel;
  26. }
  27. }
  28. return result;
  29. }
  30. #define GET_COMMENT(x, y, name) json_string name = extractComment(x, y)
  31. #define RETURN_NODE(node, name){\
  32. JSONNode res = node;\
  33. res.set_comment(name);\
  34. return res;\
  35. }
  36. #define RETURN_NODE_NOCOPY(node, name){\
  37. node.set_comment(name);\
  38. return node;\
  39. }
  40. #define SET_COMMENT(node, name) node.set_comment(name)
  41. #define COMMENT_ARG(name) ,name
  42. #else
  43. #define GET_COMMENT(x, y, name) (void)0
  44. #define RETURN_NODE(node, name) return node
  45. #define RETURN_NODE_NOCOPY(node, name) return node
  46. #define SET_COMMENT(node, name) (void)0
  47. #define COMMENT_ARG(name)
  48. #endif
  49. inline bool isHex(json_char c) json_pure;
  50. inline bool isHex(json_char c) json_nothrow {
  51. return (((c >= JSON_TEXT('0')) && (c <= JSON_TEXT('9'))) ||
  52. ((c >= JSON_TEXT('A')) && (c <= JSON_TEXT('F'))) ||
  53. ((c >= JSON_TEXT('a')) && (c <= JSON_TEXT('f'))));
  54. }
  55. #ifdef JSON_STRICT
  56. #include "NumberToString.h"
  57. #endif
  58. json_number FetchNumber(const json_string & _string) json_nothrow;
  59. json_number FetchNumber(const json_string & _string) json_nothrow {
  60. #ifdef JSON_STRICT
  61. return NumberToString::_atof(_string.c_str());
  62. #else
  63. #ifdef JSON_UNICODE
  64. const size_t len = _string.length();
  65. #if defined(_MSC_VER) && defined(JSON_SAFE)
  66. const size_t bytes = (len * (sizeof(json_char) / sizeof(char))) + 1;
  67. json_auto<char> temp(bytes);
  68. size_t res;
  69. errno_t err = std::wcstombs_s(&res, temp.ptr, bytes, _string.c_str(), len);
  70. if (err != 0){
  71. return (json_number)0.0;
  72. }
  73. #elif defined(JSON_SAFE)
  74. const size_t bytes = (len * (sizeof(json_char) / sizeof(char))) + 1;
  75. json_auto<char> temp(bytes);
  76. size_t res = std::wcstombs(temp.ptr, _string.c_str(), len);
  77. if (res == (size_t)-1){ //-1 is error code for this function
  78. return (json_number)0.0;
  79. }
  80. #else
  81. json_auto<char> temp(len + 1);
  82. size_t res = std::wcstombs(temp.ptr, _string.c_str(), len);
  83. #endif
  84. temp.ptr[res] = JSON_TEXT('\0');
  85. return (json_number)std::atof(temp.ptr);
  86. #else
  87. return (json_number)std::atof(_string.c_str());
  88. #endif
  89. #endif
  90. }
  91. JSONNode JSONPreparse::isValidNumber(json_string::const_iterator & ptr, json_string::const_iterator & end){
  92. //ptr points at the first character in the number
  93. //ptr will end up past the last character
  94. json_string::const_iterator start = ptr;
  95. bool decimal = false;
  96. bool scientific = false;
  97. //first letter is weird
  98. switch(*ptr){
  99. #ifndef JSON_STRICT
  100. case JSON_TEXT('.'):
  101. decimal = true;
  102. break;
  103. case JSON_TEXT('+'):
  104. #endif
  105. case JSON_TEXT('-'):
  106. case JSON_TEXT('1'):
  107. case JSON_TEXT('2'):
  108. case JSON_TEXT('3'):
  109. case JSON_TEXT('4'):
  110. case JSON_TEXT('5'):
  111. case JSON_TEXT('6'):
  112. case JSON_TEXT('7'):
  113. case JSON_TEXT('8'):
  114. case JSON_TEXT('9'):
  115. break;
  116. case JSON_TEXT('0'):
  117. ++ptr;
  118. switch(*ptr){
  119. case JSON_TEXT('.'):
  120. decimal = true;
  121. break;
  122. case JSON_TEXT('e'):
  123. case JSON_TEXT('E'):
  124. scientific = true;
  125. ++ptr;
  126. if (ptr == end) throw false;
  127. switch(*ptr){
  128. case JSON_TEXT('-'):
  129. case JSON_TEXT('+'):
  130. case JSON_TEXT('0'):
  131. case JSON_TEXT('1'):
  132. case JSON_TEXT('2'):
  133. case JSON_TEXT('3'):
  134. case JSON_TEXT('4'):
  135. case JSON_TEXT('5'):
  136. case JSON_TEXT('6'):
  137. case JSON_TEXT('7'):
  138. case JSON_TEXT('8'):
  139. case JSON_TEXT('9'):
  140. break;
  141. default:
  142. throw false;
  143. }
  144. break;
  145. #ifndef JSON_STRICT
  146. case JSON_TEXT('x'):
  147. while(isHex(*++ptr)){};
  148. return JSONNode(json_global(EMPTY_JSON_STRING), FetchNumber(json_string(start, end - 1)));
  149. #ifdef JSON_OCTAL
  150. #ifdef __GNUC__
  151. case JSON_TEXT('0') ... JSON_TEXT('7'): //octal
  152. #else
  153. case JSON_TEXT('0'):
  154. case JSON_TEXT('1'):
  155. case JSON_TEXT('2'):
  156. case JSON_TEXT('3'):
  157. case JSON_TEXT('4'):
  158. case JSON_TEXT('5'):
  159. case JSON_TEXT('6'):
  160. case JSON_TEXT('7'):
  161. #endif
  162. while((*++ptr >= JSON_TEXT('0')) && (*ptr <= JSON_TEXT('7'))){};
  163. if ((*ptr != JSON_TEXT('8')) && (*ptr != JSON_TEXT('9'))){
  164. return JSONNode(json_global(EMPTY_JSON_STRING), FetchNumber(json_string(start, ptr - 1)));
  165. }
  166. throw false;
  167. case JSON_TEXT('8'):
  168. case JSON_TEXT('9'):
  169. break;
  170. #else
  171. #ifdef __GNUC__
  172. case JSON_TEXT('0') ... JSON_TEXT('9'):
  173. #else
  174. case JSON_TEXT('0'):
  175. case JSON_TEXT('1'):
  176. case JSON_TEXT('2'):
  177. case JSON_TEXT('3'):
  178. case JSON_TEXT('4'):
  179. case JSON_TEXT('5'):
  180. case JSON_TEXT('6'):
  181. case JSON_TEXT('7'):
  182. case JSON_TEXT('8'):
  183. case JSON_TEXT('9'):
  184. #endif
  185. break;
  186. #endif
  187. #else
  188. #ifdef __GNUC__
  189. case JSON_TEXT('0') ... JSON_TEXT('9'):
  190. #else
  191. case JSON_TEXT('0'):
  192. case JSON_TEXT('1'):
  193. case JSON_TEXT('2'):
  194. case JSON_TEXT('3'):
  195. case JSON_TEXT('4'):
  196. case JSON_TEXT('5'):
  197. case JSON_TEXT('6'):
  198. case JSON_TEXT('7'):
  199. case JSON_TEXT('8'):
  200. case JSON_TEXT('9'):
  201. #endif
  202. break;
  203. #endif
  204. default: //just a 0
  205. return JSONNode(json_global(EMPTY_JSON_STRING), FetchNumber(json_string(start, ptr - 1)));;
  206. }
  207. break;
  208. default:
  209. throw false;
  210. }
  211. ++ptr;
  212. //next digits
  213. while (true){
  214. switch(*ptr){
  215. case JSON_TEXT('.'):
  216. if (json_unlikely(decimal)) throw false; //multiple decimals
  217. if (json_unlikely(scientific)) throw false;
  218. decimal = true;
  219. break;
  220. case JSON_TEXT('e'):
  221. case JSON_TEXT('E'):
  222. if (json_likely(scientific)) throw false;
  223. scientific = true;
  224. ++ptr;
  225. switch(*ptr){
  226. case JSON_TEXT('-'):
  227. case JSON_TEXT('+'):
  228. #ifdef __GNUC__
  229. case JSON_TEXT('0') ... JSON_TEXT('9'):
  230. #else
  231. case JSON_TEXT('0'):
  232. case JSON_TEXT('1'):
  233. case JSON_TEXT('2'):
  234. case JSON_TEXT('3'):
  235. case JSON_TEXT('4'):
  236. case JSON_TEXT('5'):
  237. case JSON_TEXT('6'):
  238. case JSON_TEXT('7'):
  239. case JSON_TEXT('8'):
  240. case JSON_TEXT('9'):
  241. #endif
  242. break;
  243. default:
  244. throw false;
  245. }
  246. break;
  247. #ifdef __GNUC__
  248. case JSON_TEXT('0') ... JSON_TEXT('9'):
  249. #else
  250. case JSON_TEXT('0'):
  251. case JSON_TEXT('1'):
  252. case JSON_TEXT('2'):
  253. case JSON_TEXT('3'):
  254. case JSON_TEXT('4'):
  255. case JSON_TEXT('5'):
  256. case JSON_TEXT('6'):
  257. case JSON_TEXT('7'):
  258. case JSON_TEXT('8'):
  259. case JSON_TEXT('9'):
  260. #endif
  261. break;
  262. default:
  263. return JSONNode(json_global(EMPTY_JSON_STRING), FetchNumber(json_string(start, ptr)));;
  264. }
  265. ++ptr;
  266. }
  267. throw false;
  268. }
  269. #ifndef JSON_STRICT
  270. #define LETTERCASE(x, y)\
  271. case JSON_TEXT(x):\
  272. case JSON_TEXT(y)
  273. #define LETTERCHECK(x, y)\
  274. if (json_unlikely((*++ptr != JSON_TEXT(x)) && (*ptr != JSON_TEXT(y)))) throw false
  275. #else
  276. #define LETTERCASE(x, y)\
  277. case JSON_TEXT(x)
  278. #define LETTERCHECK(x, y)\
  279. if (json_unlikely(*++ptr != JSON_TEXT(x))) throw false
  280. #endif
  281. JSONNode JSONPreparse::isValidMember(json_string::const_iterator & ptr, json_string::const_iterator & end){
  282. //ptr is on the first character of the member
  283. //ptr will end up immediately after the last character in the member
  284. if (ptr == end) throw false;
  285. switch(*ptr){
  286. case JSON_TEXT('\"'):{
  287. return JSONNode::stringType(isValidString(++ptr, end));
  288. }
  289. case JSON_TEXT('{'):
  290. return isValidObject(++ptr, end);
  291. case JSON_TEXT('['):
  292. return isValidArray(++ptr, end);
  293. LETTERCASE('t', 'T'):
  294. LETTERCHECK('r', 'R');
  295. LETTERCHECK('u', 'U');
  296. LETTERCHECK('e', 'E');
  297. ++ptr;
  298. return JSONNode(json_global(EMPTY_JSON_STRING), true);
  299. LETTERCASE('f', 'F'):
  300. LETTERCHECK('a', 'A');
  301. LETTERCHECK('l', 'L');
  302. LETTERCHECK('s', 'S');
  303. LETTERCHECK('e', 'E');
  304. ++ptr;
  305. return JSONNode(json_global(EMPTY_JSON_STRING), false);
  306. LETTERCASE('n', 'N'):
  307. LETTERCHECK('u', 'U');
  308. LETTERCHECK('l', 'L');
  309. LETTERCHECK('l', 'L');
  310. ++ptr;
  311. return JSONNode(JSON_NULL);
  312. #ifndef JSON_STRICT
  313. case JSON_TEXT('}'): //null in libjson
  314. case JSON_TEXT(']'): //null in libjson
  315. case JSON_TEXT(','): //null in libjson
  316. return JSONNode(JSON_NULL);
  317. #endif
  318. }
  319. //a number
  320. return isValidNumber(ptr, end);
  321. }
  322. json_string JSONPreparse::isValidString(json_string::const_iterator & ptr, json_string::const_iterator & end){
  323. //ptr is pointing to the first character after the quote
  324. //ptr will end up behind the closing "
  325. json_string::const_iterator start = ptr;
  326. while(ptr != end){
  327. switch(*ptr){
  328. case JSON_TEXT('\\'):
  329. switch(*(++ptr)){
  330. case JSON_TEXT('\"'):
  331. case JSON_TEXT('\\'):
  332. case JSON_TEXT('/'):
  333. case JSON_TEXT('b'):
  334. case JSON_TEXT('f'):
  335. case JSON_TEXT('n'):
  336. case JSON_TEXT('r'):
  337. case JSON_TEXT('t'):
  338. break;
  339. case JSON_TEXT('u'):
  340. if (json_unlikely(!isHex(*++ptr))) throw false;
  341. if (json_unlikely(!isHex(*++ptr))) throw false;
  342. //fallthrough to \x
  343. #ifndef JSON_STRICT
  344. case JSON_TEXT('x'): //hex
  345. #endif
  346. if (json_unlikely(!isHex(*++ptr))) throw false;
  347. if (json_unlikely(!isHex(*++ptr))) throw false;
  348. break;
  349. #ifndef JSON_OCTAL
  350. #ifdef __GNUC__
  351. case JSON_TEXT('0') ... JSON_TEXT('7'): //octal
  352. #else
  353. case JSON_TEXT('0'):
  354. case JSON_TEXT('1'):
  355. case JSON_TEXT('2'):
  356. case JSON_TEXT('3'):
  357. case JSON_TEXT('4'):
  358. case JSON_TEXT('5'):
  359. case JSON_TEXT('6'):
  360. case JSON_TEXT('7'):
  361. #endif
  362. if (json_unlikely((*++ptr < JSON_TEXT('0')) || (*ptr > JSON_TEXT('7')))) throw false;
  363. if (json_unlikely((*++ptr < JSON_TEXT('0')) || (*ptr > JSON_TEXT('7')))) throw false;
  364. break;
  365. #endif
  366. default:
  367. throw false;
  368. }
  369. break;
  370. case JSON_TEXT('\"'):
  371. return json_string(start, ptr++);
  372. }
  373. ++ptr;
  374. }
  375. throw false;
  376. }
  377. void JSONPreparse::isValidNamedObject(json_string::const_iterator & ptr, json_string::const_iterator & end, JSONNode & parent COMMENT_PARAM(comment)) {
  378. //ptr should be right before the string name
  379. {
  380. json_string _name = isValidString(++ptr, end);
  381. if (json_unlikely(*ptr++ != JSON_TEXT(':'))) throw false;
  382. JSONNode res = isValidMember(ptr, end);
  383. res.set_name_(_name);
  384. SET_COMMENT(res, comment);
  385. #ifdef JSON_LIBRARY
  386. parent.push_back(&res);
  387. #else
  388. parent.push_back(res);
  389. #endif
  390. }
  391. if (ptr == end) throw false;
  392. switch(*ptr){
  393. case JSON_TEXT(','):
  394. ++ptr;
  395. {
  396. GET_COMMENT(ptr, end, nextcomment);
  397. isValidNamedObject(ptr, end, parent COMMENT_ARG(nextcomment)); //will handle all of them
  398. }
  399. return;
  400. case JSON_TEXT('}'):
  401. ++ptr;
  402. return;
  403. default:
  404. throw false;
  405. }
  406. }
  407. JSONNode JSONPreparse::isValidObject(json_string::const_iterator & ptr, json_string::const_iterator & end) {
  408. //ptr should currently be pointing past the {, so this must be the start of a name, or the closing }
  409. //ptr will end up past the last }
  410. JSONNode res(JSON_NODE);
  411. GET_COMMENT(ptr, end, comment);
  412. switch(*ptr){
  413. case JSON_TEXT('\"'):
  414. isValidNamedObject(ptr, end, res COMMENT_ARG(comment));
  415. return res;
  416. case JSON_TEXT('}'):
  417. ++ptr;
  418. return res;
  419. default:
  420. throw false;
  421. }
  422. }
  423. void pushArrayMember(JSONNode & res, json_string::const_iterator & ptr, json_string::const_iterator & end);
  424. void pushArrayMember(JSONNode & res, json_string::const_iterator & ptr, json_string::const_iterator & end){
  425. GET_COMMENT(ptr, end, comment);
  426. JSONNode temp = JSONPreparse::isValidMember(ptr, end);
  427. SET_COMMENT(temp, comment);
  428. #ifdef JSON_LIBRARY
  429. res.push_back(&temp);
  430. #else
  431. res.push_back(temp);
  432. #endif
  433. }
  434. JSONNode JSONPreparse::isValidArray(json_string::const_iterator & ptr, json_string::const_iterator & end) {
  435. //ptr should currently be pointing past the [, so this must be the start of a member, or the closing ]
  436. //ptr will end up past the last ]
  437. JSONNode res(JSON_ARRAY);
  438. do{
  439. switch(*ptr){
  440. case JSON_TEXT(']'):
  441. ++ptr;
  442. return res;
  443. default:
  444. pushArrayMember(res, ptr, end);
  445. switch(*ptr){
  446. case JSON_TEXT(','):
  447. break;
  448. case JSON_TEXT(']'):
  449. ++ptr;
  450. return res;
  451. default:
  452. throw false;
  453. }
  454. break;
  455. }
  456. } while (++ptr != end);
  457. throw false;
  458. }
  459. JSONNode JSONPreparse::isValidRoot(const json_string & json) json_throws(std::invalid_argument) {
  460. json_string::const_iterator it = json.begin();
  461. json_string::const_iterator end = json.end();
  462. try {
  463. GET_COMMENT(it, end, comment);
  464. switch(*it){
  465. case JSON_TEXT('{'):
  466. RETURN_NODE(isValidObject(++it, end), comment);
  467. case JSON_TEXT('['):
  468. RETURN_NODE(isValidArray(++it, end), comment);
  469. }
  470. } catch (...){}
  471. #ifndef JSON_NO_EXCEPTIONS
  472. throw std::invalid_argument(json_global(EMPTY_STD_STRING));
  473. #else
  474. return JSONNode(JSON_NULL);
  475. #endif
  476. }
  477. #endif