JSONValidator.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. #include "JSONValidator.h"
  2. #ifdef JSON_VALIDATE
  3. inline bool isHex(json_char c) json_pure;
  4. inline bool isHex(json_char c) json_nothrow {
  5. return (((c >= JSON_TEXT('0')) && (c <= JSON_TEXT('9'))) ||
  6. ((c >= JSON_TEXT('A')) && (c <= JSON_TEXT('F'))) ||
  7. ((c >= JSON_TEXT('a')) && (c <= JSON_TEXT('f'))));
  8. }
  9. bool JSONValidator::isValidNumber(const json_char * & ptr) json_nothrow {
  10. //ptr points at the first character in the number
  11. //ptr will end up past the last character
  12. bool decimal = false;
  13. bool scientific = false;
  14. //first letter is weird
  15. switch(*ptr){
  16. #ifndef JSON_STRICT
  17. case JSON_TEXT('.'):
  18. decimal = true;
  19. break;
  20. case JSON_TEXT('+'):
  21. #endif
  22. case JSON_TEXT('-'):
  23. #ifdef JSON_STRICT
  24. switch(*(ptr + 1)){
  25. case '.':
  26. case 'e':
  27. case 'E':
  28. case '\0':
  29. return false;
  30. }
  31. break;
  32. #endif
  33. case JSON_TEXT('1'):
  34. case JSON_TEXT('2'):
  35. case JSON_TEXT('3'):
  36. case JSON_TEXT('4'):
  37. case JSON_TEXT('5'):
  38. case JSON_TEXT('6'):
  39. case JSON_TEXT('7'):
  40. case JSON_TEXT('8'):
  41. case JSON_TEXT('9'):
  42. break;
  43. case JSON_TEXT('0'):
  44. ++ptr;
  45. switch(*ptr){
  46. case JSON_TEXT('.'):
  47. decimal = true;
  48. break;
  49. case JSON_TEXT('e'):
  50. case JSON_TEXT('E'):
  51. scientific = true;
  52. ++ptr;
  53. switch(*ptr){
  54. case JSON_TEXT('\0'):
  55. return false;
  56. case JSON_TEXT('-'):
  57. case JSON_TEXT('+'):
  58. case JSON_TEXT('0'):
  59. case JSON_TEXT('1'):
  60. case JSON_TEXT('2'):
  61. case JSON_TEXT('3'):
  62. case JSON_TEXT('4'):
  63. case JSON_TEXT('5'):
  64. case JSON_TEXT('6'):
  65. case JSON_TEXT('7'):
  66. case JSON_TEXT('8'):
  67. case JSON_TEXT('9'):
  68. break;
  69. default:
  70. return false;
  71. }
  72. break;
  73. #ifndef JSON_STRICT
  74. case JSON_TEXT('x'):
  75. while(isHex(*++ptr)){};
  76. return true;
  77. #ifdef JSON_OCTAL
  78. #ifdef __GNUC__
  79. case JSON_TEXT('0') ... JSON_TEXT('7'): //octal
  80. #else
  81. case JSON_TEXT('0'):
  82. case JSON_TEXT('1'):
  83. case JSON_TEXT('2'):
  84. case JSON_TEXT('3'):
  85. case JSON_TEXT('4'):
  86. case JSON_TEXT('5'):
  87. case JSON_TEXT('6'):
  88. case JSON_TEXT('7'):
  89. #endif
  90. while((*++ptr >= JSON_TEXT('0')) && (*ptr <= JSON_TEXT('7'))){};
  91. return ((*ptr != JSON_TEXT('8')) && (*ptr != JSON_TEXT('9')));
  92. case JSON_TEXT('8'):
  93. case JSON_TEXT('9'):
  94. break;
  95. #else
  96. #ifdef __GNUC__
  97. case JSON_TEXT('0') ... JSON_TEXT('9'):
  98. #else
  99. case JSON_TEXT('0'):
  100. case JSON_TEXT('1'):
  101. case JSON_TEXT('2'):
  102. case JSON_TEXT('3'):
  103. case JSON_TEXT('4'):
  104. case JSON_TEXT('5'):
  105. case JSON_TEXT('6'):
  106. case JSON_TEXT('7'):
  107. case JSON_TEXT('8'):
  108. case JSON_TEXT('9'):
  109. #endif
  110. break;
  111. #endif
  112. #else
  113. #ifdef __GNUC__
  114. case JSON_TEXT('0') ... JSON_TEXT('9'):
  115. #else
  116. case JSON_TEXT('0'):
  117. case JSON_TEXT('1'):
  118. case JSON_TEXT('2'):
  119. case JSON_TEXT('3'):
  120. case JSON_TEXT('4'):
  121. case JSON_TEXT('5'):
  122. case JSON_TEXT('6'):
  123. case JSON_TEXT('7'):
  124. case JSON_TEXT('8'):
  125. case JSON_TEXT('9'):
  126. #endif
  127. break;
  128. #endif
  129. default: //just a 0
  130. return true;
  131. }
  132. break;
  133. default:
  134. return false;
  135. }
  136. ++ptr;
  137. //next digits
  138. while (true){
  139. switch(*ptr){
  140. case JSON_TEXT('.'):
  141. if (json_unlikely(decimal)) return false; //multiple decimals
  142. if (json_unlikely(scientific)) return false;
  143. decimal = true;
  144. break;
  145. case JSON_TEXT('e'):
  146. case JSON_TEXT('E'):
  147. if (json_likely(scientific)) return false;
  148. scientific = true;
  149. ++ptr;
  150. switch(*ptr){
  151. case JSON_TEXT('-'):
  152. case JSON_TEXT('+'):
  153. #ifdef __GNUC__
  154. case JSON_TEXT('0') ... JSON_TEXT('9'):
  155. #else
  156. case JSON_TEXT('0'):
  157. case JSON_TEXT('1'):
  158. case JSON_TEXT('2'):
  159. case JSON_TEXT('3'):
  160. case JSON_TEXT('4'):
  161. case JSON_TEXT('5'):
  162. case JSON_TEXT('6'):
  163. case JSON_TEXT('7'):
  164. case JSON_TEXT('8'):
  165. case JSON_TEXT('9'):
  166. #endif
  167. break;
  168. default:
  169. return false;
  170. }
  171. break;
  172. #ifdef __GNUC__
  173. case JSON_TEXT('0') ... JSON_TEXT('9'):
  174. #else
  175. case JSON_TEXT('0'):
  176. case JSON_TEXT('1'):
  177. case JSON_TEXT('2'):
  178. case JSON_TEXT('3'):
  179. case JSON_TEXT('4'):
  180. case JSON_TEXT('5'):
  181. case JSON_TEXT('6'):
  182. case JSON_TEXT('7'):
  183. case JSON_TEXT('8'):
  184. case JSON_TEXT('9'):
  185. #endif
  186. break;
  187. default:
  188. return true;
  189. }
  190. ++ptr;
  191. }
  192. return false;
  193. }
  194. #ifndef JSON_STRICT
  195. #define LETTERCASE(x, y)\
  196. case JSON_TEXT(x):\
  197. case JSON_TEXT(y)
  198. #define LETTERCHECK(x, y)\
  199. if (json_unlikely((*++ptr != JSON_TEXT(x)) && (*ptr != JSON_TEXT(y)))) return false
  200. #else
  201. #define LETTERCASE(x, y)\
  202. case JSON_TEXT(x)
  203. #define LETTERCHECK(x, y)\
  204. if (json_unlikely(*++ptr != JSON_TEXT(x))) return false
  205. #endif
  206. bool JSONValidator::isValidMember(const json_char * & ptr DEPTH_PARAM) json_nothrow {
  207. //ptr is on the first character of the member
  208. //ptr will end up immediately after the last character in the member
  209. switch(*ptr){
  210. case JSON_TEXT('\"'):
  211. return isValidString(++ptr);
  212. case JSON_TEXT('{'):
  213. INC_DEPTH();
  214. return isValidObject(++ptr DEPTH_ARG(depth_param));
  215. case JSON_TEXT('['):
  216. INC_DEPTH();
  217. return isValidArray(++ptr DEPTH_ARG(depth_param));
  218. LETTERCASE('t', 'T'):
  219. LETTERCHECK('r', 'R');
  220. LETTERCHECK('u', 'U');
  221. LETTERCHECK('e', 'E');
  222. ++ptr;
  223. return true;
  224. LETTERCASE('f', 'F'):
  225. LETTERCHECK('a', 'A');
  226. LETTERCHECK('l', 'L');
  227. LETTERCHECK('s', 'S');
  228. LETTERCHECK('e', 'E');
  229. ++ptr;
  230. return true;
  231. LETTERCASE('n', 'N'):
  232. LETTERCHECK('u', 'U');
  233. LETTERCHECK('l', 'L');
  234. LETTERCHECK('l', 'L');
  235. ++ptr;
  236. return true;
  237. #ifndef JSON_STRICT
  238. case JSON_TEXT('}'): //null in libjson
  239. case JSON_TEXT(']'): //null in libjson
  240. case JSON_TEXT(','): //null in libjson
  241. return true;
  242. #endif
  243. case JSON_TEXT('\0'):
  244. return false;
  245. }
  246. //a number
  247. return isValidNumber(ptr);
  248. }
  249. bool JSONValidator::isValidString(const json_char * & ptr) json_nothrow {
  250. //ptr is pointing to the first character after the quote
  251. //ptr will end up behind the closing "
  252. while(true){
  253. switch(*ptr){
  254. case JSON_TEXT('\\'):
  255. switch(*(++ptr)){
  256. case JSON_TEXT('\"'):
  257. case JSON_TEXT('\\'):
  258. case JSON_TEXT('/'):
  259. case JSON_TEXT('b'):
  260. case JSON_TEXT('f'):
  261. case JSON_TEXT('n'):
  262. case JSON_TEXT('r'):
  263. case JSON_TEXT('t'):
  264. break;
  265. case JSON_TEXT('u'):
  266. if (json_unlikely(!isHex(*++ptr))) return false;
  267. if (json_unlikely(!isHex(*++ptr))) return false;
  268. //fallthrough to \x
  269. #ifndef JSON_STRICT
  270. case JSON_TEXT('x'): //hex
  271. #endif
  272. if (json_unlikely(!isHex(*++ptr))) return false;
  273. if (json_unlikely(!isHex(*++ptr))) return false;
  274. break;
  275. #ifdef JSON_OCTAL
  276. #ifdef __GNUC__
  277. case JSON_TEXT('0') ... JSON_TEXT('7'): //octal
  278. #else
  279. case JSON_TEXT('0'):
  280. case JSON_TEXT('1'):
  281. case JSON_TEXT('2'):
  282. case JSON_TEXT('3'):
  283. case JSON_TEXT('4'):
  284. case JSON_TEXT('5'):
  285. case JSON_TEXT('6'):
  286. case JSON_TEXT('7'):
  287. #endif
  288. if (json_unlikely((*++ptr < JSON_TEXT('0')) || (*ptr > JSON_TEXT('7')))) return false;
  289. if (json_unlikely((*++ptr < JSON_TEXT('0')) || (*ptr > JSON_TEXT('7')))) return false;
  290. break;
  291. #endif
  292. default:
  293. return false;
  294. }
  295. break;
  296. case JSON_TEXT('\"'):
  297. ++ptr;
  298. return true;
  299. case JSON_TEXT('\0'):
  300. return false;
  301. }
  302. ++ptr;
  303. }
  304. return false;
  305. }
  306. bool JSONValidator::isValidNamedObject(const json_char * &ptr DEPTH_PARAM) json_nothrow {
  307. if (json_unlikely(!isValidString(++ptr))) return false;
  308. if (json_unlikely(*ptr++ != JSON_TEXT(':'))) return false;
  309. if (json_unlikely(!isValidMember(ptr DEPTH_ARG(depth_param)))) return false;
  310. switch(*ptr){
  311. case JSON_TEXT(','):
  312. return isValidNamedObject(++ptr DEPTH_ARG(depth_param));
  313. case JSON_TEXT('}'):
  314. ++ptr;
  315. return true;
  316. default:
  317. return false;
  318. }
  319. }
  320. bool JSONValidator::isValidObject(const json_char * & ptr DEPTH_PARAM) json_nothrow {
  321. //ptr should currently be pointing past the {, so this must be the start of a name, or the closing }
  322. //ptr will end up past the last }
  323. do{
  324. switch(*ptr){
  325. case JSON_TEXT('\"'):
  326. return isValidNamedObject(ptr DEPTH_ARG(depth_param));
  327. case JSON_TEXT('}'):
  328. ++ptr;
  329. return true;
  330. default:
  331. return false;
  332. }
  333. } while (*++ptr);
  334. return false;
  335. }
  336. bool JSONValidator::isValidArray(const json_char * & ptr DEPTH_PARAM) json_nothrow {
  337. //ptr should currently be pointing past the [, so this must be the start of a member, or the closing ]
  338. //ptr will end up past the last ]
  339. do{
  340. switch(*ptr){
  341. case JSON_TEXT(']'):
  342. ++ptr;
  343. return true;
  344. default:
  345. if (json_unlikely(!isValidMember(ptr DEPTH_ARG(depth_param)))) return false;
  346. switch(*ptr){
  347. case JSON_TEXT(','):
  348. break;
  349. case JSON_TEXT(']'):
  350. ++ptr;
  351. return true;
  352. default:
  353. return false;
  354. }
  355. break;
  356. }
  357. } while (*++ptr);
  358. return false;
  359. }
  360. bool JSONValidator::isValidRoot(const json_char * json) json_nothrow {
  361. const json_char * ptr = json;
  362. switch(*ptr){
  363. case JSON_TEXT('{'):
  364. if (json_likely(isValidObject(++ptr DEPTH_ARG(1)))){
  365. return *ptr == JSON_TEXT('\0');
  366. }
  367. return false;
  368. case JSON_TEXT('['):
  369. if (json_likely(isValidArray(++ptr DEPTH_ARG(1)))){
  370. return *ptr == JSON_TEXT('\0');
  371. }
  372. return false;
  373. }
  374. return false;
  375. }
  376. #ifdef JSON_STREAM
  377. //It has already been checked for a complete structure, so we know it's not complete
  378. bool JSONValidator::isValidPartialRoot(const json_char * json) json_nothrow {
  379. const json_char * ptr = json;
  380. switch(*ptr){
  381. case JSON_TEXT('{'):
  382. JSON_ASSERT_SAFE(!isValidObject(++ptr DEPTH_ARG(1)), JSON_TEXT("Partial Object seems to be valid"), );
  383. return *ptr == JSON_TEXT('\0');
  384. case JSON_TEXT('['):
  385. JSON_ASSERT_SAFE(!isValidArray(++ptr DEPTH_ARG(1)), JSON_TEXT("Partial Object seems to be valid"), );
  386. return *ptr == JSON_TEXT('\0');
  387. }
  388. return false;
  389. }
  390. #endif
  391. #endif