From 68e50ee16642446f8621cad4654d20298165308e Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Fri, 11 Jan 2013 14:13:47 -0500 Subject: [PATCH] update json parsing to be more flexible and report better errors --- include/fc/value_cast.hpp | 201 ++++++++++++++++++++------------------ include/fc/value_io.hpp | 5 + 2 files changed, 113 insertions(+), 93 deletions(-) diff --git a/include/fc/value_cast.hpp b/include/fc/value_cast.hpp index d40f34d..6c4968c 100644 --- a/include/fc/value_cast.hpp +++ b/include/fc/value_cast.hpp @@ -8,6 +8,7 @@ #include #include #include +#include //#include @@ -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(v); } - virtual void operator()( const int16_t& v ){ m_out = fc::numeric_cast(v); } - virtual void operator()( const int32_t& v ){ m_out = fc::numeric_cast(v); } - virtual void operator()( const int64_t& v ){ m_out = fc::numeric_cast(v); } - virtual void operator()( const uint8_t& v ){ m_out = fc::numeric_cast(v); } - virtual void operator()( const uint16_t& v ){ m_out = fc::numeric_cast(v); } - virtual void operator()( const uint32_t& v ){ m_out = fc::numeric_cast(v); } - virtual void operator()( const uint64_t& v ){ m_out = fc::numeric_cast(v); } - virtual void operator()( const float& v ){ m_out = fc::numeric_cast(v); } - virtual void operator()( const double& v ){ m_out = fc::numeric_cast(v); } - virtual void operator()( const bool& v ){ m_out = v; } - virtual void operator()( const fc::string& v ) { m_out = fc::lexical_cast(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(v); } + virtual void operator()( const int16_t& v ) { m_out = fc::numeric_cast(v); } + virtual void operator()( const int32_t& v ) { m_out = fc::numeric_cast(v); } + virtual void operator()( const int64_t& v ) { m_out = fc::numeric_cast(v); } + virtual void operator()( const uint8_t& v ) { m_out = fc::numeric_cast(v); } + virtual void operator()( const uint16_t& v ) { m_out = fc::numeric_cast(v); } + virtual void operator()( const uint32_t& v ) { m_out = fc::numeric_cast(v); } + virtual void operator()( const uint64_t& v ) { m_out = fc::numeric_cast(v); } + virtual void operator()( const float& v ) { m_out = fc::numeric_cast(v); } + virtual void operator()( const double& v ) { m_out = fc::numeric_cast(v); } + virtual void operator()( const bool& v ) { m_out = v; } + virtual void operator()( const fc::string& v ) { m_out = fc::lexical_cast(v); } + virtual void operator()( const value::object& ) { FC_THROW_REPORT("bad cast to ${type} from object", + fc::value().set("type",fc::get_typename::name())); } + virtual void operator()( const value::array& ) { FC_THROW_REPORT("bad cast to ${type} from array", + fc::value().set("type",fc::get_typename::name())); } + virtual void operator()( ) { FC_THROW_REPORT("bad cast to ${type} from null", + fc::value().set("type",fc::get_typename::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 : value::const_visitor { cast_visitor( fc::string& out ) :m_out(out){} - virtual void operator()( const int8_t& v ){ m_out = fc::lexical_cast(v); } - virtual void operator()( const int16_t& v ){ m_out = fc::lexical_cast(v); } - virtual void operator()( const int32_t& v ){ m_out = fc::lexical_cast(v); } - virtual void operator()( const int64_t& v ){ m_out = fc::lexical_cast(v); } - virtual void operator()( const uint8_t& v ){ m_out = fc::lexical_cast(v); } - virtual void operator()( const uint16_t& v ){ m_out = fc::lexical_cast(v); } - virtual void operator()( const uint32_t& v ){ m_out = fc::lexical_cast(v); } - virtual void operator()( const uint64_t& v ){ m_out = fc::lexical_cast(v); } - virtual void operator()( const float& v ){ m_out = fc::lexical_cast(v); } - virtual void operator()( const double& v ){ m_out = fc::lexical_cast(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(v); } + virtual void operator()( const int16_t& v ) { m_out = fc::lexical_cast(v); } + virtual void operator()( const int32_t& v ) { m_out = fc::lexical_cast(v); } + virtual void operator()( const int64_t& v ) { m_out = fc::lexical_cast(v); } + virtual void operator()( const uint8_t& v ) { m_out = fc::lexical_cast(v); } + virtual void operator()( const uint16_t& v ) { m_out = fc::lexical_cast(v); } + virtual void operator()( const uint32_t& v ) { m_out = fc::lexical_cast(v); } + virtual void operator()( const uint64_t& v ) { m_out = fc::lexical_cast(v); } + virtual void operator()( const float& v ) { m_out = fc::lexical_cast(v); } + virtual void operator()( const double& v ) { m_out = fc::lexical_cast(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::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::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> : value::const_visitor { cast_visitor( fc::vector& 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 from int8");} + virtual void operator()( const int16_t& v ) { FC_THROW_REPORT("bad cast to vector from int16");} + virtual void operator()( const int32_t& v ) { FC_THROW_REPORT("bad cast to vector from int32");} + virtual void operator()( const int64_t& v ) { FC_THROW_REPORT("bad cast to vector from int64");} + virtual void operator()( const uint8_t& v ) { FC_THROW_REPORT("bad cast to vector from uint8");} + virtual void operator()( const uint16_t& v ) { FC_THROW_REPORT("bad cast to vector from uint16");} + virtual void operator()( const uint32_t& v ) { FC_THROW_REPORT("bad cast to vector from uint32");} + virtual void operator()( const uint64_t& v ) { FC_THROW_REPORT("bad cast to vector from uint64");} + virtual void operator()( const float& v ) { FC_THROW_REPORT("bad cast to vector from float");} + virtual void operator()( const double& v ) { FC_THROW_REPORT("bad cast to vector from double");} + virtual void operator()( const bool& v ) { FC_THROW_REPORT("bad cast to vector from bool");} + virtual void operator()( const fc::string& v ) { FC_THROW_REPORT("bad cast to vector from string");} + virtual void operator()( const value::object& a ) { FC_THROW_REPORT("bad cast to vector 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( *i ) ); + try { + m_out.push_back( value_cast( *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::name()) ); + } + ++idx; } } - virtual void operator()( ) { FC_THROW_MSG("bad cast");} + virtual void operator()( ) { FC_THROW_REPORT("bad cast");} private: fc::vector& m_out; @@ -189,20 +200,20 @@ namespace fc { template<> struct cast_visitor : 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 @@ -221,7 +232,11 @@ namespace fc { :_val(v),idx(0){} template void operator()( Member& m ) { - m = value_cast(_val[idx]); + try { + m = value_cast(_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; diff --git a/include/fc/value_io.hpp b/include/fc/value_io.hpp index 9cd1225..d839d2c 100644 --- a/include/fc/value_io.hpp +++ b/include/fc/value_io.hpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace fc { template @@ -129,7 +130,11 @@ namespace fc { template 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::type >::type::value ) {