#pragma once #include #include #include #include #include #include #include #include #include #include //#include namespace fc { namespace detail { void cast_value( const value& v, int8_t& ); void cast_value( const value& v, int16_t& ); void cast_value( const value& v, int32_t& ); void cast_value( const value& v, int64_t& ); void cast_value( const value& v, uint8_t& ); void cast_value( const value& v, uint16_t& ); void cast_value( const value& v, uint32_t& ); void cast_value( const value& v, uint64_t& ); void cast_value( const value& v, double& ); void cast_value( const value& v, float& ); void cast_value( const value& v, bool& ); void cast_value( const value& v, fc::string& ); void cast_value( const value& v, value& ); template void cast_value( const value& v, T& t) { unpack(v,t); } template void cast_value( const value& v, fc::vector& out ) { if( v.type() != value::array_type ) { FC_THROW_REPORT( "Error casting ${type} to array", fc::value("type", fc::reflector::to_string(v.type()) ) ); } out.resize(v.size()); const fc::vector& val = v.as_array(); auto oitr = out.begin(); int idx = 0; for( auto itr = val.begin(); itr != val.end(); ++itr, ++oitr, ++idx ) { try { *oitr = value_cast(*itr); // value_cast( *itr, *oitr ); } catch ( fc::error_report& er ) { throw FC_REPORT_PUSH( er, "Error casting value[${index}] to ${type}", fc::value("index",idx) ("type", fc::get_typename::name()) ); } } } template struct cast_if_tuple { template static T cast( const value& v ) { typename fc::deduce::type out; cast_value(v,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; } }; 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); } }