10 #include "JSONPreparse.h"
12 #if (defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY))
15 json_string extractComment(json_string::const_iterator & ptr, json_string::const_iterator & end);
16 json_string extractComment(json_string::const_iterator & ptr, json_string::const_iterator & end){
17 json_string::const_iterator start;
20 if (json_unlikely(((ptr != end) && (*ptr == JSON_TEMP_COMMENT_IDENTIFIER)))){
22 for(; (ptr != end) && (*(ptr) != JSON_TEMP_COMMENT_IDENTIFIER); ++ptr){}
23 result += json_string(start, ptr);
24 if (json_unlikely(ptr == end))
return result;
26 if (json_unlikely(((ptr != end) && (*ptr == JSON_TEMP_COMMENT_IDENTIFIER)))){
27 result += JSON_TEXT(
'\n');
33 #define GET_COMMENT(x, y, name) json_string name = extractComment(x, y)
34 #define RETURN_NODE(node, name){\
36 res.set_comment(name);\
39 #define RETURN_NODE_NOCOPY(node, name){\
40 node.set_comment(name);\
43 #define SET_COMMENT(node, name) node.set_comment(name)
44 #define COMMENT_ARG(name) ,name
46 #define GET_COMMENT(x, y, name) (void)0
47 #define RETURN_NODE(node, name) return node
48 #define RETURN_NODE_NOCOPY(node, name) return node
49 #define SET_COMMENT(node, name) (void)0
50 #define COMMENT_ARG(name)
53 inline bool isHex(json_char c) json_pure;
54 inline bool isHex(json_char c) json_nothrow {
55 return (((c >= JSON_TEXT(
'0')) && (c <= JSON_TEXT(
'9'))) ||
56 ((c >= JSON_TEXT(
'A')) && (c <= JSON_TEXT(
'F'))) ||
57 ((c >= JSON_TEXT(
'a')) && (c <= JSON_TEXT(
'f'))));
61 #include "NumberToString.h"
64 json_number FetchNumber(
const json_string & _string) json_nothrow;
65 json_number FetchNumber(
const json_string & _string) json_nothrow {
67 return NumberToString::_atof(_string.c_str());
70 const size_t len = _string.length();
71 #if defined(_MSC_VER) && defined(JSON_SAFE)
72 const size_t bytes = (len * (
sizeof(json_char) /
sizeof(
char))) + 1;
73 json_auto<char> temp(bytes);
75 errno_t err = std::wcstombs_s(&res, temp.ptr, bytes, _string.c_str(), len);
77 return (json_number)0.0;
79 #elif defined(JSON_SAFE)
80 const size_t bytes = (len * (
sizeof(json_char) /
sizeof(
char))) + 1;
81 json_auto<char> temp(bytes);
82 size_t res = std::wcstombs(temp.ptr, _string.c_str(), len);
83 if (res == (
size_t)-1){
84 return (json_number)0.0;
87 json_auto<char> temp(len + 1);
88 size_t res = std::wcstombs(temp.ptr, _string.c_str(), len);
90 temp.ptr[res] = JSON_TEXT(
'\0');
91 return (json_number)std::atof(temp.ptr);
93 return (json_number)std::atof(_string.c_str());
98 JSONNode JSONPreparse::isValidNumber(json_string::const_iterator & ptr, json_string::const_iterator & end){
101 json_string::const_iterator start = ptr;
102 bool decimal =
false;
103 bool scientific =
false;
135 if (ptr == end)
throw false;
157 while(isHex(*++ptr)){};
158 return JSONNode(json_global(EMPTY_JSON_STRING), FetchNumber(json_string(start, end - 1)));
161 case JSON_TEXT(
'0') ... JSON_TEXT(
'7'):
172 while((*++ptr >= JSON_TEXT(
'0')) && (*ptr <= JSON_TEXT(
'7'))){};
173 if ((*ptr != JSON_TEXT(
'8')) && (*ptr != JSON_TEXT(
'9'))){
174 return JSONNode(json_global(EMPTY_JSON_STRING), FetchNumber(json_string(start, ptr - 1)));
182 case JSON_TEXT(
'0') ... JSON_TEXT(
'9'):
199 case JSON_TEXT(
'0') ... JSON_TEXT(
'9'):
215 return JSONNode(json_global(EMPTY_JSON_STRING), FetchNumber(json_string(start, ptr - 1)));;
227 if (json_unlikely(decimal)) throw false;
228 if (json_unlikely(scientific))
throw false;
233 if (json_likely(scientific)) throw false;
240 case JSON_TEXT(
'0') ... JSON_TEXT(
'9'):
259 case JSON_TEXT(
'0') ... JSON_TEXT(
'9'):
274 return JSONNode(json_global(EMPTY_JSON_STRING), FetchNumber(json_string(start, ptr)));;
282 #define LETTERCASE(x, y)\
285 #define LETTERCHECK(x, y)\
286 if (json_unlikely((*++ptr != JSON_TEXT(x)) && (*ptr != JSON_TEXT(y)))) throw false
288 #define LETTERCASE(x, y)\
290 #define LETTERCHECK(x, y)\
291 if (json_unlikely(*++ptr != JSON_TEXT(x))) throw false
293 JSONNode JSONPreparse::isValidMember(json_string::const_iterator & ptr, json_string::const_iterator & end){
296 if (ptr == end)
throw false;
299 case JSON_TEXT(
'\"'):{
300 return JSONNode::stringType(isValidString(++ptr, end));
303 return isValidObject(++ptr, end);
305 return isValidArray(++ptr, end);
306 LETTERCASE(
't',
'T'):
307 LETTERCHECK(
'r',
'R');
308 LETTERCHECK(
'u',
'U');
309 LETTERCHECK(
'e',
'E');
311 return JSONNode(json_global(EMPTY_JSON_STRING),
true);
312 LETTERCASE(
'f',
'F'):
313 LETTERCHECK(
'a',
'A');
314 LETTERCHECK(
'l',
'L');
315 LETTERCHECK(
's',
'S');
316 LETTERCHECK(
'e',
'E');
318 return JSONNode(json_global(EMPTY_JSON_STRING),
false);
319 LETTERCASE(
'n',
'N'):
320 LETTERCHECK(
'u',
'U');
321 LETTERCHECK(
'l',
'L');
322 LETTERCHECK(
'l',
'L');
324 return JSONNode(JSON_NULL);
329 return JSONNode(JSON_NULL);
333 return isValidNumber(ptr, end);
336 json_string JSONPreparse::isValidString(json_string::const_iterator & ptr, json_string::const_iterator & end){
339 json_string::const_iterator start = ptr;
343 case JSON_TEXT(
'\\'):
345 case JSON_TEXT(
'\"'):
346 case JSON_TEXT(
'\\'):
355 if (json_unlikely(!isHex(*++ptr))) throw false;
356 if (json_unlikely(!isHex(*++ptr)))
throw false;
361 if (json_unlikely(!isHex(*++ptr))) throw false;
362 if (json_unlikely(!isHex(*++ptr)))
throw false;
366 case JSON_TEXT(
'0') ... JSON_TEXT(
'7'):
377 if (json_unlikely((*++ptr < JSON_TEXT(
'0')) || (*ptr > JSON_TEXT(
'7')))) throw false;
378 if (json_unlikely((*++ptr < JSON_TEXT(
'0')) || (*ptr > JSON_TEXT(
'7'))))
throw false;
385 case JSON_TEXT(
'\"'):
386 return json_string(start, ptr++);
393 void JSONPreparse::isValidNamedObject(json_string::const_iterator & ptr, json_string::const_iterator & end, JSONNode & parent COMMENT_PARAM(comment)) {
396 json_string _name = isValidString(++ptr, end);
397 if (json_unlikely(*ptr++ != JSON_TEXT(
':')))
throw false;
398 JSONNode res = isValidMember(ptr, end);
399 res.set_name_(_name);
400 SET_COMMENT(res, comment);
402 parent.push_back(&res);
404 parent.push_back(res);
407 if (ptr == end)
throw false;
412 GET_COMMENT(ptr, end, nextcomment);
413 isValidNamedObject(ptr, end, parent COMMENT_ARG(nextcomment));
424 JSONNode JSONPreparse::isValidObject(json_string::const_iterator & ptr, json_string::const_iterator & end) {
427 JSONNode res(JSON_NODE);
428 GET_COMMENT(ptr, end, comment);
430 case JSON_TEXT(
'\"'):
431 isValidNamedObject(ptr, end, res COMMENT_ARG(comment));
441 void pushArrayMember(JSONNode & res, json_string::const_iterator & ptr, json_string::const_iterator & end);
442 void pushArrayMember(JSONNode & res, json_string::const_iterator & ptr, json_string::const_iterator & end){
443 GET_COMMENT(ptr, end, comment);
444 JSONNode temp = JSONPreparse::isValidMember(ptr, end);
445 SET_COMMENT(temp, comment);
447 res.push_back(&temp);
453 JSONNode JSONPreparse::isValidArray(json_string::const_iterator & ptr, json_string::const_iterator & end) {
456 JSONNode res(JSON_ARRAY);
463 pushArrayMember(res, ptr, end);
475 }
while (++ptr != end);
479 JSONNode JSONPreparse::isValidRoot(
const json_string & json) json_throws(std::invalid_argument) {
480 json_string::const_iterator it = json.begin();
481 json_string::const_iterator end = json.end();
483 GET_COMMENT(it, end, comment);
486 RETURN_NODE(isValidObject(++it, end), comment);
488 RETURN_NODE(isValidArray(++it, end), comment);
492 #ifndef JSON_NO_EXCEPTIONS
493 throw std::invalid_argument(json_global(EMPTY_STD_STRING));
495 return JSONNode(JSON_NULL);