#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include namespace fc { namespace raw { template inline void pack( Stream& s, const variant_object& v ); template inline void unpack( Stream& s, variant_object& v ); template inline void pack( Stream& s, const variant& v ); template inline void unpack( Stream& s, variant& v ); template inline void pack( Stream& s, const fc::time_point& tp ) { uint64_t usec = tp.time_since_epoch().count(); s.write( (const char*)&usec, sizeof(usec) ); } template inline void unpack( Stream& s, fc::time_point& tp ) { uint64_t usec; s.read( (char*)&usec, sizeof(usec) ); tp = fc::time_point() + fc::microseconds(usec); } template inline void pack( Stream& s, const fc::array& v) { s.write((const char*)&v.data[0],N*sizeof(T)); } template inline void unpack( Stream& s, fc::array& v) { s.read((char*)&v.data[0],N*sizeof(T)); } template inline void pack( Stream& s, const signed_int& v ) { uint32_t val = (v.value<<1) ^ (v.value>>31); do { uint8_t b = uint8_t(val) & 0x7f; val >>= 7; b |= ((val > 0) << 7); s.write((char*)&b,1);//.put(b); } while( val ); } template inline void pack( Stream& s, const unsigned_int& v ) { uint64_t val = v.value; do { uint8_t b = uint8_t(val) & 0x7f; val >>= 7; b |= ((val > 0) << 7); s.write((char*)&b,1);//.put(b); }while( val ); } template inline void unpack( Stream& s, signed_int& vi ) { uint32_t v = 0; char b = 0; int by = 0; do { s.get(b); v |= uint32_t(uint8_t(b) & 0x7f) << by; by += 7; } while( uint8_t(b) & 0x80 ); vi.value = ((v>>1) ^ (v>>31)) + (v&0x01); vi.value = v&0x01 ? vi.value : -vi.value; vi.value = -vi.value; } template inline void unpack( Stream& s, unsigned_int& vi ) { uint64_t v = 0; char b = 0; uint8_t by = 0; do { s.get(b); v |= uint32_t(uint8_t(b) & 0x7f) << by; by += 7; } while( uint8_t(b) & 0x80 ); vi.value = v; } template inline void pack( Stream& s, const char* v ) { pack( s, fc::string(v) ); } // optional template inline void pack( Stream& s, const fc::optional& v ) { pack( s, bool(!!v) ); if( !!v ) pack( s, *v ); } template void unpack( Stream& s, fc::optional& v ) { bool b; unpack( s, b ); if( b ) { v = T(); unpack( s, *v ); } } // std::vector template inline void pack( Stream& s, const std::vector& value ) { pack( s, unsigned_int(value.size()) ); if( value.size() ) s.write( &value.front(), value.size() ); } template inline void unpack( Stream& s, std::vector& value ) { unsigned_int size; unpack( s, size ); value.resize(size.value); if( value.size() ) s.read( value.data(), value.size() ); } // fc::string template inline void pack( Stream& s, const fc::string& v ) { pack( s, unsigned_int(v.size()) ); if( v.size() ) s.write( v.c_str(), v.size() ); } template inline void unpack( Stream& s, fc::string& v ) { std::vector tmp; unpack(s,tmp); v = fc::string(tmp.begin(),tmp.end()); } // bool template inline void pack( Stream& s, const bool& v ) { pack( s, uint8_t(v) ); } template inline void unpack( Stream& s, bool& v ) { uint8_t b; unpack( s, b ); v=b; } namespace detail { template struct pack_object_visitor { pack_object_visitor(const Class& _c, Stream& _s) :c(_c),s(_s){} template void operator()( const char* name )const { raw::pack( s, c.*p ); } private: const Class& c; Stream& s; }; template struct unpack_object_visitor { unpack_object_visitor(Class& _c, Stream& _s) :c(_c),s(_s){} template inline void operator()( const char* name )const { raw::unpack( s, c.*p ); } private: Class& c; Stream& s; }; template struct if_class{ template static inline void pack( Stream& s, const T& v ) { s << v; } template static inline void unpack( Stream& s, T& v ) { s >> v; } }; template<> struct if_class { template static inline void pack( Stream& s, const T& v ) { s.write( (char*)&v, sizeof(v) ); } template static inline void unpack( Stream& s, T& v ) { s.read( (char*)&v, sizeof(v) ); } }; template struct if_reflected { template static inline void pack( Stream& s, const T& v ) { if_class::type>::pack(s,v); } template static inline void unpack( Stream& s, T& v ) { if_class::type>::unpack(s,v); } }; template<> struct if_reflected { template static inline void pack( Stream& s, const T& v ) { fc::reflector::visit( pack_object_visitor( v, s ) ); } template static inline void unpack( Stream& s, T& v ) { fc::reflector::visit( unpack_object_visitor( v, s ) ); } }; } // namesapce detail template inline void pack( Stream& s, const std::vector& value ) { pack( s, unsigned_int(value.size()) ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { fc::raw::pack( s, *itr ); ++itr; } } template inline void unpack( Stream& s, std::vector& value ) { unsigned_int size; unpack( s, size ); value.resize(size.value); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { fc::raw::unpack( s, *itr ); ++itr; } } template inline void pack( Stream& s, const T& v ) { fc::raw::detail::if_reflected< typename fc::reflector::is_defined >::pack(s,v); } template inline void unpack( Stream& s, T& v ) { fc::raw::detail::if_reflected< typename fc::reflector::is_defined >::unpack(s,v); } template class variant_packer : public variant::visitor { public: variant_packer( Stream& _s ):s(_s){} virtual void handle()const { } virtual void handle( const int64_t& v )const { fc::raw::pack( s, v ); } virtual void handle( const uint64_t& v )const { fc::raw::pack( s, v ); } virtual void handle( const double& v )const { fc::raw::pack( s, v ); } virtual void handle( const bool& v )const { fc::raw::pack( s, v ); } virtual void handle( const string& v )const { fc::raw::pack( s, v ); } virtual void handle( const variant_object& v)const { fc::raw::pack( s, v ); } virtual void handle( const variants& v)const { fc::raw::pack( s, v ); } Stream& s; }; template inline void pack( Stream& s, const variant& v ) { pack( s, uint8_t(v.get_type()) ); v.visit( variant_packer(s) ); } template inline void unpack( Stream& s, variant& v ) { uint8_t t; unpack( s, t ); switch( t ) { case variant::null_type: return; case variant::int64_type: { int64_t val; raw::unpack(s,val); v = val; return; } case variant::uint64_type: { uint64_t val; raw::unpack(s,val); v = val; return; } case variant::double_type: { double val; raw::unpack(s,val); v = val; return; } case variant::bool_type: { bool val; raw::unpack(s,val); v = val; return; } case variant::string_type: { fc::string val; raw::unpack(s,val); v = fc::move(val); return; } case variant::array_type: { variants val; raw::unpack(s,val); v = fc::move(val); return; } case variant::object_type: { variant_object val; raw::unpack(s,val); v = fc::move(val); return; } default: FC_THROW_EXCEPTION( parse_error_exception, "Unknown Variant Type ${t}", ("t", t) ); } } template inline void pack( Stream& s, const variant_object& v ) { unsigned_int vs = v.size(); pack( s, vs ); for( auto itr = v.begin(); itr != v.end(); ++itr ) { pack( s, itr->key() ); pack( s, itr->value() ); } wlog( "------------ done pack -------------" ); } template inline void unpack( Stream& s, variant_object& v ) { unsigned_int vs; unpack( s, vs ); mutable_variant_object mvo; mvo.reserve(vs.value); for( auto i = 0; i < vs.value; ++i ) { fc::string key; fc::variant value; fc::raw::unpack(s,key); fc::raw::unpack(s,value); mvo.set( fc::move(key), fc::move(value) ); } v = fc::move(mvo); } template inline std::vector pack( const T& v ) { datastream ps; raw::pack(ps,v ); std::vector vec(ps.tellp()); if( vec.size() ) { datastream ds( vec.data(), size_t(vec.size()) ); raw::pack(ds,v); } return vec; } template inline T unpack( const std::vector& s ) { T tmp; if( s.size() ) { datastream ds( s.data(), size_t(s.size()) ); raw::unpack(ds,tmp); } return tmp; } template inline void pack( char* d, uint32_t s, const T& v ) { datastream ds(d,s); raw::pack(ds,v ); } template inline T unpack( const char* d, uint32_t s ) { T v; datastream ds( d, s ); raw::unpack(ds,v); return v; } template inline void unpack( const char* d, uint32_t s, T& v ) { datastream ds( d, s ); raw::unpack(ds,v); return v; } } } // namespace fc::raw