#include #include #include #include #include namespace fc { namespace detail { class value_visitor { public: virtual void operator()( int8_t& v ){}; virtual void operator()( int16_t& v ){}; virtual void operator()( int32_t& v ){}; virtual void operator()( int64_t& v ){}; virtual void operator()( uint8_t& v ){}; virtual void operator()( uint16_t& v ){}; virtual void operator()( uint32_t& v ){}; virtual void operator()( uint64_t& v ){}; virtual void operator()( float& v ){}; virtual void operator()( double& v ){}; virtual void operator()( bool& v ){}; virtual void operator()( fc::string& v ){}; virtual void operator()( value::object& ){}; virtual void operator()( value::array& ){}; virtual void operator()( ){}; }; 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 { 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()( ) { } }; void cast_value( const value& v, int8_t& out ){ v.visit( cast_visitor(out) ); } void cast_value( const value& v, int16_t& out ){ v.visit( cast_visitor(out) ); } void cast_value( const value& v, int32_t& out ){ v.visit( cast_visitor(out) ); } void cast_value( const value& v, int64_t& out ){ v.visit( cast_visitor(out) ); } void cast_value( const value& v, uint8_t& out ){ v.visit( cast_visitor(out) ); } void cast_value( const value& v, uint16_t& out ){ v.visit( cast_visitor(out) ); } void cast_value( const value& v, uint32_t& out ){ v.visit( cast_visitor(out) ); } void cast_value( const value& v, uint64_t& out ){ v.visit( cast_visitor(out) ); } void cast_value( const value& v, double& out ){ v.visit( cast_visitor(out) ); } void cast_value( const value& v, float& out ){ v.visit( cast_visitor(out) ); } void cast_value( const value& v, bool& out ){ v.visit( cast_visitor(out) ); } void cast_value( const value& v, fc::string& out ){ v.visit( cast_visitor(out) ); } void cast_value( const value& v, value& out ){ out = v; } struct value_holder { virtual ~value_holder(); virtual value::value_type type()const; const char* get_typename()const { return fc::reflector::to_string(type()); } 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 value_holder::visit( value::const_visitor&& v )const {v(); } void value_holder::visit( value_visitor&& v ) {v(); } template struct get_value_type{}; template<> struct get_value_type { static value::value_type type(){ return value::null_type; } }; template<> struct get_value_type { static value::value_type type(){ return value::int8_type; } }; template<> struct get_value_type{ static value::value_type type(){ return value::int16_type; } }; template<> struct get_value_type{ static value::value_type type(){ return value::int32_type; } }; template<> struct get_value_type{ static value::value_type type(){ return value::int64_type; } }; template<> struct get_value_type{ static value::value_type type(){ return value::uint8_type; } }; template<> struct get_value_type{ static value::value_type type(){ return value::uint16_type; } }; template<> struct get_value_type{ static value::value_type type(){ return value::uint32_type; } }; template<> struct get_value_type{ static value::value_type type(){ return value::uint64_type; } }; template<> struct get_value_type{ static value::value_type type(){ return value::double_type; } }; template<> struct get_value_type{ static value::value_type type(){ return value::float_type; } }; template<> struct get_value_type{ static value::value_type type(){ return value::string_type; } }; template<> struct get_value_type{ static value::value_type type(){ return value::bool_type; } }; template<> struct get_value_type>{ static value::value_type type(){ return value::array_type; } }; template<> struct get_value_type{ static value::value_type type(){ return value::object_type; } }; // fundamental values... template struct value_holder_impl : value_holder { static_assert( !fc::is_class::value, "only fundamental types can be stored without specialization" ); value_holder_impl(){ static_assert( sizeof(value_holder_impl) <= 40, "Validate size" ); } virtual value::value_type type()const { return get_value_type::type(); } virtual void visit( value::const_visitor&& v )const{ v(val); } virtual void visit( value_visitor&& v ) { v(val); } virtual void clear() { val = T(); } virtual size_t size()const { return 0; } virtual value_holder* move_helper( char* c ){ return new(c) value_holder_impl( fc::move(val) ); } virtual value_holder* copy_helper( char* c )const{ return new(c) value_holder_impl(val); } template value_holder_impl( V&& v ):val( fc::forward(v) ){} T val; }; template<> struct value_holder_impl : value_holder { value_holder_impl(){}; virtual void visit( value::const_visitor&& v )const{ v(); } virtual void visit( value_visitor&& v ) { v(); } virtual value_holder* move_helper( char* c ) { return new(c) value_holder_impl(); } virtual value_holder* copy_helper( char* c )const{ return new(c) value_holder_impl(); } }; template<> struct value_holder_impl : value_holder { template value_holder_impl( V&& v ):val( fc::forward(v) ){ static_assert( sizeof(value_holder_impl) <= 40, "Validate size" ); } virtual value::value_type type()const { return value::string_type; } virtual void visit( value::const_visitor&& v )const { v(val); } virtual void visit( value_visitor&& v ) { v(val); } virtual value_holder* move_helper( char* c ){ return new(c) value_holder_impl( fc::move(val) ); } virtual value_holder* copy_helper( char* c )const{ return new(c) value_holder_impl(val); } virtual void clear() { val = fc::string(); } virtual size_t size()const { FC_THROW_REPORT( "Attempt to access string as array" ); } fc::string val; }; template<> struct value_holder_impl : value_holder { virtual value::value_type type()const { return value::object_type; } virtual void visit( value::const_visitor&& v )const; virtual void visit( value_visitor&& v ); virtual value_holder* move_helper( char* c ); virtual value_holder* copy_helper( char* c )const; virtual void reserve( size_t s ); virtual void clear(); virtual size_t size()const; template value_holder_impl( V&& v ):val( fc::forward(v) ){} value::object val; }; template<> struct value_holder_impl : value_holder { virtual value::value_type type()const { return value::array_type; } virtual void visit( value::const_visitor&& v )const; virtual void visit( value_visitor&& v ); virtual value_holder* move_helper( char* c ); virtual value_holder* copy_helper( char* c )const; virtual void resize( size_t s ); virtual void reserve( size_t s ); virtual value& at( size_t i); virtual const value& at( size_t i)const; virtual void push_back( value&& v ); template value_holder_impl( V&& v ):val( fc::forward(v) ){} virtual void clear(); virtual size_t size()const; value::array val; }; static_assert( sizeof( value_holder_impl ) <= 40, "sanity check" ); static_assert( sizeof( value_holder_impl ) <= 40, "sanity check" ); value_holder::~value_holder(){} value::value_type value_holder::type()const { return value::null_type; } value_holder* value_holder::move_helper( char* c ) { return new(c) value_holder_impl(); } value_holder* value_holder::copy_helper( char* c )const { return new(c) value_holder_impl(); } void new_value_holder_void( value* v ) { new (v) value_holder_impl(); } void value_holder::clear() {} size_t value_holder::size()const { return 0; } void value_holder::resize( size_t ) { FC_THROW_MSG("value type '%s' not an array", get_typename()); } void value_holder::reserve( size_t ) { FC_THROW_MSG("value type '%s' not an array or object", get_typename()); } value& value_holder::at( size_t ) { FC_THROW_MSG("value type '%s' not an array", get_typename()); return *((value*)0); } const value& value_holder::at( size_t )const { FC_THROW_MSG("value type '%s' not an array", get_typename()); return *((const value*)0); } void value_holder::push_back( value&& v ) { FC_THROW_MSG("value type '%s' not an array", get_typename()); } void value_holder_impl::resize( size_t s ) { val.resize(s); } void value_holder_impl::reserve( size_t s ) { val.reserve(s); } value& value_holder_impl::at( size_t i) { return val[i]; } const value& value_holder_impl::at( size_t i)const { return val[i]; } value_holder* value_holder_impl::move_helper( char* c ){ return new(c) value_holder_impl( fc::move(val) ); } value_holder* value_holder_impl::copy_helper( char* c )const{ return new(c) value_holder_impl(val); } void value_holder_impl::clear() { val.clear(); } size_t value_holder_impl::size()const { return static_cast(val.size()); } void value_holder_impl::visit( value::const_visitor&& v )const { v(val); } void value_holder_impl::visit( value_visitor&& v ) { v(val); } void value_holder_impl::push_back( value&& v ) { val.push_back( fc::move(v) ); } void value_holder_impl::visit( value::const_visitor&& v )const { v(val); } void value_holder_impl::visit( value_visitor&& v ) { v(val); } value_holder* value_holder_impl::move_helper( char* c ) { return new(c) value_holder_impl( fc::move(val) ); } value_holder* value_holder_impl::copy_helper( char* c )const { return new(c) value_holder_impl(val); } void value_holder_impl::reserve( size_t s ) { val.fields.reserve(s); } void value_holder_impl::clear() { val = value::object(); } size_t value_holder_impl::size()const { return val.fields.size(); } } // namespace detail static detail::value_holder* gh( aligned<40>& h ) { return (detail::value_holder*)h._store._data; } static const detail::value_holder* gh( const aligned<40>& h ) { return (const detail::value_holder*)h._store._data; } value::value() { new (holder) detail::value_holder_impl(); } value::value( value&& m ) { gh(m.holder)->move_helper(holder._store._data); } value::value( const value& m ){ gh(m.holder)->copy_helper(holder._store._data); } value::value( const char* c ) { new (holder) detail::value_holder_impl( c ); } value::value( char* c ) { new (holder) detail::value_holder_impl( c ); } value::~value() { gh(holder)->~value_holder(); } value::value( int8_t v){ static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); new (holder) detail::value_holder_impl(v); } value::value( int16_t v){ static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); new (holder) detail::value_holder_impl(v); } value::value( int32_t v){ new (holder) detail::value_holder_impl(v); } value::value( int64_t v){ new (holder) detail::value_holder_impl(v); } value::value( uint8_t v){ new (holder) detail::value_holder_impl(v); } value::value( uint16_t v){ new (holder) detail::value_holder_impl(v); } value::value( uint32_t v){ new (holder) detail::value_holder_impl(v); } value::value( uint64_t v){ new (holder) detail::value_holder_impl(v); } value::value( double v){ new (holder) detail::value_holder_impl(v); } value::value( float v){ new (holder) detail::value_holder_impl(v); } value::value( bool v){ new (holder) detail::value_holder_impl(v); } value::value( fc::string&& v){ static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); new (holder) detail::value_holder_impl(fc::move(v)); } value::value( fc::string& v){ static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); new (holder) detail::value_holder_impl(v); } value::value( const fc::string& v){ static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); new (holder) detail::value_holder_impl(v); } value::value( const fc::string& v, const value& val ) { static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); new (holder) detail::value_holder_impl(value::object()); set( v, val ); } value::value( value::object&& o ){ static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); new (holder) detail::value_holder_impl(fc::move(o)); } value::value( value::array&& a ){ static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); new (holder) detail::value_holder_impl(fc::move(a)); } value::value( const value::array& a ){ static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); new (holder) detail::value_holder_impl(a); } value::value( value::array& a ){ static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); new (holder) detail::value_holder_impl(a); } value::value( const value::object& a ){ static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); new (holder) detail::value_holder_impl(a); } value::value( value::object& a ){ static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); new (holder) detail::value_holder_impl(a); } bool operator == ( const value& v, std::nullptr_t ) { return v.is_null(); } bool operator != ( const value& v, std::nullptr_t ) { return v.is_null(); } value& value::operator=( value&& v ){ decltype(holder) tmp; gh(holder)->move_helper(tmp); gh(v.holder)->move_helper(holder); gh(tmp)->move_helper(v.holder); return *this; } value& value::operator=( const value& v ){ if( this == &v ) return *this; gh(holder)->~value_holder(); gh(v.holder)->copy_helper(holder); return *this; } bool value::is_null()const { return gh(holder)->type() == null_type; } bool value::is_object()const { return gh(holder)->type() == object_type; } bool value::is_array()const { return gh(holder)->type() == array_type; } bool value::is_string()const { return gh(holder)->type() == string_type; } const fc::vector& value::as_array()const { if( gh(holder)->type() != array_type ) { FC_THROW_REPORT( "Attempt to dereference value of type ${type} as value array", value("type",gh(holder)->get_typename() ) ); } const detail::value_holder_impl* o = static_cast*>(gh(holder)); return o->val; } fc::vector& value::as_array(){ if( gh(holder)->type() != array_type ) { FC_THROW_REPORT( "Attempt to dereference value of type ${type} as value array", value("type",gh(holder)->get_typename() ) ); } detail::value_holder_impl* o = static_cast*>(gh(holder)); return o->val; } const value::object& value::as_object()const { if( gh(holder)->type() != object_type ) { FC_THROW_REPORT( "Attempt to dereference value of type ${type} as value object", value("type",gh(holder)->get_typename() ) ); } const detail::value_holder_impl* o = static_cast*>(gh(holder)); return o->val; } value::object& value::as_object(){ if( gh(holder)->type() != object_type ) { FC_THROW_REPORT( "Attempt to dereference value of type ${type} as value object", value("type",gh(holder)->get_typename() ) ); } detail::value_holder_impl* o = static_cast*>(gh(holder)); return o->val; } const fc::string& value::as_string()const { if( gh(holder)->type() != string_type ) { FC_THROW_REPORT( "Attempt to dereference value of type ${type} as value string", value("type",gh(holder)->get_typename() ) ); } const detail::value_holder_impl* o = static_cast*>(gh(holder)); return o->val; } fc::string& value::as_string(){ if( gh(holder)->type() != string_type ) { FC_THROW_REPORT( "Attempt to dereference value of type ${type} as value string", value("type",gh(holder)->get_typename() ) ); } detail::value_holder_impl* o = static_cast*>(gh(holder)); return o->val; } value::object::const_iterator value::find( const char* key )const { if( gh(holder)->type() == object_type ) { const detail::value_holder_impl* o = static_cast*>(gh(holder)); for( auto i = o->val.fields.begin(); i != o->val.fields.end(); ++i ) { if( strcmp( i->key.c_str(), key ) == 0 ) return i; } return o->val.fields.end(); } //FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() ); return value::object::const_iterator(); } value::object::const_iterator value::begin()const { if( gh(holder)->type() == object_type ) { const detail::value_holder_impl* o = static_cast*>(gh(holder)); return o->val.fields.begin(); } //// FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() ); return value::object::const_iterator(); //return nullptr; } value::object::const_iterator value::end()const { if( gh(holder)->type()== object_type ) { const detail::value_holder_impl* o = static_cast*>(gh(holder)); return o->val.fields.end(); } ////FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() ); return value::object::const_iterator(); //return nullptr; } /** * If this value is an object, remove key from the object * * @return *this; */ value& value::clear( const fc::string& key ) { if( gh(holder)->type()== object_type ) { detail::value_holder_impl* o = dynamic_cast*>(gh(holder)); for( auto i = o->val.fields.begin(); i != o->val.fields.end(); ++i ) { if( strcmp( i->key.c_str(), key.c_str() ) == 0 ) { o->val.fields.erase(i); return *this; } } } return *this; } value& value::operator[]( const char* key ) { if( gh(holder)->type()== object_type ) { detail::value_holder_impl* o = dynamic_cast*>(gh(holder)); for( auto i = o->val.fields.begin(); i != o->val.fields.end(); ++i ) { if( strcmp( i->key.c_str(), key ) == 0 ) return i->val; } o->val.fields.reserve(o->val.fields.size()+1); o->val.fields.push_back( key_val(key) ); return o->val.fields.back().val; } else if (gh(holder)->type() == null_type ) { new (gh(holder)) detail::value_holder_impl(value::object()); return (*this)[key]; } FC_THROW_REPORT( "Bad cast of ${type} to object", fc::value().set("type", gh(holder)->get_typename()) ); return *((value*)0); } value& value::operator[]( const fc::string& key ) { return (*this)[key.c_str()]; } const value& value::operator[]( const fc::string& key )const { return (*this)[key.c_str()]; } const value& value::operator[]( const char* key )const { auto i = find(key); if( i == end() ) { FC_THROW_MSG( "Key '%s' not found in object", key ); } return i->val; } void value::clear() { gh(holder)->clear(); } size_t value::size()const { return gh(holder)->size(); } void value::resize( size_t s ) { gh(holder)->resize(s); } void value::reserve( size_t s ) { gh(holder)->reserve(s); } value& value::push_back( value&& v ) { if (gh(holder)->type() == null_type ) { new (gh(holder)) detail::value_holder_impl(value::array()); return push_back( fc::move(v) ); } gh(holder)->push_back(fc::move(v)); return *this; } value& value::push_back( const value& v ) { if (gh(holder)->type() == null_type ) { new (gh(holder)) detail::value_holder_impl(value::array()); return push_back( v ); } gh(holder)->push_back(value(v)); return *this; } value& value::operator[]( int32_t idx ) { return gh(holder)->at(idx); } const value& value::operator[]( int32_t idx )const { return gh(holder)->at(idx); } value::value_type value::type()const { return gh(holder)->type(); } void value::visit( value::const_visitor&& v )const { auto h = ((detail::value_holder*)&holder[0]); h->visit( fc::move(v) ); } /* sets the subkey key with v and return *this */ value& value::set( const char* key, fc::value v ) { (*this)[key] = fc::move(v); return *this; } value& value::operator()( const char* key, fc::value v ) { (*this)[key] = fc::move(v); return *this; } value& value::set( const fc::string& key, fc::value v ) { (*this)[key.c_str()] = fc::move(v); return *this; } } // namepace fc