From 0fb65e4d3865a3c8ecd1db510672b9152f064abe Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 11 Aug 2018 11:17:28 -0400 Subject: [PATCH 1/7] Added to_variant(bool, ...) --- include/fc/variant.hpp | 2 ++ src/variant.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/include/fc/variant.hpp b/include/fc/variant.hpp index fd286eae7..c00a80d96 100644 --- a/include/fc/variant.hpp +++ b/include/fc/variant.hpp @@ -92,6 +92,8 @@ namespace fc void to_variant( const uint64_t& var, variant& vo, uint32_t max_depth = 1 ); void to_variant( const int64_t& var, variant& vo, uint32_t max_depth = 1 ); + void to_variant( const bool& var, variant& vo, uint32_t max_depth = 1 ); + void to_variant( const variant_object& var, variant& vo, uint32_t max_depth ); void from_variant( const variant& var, variant_object& vo, uint32_t max_depth ); void to_variant( const mutable_variant_object& var, variant& vo, uint32_t max_depth ); diff --git a/src/variant.cpp b/src/variant.cpp index 31204d486..2ee8256ef 100644 --- a/src/variant.cpp +++ b/src/variant.cpp @@ -629,6 +629,7 @@ void from_variant( const variant& var, uint64_t& vo, uint32_t max_depth ) vo = var.as_uint64(); } +void to_variant( const bool& var, variant& vo, uint32_t max_depth ) { vo = uint64_t(var); } void from_variant( const variant& var, bool& vo, uint32_t max_depth ) { vo = var.as_bool(); From b83108c41a637079cc17ce03f62f9e68cf8207cc Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 11 Aug 2018 11:18:55 -0400 Subject: [PATCH 2/7] Added static visit(...) methods to static_variant --- include/fc/static_variant.hpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/fc/static_variant.hpp b/include/fc/static_variant.hpp index 88efedad7..45e781bac 100644 --- a/include/fc/static_variant.hpp +++ b/include/fc/static_variant.hpp @@ -326,6 +326,16 @@ class static_variant { return impl::storage_ops<0, Types...>::apply(_tag, storage, v); } + template + static typename visitor::result_type visit(visitor& v) { + return impl::storage_ops<0, Types...>::apply((const tag_type)w, (const void*)nullptr, v); + } + + template + static typename visitor::result_type visit(const visitor& v) { + return impl::storage_ops<0, Types...>::apply((const tag_type)w, (const void*)nullptr, v); + } + static int count() { return impl::type_info::count; } void set_which( tag_type w ) { FC_ASSERT( w >= 0 ); From 70dbcc11e39d12b74a71ef43169de37e030b88c0 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 11 Aug 2018 11:20:10 -0400 Subject: [PATCH 3/7] Added visit_local_member(...) methods to reflector --- include/fc/reflect/reflect.hpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/fc/reflect/reflect.hpp b/include/fc/reflect/reflect.hpp index 45efbe05d..5a97a8ee9 100644 --- a/include/fc/reflect/reflect.hpp +++ b/include/fc/reflect/reflect.hpp @@ -87,6 +87,9 @@ void throw_bad_enum_cast( const char* k, const char* e ); visitor.TEMPLATE operator()( BOOST_PP_STRINGIZE(elem) ); \ } +#define FC_REFLECT_VISIT_MEMBER_I( r, visitor, I, elem ) \ + case I: FC_REFLECT_VISIT_MEMBER( r, visitor, elem ) break; + #define FC_REFLECT_BASE_MEMBER_COUNT( r, OP, elem ) \ OP fc::reflector::total_member_count @@ -99,6 +102,13 @@ template\ static inline void visit( const Visitor& v ) { \ BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_BASE, v, INHERITS ) \ BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_MEMBER, v, MEMBERS ) \ +}\ +template\ +static inline void visit_local_member( const Visitor& v, IndexType index ) { \ + switch( index ) {\ + BOOST_PP_SEQ_FOR_EACH_I( FC_REFLECT_VISIT_MEMBER_I, v, MEMBERS ) \ + default: break;\ + }\ } #define FC_REFLECT_DERIVED_IMPL_EXT( TYPE, INHERITS, MEMBERS ) \ From 72a8168b2b7370ef7dfc9c1180b518cd127e489d Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Tue, 9 Oct 2018 16:17:34 +0200 Subject: [PATCH 4/7] Added a test for static_variant visitor call depth --- tests/stacktrace_test.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/stacktrace_test.cpp b/tests/stacktrace_test.cpp index baafa7669..bc710a5c1 100644 --- a/tests/stacktrace_test.cpp +++ b/tests/stacktrace_test.cpp @@ -1,9 +1,15 @@ #include +#include + #include + #include +#include #include +#include + BOOST_AUTO_TEST_SUITE(fc_stacktrace) BOOST_AUTO_TEST_CASE(stacktrace_test) @@ -40,6 +46,38 @@ BOOST_AUTO_TEST_CASE(threaded_stacktrace_test) #endif } +#if BOOST_VERSION / 100000 >= 1 && ((BOOST_VERSION / 100) % 1000) >= 65 +class _svdt_visitor +{ +public: + typedef std::string result_type; + std::string operator()( int64_t i )const + { + std::stringstream ss; + fc::print_stacktrace(ss); + return ss.str(); + } + template + std::string operator()( T i )const { return "Unexpected!"; } +}; + +BOOST_AUTO_TEST_CASE(static_variant_depth_test) +{ + int64_t i = 1; + fc::static_variant test(i); + + std::string stacktrace = test.visit( _svdt_visitor() ); + //std::cerr << stacktrace << "\n"; + std::vector lines; + boost::split( lines, stacktrace, boost::is_any_of("\n") ); + int count = 0; + for( const auto& line : lines ) + if( line.find("_svdt_visitor") != std::string::npos ) count++; + BOOST_CHECK_LT( 3, count ); // test.visit(), static_variant::visit, function object, visitor + BOOST_CHECK_GT( 8, count ); // some is implementation-dependent +} +#endif + /* this test causes a segfault on purpose to test the event handler BOOST_AUTO_TEST_CASE(cause_segfault) { From b4da12643f0d06a546cffce5d73e6656cd68316b Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Tue, 9 Oct 2018 17:55:34 +0200 Subject: [PATCH 5/7] Replaced visitors with constant-time implementations --- include/fc/static_variant.hpp | 72 ++++++++++++++++++++++++++++++----- 1 file changed, 62 insertions(+), 10 deletions(-) diff --git a/include/fc/static_variant.hpp b/include/fc/static_variant.hpp index 45e781bac..bb21416d0 100644 --- a/include/fc/static_variant.hpp +++ b/include/fc/static_variant.hpp @@ -10,6 +10,8 @@ * **/ #pragma once + +#include #include #include #include @@ -176,6 +178,34 @@ struct type_info<> { } // namespace impl +template +std::vector> init_wrappers() +{ + return std::vector>(); +} + +template +std::vector> init_wrappers() +{ + std::vector> result = init_wrappers(); + result.insert( result.begin(), [] ( Visitor& v, Data d ) { return v( *reinterpret_cast( d ) ); } ); + return result; +} + +template +std::vector> init_const_wrappers() +{ + return std::vector>(); +} + +template +std::vector> init_const_wrappers() +{ + std::vector> result = init_const_wrappers(); + result.insert( result.begin(), [] ( Visitor& v, Data d ) { return v( *reinterpret_cast( d ) ); } ); + return result; +} + template class static_variant { static_assert(impl::type_info::no_reference_types, "Reference types are not permitted in static_variant."); @@ -308,32 +338,54 @@ class static_variant { } template typename visitor::result_type visit(visitor& v) { - return impl::storage_ops<0, Types...>::apply(_tag, storage, v); + return visit( _tag, v, (void*) storage ); } template typename visitor::result_type visit(const visitor& v) { - return impl::storage_ops<0, Types...>::apply(_tag, storage, v); + return visit( _tag, v, (void*) storage ); } template typename visitor::result_type visit(visitor& v)const { - return impl::storage_ops<0, Types...>::apply(_tag, storage, v); + return visit( _tag, v, (const void*) storage ); } template typename visitor::result_type visit(const visitor& v)const { - return impl::storage_ops<0, Types...>::apply(_tag, storage, v); + return visit( _tag, v, (const void*) storage ); } - template - static typename visitor::result_type visit(visitor& v) { - return impl::storage_ops<0, Types...>::apply((const tag_type)w, (const void*)nullptr, v); + template + static typename visitor::result_type visit( tag_type tag, visitor& v, void* data ) + { + static std::vector> wrappers = init_wrappers(); + FC_ASSERT( tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); + return wrappers[tag]( v, data ); } - template - static typename visitor::result_type visit(const visitor& v) { - return impl::storage_ops<0, Types...>::apply((const tag_type)w, (const void*)nullptr, v); + template + static typename visitor::result_type visit( tag_type tag, const visitor& v, void* data ) + { + static std::vector> wrappers = init_wrappers(); + FC_ASSERT( tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); + return wrappers[tag]( v, data ); + } + + template + static typename visitor::result_type visit( tag_type tag, visitor& v, const void* data ) + { + static std::vector> wrappers = init_const_wrappers(); + FC_ASSERT( tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); + return wrappers[tag]( v, data ); + } + + template + static typename visitor::result_type visit( tag_type tag, const visitor& v, const void* data ) + { + static std::vector> wrappers = init_const_wrappers(); + FC_ASSERT( tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); + return wrappers[tag]( v, data ); } static int count() { return impl::type_info::count; } From bcce353b8ff46ea9d9b83c377f2c835d94096e79 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Wed, 10 Oct 2018 00:07:21 +0200 Subject: [PATCH 6/7] Check tag >= 0, shortened long lines --- include/fc/static_variant.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/fc/static_variant.hpp b/include/fc/static_variant.hpp index bb21416d0..3e8d908e0 100644 --- a/include/fc/static_variant.hpp +++ b/include/fc/static_variant.hpp @@ -359,32 +359,32 @@ class static_variant { template static typename visitor::result_type visit( tag_type tag, visitor& v, void* data ) { - static std::vector> wrappers = init_wrappers(); - FC_ASSERT( tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); + static auto wrappers = init_wrappers(); + FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); return wrappers[tag]( v, data ); } template static typename visitor::result_type visit( tag_type tag, const visitor& v, void* data ) { - static std::vector> wrappers = init_wrappers(); - FC_ASSERT( tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); + static auto wrappers = init_wrappers(); + FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); return wrappers[tag]( v, data ); } template static typename visitor::result_type visit( tag_type tag, visitor& v, const void* data ) { - static std::vector> wrappers = init_const_wrappers(); - FC_ASSERT( tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); + static auto wrappers = init_const_wrappers(); + FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); return wrappers[tag]( v, data ); } template static typename visitor::result_type visit( tag_type tag, const visitor& v, const void* data ) { - static std::vector> wrappers = init_const_wrappers(); - FC_ASSERT( tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); + static auto wrappers = init_const_wrappers(); + FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); return wrappers[tag]( v, data ); } From 8174d63fb44412a9cb2024aae48abb24b0b2ff0b Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Wed, 10 Oct 2018 14:36:19 +0200 Subject: [PATCH 7/7] More line wrapping --- include/fc/static_variant.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/fc/static_variant.hpp b/include/fc/static_variant.hpp index 3e8d908e0..1b2628bd8 100644 --- a/include/fc/static_variant.hpp +++ b/include/fc/static_variant.hpp @@ -187,7 +187,8 @@ std::vector> init_wr template std::vector> init_wrappers() { - std::vector> result = init_wrappers(); + std::vector> result + = init_wrappers(); result.insert( result.begin(), [] ( Visitor& v, Data d ) { return v( *reinterpret_cast( d ) ); } ); return result; } @@ -201,7 +202,8 @@ std::vector> init_co template std::vector> init_const_wrappers() { - std::vector> result = init_const_wrappers(); + std::vector> result + = init_const_wrappers(); result.insert( result.begin(), [] ( Visitor& v, Data d ) { return v( *reinterpret_cast( d ) ); } ); return result; }