18 #include <boost/filesystem/fstream.hpp>
20 namespace fc {
namespace json_relaxed
22 template<
typename T,
bool strict>
35 switch( c = in.peek() )
49 case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 'h':
50 case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
51 case 'q':
case 'r':
case 's':
case 't':
case 'u':
case 'v':
case 'w':
case 'x':
53 case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
54 case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
55 case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
57 case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
59 case '_':
case '-':
case '.':
case '+':
case '/':
69 catch(
const fc::eof_exception& eof )
73 catch (
const std::ios_base::failure&)
79 (
"token", token.
str() ) );
82 template<
typename T,
bool strict,
bool allow_escape>
93 FC_THROW_EXCEPTION( parse_error_exception,
"expected: '\"' at beginning of string, got '\''" );
101 FC_THROW_EXCEPTION( parse_error_exception,
"expected: '\"' | '\\\'' at beginning of string" );
109 return std::string();
111 catch(
const fc::eof_exception& e )
113 return std::string();
118 FC_THROW_EXCEPTION( parse_error_exception,
"triple quote unsupported in strict mode" );
145 else if( c ==
'\x04' )
147 (
"token", token.
str() ) );
148 else if( allow_escape && (c ==
'\\') )
168 else if( c ==
'\x04' )
170 (
"token", token.
str() ) );
171 else if( allow_escape && (c ==
'\\') )
173 else if( (c ==
'\r') | (c ==
'\n') )
175 (
"token", token.
str() ) );
184 (
"token", token.
str() ) );
187 template<
typename T,
bool strict>
192 char c = in.peek(), c2;
198 FC_THROW_EXCEPTION( parse_error_exception,
"expected: '\"' at beginning of string, got '\''" );
201 return quoteStringFromStream<T, strict, true>( in );
204 FC_THROW_EXCEPTION( parse_error_exception,
"raw strings not supported in strict mode" );
213 FC_THROW_EXCEPTION( parse_error_exception,
"raw strings not supported in strict mode" );
214 return quoteStringFromStream<T, strict, false>( in );
217 FC_THROW_EXCEPTION( parse_error_exception,
"unquoted strings not supported in strict mode" );
221 case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 'h':
222 case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
223 case 'q':
case 's':
case 't':
case 'u':
case 'v':
case 'w':
case 'x':
225 case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
226 case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
227 case 'Q':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
229 case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
231 case '_':
case '-':
case '.':
case '+':
case '/':
233 FC_THROW_EXCEPTION( parse_error_exception,
"unquoted strings not supported in strict mode" );
249 for(
size_t i=0; i<0x100; i++ )
251 c2v[(
unsigned char)
'0'] = 0;
252 c2v[(
unsigned char)
'1'] = 1;
253 c2v[(
unsigned char)
'2'] = 2;
254 c2v[(
unsigned char)
'3'] = 3;
255 c2v[(
unsigned char)
'4'] = 4;
256 c2v[(
unsigned char)
'5'] = 5;
257 c2v[(
unsigned char)
'6'] = 6;
258 c2v[(
unsigned char)
'7'] = 7;
259 c2v[(
unsigned char)
'8'] = 8;
260 c2v[(
unsigned char)
'9'] = 9;
261 c2v[(
unsigned char)
'a'] =
c2v[(
unsigned char)
'A'] = 10;
262 c2v[(
unsigned char)
'b'] =
c2v[(
unsigned char)
'B'] = 11;
263 c2v[(
unsigned char)
'c'] =
c2v[(
unsigned char)
'C'] = 12;
264 c2v[(
unsigned char)
'd'] =
c2v[(
unsigned char)
'D'] = 13;
265 c2v[(
unsigned char)
'e'] =
c2v[(
unsigned char)
'E'] = 14;
266 c2v[(
unsigned char)
'f'] =
c2v[(
unsigned char)
'F'] = 15;
267 c2v[(
unsigned char)
'g'] =
c2v[(
unsigned char)
'G'] = 16;
268 c2v[(
unsigned char)
'h'] =
c2v[(
unsigned char)
'H'] = 17;
269 c2v[(
unsigned char)
'i'] =
c2v[(
unsigned char)
'I'] = 18;
270 c2v[(
unsigned char)
'j'] =
c2v[(
unsigned char)
'J'] = 19;
271 c2v[(
unsigned char)
'k'] =
c2v[(
unsigned char)
'K'] = 20;
272 c2v[(
unsigned char)
'l'] =
c2v[(
unsigned char)
'L'] = 21;
273 c2v[(
unsigned char)
'm'] =
c2v[(
unsigned char)
'M'] = 22;
274 c2v[(
unsigned char)
'n'] =
c2v[(
unsigned char)
'N'] = 23;
275 c2v[(
unsigned char)
'o'] =
c2v[(
unsigned char)
'O'] = 24;
276 c2v[(
unsigned char)
'p'] =
c2v[(
unsigned char)
'P'] = 25;
277 c2v[(
unsigned char)
'q'] =
c2v[(
unsigned char)
'Q'] = 26;
278 c2v[(
unsigned char)
'r'] =
c2v[(
unsigned char)
'R'] = 27;
279 c2v[(
unsigned char)
's'] =
c2v[(
unsigned char)
'S'] = 28;
280 c2v[(
unsigned char)
't'] =
c2v[(
unsigned char)
'T'] = 29;
281 c2v[(
unsigned char)
'u'] =
c2v[(
unsigned char)
'U'] = 30;
282 c2v[(
unsigned char)
'v'] =
c2v[(
unsigned char)
'V'] = 31;
283 c2v[(
unsigned char)
'w'] =
c2v[(
unsigned char)
'W'] = 32;
284 c2v[(
unsigned char)
'x'] =
c2v[(
unsigned char)
'X'] = 33;
285 c2v[(
unsigned char)
'y'] =
c2v[(
unsigned char)
'Y'] = 34;
286 c2v[(
unsigned char)
'z'] =
c2v[(
unsigned char)
'Z'] = 35;
295 template<u
int8_t base>
299 static const uint64_t INT64_MAX_PLUS_ONE =
static_cast<uint64_t
>(INT64_MAX) + 1;
301 size_t i = start, n = token.length();
306 uint64_t maxb4mul = UINT64_MAX / base;
311 uint8_t vc = ctbl[c];
313 FC_THROW_EXCEPTION( parse_error_exception,
"illegal character {c} in integer of base {b}", (
"c", c)(
"b", base) );
317 uint64_t newval = val + vc;
325 if( token[0] ==
'-' )
327 if( val > INT64_MAX_PLUS_ONE )
330 if( val == INT64_MAX_PLUS_ONE )
337 template<
bool strict, u
int8_t base>
342 return parseInt<base>( token, start );
344 catch(
const parse_error_exception &e )
353 template<
bool strict>
357 size_t i = 0, n = token.length();
359 FC_THROW_EXCEPTION( parse_error_exception,
"expected: non-empty token, got: empty token" );
384 FC_THROW_EXCEPTION( parse_error_exception,
"binary numeric literals not supported in strict mode" );
388 return maybeParseInt<strict, 2>( token, i+1 );
392 FC_THROW_EXCEPTION( parse_error_exception,
"octal numeric literals not supported in strict mode" );
393 return maybeParseInt<strict, 8>( token, i+1 );
397 FC_THROW_EXCEPTION( parse_error_exception,
"hex numeric literals not supported in strict mode" );
398 return maybeParseInt<strict, 16>( token, i+1 );
406 FC_THROW_EXCEPTION( parse_error_exception,
"expected '.'|'e'|'E' parsing number, got '{c}'",
410 case '1':
case '2':
case '3':
case '4':
411 case '5':
case '6':
case '7':
case '8':
case '9':
413 case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 'h':
414 case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
415 case 'q':
case 'r':
case 's':
case 't':
case 'u':
case 'v':
case 'w':
case 'x':
417 case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
418 case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
419 case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
421 case '_':
case '-':
case '.':
case '+':
case '/':
423 FC_THROW_EXCEPTION( parse_error_exception,
"illegal character '{c}' parsing number", (
"c", c ) );
426 FC_THROW_EXCEPTION( parse_error_exception,
"illegal character '{c}' in token", (
"c", c ) );
436 return parseInt<10>( token, start );
441 case '0':
case '1':
case '2':
case '3':
case '4':
442 case '5':
case '6':
case '7':
case '8':
case '9':
452 FC_THROW_EXCEPTION( parse_error_exception,
"number cannot end with '.' in strict mode" );
461 case '0':
case '1':
case '2':
case '3':
case '4':
462 case '5':
case '6':
case '7':
case '8':
case '9':
469 case 'a':
case 'b':
case 'c':
case 'd':
case 'f':
case 'g':
case 'h':
470 case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
471 case 'q':
case 'r':
case 's':
case 't':
case 'u':
case 'v':
case 'w':
case 'x':
473 case 'A':
case 'B':
case 'C':
case 'D':
case 'F':
case 'G':
case 'H':
474 case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
475 case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
477 case '_':
case '-':
case '.':
case '+':
case '/':
482 FC_THROW_EXCEPTION( parse_error_exception,
"illegal character '{c}' in token", (
"c", c )(
"i",
int(c)) );
497 FC_THROW_EXCEPTION( parse_error_exception,
"expected exponent after 'e'|'E' parsing number" );
511 case '0':
case '1':
case '2':
case '3':
case '4':
512 case '5':
case '6':
case '7':
case '8':
case '9':
514 case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 'h':
515 case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
516 case 'q':
case 'r':
case 's':
case 't':
case 'u':
case 'v':
case 'w':
case 'x':
518 case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
519 case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
520 case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
522 case '_':
case '.':
case '/':
524 FC_THROW_EXCEPTION( parse_error_exception,
"illegal character '{c}' in number", (
"c", c ) );
527 FC_THROW_EXCEPTION( parse_error_exception,
"illegal character '{c}' in token", (
"c", c ) );
536 case '0':
case '1':
case '2':
case '3':
case '4':
537 case '5':
case '6':
case '7':
case '8':
case '9':
539 case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 'h':
540 case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
541 case 'q':
case 'r':
case 's':
case 't':
case 'u':
case 'v':
case 'w':
case 'x':
543 case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
544 case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
545 case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
547 case '_':
case '-':
case '.':
case '+':
case '/':
549 FC_THROW_EXCEPTION( parse_error_exception,
"illegal character '{c}' in number", (
"c", c ) );
554 case 'a':
case 'b':
case 'c':
case 'd':
case 'f':
case 'g':
case 'h':
555 case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
556 case 'q':
case 'r':
case 's':
case 't':
case 'u':
case 'v':
case 'w':
case 'x':
558 case 'A':
case 'B':
case 'C':
case 'D':
case 'F':
case 'G':
case 'H':
559 case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
560 case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
562 case '_':
case '-':
case '+':
case '/':
564 FC_THROW_EXCEPTION( parse_error_exception,
"illegal character '{c}' parsing number", (
"c", c ) );
567 FC_THROW_EXCEPTION( parse_error_exception,
"illegal character '{c}' in number", (
"c", c ) );
572 template<
typename T,
bool strict>
575 std::function<std::string(T&)> get_key = []( T& in ){
return json_relaxed::stringFromStream<T, strict>( in ); };
576 std::function<
variant(T&)> get_value = [max_depth]( T& in ){
return json_relaxed::variant_from_stream<T, strict>( in, max_depth ); };
577 return objectFromStreamBase<T>( in, get_key, get_value );
580 template<
typename T,
bool strict>
583 std::function<
variant(T&)> get_value = [max_depth]( T& in ){
return json_relaxed::variant_from_stream<T, strict>( in, max_depth ); };
584 return arrayFromStreamBase<T>( in, get_value );
587 template<
typename T,
bool strict>
591 variant result = json_relaxed::parseNumberOrStr<strict>( token );
597 template<
typename T,
bool strict>
607 if( token ==
"null" )
611 if( token ==
"true" )
615 if( token ==
"false" )
628 template<
typename T,
bool strict>
634 signed char c = in.peek();
638 return json_relaxed::stringFromStream<T, strict>( in );
640 return json_relaxed::objectFromStream<T, strict>( in, max_depth - 1 );
642 return json_relaxed::arrayFromStream<T, strict>( in, max_depth - 1 );
656 return json_relaxed::numberFromStream<T, strict>( in );
658 case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 'h':
659 case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
660 case 'q':
case 'r':
case 's':
case 't':
case 'u':
case 'v':
case 'w':
case 'x':
662 case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
663 case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
664 case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
667 return json_relaxed::wordFromStream<T, strict>( in );