- 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:
Eric Frias 2014-04-21 14:34:46 -04:00
parent 7849cc7ada
commit cd34f696ce
4 changed files with 91 additions and 30 deletions

View file

@ -56,7 +56,7 @@ namespace fc
template<typename T>
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 );
}
};

View file

@ -76,6 +76,12 @@ namespace fc { namespace rpc {
const variant& a2,
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>
Result call( const fc::string& method,
const variant& a1,
@ -86,6 +92,17 @@ namespace fc { namespace rpc {
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>
Result call( const fc::string& method,
const variant& a1,

View file

@ -264,37 +264,58 @@ namespace fc
variant token_from_stream( T& in )
{
fc::stringstream ss;
while( char c = in.peek() )
bool parsed_unexpected_character = false;
bool received_eof = false;
try
{
switch( c )
{
case 'n':
case 'u':
case 'l':
case 't':
case 'r':
case 'e':
case 'f':
case 'a':
case 's':
ss.put( in.get() );
break;
default:
{
fc::string str = ss.str();
if( str == "null" ) return variant();
if( str == "true" ) return true;
if( str == "false" ) return false;
else
{
return str;
// FC_THROW_EXCEPTION( parse_error_exception, "Invalid token '${token}'",
// ("token",str) );
}
}
}
char c;
while( (c = in.peek()) && !parsed_unexpected_character)
{
switch( c )
{
case 'n':
case 'u':
case 'l':
case 't':
case 'r':
case 'e':
case 'f':
case 'a':
case 's':
ss.put( in.get() );
break;
default:
parsed_unexpected_character = true;
break;
}
}
}
catch (fc::eof_exception&)
{
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" );
}

View file

@ -406,7 +406,30 @@ namespace fc { namespace rpc {
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 )
{