#pragma once #include #include #include #include #include #include #include #include #include #include //#include namespace fc { namespace detail { template 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_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; }; template<> struct cast_visitor : value::const_visitor { cast_visitor( bool& out ) :m_out(out){} virtual void operator()( const int8_t& v ){ m_out = v != 0; } virtual void operator()( const int16_t& v ){ m_out = v != 0; } virtual void operator()( const int32_t& v ){ m_out = v != 0; } virtual void operator()( const int64_t& v ){ m_out = v != 0; } virtual void operator()( const uint8_t& v ){ m_out = v != 0; } virtual void operator()( const uint16_t& v ){ m_out = v != 0; } virtual void operator()( const uint32_t& v ){ m_out = v != 0; } virtual void operator()( const uint64_t& v ){ m_out = v != 0; } virtual void operator()( const float& v ){ m_out = v != 0; } 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_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; }; template<> 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_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; }; template<> struct cast_visitor : value::const_visitor { cast_visitor( value::array& out ) :m_out(out){} 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; }; template<> struct cast_visitor : value::const_visitor { cast_visitor( value::object& out ) :m_out(out){} 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; }; template<> struct cast_visitor : value::const_visitor { cast_visitor( value& out ) :m_out(out){} virtual void operator()( const int8_t& v ) { m_out = v; } virtual void operator()( const int16_t& v ) { m_out = v; } virtual void operator()( const int32_t& v ) { m_out = v; } virtual void operator()( const int64_t& v ) { m_out = v; } virtual void operator()( const uint8_t& v ) { m_out = v; } virtual void operator()( const uint16_t& v ) { m_out = v; } virtual void operator()( const uint32_t& v ) { m_out = v; } virtual void operator()( const uint64_t& v ) { m_out = v; } virtual void operator()( const float& v ) { m_out = v; } virtual void operator()( const double& v ) { m_out = v; } virtual void operator()( const bool& v ) { m_out = v; } virtual void operator()( const fc::string& v ) { m_out = v; } virtual void operator()( const value::object& a ) { m_out = a; } virtual void operator()( const value::array& a ) { m_out = a; } virtual void operator()( ) { m_out = value(); } value& m_out; }; template struct cast_visitor> : value::const_visitor { cast_visitor( fc::vector& out ) :m_out(out){} 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 ) { 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_REPORT("bad cast");} private: fc::vector& m_out; }; template<> struct cast_visitor : value::const_visitor { 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 struct cast_if_tuple { template static T cast( const value& v ) { typename fc::deduce::type out; v.visit(cast_visitor(out)); return out; } }; template<> struct cast_if_tuple { struct member_visitor { member_visitor( const value& v ) :_val(v),idx(0){} template void operator()( Member& m ) { 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; int idx; }; template static Tuple cast( const value& v ) { typename fc::deduce::type out; out.visit( member_visitor(v) ); return out; } }; template struct cast_if_reflected { template static T cast( const value& v ) { return cast_if_tuple::type>::template cast(v); } }; template<> struct cast_if_reflected { template static T cast( const value& v ) { T tmp; unpack(v,tmp); return tmp; } }; class value_visitor; struct value_holder { virtual ~value_holder(); virtual const char* type()const; virtual void visit( value::const_visitor&& v )const; virtual void visit( value_visitor&& v ); virtual void clear(); virtual size_t size()const; virtual void resize( size_t ); virtual void reserve( size_t ); virtual value& at( size_t ); virtual const value& at( size_t )const; virtual void push_back( value&& v ); virtual value_holder* move_helper( char* c ); virtual value_holder* copy_helper( char* c )const; }; void new_value_holder_void( value* v ); } // namespace detail /** * Convert from value v to T * * Performs the following conversions * true -> 1.0, 1, "true" * * Not all casts are 'clean', the following conversions * could cause errors: * * signed int -> unsigned * large int -> smaller int * real -> int * non-numeric string -> number * object -> string or number * array -> string or number * number,string,array -> object */ template T value_cast( const value& v ) { return detail::cast_if_reflected::type>::is_defined>::template cast< typename fc::deduce::type >(v); } template value::value( const T& v ) { detail::new_value_holder_void(this); fc::pack( *this, v); } template value& value::operator=( const T& v ) { this->~value(); value tmp(v); *this = fc::move(tmp); return *this; } template T value::cast()const { return value_cast(*this); } }