- Add four-argument version of json-rpc call function
- fix bug in json parser that prevented correct parsing of a true/false/null at the end of input - prevent infinite recursion in a json helper function
This commit is contained in:
parent
7849cc7ada
commit
cd34f696ce
4 changed files with 91 additions and 30 deletions
|
|
@ -56,7 +56,7 @@ namespace fc
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static void save_to_file( const T& v, const string& p, bool pretty = true )
|
static void save_to_file( const T& v, const string& p, bool pretty = true )
|
||||||
{
|
{
|
||||||
save_to_file( variant(v), p, pretty );
|
save_to_file( variant(v), fc::path(p), pretty );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,12 @@ namespace fc { namespace rpc {
|
||||||
const variant& a2,
|
const variant& a2,
|
||||||
const variant& a3 );
|
const variant& a3 );
|
||||||
|
|
||||||
|
future<variant> async_call( const fc::string& method,
|
||||||
|
const variant& a1,
|
||||||
|
const variant& a2,
|
||||||
|
const variant& a3,
|
||||||
|
const variant& a4 );
|
||||||
|
|
||||||
template<typename Result>
|
template<typename Result>
|
||||||
Result call( const fc::string& method,
|
Result call( const fc::string& method,
|
||||||
const variant& a1,
|
const variant& a1,
|
||||||
|
|
@ -86,6 +92,17 @@ namespace fc { namespace rpc {
|
||||||
return async_call( method, a1, a2, a3 ).wait(timeout).as<Result>();
|
return async_call( method, a1, a2, a3 ).wait(timeout).as<Result>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Result>
|
||||||
|
Result call( const fc::string& method,
|
||||||
|
const variant& a1,
|
||||||
|
const variant& a2,
|
||||||
|
const variant& a3,
|
||||||
|
const variant& a4,
|
||||||
|
microseconds timeout = microseconds::maximum())
|
||||||
|
{
|
||||||
|
return async_call( method, a1, a2, a3, a4).wait(timeout).as<Result>();
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Result>
|
template<typename Result>
|
||||||
Result call( const fc::string& method,
|
Result call( const fc::string& method,
|
||||||
const variant& a1,
|
const variant& a1,
|
||||||
|
|
|
||||||
|
|
@ -264,37 +264,58 @@ namespace fc
|
||||||
variant token_from_stream( T& in )
|
variant token_from_stream( T& in )
|
||||||
{
|
{
|
||||||
fc::stringstream ss;
|
fc::stringstream ss;
|
||||||
while( char c = in.peek() )
|
bool parsed_unexpected_character = false;
|
||||||
|
bool received_eof = false;
|
||||||
|
try
|
||||||
{
|
{
|
||||||
switch( c )
|
char c;
|
||||||
{
|
while( (c = in.peek()) && !parsed_unexpected_character)
|
||||||
case 'n':
|
{
|
||||||
case 'u':
|
switch( c )
|
||||||
case 'l':
|
{
|
||||||
case 't':
|
case 'n':
|
||||||
case 'r':
|
case 'u':
|
||||||
case 'e':
|
case 'l':
|
||||||
case 'f':
|
case 't':
|
||||||
case 'a':
|
case 'r':
|
||||||
case 's':
|
case 'e':
|
||||||
ss.put( in.get() );
|
case 'f':
|
||||||
break;
|
case 'a':
|
||||||
default:
|
case 's':
|
||||||
{
|
ss.put( in.get() );
|
||||||
fc::string str = ss.str();
|
break;
|
||||||
if( str == "null" ) return variant();
|
default:
|
||||||
if( str == "true" ) return true;
|
parsed_unexpected_character = true;
|
||||||
if( str == "false" ) return false;
|
break;
|
||||||
else
|
}
|
||||||
{
|
}
|
||||||
return str;
|
}
|
||||||
// FC_THROW_EXCEPTION( parse_error_exception, "Invalid token '${token}'",
|
catch (fc::eof_exception&)
|
||||||
// ("token",str) );
|
{
|
||||||
}
|
received_eof = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// we can get here either by processing a delimiter as in "null,"
|
||||||
|
// an EOF like "null<EOF>", or an invalid token like "nullZ"
|
||||||
|
fc::string str = ss.str();
|
||||||
|
if( str == "null" ) return variant();
|
||||||
|
if( str == "true" ) return true;
|
||||||
|
if( str == "false" ) return false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (received_eof)
|
||||||
|
FC_THROW_EXCEPTION( parse_error_exception, "Unexpected EOF" );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// I'm not sure why we do this, a comment would be helpful.
|
||||||
|
// if we've reached this point, we've either seen a partial
|
||||||
|
// token ("tru<EOF>") or something our simple parser couldn't
|
||||||
|
// make out ("falfe")
|
||||||
|
return str;
|
||||||
|
// FC_THROW_EXCEPTION( parse_error_exception, "Invalid token '${token}'",
|
||||||
|
// ("token",str) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
FC_THROW_EXCEPTION( parse_error_exception, "Unexpected EOF" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -406,7 +406,30 @@ namespace fc { namespace rpc {
|
||||||
return my->_awaiting[id];
|
return my->_awaiting[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
future<variant> json_connection::async_call( const fc::string& method, const variant& a1, const variant& a2, const variant& a3, const variant& a4 )
|
||||||
|
{
|
||||||
|
auto id = my->_next_id++;
|
||||||
|
my->_awaiting[id] = fc::promise<variant>::ptr( new fc::promise<variant>() );
|
||||||
|
|
||||||
|
{
|
||||||
|
fc::scoped_lock<fc::mutex> lock(my->_write_mutex);
|
||||||
|
*my->_out << "{\"id\":";
|
||||||
|
*my->_out << id;
|
||||||
|
*my->_out << ",\"method\":";
|
||||||
|
json::to_stream( *my->_out, method );
|
||||||
|
*my->_out << ",\"params\":[";
|
||||||
|
fc::json::to_stream( *my->_out, a1 );
|
||||||
|
*my->_out << ",";
|
||||||
|
fc::json::to_stream( *my->_out, a2 );
|
||||||
|
*my->_out << ",";
|
||||||
|
fc::json::to_stream( *my->_out, a3 );
|
||||||
|
*my->_out << ",";
|
||||||
|
fc::json::to_stream( *my->_out, a4 );
|
||||||
|
*my->_out << "]}\n";
|
||||||
|
}
|
||||||
|
my->_out->flush();
|
||||||
|
return my->_awaiting[id];
|
||||||
|
}
|
||||||
|
|
||||||
future<variant> json_connection::async_call( const fc::string& method, mutable_variant_object named_args )
|
future<variant> json_connection::async_call( const fc::string& method, mutable_variant_object named_args )
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue