1 #include "JSONWorker.h"
3 bool used_ascii_one =
false;
4 inline json_char ascii_one(
void) json_nothrow {
6 return JSON_TEXT(
'\1');
9 #ifdef JSON_READ_PRIORITY
11 JSONNode JSONWorker::parse(
const json_string & json) json_throws(std::invalid_argument) {
12 json_auto<json_char> s;
14 s.set(RemoveWhiteSpace(json, len,
true));
15 return _parse_unformatted(s.ptr, s.ptr + len);
18 JSONNode JSONWorker::parse_unformatted(
const json_string & json) json_throws(std::invalid_argument) {
19 #if defined JSON_DEBUG || defined JSON_SAFE
20 #ifndef JSON_NO_EXCEPTIONS
21 JSON_ASSERT_SAFE((json[0] == JSON_TEXT(
'{')) || (json[0] == JSON_TEXT(
'[')), JSON_TEXT(
"Not JSON!"),
throw std::invalid_argument(json_global(EMPTY_STD_STRING)););
23 JSON_ASSERT_SAFE((json[0] == JSON_TEXT(
'{')) || (json[0] == JSON_TEXT(
'[')), JSON_TEXT(
"Not JSON!"),
return JSONNode(JSON_NULL););
26 return _parse_unformatted(json.data(), json.data() + json.length());
29 JSONNode JSONWorker::_parse_unformatted(
const json_char * json,
const json_char *
const end) json_throws(std::invalid_argument) {
31 json_char firstchar = *json;
33 json_char * runner = (json_char*)json;
34 if (json_unlikely(firstchar == JSON_TEMP_COMMENT_IDENTIFIER)){
36 while(*(++runner) != JSON_TEMP_COMMENT_IDENTIFIER){
37 JSON_ASSERT(runner != end, JSON_TEXT(
"Removing white space failed"));
40 firstchar = *(++runner);
41 if (json_unlikely(firstchar == JSON_TEMP_COMMENT_IDENTIFIER)){
42 _comment += JSON_TEXT(
'\n');
47 const json_char firstchar = *json;
53 #if defined JSON_DEBUG || defined JSON_SAFE
54 if (firstchar == JSON_TEXT(
'[')){
55 if (json_unlikely(*(end - 1) != JSON_TEXT(
']'))){
56 JSON_FAIL(JSON_TEXT(
"Missing final ]"));
60 if (json_unlikely(*(end - 1) != JSON_TEXT(
'}'))){
61 JSON_FAIL(JSON_TEXT(
"Missing final }"));
67 JSONNode foo(json_string(runner, end - runner));
68 foo.set_comment(_comment);
69 return JSONNode(
true, foo);
71 return JSONNode(json_string(json, end - json));
75 JSON_FAIL(JSON_TEXT(
"Not JSON!"));
76 #ifndef JSON_NO_EXCEPTIONS
77 throw std::invalid_argument(json_global(EMPTY_STD_STRING));
79 return JSONNode(JSON_NULL);
85 case JSON_TEXT('\"'):\
86 while (*(++p) != JSON_TEXT('\"')){\
87 JSON_ASSERT_SAFE(*p, JSON_TEXT("Null terminator inside of a quotation"), return json_string::npos;);\
91 #if defined(JSON_DEBUG) || defined(JSON_SAFE)
92 #define NULLCASE(error)\
93 case JSON_TEXT('\0'):\
94 JSON_FAIL_SAFE(error, return json_string::npos;);\
97 #define NULLCASE(error)
100 #define BRACKET(left, right)\
112 NULLCASE(JSON_TEXT("Null terminator inside of a bracket"))\
117 return json_string::npos;
121 #if defined(JSON_READ_PRIORITY) || defined(JSON_STREAM)
122 #if (JSON_READ_PRIORITY == HIGH) && (!(defined(JSON_LESS_MEMORY)))
123 #define FIND_NEXT_RELEVANT(ch, vt, po) JSONWorker::FindNextRelevant<ch>(vt, po)
124 template<json_
char ch>
125 size_t JSONWorker::FindNextRelevant(
const json_string & value_t,
const size_t pos) json_nothrow {
127 #define FIND_NEXT_RELEVANT(ch, vt, po) JSONWorker::FindNextRelevant(ch, vt, po)
128 size_t JSONWorker::FindNextRelevant(json_char ch,
const json_string & value_t,
const size_t pos) json_nothrow {
130 json_string::const_iterator start = value_t.begin();
131 json_string::const_iterator e = value_t.end();
132 for (json_string::const_iterator p = value_t.begin() + pos; p != e; ++p){
133 if (json_unlikely(*p == ch))
return p - start;
135 BRACKET(JSON_TEXT(
'['), JSON_TEXT(
']'))
136 BRACKET(JSON_TEXT('{
'), JSON_TEXT('}
'))
140 return json_string::npos;
145 #define COMMENT_DELIMITER() *runner++ = JSON_TEMP_COMMENT_IDENTIFIER
146 #define AND_RUNNER ,runner
147 inline void SingleLineComment(const json_char * & p, const json_char * const end, json_char * & runner) json_nothrow {
148 //It is okay to add two '\5
' characters here because at minimun the # and '\n
' are replaced, so it's at most the same size
150 while((++p != end) && (*p != JSON_TEXT(
'\n'))){
156 #define COMMENT_DELIMITER() (void)0
161 inline void SingleLineComment(
const json_char * & p,
const json_char *
const end) json_nothrow {
162 while((++p != end) && (*p != JSON_TEXT(
'\n')));
166 #if defined(JSON_LESS_MEMORY) && defined(JSON_READ_PRIORITY)
167 #define PRIVATE_REMOVEWHITESPACE(T, value_t, escapeQuotes, len) private_RemoveWhiteSpace(T, value_t, escapeQuotes, len)
168 json_char * private_RemoveWhiteSpace(
bool T,
const json_string & value_t,
bool escapeQuotes,
size_t & len) json_nothrow {
170 #define PRIVATE_REMOVEWHITESPACE(T, value_t, escapeQuotes, len) private_RemoveWhiteSpace<T>(value_t, escapeQuotes, len)
172 json_char * private_RemoveWhiteSpace(
const json_string & value_t,
bool escapeQuotes,
size_t & len) json_nothrow {
175 json_char * runner = result = json_malloc<json_char>(value_t.length() + 1);
176 JSON_ASSERT(result != 0, json_global(ERROR_OUT_OF_MEMORY));
177 const json_char *
const end = value_t.data() + value_t.length();
178 for(
const json_char * p = value_t.data(); p != end; ++p){
181 case JSON_TEXT(
'\t'):
182 case JSON_TEXT(
'\n'):
183 case JSON_TEXT(
'\r'):
187 if (*(++p) == JSON_TEXT(
'*')){
188 if (T) COMMENT_DELIMITER();
189 while ((*(++p) != JSON_TEXT(
'*')) || (*(p + 1) != JSON_TEXT(
'/'))){
194 if (T) *runner++ = *p;
197 if (T) COMMENT_DELIMITER();
201 JSON_ASSERT_SAFE(*p == JSON_TEXT(
'/'), JSON_TEXT(
"stray / character, not quoted, or a comment"),
goto endofrunner;);
204 SingleLineComment(p, end AND_RUNNER);
206 SingleLineComment(p, end);
210 case JSON_TEXT(
'\"'):
211 *runner++ = JSON_TEXT(
'\"');
212 while(*(++p) != JSON_TEXT(
'\"')){
213 if(p == end)
goto endofrunner;
215 case JSON_TEXT(
'\\'):
216 *runner++ = JSON_TEXT(
'\\');
218 *runner++ = (*++p == JSON_TEXT(
'\"')) ? ascii_one() : *p;
230 JSON_ASSERT_SAFE((json_uchar)*p >= 32, JSON_TEXT(
"Invalid JSON character detected (lo)"),
goto endofrunner;);
231 JSON_ASSERT_SAFE((json_uchar)*p <= 126, JSON_TEXT(
"Invalid JSON character detected (hi)"),
goto endofrunner;);
237 len = runner - result;
241 #ifdef JSON_READ_PRIORITY
242 json_char * JSONWorker::RemoveWhiteSpace(
const json_string & value_t,
size_t & len,
bool escapeQuotes) json_nothrow {
243 json_char * result = PRIVATE_REMOVEWHITESPACE(
true, value_t, escapeQuotes, len);
244 result[len] = JSON_TEXT(
'\0');
249 json_char * JSONWorker::RemoveWhiteSpaceAndCommentsC(
const json_string & value_t,
bool escapeQuotes) json_nothrow {
251 json_char * result = PRIVATE_REMOVEWHITESPACE(
false, value_t, escapeQuotes, len);
252 result[len] = JSON_TEXT(
'\0');
256 json_string JSONWorker::RemoveWhiteSpaceAndComments(
const json_string & value_t,
bool escapeQuotes) json_nothrow {
257 json_auto<json_char> s;
259 s.set(PRIVATE_REMOVEWHITESPACE(
false, value_t, escapeQuotes, len));
260 return json_string(s.ptr, len);
263 #ifdef JSON_READ_PRIORITY
269 inline json_uchar SurrogatePair(
const json_uchar hi,
const json_uchar lo) json_pure;
270 inline json_uchar SurrogatePair(
const json_uchar hi,
const json_uchar lo) json_nothrow {
271 JSON_ASSERT(
sizeof(
unsigned int) == 4, JSON_TEXT(
"size of unsigned int is not 32-bit"));
272 JSON_ASSERT(
sizeof(json_uchar) == 4, JSON_TEXT(
"size of json_char is not 32-bit"));
273 return (((hi << 10) & 0x1FFC00) + 0x10000) | lo & 0x3FF;
276 void JSONWorker::UTF(
const json_char * & pos, json_string & result,
const json_char *
const end) json_nothrow {
277 JSON_ASSERT_SAFE(((
long)end - (
long)pos) > 4, JSON_TEXT(
"UTF will go out of bounds"),
return;);
278 json_uchar first = UTF8(pos, end);
279 if (json_unlikely((first > 0xD800) && (first < 0xDBFF) &&
280 (*(pos + 1) ==
'\\') && (*(pos + 2) ==
'u'))){
281 const json_char * original_pos = pos;
283 json_uchar second = UTF8(pos, end);
285 if (json_unlikely((second > 0xDC00) && (second < 0xDFFF))){
286 result += SurrogatePair(first, second);
296 json_uchar JSONWorker::UTF8(
const json_char * & pos,
const json_char *
const end) json_nothrow {
297 JSON_ASSERT_SAFE(((
long)end - (
long)pos) > 4, JSON_TEXT(
"UTF will go out of bounds"),
return JSON_TEXT(
'\0'););
300 json_uchar temp = Hex(pos) << 8;
302 return temp | Hex(pos);
304 JSON_ASSERT(*(pos + 1) == JSON_TEXT(
'0'), JSON_TEXT(
"wide utf character (hihi)"));
305 JSON_ASSERT(*(pos + 2) == JSON_TEXT(
'0'), JSON_TEXT(
"wide utf character (hilo)"));
312 json_char JSONWorker::Hex(
const json_char * & pos) json_nothrow {
321 json_uchar hi = *pos++ - 48;
328 json_uchar lo = *pos - 48;
335 return (json_char)((hi << 4) | lo);
339 inline json_char FromOctal(
const json_char * & str,
const json_char *
const end) json_nothrow {
340 JSON_ASSERT_SAFE(((
long)end - (
long)str) > 3, JSON_TEXT(
"Octal will go out of bounds"),
return JSON_TEXT(
'\0'););
342 return (json_char)(((((json_uchar)(*(str - 2) - 48))) << 6) | (((json_uchar)(*(str - 1) - 48)) << 3) | ((json_uchar)(*str - 48)));
346 void JSONWorker::SpecialChar(
const json_char * & pos,
const json_char *
const end, json_string & res) json_nothrow {
347 JSON_ASSERT_SAFE(pos != end, JSON_TEXT(
"Special char termantion"),
return;);
353 case JSON_TEXT(
'\1'):
354 res += JSON_TEXT(
'\"');
357 res += JSON_TEXT(
'\t');
360 res += JSON_TEXT(
'\n');
363 res += JSON_TEXT(
'\r');
365 case JSON_TEXT(
'\\'):
366 res += JSON_TEXT(
'\\');
369 res += JSON_TEXT(
'/');
372 res += JSON_TEXT(
'\b');
375 res += JSON_TEXT(
'\f');
378 res += JSON_TEXT(
'\v');
384 res += UTF8(pos, end);
389 JSON_ASSERT_SAFE(((long)end - (long)pos) > 3, JSON_TEXT(
"Hex will go out of bounds"), res += JSON_TEXT(
'\0');
return;);
394 case JSON_TEXT(
'0') ... JSON_TEXT(
'7'):
406 res += FromOctal(pos, end);
411 #elif defined(JSON_DEBUG)
413 JSON_FAIL(JSON_TEXT(
"Unsupported escaped character"));
419 #ifdef JSON_LESS_MEMORY
420 inline void doflag(
const internalJSONNode * flag,
bool which,
bool x) json_nothrow {
421 if (json_likely(which)){
422 flag -> _name_encoded = x;
424 flag -> _string_encoded = x;
428 json_string JSONWorker::FixString(
const json_string & value_t,
const internalJSONNode * flag,
bool which) json_nothrow {
429 #define setflag(x) doflag(flag, which, x)
431 json_string JSONWorker::FixString(
const json_string & value_t,
bool & flag) json_nothrow {
432 #define setflag(x) flag = x
438 res.reserve(value_t.length());
439 const json_char *
const end = value_t.data() + value_t.length();
440 for(
const json_char * p = value_t.data(); p != end; ++p){
442 case JSON_TEXT(
'\\'):
444 SpecialChar(++p, end, res);
457 #ifdef JSON_ESCAPE_WRITES
458 json_string JSONWorker::toSurrogatePair(json_uchar C) json_nothrow {
459 JSON_ASSERT(
sizeof(
unsigned int) == 4, JSON_TEXT(
"size of unsigned int is not 32-bit"));
460 JSON_ASSERT(
sizeof(
unsigned short) == 2, JSON_TEXT(
"size of unsigned short is not 16-bit"));
461 JSON_ASSERT(
sizeof(json_uchar) == 4, JSON_TEXT(
"json_char is not 32-bit"));
464 unsigned short HiSurrogate = 0xD800 | (((
unsigned short)((
unsigned int)((C >> 16) & 31)) - 1) << 6) | ((
unsigned short)C) >> 10;
467 unsigned short LoSurrogate = (
unsigned short) (0xDC00 | ((
unsigned short)C & 1023));
470 res += toUTF8(HiSurrogate);
471 res += toUTF8(LoSurrogate);
477 #ifdef JSON_ESCAPE_WRITES
478 json_string JSONWorker::toUTF8(json_uchar p) json_nothrow {
480 if (json_unlikely(p > 0xFFFF))
return toSurrogatePair(p);
482 json_string res(JSON_TEXT(
"\\u"));
485 json_uchar hihi = ((p & 0xF000) >> 12) + 48;
486 if (hihi > 57) hihi += 7;
487 json_uchar hilo = ((p & 0x0F00) >> 8) + 48;
488 if (hilo > 57) hilo += 7;
492 json_uchar hi = ((p & 0x00F0) >> 4) + 48;
494 res += JSON_TEXT(
"00");
495 json_uchar hi = (p >> 4) + 48;
498 if (hi > 57) hi += 7;
499 json_uchar lo = (p & 0x000F) + 48;
500 if (lo > 57) lo += 7;
507 void JSONWorker::UnfixString(
const json_string & value_t,
bool flag, json_string & res) json_nothrow {
513 const json_char *
const end = value_t.data() + value_t.length();
514 for(
const json_char * p = value_t.data(); p != end; ++p){
516 case JSON_TEXT(
'\"'):
517 res += JSON_TEXT(
"\\\"");
519 case JSON_TEXT(
'\\'):
520 res += JSON_TEXT(
"\\\\");
522 #ifdef JSON_ESCAPE_WRITES
523 case JSON_TEXT(
'\t'):
524 res += JSON_TEXT(
"\\t");
526 case JSON_TEXT(
'\n'):
527 res += JSON_TEXT(
"\\n");
529 case JSON_TEXT(
'\r'):
530 res += JSON_TEXT(
"\\r");
533 res += JSON_TEXT(
"\\/");
535 case JSON_TEXT(
'\b'):
536 res += JSON_TEXT(
"\\b");
538 case JSON_TEXT(
'\f'):
539 res += JSON_TEXT(
"\\f");
543 if (json_unlikely(((json_uchar)(*p) < 32) || ((json_uchar)(*p) > 126))){
544 res += toUTF8((json_uchar)(*p));
559 #ifdef JSON_READ_PRIORITY
562 #define ARRAY_PARAM bool array //Just to supress warnings
564 #define ARRAY_PARAM bool
566 inline void JSONWorker::NewNode(
const internalJSONNode * parent,
const json_string & name,
const json_string & value, ARRAY_PARAM) json_nothrow {
570 json_string _comment;
572 const json_char * runner = ((array) ? value.data() : name.data());
574 const json_char *
const end = runner + value.length();
576 if (json_unlikely(*runner == JSON_TEMP_COMMENT_IDENTIFIER)){
578 const json_char * start;
582 while(*(++runner) != JSON_TEMP_COMMENT_IDENTIFIER){
583 JSON_ASSERT(runner != end, JSON_TEXT(
"Removing white space failed"));
586 if (count) _comment += json_string(start, count);
587 if (json_unlikely(*(++runner) == JSON_TEMP_COMMENT_IDENTIFIER)){
588 _comment += JSON_TEXT(
'\n');
592 internalJSONNode * myinternal;
594 myinternal = internalJSONNode::newInternal(name, runner);
596 myinternal = internalJSONNode::newInternal(++runner, value);
598 child = JSONNode::newJSONNode(myinternal);
600 child -> set_comment(_comment);
602 const_cast<internalJSONNode*
>(parent) -> CHILDREN -> push_back(child);
605 const_cast<internalJSONNode*
>(parent) -> CHILDREN -> push_back(JSONNode::newJSONNode(internalJSONNode::newInternal(name, value)));
607 const_cast<internalJSONNode*
>(parent) -> CHILDREN -> push_back(JSONNode::newJSONNode(internalJSONNode::newInternal(json_string(name.begin() + 1, name.end()), value)));
613 void JSONWorker::DoArray(
const internalJSONNode * parent,
const json_string & value_t) json_nothrow {
615 JSON_ASSERT(!value_t.empty(), JSON_TEXT(
"DoArray is empty"));
616 JSON_ASSERT_SAFE(value_t[0] == JSON_TEXT(
'['), JSON_TEXT(
"DoArray is not an array"), parent -> Nullify();
return;);
617 if (json_unlikely(value_t.length() <= 2))
return;
620 json_string newValue;
625 for(
size_t ending = FIND_NEXT_RELEVANT(JSON_TEXT(
','), value_t, 1);
626 ending != json_string::npos;
627 ending = FIND_NEXT_RELEVANT(JSON_TEXT(
','), value_t, starting)){
630 newValue.assign(value_t.begin() + starting, value_t.begin() + ending);
631 JSON_ASSERT_SAFE(FIND_NEXT_RELEVANT(JSON_TEXT(
':'), newValue, 0) == json_string::npos, JSON_TEXT(
"Key/Value pairs are not allowed in arrays"), parent -> Nullify();
return;);
632 NewNode(parent, json_global(EMPTY_JSON_STRING), newValue,
true);
634 NewNode(parent, json_global(EMPTY_JSON_STRING), json_string(value_t.begin() + starting, value_t.begin() + ending),
true);
636 starting = ending + 1;
641 newValue.assign(value_t.begin() + starting, value_t.end() - 1);
642 JSON_ASSERT_SAFE(FIND_NEXT_RELEVANT(JSON_TEXT(
':'), newValue, 0) == json_string::npos, JSON_TEXT(
"Key/Value pairs are not allowed in arrays"), parent -> Nullify();
return;);
643 NewNode(parent, json_global(EMPTY_JSON_STRING), newValue,
true);
645 NewNode(parent, json_global(EMPTY_JSON_STRING), json_string(value_t.begin() + starting, value_t.end() - 1),
true);
651 void JSONWorker::DoNode(
const internalJSONNode * parent,
const json_string & value_t) json_nothrow {
653 JSON_ASSERT(!value_t.empty(), JSON_TEXT(
"DoNode is empty"));
654 JSON_ASSERT_SAFE(value_t[0] == JSON_TEXT(
'{'), JSON_TEXT(
"DoNode is not an node"), parent -> Nullify();
return;);
655 if (json_unlikely(value_t.length() <= 2))
return;
657 size_t name_ending = FIND_NEXT_RELEVANT(JSON_TEXT(
':'), value_t, 1);
658 JSON_ASSERT_SAFE(name_ending != json_string::npos, JSON_TEXT(
"Missing :"), parent -> Nullify();
return;);
659 json_string name(value_t.begin() + 1, value_t.begin() + name_ending - 1);
660 for (
size_t value_ending = FIND_NEXT_RELEVANT(JSON_TEXT(
','), value_t, name_ending),
662 value_ending != json_string::npos;
663 value_ending = FIND_NEXT_RELEVANT(JSON_TEXT(
','), value_t, name_ending)){
665 NewNode(parent, name, json_string(value_t.begin() + name_ending + 1, value_t.begin() + value_ending),
false);
666 name_starting = value_ending + 1;
667 name_ending = FIND_NEXT_RELEVANT(JSON_TEXT(
':'), value_t, name_starting);
668 JSON_ASSERT_SAFE(name_ending != json_string::npos, JSON_TEXT(
"Missing :"), parent -> Nullify();
return;);
669 name.assign(value_t.begin() + name_starting, value_t.begin() + name_ending - 1);
672 NewNode(parent, name, json_string(value_t.begin() + name_ending + 1, value_t.end() - 1),
false);