11#include <boost/filesystem/fstream.hpp>
38 if( in.peek() ==
'\\' )
91 std::stringstream token;
98 "Expected '\"' but read '${char}'",
99 (
"char",
string(&c, (&c) + 1) ) );
103 switch( c = in.peek() )
109 FC_THROW_EXCEPTION( parse_error_exception,
"EOF before closing '\"' in string '${token}'",
110 (
"token", token.str() ) );
119 FC_THROW_EXCEPTION( parse_error_exception,
"EOF before closing '\"' in string '${token}'",
120 (
"token", token.str() ) );
122 (
"token", token.str() ) );
127 std::stringstream token;
134 switch( c = in.peek() )
147 if( isalnum( c ) || c ==
'_' || c ==
'-' || c ==
'.' || c ==
':' || c ==
'/' )
152 else return token.str();
157 catch(
const fc::eof_exception& eof )
161 catch (
const std::ios_base::failure&)
167 (
"token", token.str() ) );
170 template<
typename T, json::parse_type parser_type>
179 "Expected '{', but read '${char}'",
180 (
"char",
string(&c, &c + 1)) );
182 while( in.peek() !=
'}' )
184 if( in.peek() ==
',' )
192 if( in.peek() !=
':' )
200 obj(std::move(key),std::move(val));
203 if( in.peek() ==
'}' )
208 FC_THROW_EXCEPTION( parse_error_exception,
"Expected '}' after ${variant}", (
"variant", obj ) );
210 catch(
const fc::eof_exception& e )
212 FC_THROW_EXCEPTION( parse_error_exception,
"Unexpected EOF: ${e}", (
"e", e.to_detail_string() ) );
214 catch(
const std::ios_base::failure& e )
216 FC_THROW_EXCEPTION( parse_error_exception,
"Unexpected EOF: ${e}", (
"e", e.what() ) );
220 template<
typename T, json::parse_type parser_type>
226 if( in.peek() !=
'[' )
231 while( in.peek() !=
']' )
233 if( in.peek() ==
',' )
242 if( in.peek() !=
']' )
252 template<
typename T, json::parse_type parser_type>
255 std::stringstream ss;
259 if( in.peek() ==
'-')
275 FC_THROW_EXCEPTION(parse_error_exception,
"Can't parse a number with two decimal places");
301 catch (fc::eof_exception&)
304 catch (
const std::ios_base::failure&)
307 std::string str = ss.str();
308 if (str ==
"-." || str ==
"." || str ==
"-")
309 FC_THROW_EXCEPTION(parse_error_exception,
"Can't parse token \"${token}\" as a JSON numeric constant", (
"token", str));
319 std::stringstream ss;
320 ss.exceptions( std::ifstream::badbit );
321 bool received_eof =
false;
327 while((c = in.peek()) && !done)
348 catch (fc::eof_exception&)
352 catch (
const std::ios_base::failure&)
359 std::string str = ss.str();
388 template<
typename T, json::parse_type parser_type>
397 signed char c = in.peek();
444 std::stringstream in( utf8_str );
457 FC_ASSERT(
false,
"Unknown JSON parser type {ptype}", (
"ptype",
static_cast<int>(ptype)) );
464 std::stringstream in( utf8_str );
472 }
catch (
const fc::eof_exception& ){}
498 const auto init_size = str.size();
499 r.reserve( init_size + 13 );
501 for(
auto itr = str.begin(); itr != str.end(); ++i,++itr )
506 case '\x00':
r +=
"\\u0000";
break;
507 case '\x01':
r +=
"\\u0001";
break;
508 case '\x02':
r +=
"\\u0002";
break;
509 case '\x03':
r +=
"\\u0003";
break;
510 case '\x04':
r +=
"\\u0004";
break;
511 case '\x05':
r +=
"\\u0005";
break;
512 case '\x06':
r +=
"\\u0006";
break;
513 case '\x07':
r +=
"\\u0007";
break;
514 case '\x08':
r +=
"\\u0008";
break;
517 case '\x0b':
r +=
"\\u000b";
break;
518 case '\x0c':
r +=
"\\u000c";
break;
520 case '\x0e':
r +=
"\\u000e";
break;
521 case '\x0f':
r +=
"\\u000f";
break;
522 case '\x10':
r +=
"\\u0010";
break;
523 case '\x11':
r +=
"\\u0011";
break;
524 case '\x12':
r +=
"\\u0012";
break;
525 case '\x13':
r +=
"\\u0013";
break;
526 case '\x14':
r +=
"\\u0014";
break;
527 case '\x15':
r +=
"\\u0015";
break;
528 case '\x16':
r +=
"\\u0016";
break;
529 case '\x17':
r +=
"\\u0017";
break;
530 case '\x18':
r +=
"\\u0018";
break;
531 case '\x19':
r +=
"\\u0019";
break;
532 case '\x1a':
r +=
"\\u001a";
break;
533 case '\x1b':
r +=
"\\u001b";
break;
534 case '\x1c':
r +=
"\\u001c";
break;
535 case '\x1d':
r +=
"\\u001d";
break;
536 case '\x1e':
r +=
"\\u001e";
break;
537 case '\x1f':
r +=
"\\u001f";
break;
539 case '\x7f':
r +=
"\\u007f";
break;
543 if( escape_control_chars ) {
548 if( escape_control_chars ) {
553 if( escape_control_chars ) {
558 if( escape_control_chars ) {
563 if( escape_control_chars ) {
580 auto itr =
a.begin();
582 while( itr !=
a.end() )
597 auto itr = o.
begin();
599 while( itr != o.
end() )
676 std::stringstream ss;
684 std::stringstream ss;
688 for(
uint32_t i = 0; i < v.size(); ++i ) {
694 }
else { escape =
false; }
707 for(
int i = 0; i < level*indent; ++i ) ss<<
' ';
729 if( v[i-1] !=
'[' && v[i-1] !=
'{' ) {
734 for(
int i = 0; i < level*indent; ++i ) ss<<
' ';
760 if( quote && escape )
766 for(
int i = 0; i < level*indent; ++i ) ss<<
' ';
786 o.write( str.c_str(), str.size() );
790 const auto yield = [&](
size_t s) {
802 boost::filesystem::ifstream bi(
p, std::ios::binary );
814 FC_ASSERT(
false,
"Unknown JSON parser type {ptype}", (
"ptype",
static_cast<int>(ptype)) );
838 if( utf8_str.size() == 0 )
return false;
839 std::stringstream in( utf8_str );
855 FC_ASSERT(
false,
"Unknown JSON parser type {ptype}", (
"ptype",
static_cast<int>(ptype)) );
857 try { in.peek(); }
catch (
const eof_exception& e ) {
return true; }
static variant from_file(const fc::path &p, const parse_type ptype=parse_type::legacy_parser, const uint32_t max_depth=DEFAULT_MAX_RECURSION_DEPTH)
static bool is_valid(const std::string &json_str, const parse_type ptype=parse_type::legacy_parser, const uint32_t max_depth=DEFAULT_MAX_RECURSION_DEPTH)
@ legacy_parser_with_string_doubles
static bool save_to_file(const T &v, const fc::path &fi, const bool pretty=true, const output_formatting format=output_formatting::stringify_large_ints_and_doubles)
static constexpr size_t escape_string_yield_check_count
static string to_string(const variant &v, const yield_function_t &yield, const output_formatting format=output_formatting::stringify_large_ints_and_doubles)
static variants variants_from_string(const string &utf8_str, const parse_type ptype=parse_type::legacy_parser, uint32_t max_depth=DEFAULT_MAX_RECURSION_DEPTH)
fc::optional_delegate< void(size_t)> yield_function_t
static constexpr uint64_t max_length_limit
static string to_pretty_string(const variant &v, const yield_function_t &yield, const output_formatting format=output_formatting::stringify_large_ints_and_doubles)
static variant from_string(const string &utf8_str, const parse_type ptype=parse_type::legacy_parser, uint32_t max_depth=DEFAULT_MAX_RECURSION_DEPTH)
@ stringify_large_ints_and_doubles
An order-preserving dictionary of variants.
wraps boost::filesystem::path to provide platform independent path manipulation.
std::string generic_string() const
static constexpr time_point maximum()
An order-preserving dictionary of variants.
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object's.
variant_object & get_object()
const string & get_string() const
uint64_t as_uint64() const
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
#define FC_RETHROW_EXCEPTIONS(LOG_LEVEL, FORMAT,...)
Catchs all exception's, std::exceptions, and ... and rethrows them after appending the provided log m...
variant variant_from_stream(T &in, uint32_t max_depth)
variant number_from_stream(T &in)
std::string stringFromToken(T &in)
std::string stringFromStream(T &in)
bool is_valid_utf8(const std::string_view &str)
variant_object objectFromStream(T &in, uint32_t max_depth)
std::vector< fc::variant > variants
bool skip_white_space(T &in)
double to_double(const fc::string &)
uint64_t to_uint64(const fc::string &)
variant token_from_stream(T &in)
variants arrayFromStream(T &in, uint32_t max_depth)
std::string pretty_print(const std::string &v, uint8_t indent)
variant variant_from_stream(T &in, uint32_t max_depth)
std::string escape_string(const std::string_view &str, const json::yield_function_t &yield, bool escape_control_chars=true)
void to_stream(T &os, const variants &a, const json::yield_function_t &yield, json::output_formatting format)
std::string prune_invalid_utf8(const std::string_view &str)
int64_t to_int64(const fc::string &)
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
#define T(meth, val, expected)
unsigned __int64 uint64_t
void neg(const Operand &op)