From 782e7d687bc2ffbc275812d913128ff4188c31de Mon Sep 17 00:00:00 2001 From: abitmore Date: Sun, 11 Mar 2018 15:56:45 -0400 Subject: [PATCH 1/3] Add test case for nested-object serialization --- tests/CMakeLists.txt | 1 + tests/serialization_test.cpp | 108 +++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 tests/serialization_test.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index bf7a01d6a..6151fadde 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -54,6 +54,7 @@ add_executable( all_tests all_tests.cpp thread/thread_tests.cpp bloom_test.cpp real128_test.cpp + serialization_test.cpp time_test.cpp utf8_test.cpp ) diff --git a/tests/serialization_test.cpp b/tests/serialization_test.cpp new file mode 100644 index 000000000..1e35f8697 --- /dev/null +++ b/tests/serialization_test.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include +#include + +namespace fc { namespace test { + + struct item; + inline bool operator < ( const item& a, const item& b ); + inline bool operator == ( const item& a, const item& b ); + + struct item_wrapper + { + item_wrapper() {} + item_wrapper(item&& it) { v.reserve(1); v.insert( it ); } + boost::container::flat_set v; + }; + inline bool operator < ( const item_wrapper& a, const item_wrapper& b ); + inline bool operator == ( const item_wrapper& a, const item_wrapper& b ); + + struct item + { + item(int32_t lvl = 0) : level(lvl) {} + item(item_wrapper&& wp, int32_t lvl = 0) : level(lvl), w(wp) {} + int32_t level; + item_wrapper w; + }; + + inline bool operator == ( const item& a, const item& b ) + { return ( std::tie( a.level, a.w ) == std::tie( b.level, b.w ) ); } + + inline bool operator < ( const item& a, const item& b ) + { return ( std::tie( a.level, a.w ) < std::tie( b.level, b.w ) ); } + + inline bool operator == ( const item_wrapper& a, const item_wrapper& b ) + { return ( std::tie( a.v ) == std::tie( b.v ) ); } + + inline bool operator < ( const item_wrapper& a, const item_wrapper& b ) + { return ( std::tie( a.v ) < std::tie( b.v ) ); } + +} } + +FC_REFLECT( fc::test::item_wrapper, (v) ); +FC_REFLECT( fc::test::item, (level)(w) ); + +BOOST_AUTO_TEST_SUITE(fc_serialization) + +BOOST_AUTO_TEST_CASE( nested_objects_test ) +{ try { + + auto create_nested_object = []( uint32_t level ) + { + ilog( "Creating nested object with ${lv} level(s)", ("lv",level) ); + fc::test::item nested; + for( uint32_t i = 1; i <= level; i++ ) + { + if( i % 100 == 0 ) + ilog( "Creating level ${lv}", ("lv",i) ); + fc::test::item_wrapper wp( std::move(nested) ); + nested = fc::test::item( std::move(wp), i ); + } + return nested; + }; + + // 100 levels, should be allowed + { + auto nested = create_nested_object( 100 ); + + std::stringstream ss; + + BOOST_TEST_MESSAGE( "About to pack." ); + fc::raw::pack( ss, nested ); + + BOOST_TEST_MESSAGE( "About to unpack." ); + fc::test::item unpacked; + fc::raw::unpack( ss, unpacked ); + + BOOST_CHECK( unpacked == nested ); + } + + // 150 levels, by default packing will fail + { + auto nested = create_nested_object( 150 ); + + std::stringstream ss; + + BOOST_TEST_MESSAGE( "About to pack." ); + BOOST_CHECK_THROW( fc::raw::pack( ss, nested ), fc::assert_exception ); + } + + // 150 levels and allow packing, unpacking will fail + { + auto nested = create_nested_object( 150 ); + + std::stringstream ss; + + BOOST_TEST_MESSAGE( "About to pack." ); + fc::raw::pack( ss, nested, 1500 ); + + BOOST_TEST_MESSAGE( "About to unpack." ); + fc::test::item unpacked; + BOOST_CHECK_THROW( fc::raw::unpack( ss, unpacked ), fc::assert_exception ); + } + +} FC_CAPTURE_LOG_AND_RETHROW ( (0) ) } + +BOOST_AUTO_TEST_SUITE_END() From 86e18663a0048868a933b18e76be9a875f6d938d Mon Sep 17 00:00:00 2001 From: abitmore Date: Sun, 11 Mar 2018 16:14:22 -0400 Subject: [PATCH 2/3] Add max_depth parameter to pack/unpack functions --- include/fc/config.hpp | 4 + include/fc/container/deque_fwd.hpp | 5 +- include/fc/container/flat.hpp | 42 +- include/fc/container/flat_fwd.hpp | 15 +- include/fc/crypto/elliptic.hpp | 20 +- include/fc/crypto/pke.hpp | 20 +- include/fc/fixed_string.hpp | 14 +- include/fc/interprocess/container.hpp | 30 +- include/fc/io/enum_type.hpp | 22 +- include/fc/io/raw.hpp | 635 +++++++++++++++----------- include/fc/io/raw_fwd.hpp | 133 +++--- include/fc/io/raw_variant.hpp | 80 ++-- include/fc/network/ip.hpp | 48 +- include/fc/real128.hpp | 13 +- include/fc/uint128.hpp | 5 +- 15 files changed, 610 insertions(+), 476 deletions(-) create mode 100644 include/fc/config.hpp diff --git a/include/fc/config.hpp b/include/fc/config.hpp new file mode 100644 index 000000000..2f646bd70 --- /dev/null +++ b/include/fc/config.hpp @@ -0,0 +1,4 @@ +#ifndef FC_PACK_MAX_DEPTH + // The maximum level of object nesting is around 20% of this value + #define FC_PACK_MAX_DEPTH 1000 +#endif diff --git a/include/fc/container/deque_fwd.hpp b/include/fc/container/deque_fwd.hpp index 80359ea67..71df18d79 100644 --- a/include/fc/container/deque_fwd.hpp +++ b/include/fc/container/deque_fwd.hpp @@ -1,13 +1,14 @@ #pragma once +#include #include namespace fc { namespace raw { template - void pack( Stream& s, const std::deque& value ); + void pack( Stream& s, const std::deque& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); template - void unpack( Stream& s, std::deque& value ); + void unpack( Stream& s, std::deque& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); } } // namespace fc diff --git a/include/fc/container/flat.hpp b/include/fc/container/flat.hpp index 48fdf75c2..0b494f23a 100644 --- a/include/fc/container/flat.hpp +++ b/include/fc/container/flat.hpp @@ -8,61 +8,66 @@ namespace fc { namespace raw { template - inline void pack( Stream& s, const flat_set& value ) { - pack( s, unsigned_int((uint32_t)value.size()) ); + inline void pack( Stream& s, const flat_set& value, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { - fc::raw::pack( s, *itr ); + fc::raw::pack( s, *itr, _max_depth - 1 ); ++itr; } } template - inline void unpack( Stream& s, flat_set& value ) { - unsigned_int size; unpack( s, size ); + inline void unpack( Stream& s, flat_set& value, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + unsigned_int size; unpack( s, size, _max_depth - 1 ); value.clear(); FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE ); value.reserve(size.value); for( uint32_t i = 0; i < size.value; ++i ) { T tmp; - fc::raw::unpack( s, tmp ); + fc::raw::unpack( s, tmp, _max_depth - 1 ); value.insert( std::move(tmp) ); } } template - inline void pack( Stream& s, const flat_map& value ) { - pack( s, unsigned_int((uint32_t)value.size()) ); + inline void pack( Stream& s, const flat_map& value, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { - fc::raw::pack( s, *itr ); + fc::raw::pack( s, *itr, _max_depth - 1 ); ++itr; } } template - inline void unpack( Stream& s, flat_map& value ) + inline void unpack( Stream& s, flat_map& value, uint32_t _max_depth ) { - unsigned_int size; unpack( s, size ); + FC_ASSERT( _max_depth > 0 ); + unsigned_int size; unpack( s, size, _max_depth - 1 ); value.clear(); FC_ASSERT( size.value*(sizeof(K)+sizeof(V)) < MAX_ARRAY_ALLOC_SIZE ); value.reserve(size.value); for( uint32_t i = 0; i < size.value; ++i ) { std::pair tmp; - fc::raw::unpack( s, tmp ); + fc::raw::unpack( s, tmp, _max_depth - 1 ); value.insert( std::move(tmp) ); } } template - void pack( Stream& s, const bip::vector& value ) { - pack( s, unsigned_int((uint32_t)value.size()) ); + void pack( Stream& s, const bip::vector& value, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); if( !std::is_fundamental::value ) { auto itr = value.begin(); auto end = value.end(); while( itr != end ) { - fc::raw::pack( s, *itr ); + fc::raw::pack( s, *itr, _max_depth - 1 ); ++itr; } } else { @@ -71,13 +76,14 @@ namespace fc { } template - void unpack( Stream& s, bip::vector& value ) { + void unpack( Stream& s, bip::vector& value, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); unsigned_int size; - unpack( s, size ); + unpack( s, size, _max_depth - 1 ); value.resize( size ); if( !std::is_fundamental::value ) { for( auto& item : value ) - unpack( s, item ); + unpack( s, item, _max_depth - 1 ); } else { s.read( (char*)value.data(), value.size() ); } diff --git a/include/fc/container/flat_fwd.hpp b/include/fc/container/flat_fwd.hpp index d56323a8f..8db36b629 100644 --- a/include/fc/container/flat_fwd.hpp +++ b/include/fc/container/flat_fwd.hpp @@ -1,7 +1,8 @@ -#pragma once +#pragma once #include #include #include +#include namespace fc { @@ -11,19 +12,19 @@ namespace fc { namespace raw { template - void pack( Stream& s, const flat_set& value ); + void pack( Stream& s, const flat_set& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); template - void unpack( Stream& s, flat_set& value ); + void unpack( Stream& s, flat_set& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); template - void pack( Stream& s, const flat_map& value ); + void pack( Stream& s, const flat_map& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); template - void unpack(Stream& s, flat_map& value); + void unpack(Stream& s, flat_map& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); template - void pack( Stream& s, const bip::vector& value ); + void pack( Stream& s, const bip::vector& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); template - void unpack( Stream& s, bip::vector& value ); + void unpack( Stream& s, bip::vector& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); } // namespace raw } // fc diff --git a/include/fc/crypto/elliptic.hpp b/include/fc/crypto/elliptic.hpp index 7d3046f25..971ae3d08 100644 --- a/include/fc/crypto/elliptic.hpp +++ b/include/fc/crypto/elliptic.hpp @@ -260,31 +260,35 @@ namespace fc { namespace raw { template - void unpack( Stream& s, fc::ecc::public_key& pk) + void unpack( Stream& s, fc::ecc::public_key& pk, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); ecc::public_key_data ser; - fc::raw::unpack(s,ser); + fc::raw::unpack( s, ser, _max_depth - 1 ); pk = fc::ecc::public_key( ser ); } template - void pack( Stream& s, const fc::ecc::public_key& pk) + void pack( Stream& s, const fc::ecc::public_key& pk, uint32_t _max_depth ) { - fc::raw::pack( s, pk.serialize() ); + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, pk.serialize(), _max_depth - 1 ); } template - void unpack( Stream& s, fc::ecc::private_key& pk) + void unpack( Stream& s, fc::ecc::private_key& pk, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); fc::sha256 sec; - unpack( s, sec ); + unpack( s, sec, _max_depth - 1 ); pk = ecc::private_key::regenerate(sec); } template - void pack( Stream& s, const fc::ecc::private_key& pk) + void pack( Stream& s, const fc::ecc::private_key& pk, uint32_t _max_depth ) { - fc::raw::pack( s, pk.get_secret() ); + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, pk.get_secret(), _max_depth - 1 ); } } // namespace raw diff --git a/include/fc/crypto/pke.hpp b/include/fc/crypto/pke.hpp index 3f1c607dd..551ef99b1 100644 --- a/include/fc/crypto/pke.hpp +++ b/include/fc/crypto/pke.hpp @@ -76,31 +76,35 @@ namespace fc { namespace raw { template - void unpack( Stream& s, fc::public_key& pk) + void unpack( Stream& s, fc::public_key& pk, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { + FC_ASSERT( _max_depth > 0 ); bytes ser; - fc::raw::unpack(s,ser); + fc::raw::unpack( s, ser, _max_depth - 1 ); pk = fc::public_key( ser ); } template - void pack( Stream& s, const fc::public_key& pk) + void pack( Stream& s, const fc::public_key& pk, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { - fc::raw::pack( s, pk.serialize() ); + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, pk.serialize(), _max_depth - 1 ); } template - void unpack( Stream& s, fc::private_key& pk) + void unpack( Stream& s, fc::private_key& pk, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { + FC_ASSERT( _max_depth > 0 ); bytes ser; - fc::raw::unpack(s,ser); + fc::raw::unpack( s, ser, _max_depth - 1 ); pk = fc::private_key( ser ); } template - void pack( Stream& s, const fc::private_key& pk) + void pack( Stream& s, const fc::private_key& pk, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { - fc::raw::pack( s, pk.serialize() ); + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, pk.serialize(), _max_depth - 1 ); } } class variant; diff --git a/include/fc/fixed_string.hpp b/include/fc/fixed_string.hpp index ca6ea1fc7..ce00390aa 100644 --- a/include/fc/fixed_string.hpp +++ b/include/fc/fixed_string.hpp @@ -98,16 +98,18 @@ namespace fc { namespace raw { template - inline void pack( Stream& s, const fc::fixed_string& u ) { + inline void pack( Stream& s, const fc::fixed_string& u, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { + FC_ASSERT( _max_depth > 0 ); unsigned_int size = u.size(); - pack( s, size ); + pack( s, size, _max_depth - 1 ); s.write( (const char*)&u.data, size ); } template - inline void unpack( Stream& s, fc::fixed_string& u ) { + inline void unpack( Stream& s, fc::fixed_string& u, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { + FC_ASSERT( _max_depth > 0 ); unsigned_int size; - fc::raw::unpack( s, size ); + fc::raw::unpack( s, size, _max_depth - 1 ); if( size.value > 0 ) { if( size.value > sizeof(Storage) ) { s.read( (char*)&u.data, sizeof(Storage) ); @@ -135,12 +137,12 @@ namespace fc { /* template - inline void pack( Stream& s, const boost::multiprecision::number& d ) { + inline void pack( Stream& s, const boost::multiprecision::number& d, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { s.write( (const char*)&d, sizeof(d) ); } template - inline void unpack( Stream& s, boost::multiprecision::number& u ) { + inline void unpack( Stream& s, boost::multiprecision::number& u, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { s.read( (const char*)&u, sizeof(u) ); } */ diff --git a/include/fc/interprocess/container.hpp b/include/fc/interprocess/container.hpp index ed761b8d1..6ed73f2bd 100644 --- a/include/fc/interprocess/container.hpp +++ b/include/fc/interprocess/container.hpp @@ -122,22 +122,24 @@ namespace fc { namespace bip = boost::interprocess; template - inline void pack( Stream& s, const bip::vector& value ) { - pack( s, unsigned_int((uint32_t)value.size()) ); - auto itr = value.begin(); - auto end = value.end(); - while( itr != end ) { - fc::raw::pack( s, *itr ); - ++itr; - } + inline void pack( Stream& s, const bip::vector& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { + FC_ASSERT( _max_depth > 0 ); + pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); + auto itr = value.begin(); + auto end = value.end(); + while( itr != end ) { + fc::raw::pack( s, *itr, _max_depth - 1 ); + ++itr; + } } template - inline void unpack( Stream& s, bip::vector& value ) { - unsigned_int size; - unpack( s, size ); - value.clear(); value.resize(size); - for( auto& item : value ) - fc::raw::unpack( s, item ); + inline void unpack( Stream& s, bip::vector& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { + FC_ASSERT( _max_depth > 0 ); + unsigned_int size; + unpack( s, size, _max_depth - 1 ); + value.clear(); value.resize(size); + for( auto& item : value ) + fc::raw::unpack( s, item, _max_depth - 1 ); } } } diff --git a/include/fc/io/enum_type.hpp b/include/fc/io/enum_type.hpp index e41770ced..46da87745 100644 --- a/include/fc/io/enum_type.hpp +++ b/include/fc/io/enum_type.hpp @@ -11,16 +11,16 @@ namespace fc public: enum_type( EnumType t ) :value(t){} - + enum_type( IntType t ) :value( (EnumType)t ){} - + enum_type(){} - + explicit operator IntType()const { return static_cast(value); } operator EnumType()const { return value; } operator std::string()const { return fc::reflector::to_string(value); } - + enum_type& operator=( IntType i ) { value = (EnumType)i; return *this;} enum_type& operator=( EnumType i ) { value = i; return *this;} bool operator<( EnumType i ) const { return value < i; } @@ -60,19 +60,21 @@ namespace fc /** serializes like an IntType */ - namespace raw - { + namespace raw + { template - inline void pack( Stream& s, const fc::enum_type& tp ) + inline void pack( Stream& s, const fc::enum_type& tp, uint32_t _max_depth ) { - fc::raw::pack( s, static_cast(tp) ); + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, static_cast(tp), _max_depth - 1 ); } template - inline void unpack( Stream& s, fc::enum_type& tp ) + inline void unpack( Stream& s, fc::enum_type& tp, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); IntType t; - fc::raw::unpack( s, t ); + fc::raw::unpack( s, t, _max_depth - 1 ); tp = t; } } diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index 288c3c9d3..02873fc7b 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -19,70 +19,77 @@ namespace fc { namespace raw { template - inline void pack( Stream& s, const Arg0& a0, Args... args ) { - pack( s, a0 ); - pack( s, args... ); + inline void pack( Stream& s, const Arg0& a0, Args... args, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + pack( s, a0, _max_depth - 1 ); + pack( s, args..., _max_depth - 1 ); } template - inline void pack( Stream& s, const fc::exception& e ) + inline void pack( Stream& s, const fc::exception& e, uint32_t _max_depth ) { - fc::raw::pack( s, e.code() ); - fc::raw::pack( s, std::string(e.name()) ); - fc::raw::pack( s, std::string(e.what()) ); - fc::raw::pack( s, e.get_log() ); + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, e.code(), _max_depth - 1 ); + fc::raw::pack( s, std::string(e.name()), _max_depth - 1 ); + fc::raw::pack( s, std::string(e.what()), _max_depth - 1 ); + fc::raw::pack( s, e.get_log(), _max_depth - 1 ); } template - inline void unpack( Stream& s, fc::exception& e ) + inline void unpack( Stream& s, fc::exception& e, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); int64_t code; std::string name, what; log_messages msgs; - fc::raw::unpack( s, code ); - fc::raw::unpack( s, name ); - fc::raw::unpack( s, what ); - fc::raw::unpack( s, msgs ); + fc::raw::unpack( s, code, _max_depth - 1 ); + fc::raw::unpack( s, name, _max_depth - 1 ); + fc::raw::unpack( s, what, _max_depth - 1 ); + fc::raw::unpack( s, msgs, _max_depth - 1 ); e = fc::exception( fc::move(msgs), code, name, what ); } template - inline void pack( Stream& s, const fc::log_message& msg ) + inline void pack( Stream& s, const fc::log_message& msg, uint32_t _max_depth ) { - fc::raw::pack( s, variant(msg) ); + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, variant(msg), _max_depth - 1 ); } template - inline void unpack( Stream& s, fc::log_message& msg ) + inline void unpack( Stream& s, fc::log_message& msg, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); fc::variant vmsg; - fc::raw::unpack( s, vmsg ); + fc::raw::unpack( s, vmsg, _max_depth - 1 ); msg = vmsg.as(); } template - inline void pack( Stream& s, const fc::path& tp ) + inline void pack( Stream& s, const fc::path& tp, uint32_t _max_depth ) { - fc::raw::pack( s, tp.generic_string() ); + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, tp.generic_string(), _max_depth - 1 ); } template - inline void unpack( Stream& s, fc::path& tp ) + inline void unpack( Stream& s, fc::path& tp, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); std::string p; - fc::raw::unpack( s, p ); + fc::raw::unpack( s, p, _max_depth - 1 ); tp = p; } template - inline void pack( Stream& s, const fc::time_point_sec& tp ) + inline void pack( Stream& s, const fc::time_point_sec& tp, uint32_t _max_depth ) { uint32_t usec = tp.sec_since_epoch(); s.write( (const char*)&usec, sizeof(usec) ); } template - inline void unpack( Stream& s, fc::time_point_sec& tp ) + inline void unpack( Stream& s, fc::time_point_sec& tp, uint32_t _max_depth ) { try { uint32_t sec; s.read( (char*)&sec, sizeof(sec) ); @@ -90,14 +97,14 @@ namespace fc { } FC_RETHROW_EXCEPTIONS( warn, "" ) } template - inline void pack( Stream& s, const fc::time_point& tp ) + inline void pack( Stream& s, const fc::time_point& tp, uint32_t _max_depth ) { 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 ) + inline void unpack( Stream& s, fc::time_point& tp, uint32_t _max_depth ) { try { uint64_t usec; s.read( (char*)&usec, sizeof(usec) ); @@ -105,14 +112,14 @@ namespace fc { } FC_RETHROW_EXCEPTIONS( warn, "" ) } template - inline void pack( Stream& s, const fc::microseconds& usec ) + inline void pack( Stream& s, const fc::microseconds& usec, uint32_t _max_depth ) { uint64_t usec_as_int64 = usec.count(); s.write( (const char*)&usec_as_int64, sizeof(usec_as_int64) ); } template - inline void unpack( Stream& s, fc::microseconds& usec ) + inline void unpack( Stream& s, fc::microseconds& usec, uint32_t _max_depth ) { try { uint64_t usec_as_int64; s.read( (char*)&usec_as_int64, sizeof(usec_as_int64) ); @@ -120,30 +127,32 @@ namespace fc { } FC_RETHROW_EXCEPTIONS( warn, "" ) } template - inline void pack( Stream& s, const fc::array& v) { + inline void pack( Stream& s, const fc::array& v, uint32_t _max_depth ) { s.write((const char*)&v.data[0],N*sizeof(T)); } template - inline void pack( Stream& s, const std::shared_ptr& v) + inline void pack( Stream& s, const std::shared_ptr& v, uint32_t _max_depth ) { - fc::raw::pack( s, *v ); + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, *v, _max_depth - 1 ); } template - inline void unpack( Stream& s, fc::array& v) + inline void unpack( Stream& s, fc::array& v, uint32_t _max_depth ) { try { s.read((char*)&v.data[0],N*sizeof(T)); } FC_RETHROW_EXCEPTIONS( warn, "fc::array", ("type",fc::get_typename::name())("length",N) ) } template - inline void unpack( Stream& s, std::shared_ptr& v) + inline void unpack( Stream& s, std::shared_ptr& v, uint32_t _max_depth ) { try { - v = std::make_shared(); - fc::raw::unpack( s, *v ); + FC_ASSERT( _max_depth > 0 ); + v = std::make_shared(); + fc::raw::unpack( s, *v, _max_depth - 1 ); } FC_RETHROW_EXCEPTIONS( warn, "std::shared_ptr", ("type",fc::get_typename::name()) ) } - template inline void pack( Stream& s, const signed_int& v ) { + template inline void pack( Stream& s, const signed_int& v, uint32_t _max_depth ) { uint32_t val = (v.value<<1) ^ (v.value>>31); do { uint8_t b = uint8_t(val) & 0x7f; @@ -153,7 +162,7 @@ namespace fc { } while( val ); } - template inline void pack( Stream& s, const unsigned_int& v ) { + template inline void pack( Stream& s, const unsigned_int& v, uint32_t _max_depth ) { uint64_t val = v.value; do { uint8_t b = uint8_t(val) & 0x7f; @@ -163,7 +172,7 @@ namespace fc { }while( val ); } - template inline void unpack( Stream& s, signed_int& vi ) { + template inline void unpack( Stream& s, signed_int& vi, uint32_t _max_depth ) { uint32_t v = 0; char b = 0; int by = 0; do { s.get(b); @@ -174,7 +183,7 @@ namespace fc { vi.value = v&0x01 ? vi.value : -vi.value; vi.value = -vi.value; } - template inline void unpack( Stream& s, unsigned_int& vi ) { + template inline void unpack( Stream& s, unsigned_int& vi, uint32_t _max_depth ) { uint64_t v = 0; char b = 0; uint8_t by = 0; do { s.get(b); @@ -184,83 +193,117 @@ namespace fc { vi.value = static_cast(v); } - template inline void unpack( Stream& s, const T& vi ) + template inline void unpack( Stream& s, const T& vi, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); T tmp; - fc::raw::unpack( s, tmp ); + fc::raw::unpack( s, tmp, _max_depth - 1 ); FC_ASSERT( vi == tmp ); } - template inline void pack( Stream& s, const char* v ) { fc::raw::pack( s, fc::string(v) ); } + template inline void pack( Stream& s, const char* v, uint32_t _max_depth ) + { + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, fc::string(v), _max_depth - 1 ); + } template - void pack( Stream& s, const safe& v ) { fc::raw::pack( s, v.value ); } + void pack( Stream& s, const safe& v, uint32_t _max_depth ) + { + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, v.value, _max_depth - 1 ); + } template - void unpack( Stream& s, fc::safe& v ) { fc::raw::unpack( s, v.value ); } + void unpack( Stream& s, fc::safe& v, uint32_t _max_depth ) + { + FC_ASSERT( _max_depth > 0 ); + fc::raw::unpack( s, v.value, _max_depth - 1 ); + } template - void pack( Stream& s, const fc::fwd& v ) { - fc::raw::pack( *v ); + void pack( Stream& s, const fc::fwd& v, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( *v, _max_depth - 1 ); // TODO not sure about this } template - void unpack( Stream& s, fc::fwd& v ) { - fc::raw::unpack( *v ); + void unpack( Stream& s, fc::fwd& v, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + fc::raw::unpack( *v, _max_depth - 1 ); // TODO not sure about this } template - void pack( Stream& s, const fc::smart_ref& v ) { fc::raw::pack( s, *v ); } + void pack( Stream& s, const fc::smart_ref& v, uint32_t _max_depth ) + { + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, *v, _max_depth - 1 ); + } template - void unpack( Stream& s, fc::smart_ref& v ) { fc::raw::unpack( s, *v ); } + void unpack( Stream& s, fc::smart_ref& v, uint32_t _max_depth ) + { + FC_ASSERT( _max_depth > 0 ); + fc::raw::unpack( s, *v, _max_depth - 1 ); + } // optional template - void pack( Stream& s, const fc::optional& v ) { - fc::raw::pack( s, bool(!!v) ); - if( !!v ) fc::raw::pack( s, *v ); + void pack( Stream& s, const fc::optional& v, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, bool(!!v), _max_depth - 1 ); + if( !!v ) fc::raw::pack( s, *v, _max_depth - 1 ); } template - void unpack( Stream& s, fc::optional& v ) + void unpack( Stream& s, fc::optional& v, uint32_t _max_depth ) { try { - bool b; fc::raw::unpack( s, b ); - if( b ) { v = T(); fc::raw::unpack( s, *v ); } + FC_ASSERT( _max_depth > 0 ); + bool b; fc::raw::unpack( s, b, _max_depth - 1 ); + if( b ) { v = T(); fc::raw::unpack( s, *v, _max_depth - 1 ); } } FC_RETHROW_EXCEPTIONS( warn, "optional<${type}>", ("type",fc::get_typename::name() ) ) } // std::vector - template inline void pack( Stream& s, const std::vector& value ) { - fc::raw::pack( s, unsigned_int((uint32_t)value.size()) ); - if( value.size() ) - s.write( &value.front(), (uint32_t)value.size() ); + template inline void pack( Stream& s, const std::vector& value, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); + if( value.size() ) + s.write( &value.front(), (uint32_t)value.size() ); } - template inline void unpack( Stream& s, std::vector& value ) { - unsigned_int size; fc::raw::unpack( s, size ); - FC_ASSERT( size.value < MAX_ARRAY_ALLOC_SIZE ); - value.resize(size.value); - if( value.size() ) - s.read( value.data(), value.size() ); + template inline void unpack( Stream& s, std::vector& value, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + unsigned_int size; fc::raw::unpack( s, size, _max_depth - 1 ); + FC_ASSERT( size.value < MAX_ARRAY_ALLOC_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 ) { - fc::raw::pack( s, unsigned_int((uint32_t)v.size())); - if( v.size() ) s.write( v.c_str(), v.size() ); + template inline void pack( Stream& s, const fc::string& v, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, unsigned_int((uint32_t)v.size()), _max_depth - 1 ); + if( v.size() ) s.write( v.c_str(), v.size() ); } - template inline void unpack( Stream& s, fc::string& v ) { - std::vector tmp; fc::raw::unpack(s,tmp); - if( tmp.size() ) - v = fc::string(tmp.data(),tmp.data()+tmp.size()); - else v = fc::string(); + template inline void unpack( Stream& s, fc::string& v, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + std::vector tmp; fc::raw::unpack( s, tmp, _max_depth - 1 ); + if( tmp.size() ) + v = fc::string( tmp.data(), tmp.data()+tmp.size() ); + else v = fc::string(); } // bool - template inline void pack( Stream& s, const bool& v ) { fc::raw::pack( s, uint8_t(v) ); } - template inline void unpack( Stream& s, bool& v ) + template inline void pack( Stream& s, const bool& v, uint32_t _max_depth ) + { + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, uint8_t(v), _max_depth - 1 ); + } + template inline void unpack( Stream& s, bool& v, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); uint8_t b; - fc::raw::unpack( s, b ); + fc::raw::unpack( s, b, _max_depth - 1 ); FC_ASSERT( (b & ~1) == 0 ); v=(b!=0); } @@ -269,49 +312,56 @@ namespace fc { template struct pack_object_visitor { - pack_object_visitor(const Class& _c, Stream& _s) - :c(_c),s(_s){} + pack_object_visitor( const Class& _c, Stream& _s, uint32_t _max_depth ) + :c(_c),s(_s),max_depth(_max_depth) + { + FC_ASSERT( _max_depth > 0 ); + } template void operator()( const char* name )const { - fc::raw::pack( s, c.*p ); + fc::raw::pack( s, c.*p, max_depth - 1 ); } private: const Class& c; Stream& s; + uint32_t max_depth; }; template struct unpack_object_visitor { - unpack_object_visitor(Class& _c, Stream& _s) - :c(_c),s(_s){} + unpack_object_visitor( Class& _c, Stream& _s, uint32_t _max_depth ) : c(_c),s(_s),max_depth(_max_depth) + { + FC_ASSERT( _max_depth > 0 ); + } template inline void operator()( const char* name )const { try { - fc::raw::unpack( s, c.*p ); + fc::raw::unpack( s, c.*p, max_depth - 1 ); } FC_RETHROW_EXCEPTIONS( warn, "Error unpacking field ${field}", ("field",name) ) } private: Class& c; Stream& s; + uint32_t max_depth; }; template struct if_class{ template - static inline void pack( Stream& s, const T& v ) { s << v; } + static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) { s << v; } template - static inline void unpack( Stream& s, T& v ) { s >> v; } + static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) { s >> v; } }; template<> struct if_class { template - static inline void pack( Stream& s, const T& v ) { + static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) { s.write( (char*)&v, sizeof(v) ); } template - static inline void unpack( Stream& s, T& v ) { + static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) { s.read( (char*)&v, sizeof(v) ); } }; @@ -319,24 +369,28 @@ namespace fc { template struct if_enum { template - static inline void pack( Stream& s, const T& v ) { - fc::reflector::visit( pack_object_visitor( v, s ) ); + static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + fc::reflector::visit( pack_object_visitor( v, s, _max_depth - 1 ) ); } template - static inline void unpack( Stream& s, T& v ) { - fc::reflector::visit( unpack_object_visitor( v, s ) ); + static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + fc::reflector::visit( unpack_object_visitor( v, s, _max_depth - 1 ) ); } }; template<> struct if_enum { template - static inline void pack( Stream& s, const T& v ) { - fc::raw::pack(s, (int64_t)v); + static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, (int64_t)v, _max_depth - 1 ); } template - static inline void unpack( Stream& s, T& v ) { + static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); int64_t temp; - fc::raw::unpack(s, temp); + fc::raw::unpack( s, temp, _max_depth - 1 ); v = (T)temp; } }; @@ -344,283 +398,314 @@ namespace fc { template struct if_reflected { template - static inline void pack( Stream& s, const T& v ) { - if_class::type>::pack(s,v); + static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + if_class::type>::pack( s, v, _max_depth - 1 ); } template - static inline void unpack( Stream& s, T& v ) { - if_class::type>::unpack(s,v); + static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + if_class::type>::unpack( s, v, _max_depth - 1 ); } }; template<> struct if_reflected { template - static inline void pack( Stream& s, const T& v ) { - if_enum< typename fc::reflector::is_enum >::pack(s,v); + static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + if_enum< typename fc::reflector::is_enum >::pack( s, v, _max_depth - 1 ); } template - static inline void unpack( Stream& s, T& v ) { - if_enum< typename fc::reflector::is_enum >::unpack(s,v); + static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + if_enum< typename fc::reflector::is_enum >::unpack( s, v, _max_depth - 1 ); } }; } // namesapce detail template - inline void pack( Stream& s, const std::unordered_set& value ) { - fc::raw::pack( s, unsigned_int((uint32_t)value.size()) ); - auto itr = value.begin(); - auto end = value.end(); - while( itr != end ) { - fc::raw::pack( s, *itr ); - ++itr; - } + inline void pack( Stream& s, const std::unordered_set& value, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); + auto itr = value.begin(); + auto end = value.end(); + while( itr != end ) { + fc::raw::pack( s, *itr, _max_depth - 1 ); + ++itr; + } } template - inline void unpack( Stream& s, std::unordered_set& value ) { - unsigned_int size; fc::raw::unpack( s, size ); - value.clear(); - FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE ); - value.reserve(size.value); - for( uint32_t i = 0; i < size.value; ++i ) - { + inline void unpack( Stream& s, std::unordered_set& value, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + unsigned_int size; fc::raw::unpack( s, size, _max_depth - 1 ); + value.clear(); + FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE ); + value.reserve(size.value); + for( uint32_t i = 0; i < size.value; ++i ) + { T tmp; - fc::raw::unpack( s, tmp ); + fc::raw::unpack( s, tmp, _max_depth - 1 ); value.insert( std::move(tmp) ); - } + } } template - inline void pack( Stream& s, const std::pair& value ) { - fc::raw::pack( s, value.first ); - fc::raw::pack( s, value.second ); + inline void pack( Stream& s, const std::pair& value, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, value.first, _max_depth - 1 ); + fc::raw::pack( s, value.second, _max_depth - 1 ); } template - inline void unpack( Stream& s, std::pair& value ) + inline void unpack( Stream& s, std::pair& value, uint32_t _max_depth ) { - fc::raw::unpack( s, value.first ); - fc::raw::unpack( s, value.second ); + FC_ASSERT( _max_depth > 0 ); + fc::raw::unpack( s, value.first, _max_depth - 1 ); + fc::raw::unpack( s, value.second, _max_depth - 1 ); } template - inline void pack( Stream& s, const std::unordered_map& value ) { - fc::raw::pack( s, unsigned_int((uint32_t)value.size()) ); - auto itr = value.begin(); - auto end = value.end(); - while( itr != end ) { - fc::raw::pack( s, *itr ); - ++itr; - } + inline void pack( Stream& s, const std::unordered_map& value, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); + auto itr = value.begin(); + auto end = value.end(); + while( itr != end ) { + fc::raw::pack( s, *itr, _max_depth - 1 ); + ++itr; + } } template - inline void unpack( Stream& s, std::unordered_map& value ) + inline void unpack( Stream& s, std::unordered_map& value, uint32_t _max_depth ) { - unsigned_int size; fc::raw::unpack( s, size ); - value.clear(); - FC_ASSERT( size.value*(sizeof(K)+sizeof(V)) < MAX_ARRAY_ALLOC_SIZE ); - value.reserve(size.value); - for( uint32_t i = 0; i < size.value; ++i ) - { + FC_ASSERT( _max_depth > 0 ); + unsigned_int size; fc::raw::unpack( s, size, _max_depth - 1 ); + value.clear(); + FC_ASSERT( size.value*(sizeof(K)+sizeof(V)) < MAX_ARRAY_ALLOC_SIZE ); + value.reserve(size.value); + for( uint32_t i = 0; i < size.value; ++i ) + { std::pair tmp; - fc::raw::unpack( s, tmp ); + fc::raw::unpack( s, tmp, _max_depth - 1 ); value.insert( std::move(tmp) ); - } + } } template - inline void pack( Stream& s, const std::map& value ) { - fc::raw::pack( s, unsigned_int((uint32_t)value.size()) ); - auto itr = value.begin(); - auto end = value.end(); - while( itr != end ) { - fc::raw::pack( s, *itr ); - ++itr; - } + inline void pack( Stream& s, const std::map& value, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); + auto itr = value.begin(); + auto end = value.end(); + while( itr != end ) { + fc::raw::pack( s, *itr, _max_depth - 1 ); + ++itr; + } } template - inline void unpack( Stream& s, std::map& value ) + inline void unpack( Stream& s, std::map& value, uint32_t _max_depth ) { - unsigned_int size; fc::raw::unpack( s, size ); - value.clear(); - FC_ASSERT( size.value*(sizeof(K)+sizeof(V)) < MAX_ARRAY_ALLOC_SIZE ); - for( uint32_t i = 0; i < size.value; ++i ) - { + FC_ASSERT( _max_depth > 0 ); + unsigned_int size; fc::raw::unpack( s, size, _max_depth - 1 ); + value.clear(); + FC_ASSERT( size.value*(sizeof(K)+sizeof(V)) < MAX_ARRAY_ALLOC_SIZE ); + for( uint32_t i = 0; i < size.value; ++i ) + { std::pair tmp; - fc::raw::unpack( s, tmp ); + fc::raw::unpack( s, tmp, _max_depth - 1 ); value.insert( std::move(tmp) ); - } + } } template - inline void pack( Stream& s, const std::deque& value ) { - fc::raw::pack( s, unsigned_int((uint32_t)value.size()) ); - auto itr = value.begin(); - auto end = value.end(); - while( itr != end ) { - fc::raw::pack( s, *itr ); - ++itr; - } + inline void pack( Stream& s, const std::deque& value, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); + auto itr = value.begin(); + auto end = value.end(); + while( itr != end ) { + fc::raw::pack( s, *itr, _max_depth - 1 ); + ++itr; + } } template - inline void unpack( Stream& s, std::deque& value ) { - unsigned_int size; fc::raw::unpack( s, size ); - FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE ); - value.resize(size.value); - auto itr = value.begin(); - auto end = value.end(); - while( itr != end ) { - fc::raw::unpack( s, *itr ); - ++itr; - } + inline void unpack( Stream& s, std::deque& value, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + unsigned_int size; fc::raw::unpack( s, size, _max_depth - 1 ); + FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE ); + value.resize(size.value); + auto itr = value.begin(); + auto end = value.end(); + while( itr != end ) { + fc::raw::unpack( s, *itr, _max_depth - 1 ); + ++itr; + } } template - inline void pack( Stream& s, const std::vector& value ) { - fc::raw::pack( s, unsigned_int((uint32_t)value.size()) ); - auto itr = value.begin(); - auto end = value.end(); - while( itr != end ) { - fc::raw::pack( s, *itr ); - ++itr; - } + inline void pack( Stream& s, const std::vector& value, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); + auto itr = value.begin(); + auto end = value.end(); + while( itr != end ) { + fc::raw::pack( s, *itr, _max_depth - 1 ); + ++itr; + } } template - inline void unpack( Stream& s, std::vector& value ) { - unsigned_int size; fc::raw::unpack( s, size ); - FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE ); - value.resize(size.value); - auto itr = value.begin(); - auto end = value.end(); - while( itr != end ) { - fc::raw::unpack( s, *itr ); - ++itr; - } + inline void unpack( Stream& s, std::vector& value, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + unsigned_int size; fc::raw::unpack( s, size, _max_depth - 1 ); + FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE ); + value.resize(size.value); + auto itr = value.begin(); + auto end = value.end(); + while( itr != end ) { + fc::raw::unpack( s, *itr, _max_depth - 1 ); + ++itr; + } } template - inline void pack( Stream& s, const std::set& value ) { - fc::raw::pack( s, unsigned_int((uint32_t)value.size()) ); - auto itr = value.begin(); - auto end = value.end(); - while( itr != end ) { - fc::raw::pack( s, *itr ); - ++itr; - } + inline void pack( Stream& s, const std::set& value, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); + auto itr = value.begin(); + auto end = value.end(); + while( itr != end ) { + fc::raw::pack( s, *itr, _max_depth - 1 ); + ++itr; + } } template - inline void unpack( Stream& s, std::set& value ) { - unsigned_int size; fc::raw::unpack( s, size ); - for( uint64_t i = 0; i < size.value; ++i ) - { - T tmp; - fc::raw::unpack( s, tmp ); - value.insert( std::move(tmp) ); - } + inline void unpack( Stream& s, std::set& value, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + unsigned_int size; fc::raw::unpack( s, size, _max_depth - 1 ); + for( uint64_t i = 0; i < size.value; ++i ) + { + T tmp; + fc::raw::unpack( s, tmp, _max_depth - 1 ); + value.insert( std::move(tmp) ); + } } template - inline void pack( Stream& s, const T& v ) { - fc::raw::detail::if_reflected< typename fc::reflector::is_defined >::pack(s,v); + inline void pack( Stream& s, const T& v, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + fc::raw::detail::if_reflected< typename fc::reflector::is_defined >::pack( s, v, _max_depth - 1 ); } template - inline void unpack( Stream& s, T& v ) + inline void unpack( Stream& s, T& v, uint32_t _max_depth ) { try { - fc::raw::detail::if_reflected< typename fc::reflector::is_defined >::unpack(s,v); + FC_ASSERT( _max_depth > 0 ); + fc::raw::detail::if_reflected< typename fc::reflector::is_defined >::unpack( s, v, _max_depth - 1 ); } FC_RETHROW_EXCEPTIONS( warn, "error unpacking ${type}", ("type",fc::get_typename::name() ) ) } template - inline size_t pack_size( const T& v ) + inline size_t pack_size( const T& v ) { - datastream ps; - fc::raw::pack(ps,v ); - return ps.tellp(); + datastream ps; + fc::raw::pack( ps, v ); + return ps.tellp(); } template - inline std::vector pack( const T& v ) { - datastream ps; - fc::raw::pack(ps,v ); - std::vector vec(ps.tellp()); - - if( vec.size() ) { - datastream ds( vec.data(), size_t(vec.size()) ); - fc::raw::pack(ds,v); - } - return vec; + inline std::vector pack( const T& v, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + datastream ps; + fc::raw::pack( ps, v, _max_depth - 1 ); + std::vector vec(ps.tellp()); + + if( vec.size() ) { + datastream ds( vec.data(), size_t(vec.size()) ); + fc::raw::pack( ds, v, _max_depth - 1 ); + } + return vec; } template - inline std::vector pack( const T& v, Next... next ) { - datastream ps; - fc::raw::pack(ps,v,next...); - std::vector vec(ps.tellp()); - - if( vec.size() ) { - datastream ds( vec.data(), size_t(vec.size()) ); - fc::raw::pack(ds,v,next...); - } - return vec; + inline std::vector pack( const T& v, Next... next, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + datastream ps; + fc::raw::pack( ps, v, next..., _max_depth - 1 ); + std::vector vec(ps.tellp()); + + if( vec.size() ) { + datastream ds( vec.data(), size_t(vec.size()) ); + fc::raw::pack( ds, v, next..., _max_depth - 1 ); + } + return vec; } template - inline T unpack( const std::vector& s ) + inline T unpack( const std::vector& s, uint32_t _max_depth ) { try { - T tmp; - if( s.size() ) { - datastream ds( s.data(), size_t(s.size()) ); - fc::raw::unpack(ds,tmp); - } - return tmp; + FC_ASSERT( _max_depth > 0 ); + T tmp; + if( s.size() ) { + datastream ds( s.data(), size_t(s.size()) ); + fc::raw::unpack( ds, tmp, _max_depth - 1 ); + } + return tmp; } FC_RETHROW_EXCEPTIONS( warn, "error unpacking ${type}", ("type",fc::get_typename::name() ) ) } template - inline void unpack( const std::vector& s, T& tmp ) + inline void unpack( const std::vector& s, T& tmp, uint32_t _max_depth ) { try { - if( s.size() ) { - datastream ds( s.data(), size_t(s.size()) ); - fc::raw::unpack(ds,tmp); - } + FC_ASSERT( _max_depth > 0 ); + if( s.size() ) { + datastream ds( s.data(), size_t(s.size()) ); + fc::raw::unpack( ds, tmp, _max_depth - 1 ); + } } FC_RETHROW_EXCEPTIONS( warn, "error unpacking ${type}", ("type",fc::get_typename::name() ) ) } template - inline void pack( char* d, uint32_t s, const T& v ) { - datastream ds(d,s); - fc::raw::pack(ds,v ); + inline void pack( char* d, uint32_t s, const T& v, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); + datastream ds(d,s); + fc::raw::pack( ds, v, _max_depth - 1 ); } template - inline T unpack( const char* d, uint32_t s ) + inline T unpack( const char* d, uint32_t s, uint32_t _max_depth ) { try { - T v; - datastream ds( d, s ); - fc::raw::unpack(ds,v); - return v; + FC_ASSERT( _max_depth > 0 ); + T v; + datastream ds( d, s ); + fc::raw::unpack( ds, v, _max_depth - 1 ); + return v; } FC_RETHROW_EXCEPTIONS( warn, "error unpacking ${type}", ("type",fc::get_typename::name() ) ) } template - inline void unpack( const char* d, uint32_t s, T& v ) + inline void unpack( const char* d, uint32_t s, T& v, uint32_t _max_depth ) { try { - datastream ds( d, s ); - fc::raw::unpack(ds,v); - return v; + FC_ASSERT( _max_depth > 0 ); + datastream ds( d, s ); + fc::raw::unpack( ds, v, _max_depth - 1 ); + return v; } FC_RETHROW_EXCEPTIONS( warn, "error unpacking ${type}", ("type",fc::get_typename::name() ) ) } template struct pack_static_variant { Stream& stream; - pack_static_variant( Stream& s ):stream(s){} + uint32_t max_depth; + pack_static_variant( Stream& s, uint32_t _max_depth ):stream(s),max_depth(_max_depth) + { + FC_ASSERT( _max_depth > 0 ); + } typedef void result_type; template void operator()( const T& v )const { - fc::raw::pack( stream, v ); + fc::raw::pack( stream, v, max_depth - 1 ); } }; @@ -628,29 +713,35 @@ namespace fc { struct unpack_static_variant { Stream& stream; - unpack_static_variant( Stream& s ):stream(s){} + uint32_t max_depth; + unpack_static_variant( Stream& s, uint32_t _max_depth ) : stream(s),max_depth(_max_depth) + { + FC_ASSERT( _max_depth > 0 ); + } typedef void result_type; template void operator()( T& v )const { - fc::raw::unpack( stream, v ); + fc::raw::unpack( stream, v, max_depth - 1 ); } }; template - void pack( Stream& s, const static_variant& sv ) + void pack( Stream& s, const static_variant& sv, uint32_t _max_depth ) { - fc::raw::pack( s, unsigned_int(sv.which()) ); - sv.visit( pack_static_variant(s) ); + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, unsigned_int(sv.which()), _max_depth - 1 ); + sv.visit( pack_static_variant( s, _max_depth - 1 ) ); } - template void unpack( Stream& s, static_variant& sv ) + template void unpack( Stream& s, static_variant& sv, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); unsigned_int w; - fc::raw::unpack( s, w ); + fc::raw::unpack( s, w, _max_depth - 1 ); sv.set_which(w.value); - sv.visit( unpack_static_variant(s) ); + sv.visit( unpack_static_variant( s, _max_depth - 1 ) ); } } } // namespace fc::raw diff --git a/include/fc/io/raw_fwd.hpp b/include/fc/io/raw_fwd.hpp index f397202fb..42e955ade 100644 --- a/include/fc/io/raw_fwd.hpp +++ b/include/fc/io/raw_fwd.hpp @@ -1,4 +1,5 @@ #pragma once +#include #include #include #include @@ -11,9 +12,9 @@ #include #include -#define MAX_ARRAY_ALLOC_SIZE (1024*1024*10) +#define MAX_ARRAY_ALLOC_SIZE (1024*1024*10) -namespace fc { +namespace fc { class time_point; class time_point_sec; class variant; @@ -31,94 +32,94 @@ namespace fc { template inline size_t pack_size( const T& v ); - template inline void pack( Stream& s, const fc::fixed_string& u ); - template inline void unpack( Stream& s, fc::fixed_string& u ); + template inline void pack( Stream& s, const fc::fixed_string& u, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void unpack( Stream& s, fc::fixed_string& u, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); template - inline void pack( Stream& s, const fc::enum_type& tp ); + inline void pack( Stream& s, const fc::enum_type& tp, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); template - inline void unpack( Stream& s, fc::enum_type& tp ); + inline void unpack( Stream& s, fc::enum_type& tp, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void pack( Stream& s, const std::set& value ); - template inline void unpack( Stream& s, std::set& value ); - template inline void pack( Stream& s, const std::unordered_set& value ); - template inline void unpack( Stream& s, std::unordered_set& value ); + template inline void pack( Stream& s, const std::set& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void unpack( Stream& s, std::set& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void pack( Stream& s, const std::unordered_set& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void unpack( Stream& s, std::unordered_set& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template void pack( Stream& s, const static_variant& sv ); - template void unpack( Stream& s, static_variant& sv ); + template void pack( Stream& s, const static_variant& sv, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template void unpack( Stream& s, static_variant& sv, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void pack( Stream& s, const flat_set& value ); - template inline void unpack( Stream& s, flat_set& value ); + //template inline void pack( Stream& s, const flat_set& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + //template inline void unpack( Stream& s, flat_set& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void pack( Stream& s, const std::deque& value ); - template inline void unpack( Stream& s, std::deque& value ); + //template inline void pack( Stream& s, const std::deque& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + //template inline void unpack( Stream& s, std::deque& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void pack( Stream& s, const std::unordered_map& value ); - template inline void unpack( Stream& s, std::unordered_map& value ); + template inline void pack( Stream& s, const std::unordered_map& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void unpack( Stream& s, std::unordered_map& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void pack( Stream& s, const std::map& value ); - template inline void unpack( Stream& s, std::map& value ); + template inline void pack( Stream& s, const std::map& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void unpack( Stream& s, std::map& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void pack( Stream& s, const flat_map& value ); - template inline void unpack( Stream& s, flat_map& value ); + //template inline void pack( Stream& s, const flat_map& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + //template inline void unpack( Stream& s, flat_map& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void pack( Stream& s, const std::pair& value ); - template inline void unpack( Stream& s, std::pair& value ); + template inline void pack( Stream& s, const std::pair& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void unpack( Stream& s, std::pair& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - 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 variant_object& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void unpack( Stream& s, variant_object& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void pack( Stream& s, const variant& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void unpack( Stream& s, variant& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void pack( Stream& s, const path& v ); - template inline void unpack( Stream& s, path& v ); - template inline void pack( Stream& s, const ip::endpoint& v ); - template inline void unpack( Stream& s, ip::endpoint& v ); + template inline void pack( Stream& s, const path& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void unpack( Stream& s, path& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void pack( Stream& s, const ip::endpoint& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void unpack( Stream& s, ip::endpoint& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template void unpack( Stream& s, fc::optional& v ); - template void unpack( Stream& s, const T& v ); - template void pack( Stream& s, const fc::optional& v ); - template void pack( Stream& s, const safe& v ); - template void unpack( Stream& s, fc::safe& v ); + template void unpack( Stream& s, fc::optional& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template void unpack( Stream& s, const T& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template void pack( Stream& s, const fc::optional& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template void pack( Stream& s, const safe& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template void unpack( Stream& s, fc::safe& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template void unpack( Stream& s, time_point& ); - template void pack( Stream& s, const time_point& ); - template void unpack( Stream& s, time_point_sec& ); - template void pack( Stream& s, const time_point_sec& ); - template void unpack( Stream& s, std::string& ); - template void pack( Stream& s, const std::string& ); - template void unpack( Stream& s, fc::ecc::public_key& ); - template void pack( Stream& s, const fc::ecc::public_key& ); - template void unpack( Stream& s, fc::ecc::private_key& ); - template void pack( Stream& s, const fc::ecc::private_key& ); + template void unpack( Stream& s, time_point&, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template void pack( Stream& s, const time_point&, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template void unpack( Stream& s, time_point_sec&, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template void pack( Stream& s, const time_point_sec&, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template void unpack( Stream& s, std::string&, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template void pack( Stream& s, const std::string&, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template void unpack( Stream& s, fc::ecc::public_key&, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template void pack( Stream& s, const fc::ecc::public_key&, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template void unpack( Stream& s, fc::ecc::private_key&, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template void pack( Stream& s, const fc::ecc::private_key&, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void pack( Stream& s, const T& v ); - template inline void unpack( Stream& s, T& v ); + template inline void pack( Stream& s, const T& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void unpack( Stream& s, T& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void pack( Stream& s, const std::vector& v ); - template inline void unpack( Stream& s, std::vector& v ); + template inline void pack( Stream& s, const std::vector& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void unpack( Stream& s, std::vector& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void pack( Stream& s, const signed_int& v ); - template inline void unpack( Stream& s, signed_int& vi ); + template inline void pack( Stream& s, const signed_int& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void unpack( Stream& s, signed_int& vi, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void pack( Stream& s, const unsigned_int& v ); - template inline void unpack( Stream& s, unsigned_int& vi ); + template inline void pack( Stream& s, const unsigned_int& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void unpack( Stream& s, unsigned_int& vi, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void pack( Stream& s, const char* v ); - template inline void pack( Stream& s, const std::vector& value ); - template inline void unpack( Stream& s, std::vector& value ); + template inline void pack( Stream& s, const char* v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void pack( Stream& s, const std::vector& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void unpack( Stream& s, std::vector& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void pack( Stream& s, const fc::array& v); - template inline void unpack( Stream& s, fc::array& v); + template inline void pack( Stream& s, const fc::array& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void unpack( Stream& s, fc::array& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH); - template inline void pack( Stream& s, const bool& v ); - template inline void unpack( Stream& s, bool& v ); + template inline void pack( Stream& s, const bool& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void unpack( Stream& s, bool& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline std::vector pack( const T& v ); - template inline T unpack( const std::vector& s ); - template inline T unpack( const char* d, uint32_t s ); - template inline void unpack( const char* d, uint32_t s, T& v ); + template inline std::vector pack( const T& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline T unpack( const std::vector& s, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline T unpack( const char* d, uint32_t s, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void unpack( const char* d, uint32_t s, T& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); } } diff --git a/include/fc/io/raw_variant.hpp b/include/fc/io/raw_variant.hpp index 24fe3f6e3..9df0118c9 100644 --- a/include/fc/io/raw_variant.hpp +++ b/include/fc/io/raw_variant.hpp @@ -10,53 +10,59 @@ namespace fc { namespace raw { class variant_packer : public variant::visitor { public: - variant_packer( Stream& _s ):s(_s){} + variant_packer( Stream& _s, uint32_t _max_depth ):s(_s),max_depth(_max_depth) + { + FC_ASSERT( _max_depth > 0 ); + } virtual void handle()const { } virtual void handle( const int64_t& v )const { - fc::raw::pack( s, v ); + fc::raw::pack( s, v, max_depth - 1 ); } virtual void handle( const uint64_t& v )const { - fc::raw::pack( s, v ); + fc::raw::pack( s, v, max_depth - 1 ); } - virtual void handle( const double& v )const + virtual void handle( const double& v )const { - fc::raw::pack( s, v ); + fc::raw::pack( s, v, max_depth - 1 ); } virtual void handle( const bool& v )const { - fc::raw::pack( s, v ); + fc::raw::pack( s, v, max_depth - 1 ); } virtual void handle( const string& v )const { - fc::raw::pack( s, v ); + fc::raw::pack( s, v, max_depth - 1 ); } virtual void handle( const variant_object& v)const { - fc::raw::pack( s, v ); + fc::raw::pack( s, v, max_depth - 1 ); } virtual void handle( const variants& v)const { - fc::raw::pack( s, v ); + fc::raw::pack( s, v, max_depth - 1 ); } - + Stream& s; - + uint32_t max_depth; + }; - template - inline void pack( Stream& s, const variant& v ) + template + inline void pack( Stream& s, const variant& v, uint32_t _max_depth ) { - pack( s, uint8_t(v.get_type()) ); - v.visit( variant_packer(s) ); + FC_ASSERT( _max_depth > 0 ); + pack( s, uint8_t(v.get_type()), _max_depth - 1 ); + v.visit( variant_packer( s, _max_depth - 1 ) ); } - template - inline void unpack( Stream& s, variant& v ) + template + inline void unpack( Stream& s, variant& v, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); uint8_t t; - unpack( s, t ); + unpack( s, t, _max_depth - 1 ); switch( t ) { case variant::null_type: @@ -64,49 +70,49 @@ namespace fc { namespace raw { case variant::int64_type: { int64_t val; - raw::unpack(s,val); + raw::unpack( s, val, _max_depth - 1 ); v = val; return; } case variant::uint64_type: { uint64_t val; - raw::unpack(s,val); + raw::unpack( s, val, _max_depth - 1 ); v = val; return; } case variant::double_type: { double val; - raw::unpack(s,val); + raw::unpack( s, val, _max_depth - 1 ); v = val; return; } case variant::bool_type: { bool val; - raw::unpack(s,val); + raw::unpack( s, val, _max_depth - 1 ); v = val; return; } case variant::string_type: { fc::string val; - raw::unpack(s,val); + raw::unpack( s, val, _max_depth - 1 ); v = fc::move(val); return; } case variant::array_type: { variants val; - raw::unpack(s,val); + raw::unpack( s, val, _max_depth - 1 ); v = fc::move(val); return; } case variant::object_type: { - variant_object val; - raw::unpack(s,val); + variant_object val; + raw::unpack( s, val, _max_depth - 1 ); v = fc::move(val); return; } @@ -115,22 +121,24 @@ namespace fc { namespace raw { } } - template - inline void pack( Stream& s, const variant_object& v ) + template + inline void pack( Stream& s, const variant_object& v, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); unsigned_int vs = (uint32_t)v.size(); - pack( s, vs ); + pack( s, vs, _max_depth - 1 ); for( auto itr = v.begin(); itr != v.end(); ++itr ) { - pack( s, itr->key() ); - pack( s, itr->value() ); + pack( s, itr->key(), _max_depth - 1 ); + pack( s, itr->value(), _max_depth - 1 ); } } - template - inline void unpack( Stream& s, variant_object& v ) + template + inline void unpack( Stream& s, variant_object& v, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); unsigned_int vs; - unpack( s, vs ); + unpack( s, vs, _max_depth - 1 ); mutable_variant_object mvo; mvo.reserve(vs.value); @@ -138,8 +146,8 @@ namespace fc { namespace raw { { fc::string key; fc::variant value; - fc::raw::unpack(s,key); - fc::raw::unpack(s,value); + fc::raw::unpack( s, key, _max_depth - 1 ); + fc::raw::unpack( s, value, _max_depth - 1 ); mvo.set( fc::move(key), fc::move(value) ); } v = fc::move(mvo); diff --git a/include/fc/network/ip.hpp b/include/fc/network/ip.hpp index 5a1bd0c98..5292dbff7 100644 --- a/include/fc/network/ip.hpp +++ b/include/fc/network/ip.hpp @@ -40,7 +40,7 @@ namespace fc { private: uint32_t _ip; }; - + class endpoint { public: endpoint(); @@ -58,16 +58,16 @@ namespace fc { friend bool operator==( const endpoint& a, const endpoint& b ); friend bool operator!=( const endpoint& a, const endpoint& b ); friend bool operator< ( const endpoint& a, const endpoint& b ); - + private: /** * The compiler pads endpoint to a full 8 bytes, so while * a port number is limited in range to 16 bits, we specify - * a full 32 bits so that memcmp can be used with sizeof(), - * otherwise 2 bytes will be 'random' and you do not know + * a full 32 bits so that memcmp can be used with sizeof(), + * otherwise 2 bytes will be 'random' and you do not know * where they are stored. */ - uint32_t _port; + uint32_t _port; address _ip; }; @@ -80,41 +80,45 @@ namespace fc { void from_variant( const variant& var, ip::address& vo ); - namespace raw + namespace raw { - template - inline void pack( Stream& s, const ip::address& v ) + template + inline void pack( Stream& s, const ip::address& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { - fc::raw::pack( s, uint32_t(v) ); + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, uint32_t(v), _max_depth - 1 ); } - template - inline void unpack( Stream& s, ip::address& v ) + template + inline void unpack( Stream& s, ip::address& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { + FC_ASSERT( _max_depth > 0 ); uint32_t _ip; - fc::raw::unpack( s, _ip ); + fc::raw::unpack( s, _ip, _max_depth - 1 ); v = ip::address(_ip); } - template - inline void pack( Stream& s, const ip::endpoint& v ) + template + inline void pack( Stream& s, const ip::endpoint& v, uint32_t _max_depth ) { - fc::raw::pack( s, v.get_address() ); - fc::raw::pack( s, v.port() ); + FC_ASSERT( _max_depth > 0 ); + fc::raw::pack( s, v.get_address(), _max_depth - 1 ); + fc::raw::pack( s, v.port(), _max_depth - 1 ); } - template - inline void unpack( Stream& s, ip::endpoint& v ) + template + inline void unpack( Stream& s, ip::endpoint& v, uint32_t _max_depth ) { + FC_ASSERT( _max_depth > 0 ); ip::address a; uint16_t p; - fc::raw::unpack( s, a ); - fc::raw::unpack( s, p ); + fc::raw::unpack( s, a, _max_depth - 1 ); + fc::raw::unpack( s, p, _max_depth - 1 ); v = ip::endpoint(a,p); } } } // namespace fc -FC_REFLECT_TYPENAME( fc::ip::address ) -FC_REFLECT_TYPENAME( fc::ip::endpoint ) +FC_REFLECT_TYPENAME( fc::ip::address ) +FC_REFLECT_TYPENAME( fc::ip::endpoint ) namespace std { template<> diff --git a/include/fc/real128.hpp b/include/fc/real128.hpp index 3a7d26dbe..142f5ec1f 100644 --- a/include/fc/real128.hpp +++ b/include/fc/real128.hpp @@ -1,5 +1,5 @@ #pragma once -#include +#include #define FC_REAL128_PRECISION (uint64_t(1000000) * uint64_t(1000000) * uint64_t(1000000)) @@ -27,7 +27,7 @@ namespace fc { real128& operator -= ( const real128& o ); real128& operator /= ( const real128& o ); real128& operator *= ( const real128& o ); - + static real128 from_fixed( const uint128& fixed ); uint64_t to_uint64()const; @@ -39,12 +39,15 @@ namespace fc { void to_variant( const real128& var, variant& vo ); void from_variant( const variant& var, real128& vo ); - namespace raw + namespace raw { template - inline void pack( Stream& s, const real128& value_to_pack ) { s.write( (char*)&value_to_pack, sizeof(value_to_pack) ); } + inline void pack( Stream& s, const real128& value_to_pack, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) + { s.write( (char*)&value_to_pack, sizeof(value_to_pack) ); } + template - inline void unpack( Stream& s, real128& value_to_unpack ) { s.read( (char*)&value_to_unpack, sizeof(value_to_unpack) ); } + inline void unpack( Stream& s, real128& value_to_unpack, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) + { s.read( (char*)&value_to_unpack, sizeof(value_to_unpack) ); } } diff --git a/include/fc/uint128.hpp b/include/fc/uint128.hpp index 5e599dc38..e2a72ccc7 100644 --- a/include/fc/uint128.hpp +++ b/include/fc/uint128.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -126,9 +127,9 @@ namespace fc namespace raw { template - inline void pack( Stream& s, const uint128& u ) { s.write( (char*)&u, sizeof(u) ); } + inline void pack( Stream& s, const uint128& u, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { s.write( (char*)&u, sizeof(u) ); } template - inline void unpack( Stream& s, uint128& u ) { s.read( (char*)&u, sizeof(u) ); } + inline void unpack( Stream& s, uint128& u, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { s.read( (char*)&u, sizeof(u) ); } } size_t city_hash_size_t(const char *buf, size_t len); From 43ac0b0520613fc3256e7b2dae0b91d0c27c1d2a Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 13 Mar 2018 13:03:37 -0400 Subject: [PATCH 3/3] Slightly improve performance for pack/unpack --- include/fc/container/flat.hpp | 30 +++-- include/fc/interprocess/container.hpp | 10 +- include/fc/io/raw.hpp | 155 +++++++++++++++----------- include/fc/io/raw_variant.hpp | 54 ++++----- include/fc/network/ip.hpp | 10 +- 5 files changed, 148 insertions(+), 111 deletions(-) diff --git a/include/fc/container/flat.hpp b/include/fc/container/flat.hpp index 0b494f23a..b323c2525 100644 --- a/include/fc/container/flat.hpp +++ b/include/fc/container/flat.hpp @@ -10,36 +10,39 @@ namespace fc { template inline void pack( Stream& s, const flat_set& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); + --_max_depth; + pack( s, unsigned_int((uint32_t)value.size()), _max_depth ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { - fc::raw::pack( s, *itr, _max_depth - 1 ); + fc::raw::pack( s, *itr, _max_depth ); ++itr; } } template inline void unpack( Stream& s, flat_set& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - unsigned_int size; unpack( s, size, _max_depth - 1 ); + --_max_depth; + unsigned_int size; unpack( s, size, _max_depth ); value.clear(); FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE ); value.reserve(size.value); for( uint32_t i = 0; i < size.value; ++i ) { T tmp; - fc::raw::unpack( s, tmp, _max_depth - 1 ); + fc::raw::unpack( s, tmp, _max_depth ); value.insert( std::move(tmp) ); } } template inline void pack( Stream& s, const flat_map& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); + --_max_depth; + pack( s, unsigned_int((uint32_t)value.size()), _max_depth ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { - fc::raw::pack( s, *itr, _max_depth - 1 ); + fc::raw::pack( s, *itr, _max_depth ); ++itr; } } @@ -47,14 +50,15 @@ namespace fc { inline void unpack( Stream& s, flat_map& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - unsigned_int size; unpack( s, size, _max_depth - 1 ); + --_max_depth; + unsigned_int size; unpack( s, size, _max_depth ); value.clear(); FC_ASSERT( size.value*(sizeof(K)+sizeof(V)) < MAX_ARRAY_ALLOC_SIZE ); value.reserve(size.value); for( uint32_t i = 0; i < size.value; ++i ) { std::pair tmp; - fc::raw::unpack( s, tmp, _max_depth - 1 ); + fc::raw::unpack( s, tmp, _max_depth ); value.insert( std::move(tmp) ); } } @@ -62,12 +66,13 @@ namespace fc { template void pack( Stream& s, const bip::vector& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); + --_max_depth; + pack( s, unsigned_int((uint32_t)value.size()), _max_depth ); if( !std::is_fundamental::value ) { auto itr = value.begin(); auto end = value.end(); while( itr != end ) { - fc::raw::pack( s, *itr, _max_depth - 1 ); + fc::raw::pack( s, *itr, _max_depth ); ++itr; } } else { @@ -78,12 +83,13 @@ namespace fc { template void unpack( Stream& s, bip::vector& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); + --_max_depth; unsigned_int size; - unpack( s, size, _max_depth - 1 ); + unpack( s, size, _max_depth ); value.resize( size ); if( !std::is_fundamental::value ) { for( auto& item : value ) - unpack( s, item, _max_depth - 1 ); + unpack( s, item, _max_depth ); } else { s.read( (char*)value.data(), value.size() ); } diff --git a/include/fc/interprocess/container.hpp b/include/fc/interprocess/container.hpp index 6ed73f2bd..f61a68c4e 100644 --- a/include/fc/interprocess/container.hpp +++ b/include/fc/interprocess/container.hpp @@ -124,22 +124,24 @@ namespace fc { template inline void pack( Stream& s, const bip::vector& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { FC_ASSERT( _max_depth > 0 ); - pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); + --_max_depth; + pack( s, unsigned_int((uint32_t)value.size()), _max_depth ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { - fc::raw::pack( s, *itr, _max_depth - 1 ); + fc::raw::pack( s, *itr, _max_depth ); ++itr; } } template inline void unpack( Stream& s, bip::vector& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { FC_ASSERT( _max_depth > 0 ); + --_max_depth; unsigned_int size; - unpack( s, size, _max_depth - 1 ); + unpack( s, size, _max_depth ); value.clear(); value.resize(size); for( auto& item : value ) - fc::raw::unpack( s, item, _max_depth - 1 ); + fc::raw::unpack( s, item, _max_depth ); } } } diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index 02873fc7b..d7e8bcd72 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -21,31 +21,34 @@ namespace fc { template inline void pack( Stream& s, const Arg0& a0, Args... args, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - pack( s, a0, _max_depth - 1 ); - pack( s, args..., _max_depth - 1 ); + --_max_depth; + pack( s, a0, _max_depth ); + pack( s, args..., _max_depth ); } template inline void pack( Stream& s, const fc::exception& e, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - fc::raw::pack( s, e.code(), _max_depth - 1 ); - fc::raw::pack( s, std::string(e.name()), _max_depth - 1 ); - fc::raw::pack( s, std::string(e.what()), _max_depth - 1 ); - fc::raw::pack( s, e.get_log(), _max_depth - 1 ); + --_max_depth; + fc::raw::pack( s, e.code(), _max_depth ); + fc::raw::pack( s, std::string(e.name()), _max_depth ); + fc::raw::pack( s, std::string(e.what()), _max_depth ); + fc::raw::pack( s, e.get_log(), _max_depth ); } template inline void unpack( Stream& s, fc::exception& e, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); + --_max_depth; int64_t code; std::string name, what; log_messages msgs; - fc::raw::unpack( s, code, _max_depth - 1 ); - fc::raw::unpack( s, name, _max_depth - 1 ); - fc::raw::unpack( s, what, _max_depth - 1 ); - fc::raw::unpack( s, msgs, _max_depth - 1 ); + fc::raw::unpack( s, code, _max_depth ); + fc::raw::unpack( s, name, _max_depth ); + fc::raw::unpack( s, what, _max_depth ); + fc::raw::unpack( s, msgs, _max_depth ); e = fc::exception( fc::move(msgs), code, name, what ); } @@ -54,7 +57,7 @@ namespace fc { inline void pack( Stream& s, const fc::log_message& msg, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - fc::raw::pack( s, variant(msg), _max_depth - 1 ); + fc::raw::pack( s, variant(msg), _max_depth - 1 ); // TODO check variant depth? } template inline void unpack( Stream& s, fc::log_message& msg, uint32_t _max_depth ) @@ -62,7 +65,7 @@ namespace fc { FC_ASSERT( _max_depth > 0 ); fc::variant vmsg; fc::raw::unpack( s, vmsg, _max_depth - 1 ); - msg = vmsg.as(); + msg = vmsg.as(); // TODO check depth? } template @@ -250,16 +253,18 @@ namespace fc { template void pack( Stream& s, const fc::optional& v, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - fc::raw::pack( s, bool(!!v), _max_depth - 1 ); - if( !!v ) fc::raw::pack( s, *v, _max_depth - 1 ); + --_max_depth; + fc::raw::pack( s, bool(!!v), _max_depth ); + if( !!v ) fc::raw::pack( s, *v, _max_depth ); } template void unpack( Stream& s, fc::optional& v, uint32_t _max_depth ) { try { FC_ASSERT( _max_depth > 0 ); - bool b; fc::raw::unpack( s, b, _max_depth - 1 ); - if( b ) { v = T(); fc::raw::unpack( s, *v, _max_depth - 1 ); } + --_max_depth; + bool b; fc::raw::unpack( s, b, _max_depth ); + if( b ) { v = T(); fc::raw::unpack( s, *v, _max_depth ); } } FC_RETHROW_EXCEPTIONS( warn, "optional<${type}>", ("type",fc::get_typename::name() ) ) } // std::vector @@ -313,24 +318,24 @@ namespace fc { template struct pack_object_visitor { pack_object_visitor( const Class& _c, Stream& _s, uint32_t _max_depth ) - :c(_c),s(_s),max_depth(_max_depth) + :c(_c),s(_s),max_depth(_max_depth - 1) { FC_ASSERT( _max_depth > 0 ); } template void operator()( const char* name )const { - fc::raw::pack( s, c.*p, max_depth - 1 ); + fc::raw::pack( s, c.*p, max_depth ); } private: - const Class& c; - Stream& s; - uint32_t max_depth; + const Class& c; + Stream& s; + const uint32_t max_depth; }; template struct unpack_object_visitor { - unpack_object_visitor( Class& _c, Stream& _s, uint32_t _max_depth ) : c(_c),s(_s),max_depth(_max_depth) + unpack_object_visitor( Class& _c, Stream& _s, uint32_t _max_depth ) : c(_c),s(_s),max_depth(_max_depth - 1) { FC_ASSERT( _max_depth > 0 ); } @@ -338,12 +343,12 @@ namespace fc { template inline void operator()( const char* name )const { try { - fc::raw::unpack( s, c.*p, max_depth - 1 ); + fc::raw::unpack( s, c.*p, max_depth ); } FC_RETHROW_EXCEPTIONS( warn, "Error unpacking field ${field}", ("field",name) ) } private: Class& c; Stream& s; - uint32_t max_depth; + const uint32_t max_depth; }; template @@ -427,25 +432,27 @@ namespace fc { template inline void pack( Stream& s, const std::unordered_set& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); + --_max_depth; + fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { - fc::raw::pack( s, *itr, _max_depth - 1 ); + fc::raw::pack( s, *itr, _max_depth ); ++itr; } } template inline void unpack( Stream& s, std::unordered_set& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - unsigned_int size; fc::raw::unpack( s, size, _max_depth - 1 ); + --_max_depth; + unsigned_int size; fc::raw::unpack( s, size, _max_depth ); value.clear(); FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE ); value.reserve(size.value); for( uint32_t i = 0; i < size.value; ++i ) { T tmp; - fc::raw::unpack( s, tmp, _max_depth - 1 ); + fc::raw::unpack( s, tmp, _max_depth ); value.insert( std::move(tmp) ); } } @@ -454,25 +461,28 @@ namespace fc { template inline void pack( Stream& s, const std::pair& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - fc::raw::pack( s, value.first, _max_depth - 1 ); - fc::raw::pack( s, value.second, _max_depth - 1 ); + --_max_depth; + fc::raw::pack( s, value.first, _max_depth ); + fc::raw::pack( s, value.second, _max_depth ); } template inline void unpack( Stream& s, std::pair& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - fc::raw::unpack( s, value.first, _max_depth - 1 ); - fc::raw::unpack( s, value.second, _max_depth - 1 ); + --_max_depth; + fc::raw::unpack( s, value.first, _max_depth ); + fc::raw::unpack( s, value.second, _max_depth ); } template inline void pack( Stream& s, const std::unordered_map& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); + --_max_depth; + fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { - fc::raw::pack( s, *itr, _max_depth - 1 ); + fc::raw::pack( s, *itr, _max_depth ); ++itr; } } @@ -480,25 +490,27 @@ namespace fc { inline void unpack( Stream& s, std::unordered_map& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - unsigned_int size; fc::raw::unpack( s, size, _max_depth - 1 ); + --_max_depth; + unsigned_int size; fc::raw::unpack( s, size, _max_depth ); value.clear(); FC_ASSERT( size.value*(sizeof(K)+sizeof(V)) < MAX_ARRAY_ALLOC_SIZE ); value.reserve(size.value); for( uint32_t i = 0; i < size.value; ++i ) { std::pair tmp; - fc::raw::unpack( s, tmp, _max_depth - 1 ); + fc::raw::unpack( s, tmp, _max_depth ); value.insert( std::move(tmp) ); } } template inline void pack( Stream& s, const std::map& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); + --_max_depth; + fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { - fc::raw::pack( s, *itr, _max_depth - 1 ); + fc::raw::pack( s, *itr, _max_depth ); ++itr; } } @@ -506,13 +518,14 @@ namespace fc { inline void unpack( Stream& s, std::map& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - unsigned_int size; fc::raw::unpack( s, size, _max_depth - 1 ); + --_max_depth; + unsigned_int size; fc::raw::unpack( s, size, _max_depth ); value.clear(); FC_ASSERT( size.value*(sizeof(K)+sizeof(V)) < MAX_ARRAY_ALLOC_SIZE ); for( uint32_t i = 0; i < size.value; ++i ) { std::pair tmp; - fc::raw::unpack( s, tmp, _max_depth - 1 ); + fc::raw::unpack( s, tmp, _max_depth ); value.insert( std::move(tmp) ); } } @@ -520,11 +533,12 @@ namespace fc { template inline void pack( Stream& s, const std::deque& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); + --_max_depth; + fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { - fc::raw::pack( s, *itr, _max_depth - 1 ); + fc::raw::pack( s, *itr, _max_depth ); ++itr; } } @@ -532,13 +546,14 @@ namespace fc { template inline void unpack( Stream& s, std::deque& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - unsigned_int size; fc::raw::unpack( s, size, _max_depth - 1 ); + --_max_depth; + unsigned_int size; fc::raw::unpack( s, size, _max_depth ); FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE ); value.resize(size.value); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { - fc::raw::unpack( s, *itr, _max_depth - 1 ); + fc::raw::unpack( s, *itr, _max_depth ); ++itr; } } @@ -546,11 +561,12 @@ namespace fc { template inline void pack( Stream& s, const std::vector& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); + --_max_depth; + fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { - fc::raw::pack( s, *itr, _max_depth - 1 ); + fc::raw::pack( s, *itr, _max_depth ); ++itr; } } @@ -558,13 +574,14 @@ namespace fc { template inline void unpack( Stream& s, std::vector& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - unsigned_int size; fc::raw::unpack( s, size, _max_depth - 1 ); + --_max_depth; + unsigned_int size; fc::raw::unpack( s, size, _max_depth ); FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE ); value.resize(size.value); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { - fc::raw::unpack( s, *itr, _max_depth - 1 ); + fc::raw::unpack( s, *itr, _max_depth ); ++itr; } } @@ -572,11 +589,12 @@ namespace fc { template inline void pack( Stream& s, const std::set& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); + --_max_depth; + fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { - fc::raw::pack( s, *itr, _max_depth - 1 ); + fc::raw::pack( s, *itr, _max_depth ); ++itr; } } @@ -584,11 +602,12 @@ namespace fc { template inline void unpack( Stream& s, std::set& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - unsigned_int size; fc::raw::unpack( s, size, _max_depth - 1 ); + --_max_depth; + unsigned_int size; fc::raw::unpack( s, size, _max_depth ); for( uint64_t i = 0; i < size.value; ++i ) { T tmp; - fc::raw::unpack( s, tmp, _max_depth - 1 ); + fc::raw::unpack( s, tmp, _max_depth ); value.insert( std::move(tmp) ); } } @@ -618,13 +637,14 @@ namespace fc { template inline std::vector pack( const T& v, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); + --_max_depth; datastream ps; - fc::raw::pack( ps, v, _max_depth - 1 ); + fc::raw::pack( ps, v, _max_depth ); std::vector vec(ps.tellp()); if( vec.size() ) { datastream ds( vec.data(), size_t(vec.size()) ); - fc::raw::pack( ds, v, _max_depth - 1 ); + fc::raw::pack( ds, v, _max_depth ); } return vec; } @@ -632,13 +652,14 @@ namespace fc { template inline std::vector pack( const T& v, Next... next, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); + --_max_depth; datastream ps; - fc::raw::pack( ps, v, next..., _max_depth - 1 ); + fc::raw::pack( ps, v, next..., _max_depth ); std::vector vec(ps.tellp()); if( vec.size() ) { datastream ds( vec.data(), size_t(vec.size()) ); - fc::raw::pack( ds, v, next..., _max_depth - 1 ); + fc::raw::pack( ds, v, next..., _max_depth ); } return vec; } @@ -696,8 +717,8 @@ namespace fc { struct pack_static_variant { Stream& stream; - uint32_t max_depth; - pack_static_variant( Stream& s, uint32_t _max_depth ):stream(s),max_depth(_max_depth) + const uint32_t max_depth; + pack_static_variant( Stream& s, uint32_t _max_depth ):stream(s),max_depth(_max_depth - 1) { FC_ASSERT( _max_depth > 0 ); } @@ -705,7 +726,7 @@ namespace fc { typedef void result_type; template void operator()( const T& v )const { - fc::raw::pack( stream, v, max_depth - 1 ); + fc::raw::pack( stream, v, max_depth ); } }; @@ -713,8 +734,8 @@ namespace fc { struct unpack_static_variant { Stream& stream; - uint32_t max_depth; - unpack_static_variant( Stream& s, uint32_t _max_depth ) : stream(s),max_depth(_max_depth) + const uint32_t max_depth; + unpack_static_variant( Stream& s, uint32_t _max_depth ) : stream(s),max_depth(_max_depth - 1) { FC_ASSERT( _max_depth > 0 ); } @@ -722,7 +743,7 @@ namespace fc { typedef void result_type; template void operator()( T& v )const { - fc::raw::unpack( stream, v, max_depth - 1 ); + fc::raw::unpack( stream, v, max_depth ); } }; @@ -731,17 +752,19 @@ namespace fc { void pack( Stream& s, const static_variant& sv, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - fc::raw::pack( s, unsigned_int(sv.which()), _max_depth - 1 ); - sv.visit( pack_static_variant( s, _max_depth - 1 ) ); + --_max_depth; + fc::raw::pack( s, unsigned_int(sv.which()), _max_depth ); + sv.visit( pack_static_variant( s, _max_depth ) ); } template void unpack( Stream& s, static_variant& sv, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); + --_max_depth; unsigned_int w; - fc::raw::unpack( s, w, _max_depth - 1 ); + fc::raw::unpack( s, w, _max_depth ); sv.set_which(w.value); - sv.visit( unpack_static_variant( s, _max_depth - 1 ) ); + sv.visit( unpack_static_variant( s, _max_depth ) ); } } } // namespace fc::raw diff --git a/include/fc/io/raw_variant.hpp b/include/fc/io/raw_variant.hpp index 9df0118c9..b07fbaa4c 100644 --- a/include/fc/io/raw_variant.hpp +++ b/include/fc/io/raw_variant.hpp @@ -10,42 +10,42 @@ namespace fc { namespace raw { class variant_packer : public variant::visitor { public: - variant_packer( Stream& _s, uint32_t _max_depth ):s(_s),max_depth(_max_depth) + variant_packer( Stream& _s, uint32_t _max_depth ):s(_s),max_depth(_max_depth - 1) { FC_ASSERT( _max_depth > 0 ); } virtual void handle()const { } virtual void handle( const int64_t& v )const { - fc::raw::pack( s, v, max_depth - 1 ); + fc::raw::pack( s, v, max_depth ); } virtual void handle( const uint64_t& v )const { - fc::raw::pack( s, v, max_depth - 1 ); + fc::raw::pack( s, v, max_depth ); } virtual void handle( const double& v )const { - fc::raw::pack( s, v, max_depth - 1 ); + fc::raw::pack( s, v, max_depth ); } virtual void handle( const bool& v )const { - fc::raw::pack( s, v, max_depth - 1 ); + fc::raw::pack( s, v, max_depth ); } virtual void handle( const string& v )const { - fc::raw::pack( s, v, max_depth - 1 ); + fc::raw::pack( s, v, max_depth ); } virtual void handle( const variant_object& v)const { - fc::raw::pack( s, v, max_depth - 1 ); + fc::raw::pack( s, v, max_depth ); } virtual void handle( const variants& v)const { - fc::raw::pack( s, v, max_depth - 1 ); + fc::raw::pack( s, v, max_depth ); } Stream& s; - uint32_t max_depth; + const uint32_t max_depth; }; @@ -54,15 +54,17 @@ namespace fc { namespace raw { inline void pack( Stream& s, const variant& v, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - pack( s, uint8_t(v.get_type()), _max_depth - 1 ); - v.visit( variant_packer( s, _max_depth - 1 ) ); + --_max_depth; + pack( s, uint8_t(v.get_type()), _max_depth ); + v.visit( variant_packer( s, _max_depth ) ); } template inline void unpack( Stream& s, variant& v, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); + --_max_depth; uint8_t t; - unpack( s, t, _max_depth - 1 ); + unpack( s, t, _max_depth ); switch( t ) { case variant::null_type: @@ -70,49 +72,49 @@ namespace fc { namespace raw { case variant::int64_type: { int64_t val; - raw::unpack( s, val, _max_depth - 1 ); + raw::unpack( s, val, _max_depth ); v = val; return; } case variant::uint64_type: { uint64_t val; - raw::unpack( s, val, _max_depth - 1 ); + raw::unpack( s, val, _max_depth ); v = val; return; } case variant::double_type: { double val; - raw::unpack( s, val, _max_depth - 1 ); + raw::unpack( s, val, _max_depth ); v = val; return; } case variant::bool_type: { bool val; - raw::unpack( s, val, _max_depth - 1 ); + raw::unpack( s, val, _max_depth ); v = val; return; } case variant::string_type: { fc::string val; - raw::unpack( s, val, _max_depth - 1 ); + raw::unpack( s, val, _max_depth ); v = fc::move(val); return; } case variant::array_type: { variants val; - raw::unpack( s, val, _max_depth - 1 ); + raw::unpack( s, val, _max_depth ); v = fc::move(val); return; } case variant::object_type: { variant_object val; - raw::unpack( s, val, _max_depth - 1 ); + raw::unpack( s, val, _max_depth ); v = fc::move(val); return; } @@ -125,20 +127,22 @@ namespace fc { namespace raw { inline void pack( Stream& s, const variant_object& v, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); + --_max_depth; unsigned_int vs = (uint32_t)v.size(); - pack( s, vs, _max_depth - 1 ); + pack( s, vs, _max_depth ); for( auto itr = v.begin(); itr != v.end(); ++itr ) { - pack( s, itr->key(), _max_depth - 1 ); - pack( s, itr->value(), _max_depth - 1 ); + pack( s, itr->key(), _max_depth ); + pack( s, itr->value(), _max_depth ); } } template inline void unpack( Stream& s, variant_object& v, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); + --_max_depth; unsigned_int vs; - unpack( s, vs, _max_depth - 1 ); + unpack( s, vs, _max_depth ); mutable_variant_object mvo; mvo.reserve(vs.value); @@ -146,8 +150,8 @@ namespace fc { namespace raw { { fc::string key; fc::variant value; - fc::raw::unpack( s, key, _max_depth - 1 ); - fc::raw::unpack( s, value, _max_depth - 1 ); + fc::raw::unpack( s, key, _max_depth ); + fc::raw::unpack( s, value, _max_depth ); mvo.set( fc::move(key), fc::move(value) ); } v = fc::move(mvo); diff --git a/include/fc/network/ip.hpp b/include/fc/network/ip.hpp index 5292dbff7..04c503020 100644 --- a/include/fc/network/ip.hpp +++ b/include/fc/network/ip.hpp @@ -101,17 +101,19 @@ namespace fc { inline void pack( Stream& s, const ip::endpoint& v, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - fc::raw::pack( s, v.get_address(), _max_depth - 1 ); - fc::raw::pack( s, v.port(), _max_depth - 1 ); + --_max_depth; + fc::raw::pack( s, v.get_address(), _max_depth ); + fc::raw::pack( s, v.port(), _max_depth ); } template inline void unpack( Stream& s, ip::endpoint& v, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); + --_max_depth; ip::address a; uint16_t p; - fc::raw::unpack( s, a, _max_depth - 1 ); - fc::raw::unpack( s, p, _max_depth - 1 ); + fc::raw::unpack( s, a, _max_depth ); + fc::raw::unpack( s, p, _max_depth ); v = ip::endpoint(a,p); }