FC Updates from BitShares and myself #21

Closed
nathanielhourt wants to merge 687 commits from dapp-support into latest-fc
2 changed files with 32 additions and 46 deletions
Showing only changes of commit 90137d400d - Show all commits

View file

@ -21,7 +21,7 @@
namespace fc { namespace json_relaxed
{
template<typename T, bool strict>
variant variant_from_stream( T& in );
variant variant_from_stream( T& in, uint32_t depth );
template<typename T>
fc::string tokenFromStream( T& in )
@ -569,16 +569,18 @@ namespace fc { namespace json_relaxed
} FC_CAPTURE_AND_RETHROW( (token) ) }
template<typename T, bool strict>
variant_object objectFromStream( T& in )
variant_object objectFromStream( T& in, uint32_t depth )
{
return objectFromStreamBase<T>( in, []( T& in ){ return json_relaxed::stringFromStream<T, strict>( in ); },
[]( T& in ){ return json_relaxed::variant_from_stream<T, strict>( in ); } );
std::function<std::string(T&)> get_key = []( T& in ){ return json_relaxed::stringFromStream<T, strict>( in ); };
std::function<variant(T&)> get_value = [depth]( T& in ){ return json_relaxed::variant_from_stream<T, strict>( in, depth ); };
return objectFromStreamBase<T>( in, get_key, get_value );
}
template<typename T, bool strict>
variants arrayFromStream( T& in )
variants arrayFromStream( T& in, uint32_t depth )
{
return arrayFromStreamBase<T>( in, []( T& in ){ return json_relaxed::variant_from_stream<T, strict>( in ); } );
std::function<variant(T&)> get_value = [depth]( T& in ){ return json_relaxed::variant_from_stream<T, strict>( in, depth ); };
return arrayFromStreamBase<T>( in, get_value );
}
template<typename T, bool strict>
@ -623,8 +625,9 @@ namespace fc { namespace json_relaxed
}
template<typename T, bool strict>
variant variant_from_stream( T& in )
variant variant_from_stream( T& in, uint32_t depth )
{
FC_ASSERT( depth < MAX_RECURSION_DEPTH, "Too many nested items in JSON string!" );
skip_white_space(in);
signed char c = in.peek();
switch( c )
@ -632,9 +635,9 @@ namespace fc { namespace json_relaxed
case '"':
return json_relaxed::stringFromStream<T, strict>( in );
case '{':
return json_relaxed::objectFromStream<T, strict>( in );
return json_relaxed::objectFromStream<T, strict>( in, depth + 1 );
case '[':
return json_relaxed::arrayFromStream<T, strict>( in );
return json_relaxed::arrayFromStream<T, strict>( in, depth + 1 );
case '-':
case '+':
case '.':

View file

@ -14,15 +14,15 @@
namespace fc
{
// forward declarations of provided functions
template<typename T, json::parse_type parser_type> variant variant_from_stream( T& in );
template<typename T, json::parse_type parser_type> variant variant_from_stream( T& in, uint32_t depth = 0 );
template<typename T> char parseEscape( T& in );
template<typename T> fc::string stringFromStream( T& in );
template<typename T> bool skip_white_space( T& in );
template<typename T> fc::string stringFromToken( T& in );
template<typename T> variant_object objectFromStreamBase( T& in, std::function<std::string(T&)>& get_key, std::function<variant(T&)>& get_value );
template<typename T, json::parse_type parser_type> variant_object objectFromStream( T& in );
template<typename T, json::parse_type parser_type> variant_object objectFromStream( T& in, uint32_t depth );
template<typename T> variants arrayFromStreamBase( T& in, std::function<variant(T&)>& get_value );
template<typename T, json::parse_type parser_type> variants arrayFromStream( T& in );
template<typename T, json::parse_type parser_type> variants arrayFromStream( T& in, uint32_t depth );
template<typename T, json::parse_type parser_type> variant number_from_stream( T& in );
template<typename T> variant token_from_stream( T& in );
void escape_string( const string& str, ostream& os );
@ -32,6 +32,8 @@ namespace fc
fc::string pretty_print( const fc::string& v, uint8_t indent );
}
#define MAX_RECURSION_DEPTH 200
#include <fc/io/json_relaxed.hpp>
namespace fc
@ -169,7 +171,7 @@ namespace fc
}
template<typename T>
variant_object objectFromStreamBase( T& in, std::string (*get_key)(T&), variant (*get_value)(T&) )
variant_object objectFromStreamBase( T& in, std::function<std::string(T&)>& get_key, std::function<variant(T&)>& get_value )
{
mutable_variant_object obj;
try
@ -218,14 +220,15 @@ namespace fc
}
template<typename T, json::parse_type parser_type>
variant_object objectFromStream( T& in )
variant_object objectFromStream( T& in, uint32_t depth )
{
return objectFromStreamBase<T>( in, []( T& in ){ return stringFromStream( in ); },
[]( T& in ){ return variant_from_stream<T, parser_type>( in ); } );
std::function<std::string(T&)> get_key = []( T& in ){ return stringFromStream( in ); };
std::function<variant(T&)> get_value = [depth]( T& in ){ return variant_from_stream<T, parser_type>( in, depth ); };
return objectFromStreamBase<T>( in, get_key, get_value );
}
template<typename T>
variants arrayFromStreamBase( T& in, variant (*get_value)(T&) )
variants arrayFromStreamBase( T& in, std::function<variant(T&)>& get_value )
{
variants ar;
try
@ -255,9 +258,10 @@ namespace fc
}
template<typename T, json::parse_type parser_type>
variants arrayFromStream( T& in )
variants arrayFromStream( T& in, uint32_t depth )
{
return arrayFromStreamBase<T>( in, []( T& in ){ return variant_from_stream<T, parser_type>( in ); } );
std::function<variant(T&)> get_value = [depth]( T& in ){ return variant_from_stream<T, parser_type>( in, depth ); };
return arrayFromStreamBase<T>( in, get_value );
}
template<typename T, json::parse_type parser_type>
@ -401,8 +405,10 @@ namespace fc
template<typename T, json::parse_type parser_type>
variant variant_from_stream( T& in )
variant variant_from_stream( T& in, uint32_t depth )
{
if( depth > MAX_RECURSION_DEPTH )
FC_THROW_EXCEPTION( parse_error_exception, "Too many nested items in JSON input!" );
skip_white_space(in);
signed char c = in.peek();
switch( c )
@ -410,9 +416,9 @@ namespace fc
case '"':
return stringFromStream( in );
case '{':
return objectFromStream<T, parser_type>( in );
return objectFromStream<T, parser_type>( in, depth + 1 );
case '[':
return arrayFromStream<T, parser_type>( in );
return arrayFromStream<T, parser_type>( in, depth + 1 );
case '-':
case '.':
case '0':
@ -441,30 +447,8 @@ namespace fc
}
}
/** the purpose of this check is to verify that we will not get a stack overflow in the recursive descent parser */
void check_string_depth( const string& utf8_str )
{
int32_t open_object = 0;
int32_t open_array = 0;
for( auto c : utf8_str )
{
switch( c )
{
case '{': open_object++; break;
case '}': open_object--; break;
case '[': open_array++; break;
case ']': open_array--; break;
default: break;
}
FC_ASSERT( open_object < 100 && open_array < 100, "object graph too deep", ("object depth",open_object)("array depth", open_array) );
}
}
variant json::from_string( const std::string& utf8_str, parse_type ptype )
{ try {
check_string_depth( utf8_str );
fc::istream_ptr in( new fc::stringstream( utf8_str ) );
fc::buffered_istream bin( in );
return from_stream( bin, ptype );
@ -474,10 +458,9 @@ namespace fc
{
variants result;
try {
check_string_depth( utf8_str );
fc::stringstream in( utf8_str );
while( true )
result.push_back(json_relaxed::variant_from_stream<fc::stringstream, false>( in ));
result.push_back(json_relaxed::variant_from_stream<fc::stringstream, false>( in, 0 ));
} catch ( const fc::eof_exception& ) {
return result;
} FC_RETHROW_EXCEPTIONS( warn, "", ("str",utf8_str) )