update json parsing to be more flexible and report better errors

This commit is contained in:
Daniel Larimer 2013-01-11 14:13:47 -05:00
parent 38f97ef61a
commit 68e50ee166
2 changed files with 113 additions and 93 deletions

View file

@ -8,6 +8,7 @@
#include <fc/tuple.hpp>
#include <fc/vector.hpp>
#include <fc/typename.hpp>
#include <fc/error_report.hpp>
//#include <typeinfo>
@ -19,21 +20,24 @@ namespace fc {
struct cast_visitor : value::const_visitor {
cast_visitor( T& out )
:m_out(out){}
virtual void operator()( const int8_t& v ){ m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const int16_t& v ){ m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const int32_t& v ){ m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const int64_t& v ){ m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const uint8_t& v ){ m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const uint16_t& v ){ m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const uint32_t& v ){ m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const uint64_t& v ){ m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const float& v ){ m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const double& v ){ m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const bool& v ){ m_out = v; }
virtual void operator()( const fc::string& v ) { m_out = fc::lexical_cast<T>(v); }
virtual void operator()( const value::object& ) { FC_THROW_MSG("bad cast"); }
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast"); }
virtual void operator()( ) { FC_THROW_MSG("bad cast"); }
virtual void operator()( const int8_t& v ) { m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const int16_t& v ) { m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const int32_t& v ) { m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const int64_t& v ) { m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const uint8_t& v ) { m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const uint16_t& v ) { m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const uint32_t& v ) { m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const uint64_t& v ) { m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const float& v ) { m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const double& v ) { m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const bool& v ) { m_out = v; }
virtual void operator()( const fc::string& v ) { m_out = fc::lexical_cast<T>(v); }
virtual void operator()( const value::object& ) { FC_THROW_REPORT("bad cast to ${type} from object",
fc::value().set("type",fc::get_typename<T>::name())); }
virtual void operator()( const value::array& ) { FC_THROW_REPORT("bad cast to ${type} from array",
fc::value().set("type",fc::get_typename<T>::name())); }
virtual void operator()( ) { FC_THROW_REPORT("bad cast to ${type} from null",
fc::value().set("type",fc::get_typename<T>::name())); }
private:
T& m_out;
};
@ -53,9 +57,9 @@ namespace fc {
virtual void operator()( const double& v ){ m_out = v != 0; }
virtual void operator()( const bool& v ){ m_out = v; }
virtual void operator()( const fc::string& v ) { m_out = !(v != "true"); }
virtual void operator()( const value::object& ) { FC_THROW_MSG("bad cast"); }
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast"); }
virtual void operator()( ) { FC_THROW_MSG("bad cast"); }
virtual void operator()( const value::object& ) { FC_THROW_REPORT("bad cast to bool from object"); }
virtual void operator()( const value::array& ) { FC_THROW_REPORT("bad cast to bool from array"); }
virtual void operator()( ) { FC_THROW_REPORT("bad cast to bool from null"); }
private:
bool& m_out;
};
@ -64,21 +68,21 @@ namespace fc {
struct cast_visitor<fc::string> : value::const_visitor {
cast_visitor( fc::string& out )
:m_out(out){}
virtual void operator()( const int8_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const int16_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const int32_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const int64_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const uint8_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const uint16_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const uint32_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const uint64_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const float& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const double& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const bool& v ){ m_out = v != 0 ? "true" : "false"; }
virtual void operator()( const fc::string& v ) { m_out = v; }
virtual void operator()( const value::object& ) { FC_THROW_MSG("bad cast"); }
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast"); }
virtual void operator()( ) { FC_THROW_MSG("bad cast"); }
virtual void operator()( const int8_t& v ) { m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const int16_t& v ) { m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const int32_t& v ) { m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const int64_t& v ) { m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const uint8_t& v ) { m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const uint16_t& v ) { m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const uint32_t& v ) { m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const uint64_t& v ) { m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const float& v ) { m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const double& v ) { m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const bool& v ) { m_out = v != 0 ? "true" : "false"; }
virtual void operator()( const fc::string& v ) { m_out = v; }
virtual void operator()( const value::object& ){ FC_THROW_REPORT("bad cast to string from object"); }
virtual void operator()( const value::array& ) { FC_THROW_REPORT("bad cast to string from array"); }
virtual void operator()( ) { m_out = fc::string(); }
private:
fc::string& m_out;
@ -88,21 +92,21 @@ namespace fc {
struct cast_visitor<value::array> : value::const_visitor {
cast_visitor( value::array& out )
:m_out(out){}
virtual void operator()( const int8_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const int16_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const int32_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const int64_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const uint8_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const uint16_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const uint32_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const uint64_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const float& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const double& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const bool& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const fc::string& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const value::object& ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const value::array& a ) { m_out = a; }
virtual void operator()( ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const int8_t& v ) { FC_THROW_REPORT("bad cast to array from int8");}
virtual void operator()( const int16_t& v ) { FC_THROW_REPORT("bad cast to array from int16");}
virtual void operator()( const int32_t& v ) { FC_THROW_REPORT("bad cast to array from int32");}
virtual void operator()( const int64_t& v ) { FC_THROW_REPORT("bad cast to array from int32");}
virtual void operator()( const uint8_t& v ) { FC_THROW_REPORT("bad cast to array from uint8");}
virtual void operator()( const uint16_t& v ) { FC_THROW_REPORT("bad cast to array from uint16");}
virtual void operator()( const uint32_t& v ) { FC_THROW_REPORT("bad cast to array from uint32");}
virtual void operator()( const uint64_t& v ) { FC_THROW_REPORT("bad cast to array from uint64");}
virtual void operator()( const float& v ) { FC_THROW_REPORT("bad cast to array from float");}
virtual void operator()( const double& v ) { FC_THROW_REPORT("bad cast to array from double");}
virtual void operator()( const bool& v ) { FC_THROW_REPORT("bad cast to array from bool");}
virtual void operator()( const fc::string& v ) { FC_THROW_REPORT("bad cast to array from string");}
virtual void operator()( const value::object& ) { FC_THROW_REPORT("bad cast to array from object");}
virtual void operator()( const value::array& a ) { m_out = a; }
virtual void operator()( ) { m_out = value::array(); }
private:
value::array& m_out;
@ -112,21 +116,21 @@ namespace fc {
struct cast_visitor<value::object> : value::const_visitor {
cast_visitor( value::object& out )
:m_out(out){}
virtual void operator()( const int8_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const int16_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const int32_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const int64_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const uint8_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const uint16_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const uint32_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const uint64_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const float& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const double& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const bool& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const fc::string& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const value::object& a ) { m_out = a; }
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast");}
virtual void operator()( ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const int8_t& v ){ FC_THROW_REPORT("bad cast to array from int8");}
virtual void operator()( const int16_t& v ){ FC_THROW_REPORT("bad cast to array from int16");}
virtual void operator()( const int32_t& v ){ FC_THROW_REPORT("bad cast to array from int32");}
virtual void operator()( const int64_t& v ){ FC_THROW_REPORT("bad cast to array from int32");}
virtual void operator()( const uint8_t& v ){ FC_THROW_REPORT("bad cast to array from uint8");}
virtual void operator()( const uint16_t& v ){ FC_THROW_REPORT("bad cast to array from uint16");}
virtual void operator()( const uint32_t& v ){ FC_THROW_REPORT("bad cast to array from uint32");}
virtual void operator()( const uint64_t& v ){ FC_THROW_REPORT("bad cast to array from uint64");}
virtual void operator()( const float& v ){ FC_THROW_REPORT("bad cast to array from float");}
virtual void operator()( const double& v ){ FC_THROW_REPORT("bad cast to array from double");}
virtual void operator()( const bool& v ){ FC_THROW_REPORT("bad cast to array from bool");}
virtual void operator()( const fc::string& v ) { FC_THROW_REPORT("bad cast to array from string");}
virtual void operator()( const value::object& a ) { m_out = a; }
virtual void operator()( const value::array& ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( ) { m_out = value::object(); }
private:
value::object& m_out;
@ -158,28 +162,35 @@ namespace fc {
struct cast_visitor<fc::vector<T>> : value::const_visitor {
cast_visitor( fc::vector<T>& out )
:m_out(out){}
virtual void operator()( const int8_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const int16_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const int32_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const int64_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const uint8_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const uint16_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const uint32_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const uint64_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const float& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const double& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const bool& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const fc::string& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const value::object& a ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const int8_t& v ) { FC_THROW_REPORT("bad cast to vector<T> from int8");}
virtual void operator()( const int16_t& v ) { FC_THROW_REPORT("bad cast to vector<T> from int16");}
virtual void operator()( const int32_t& v ) { FC_THROW_REPORT("bad cast to vector<T> from int32");}
virtual void operator()( const int64_t& v ) { FC_THROW_REPORT("bad cast to vector<T> from int64");}
virtual void operator()( const uint8_t& v ) { FC_THROW_REPORT("bad cast to vector<T> from uint8");}
virtual void operator()( const uint16_t& v ) { FC_THROW_REPORT("bad cast to vector<T> from uint16");}
virtual void operator()( const uint32_t& v ) { FC_THROW_REPORT("bad cast to vector<T> from uint32");}
virtual void operator()( const uint64_t& v ) { FC_THROW_REPORT("bad cast to vector<T> from uint64");}
virtual void operator()( const float& v ) { FC_THROW_REPORT("bad cast to vector<T> from float");}
virtual void operator()( const double& v ) { FC_THROW_REPORT("bad cast to vector<T> from double");}
virtual void operator()( const bool& v ) { FC_THROW_REPORT("bad cast to vector<T> from bool");}
virtual void operator()( const fc::string& v ) { FC_THROW_REPORT("bad cast to vector<T> from string");}
virtual void operator()( const value::object& a ) { FC_THROW_REPORT("bad cast to vector<T> from object");}
virtual void operator()( const value::array& a ) {
m_out.resize(0);
m_out.reserve( a.fields.size() );
int idx = 0;
for( auto i = a.fields.begin(); i != a.fields.end(); ++i ) {
m_out.push_back( value_cast<T>( *i ) );
try {
m_out.push_back( value_cast<T>( *i ) );
} catch( fc::error_report& er ) {
throw FC_REPORT_PUSH( er, "Error parsing array index ${index} to ${type}",
fc::value().set("index", idx).set("type",fc::get_typename<T>::name()) );
}
++idx;
}
}
virtual void operator()( ) { FC_THROW_MSG("bad cast");}
virtual void operator()( ) { FC_THROW_REPORT("bad cast");}
private:
fc::vector<T>& m_out;
@ -189,20 +200,20 @@ namespace fc {
template<>
struct cast_visitor<void> : value::const_visitor {
virtual void operator()( const int8_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const int16_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const int32_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const int64_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const uint8_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const uint16_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const uint32_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const uint64_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const float& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const double& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const bool& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const fc::string& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const value::object& a ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const int8_t& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const int16_t& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const int32_t& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const int64_t& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const uint8_t& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const uint16_t& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const uint32_t& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const uint64_t& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const float& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const double& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const bool& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const fc::string& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const value::object& a ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const value::array& ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( ) { }
};
template<typename IsTuple=fc::false_type>
@ -221,7 +232,11 @@ namespace fc {
:_val(v),idx(0){}
template<typename Member>
void operator()( Member& m ) {
m = value_cast<Member>(_val[idx]);
try {
m = value_cast<Member>(_val[idx]);
} catch ( fc::error_report& er ) {
throw FC_REPORT_PUSH( er, "Error parsing tuple element ${index}", fc::value().set("index",idx) );
}
++idx;
}
const value& _val;

View file

@ -5,6 +5,7 @@
#include <fc/value.hpp>
#include <fc/value_cast.hpp>
#include <fc/tuple.hpp>
#include <fc/error_report.hpp>
namespace fc {
template<typename T>
@ -129,7 +130,11 @@ namespace fc {
template<typename T, typename C, T (C::*p)>
void operator()( const char* name )const {
if( obj.find(name) != obj.end()) {
try {
fc::unpack( obj[name], c.*p );
} catch ( fc::error_report& er ) {
throw FC_REPORT_PUSH( er, "Error parsing field '${field_name}'", fc::value().set("field_name",name) );
}
}
else {
if( !is_optional< typename fc::remove_reference<decltype(c.*p)>::type >::type::value ) {