From 58e16e543d032e33836d6789cc11c9799a560e9b Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Fri, 5 Apr 2019 22:12:29 +0200 Subject: [PATCH 001/110] Replaced most fc::shared_ptr with std::shared_ptr --- include/fc/io/fstream.hpp | 6 +++--- include/fc/io/raw.hpp | 3 --- include/fc/io/raw_fwd.hpp | 9 +++++---- include/fc/log/appender.hpp | 18 +++++++++--------- include/fc/log/file_appender.hpp | 2 +- include/fc/log/gelf_appender.hpp | 2 +- include/fc/log/log_message.hpp | 1 - include/fc/log/logger.hpp | 14 ++++++-------- include/fc/network/http/server.hpp | 5 ++--- include/fc/network/udp_socket.hpp | 5 ++--- include/fc/variant_object.hpp | 2 +- src/io/fstream.cpp | 4 ++-- src/log/file_appender.cpp | 2 +- src/log/gelf_appender.cpp | 2 +- src/log/logger.cpp | 13 +++++-------- src/network/http/http_server.cpp | 6 +++--- src/network/udp_socket.cpp | 2 +- 17 files changed, 43 insertions(+), 53 deletions(-) diff --git a/include/fc/io/fstream.hpp b/include/fc/io/fstream.hpp index 9a0c99d..7b5465e 100644 --- a/include/fc/io/fstream.hpp +++ b/include/fc/io/fstream.hpp @@ -1,8 +1,8 @@ #pragma once -#include #include #include #include +#include namespace fc { class path; @@ -21,7 +21,7 @@ namespace fc { private: class impl; - fc::shared_ptr my; + std::shared_ptr my; }; class ifstream : virtual public istream { @@ -44,7 +44,7 @@ namespace fc { bool eof()const; private: class impl; - fc::shared_ptr my; + std::shared_ptr my; }; /** diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index 022c0ff..ff2a10c 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -3,14 +3,11 @@ #include #include #include -#include #include #include -#include #include #include #include -#include #include #include #include diff --git a/include/fc/io/raw_fwd.hpp b/include/fc/io/raw_fwd.hpp index 54f91b0..f89ff8f 100644 --- a/include/fc/io/raw_fwd.hpp +++ b/include/fc/io/raw_fwd.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -132,14 +133,14 @@ namespace fc { 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 shared_ptr& v, + template inline void pack( Stream& s, const std::shared_ptr& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void unpack( Stream& s, shared_ptr& v, + template inline void unpack( Stream& s, std::shared_ptr& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void pack( Stream& s, const shared_ptr& v, + template inline void pack( Stream& s, const std::shared_ptr& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void unpack( Stream& s, shared_ptr& v, + template inline void unpack( Stream& s, std::shared_ptr& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); template inline void pack( Stream& s, const bool& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); diff --git a/include/fc/log/appender.hpp b/include/fc/log/appender.hpp index 8f57f4c..f8f442f 100644 --- a/include/fc/log/appender.hpp +++ b/include/fc/log/appender.hpp @@ -1,5 +1,5 @@ #pragma once -#include +#include #include namespace fc { @@ -7,31 +7,31 @@ namespace fc { class log_message; class variant; - class appender_factory : public fc::retainable { + class appender_factory { public: - typedef fc::shared_ptr ptr; + typedef std::shared_ptr ptr; virtual ~appender_factory(){}; - virtual fc::shared_ptr create( const variant& args ) = 0; + virtual std::shared_ptr create( const variant& args ) = 0; }; namespace detail { template class appender_factory_impl : public appender_factory { public: - virtual fc::shared_ptr create( const variant& args ) { - return fc::shared_ptr(new T(args)); + virtual std::shared_ptr create( const variant& args ) { + return std::shared_ptr(new T(args)); } }; } - class appender : public fc::retainable { + class appender { public: - typedef fc::shared_ptr ptr; + typedef std::shared_ptr ptr; template static bool register_appender(const std::string& type) { - return register_appender( type, new detail::appender_factory_impl() ); + return register_appender( type, appender_factory::ptr( new detail::appender_factory_impl() ) ); } static appender::ptr create( const std::string& name, const std::string& type, const variant& args ); diff --git a/include/fc/log/file_appender.hpp b/include/fc/log/file_appender.hpp index bd692ef..6c4accb 100644 --- a/include/fc/log/file_appender.hpp +++ b/include/fc/log/file_appender.hpp @@ -26,7 +26,7 @@ class file_appender : public appender { private: class impl; - fc::shared_ptr my; + std::unique_ptr my; }; } // namespace fc diff --git a/include/fc/log/gelf_appender.hpp b/include/fc/log/gelf_appender.hpp index 1df2b2a..f150f82 100644 --- a/include/fc/log/gelf_appender.hpp +++ b/include/fc/log/gelf_appender.hpp @@ -24,7 +24,7 @@ namespace fc private: class impl; - fc::shared_ptr my; + std::unique_ptr my; }; } // namespace fc diff --git a/include/fc/log/log_message.hpp b/include/fc/log/log_message.hpp index 7c529c0..7706714 100644 --- a/include/fc/log/log_message.hpp +++ b/include/fc/log/log_message.hpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include diff --git a/include/fc/log/logger.hpp b/include/fc/log/logger.hpp index 6e1a52b..0d29eb8 100644 --- a/include/fc/log/logger.hpp +++ b/include/fc/log/logger.hpp @@ -1,14 +1,12 @@ #pragma once #include #include -#include +#include #include +#include namespace fc { - - class appender; - /** * * @@ -43,16 +41,16 @@ namespace fc void set_name( const std::string& n ); const std::string& name()const; - void add_appender( const fc::shared_ptr& a ); - std::vector > get_appenders()const; - void remove_appender( const fc::shared_ptr& a ); + void add_appender( const appender::ptr& a ); + std::vector get_appenders()const; + void remove_appender( const appender::ptr& a ); bool is_enabled( log_level e )const; void log( log_message m ); private: class impl; - fc::shared_ptr my; + std::shared_ptr my; }; } // namespace fc diff --git a/include/fc/network/http/server.hpp b/include/fc/network/http/server.hpp index a52ebcc..a7dc3a3 100644 --- a/include/fc/network/http/server.hpp +++ b/include/fc/network/http/server.hpp @@ -1,6 +1,5 @@ #pragma once #include -#include #include #include @@ -28,7 +27,7 @@ namespace fc { namespace http { class impl; response(); - response( const fc::shared_ptr& my); + response( const std::shared_ptr& my); response( const response& r); response( response&& r ); ~response(); @@ -42,7 +41,7 @@ namespace fc { namespace http { void write( const char* data, uint64_t len )const; private: - fc::shared_ptr my; + std::shared_ptr my; }; void listen( const fc::ip::endpoint& p ); diff --git a/include/fc/network/udp_socket.hpp b/include/fc/network/udp_socket.hpp index f150178..d6354c2 100644 --- a/include/fc/network/udp_socket.hpp +++ b/include/fc/network/udp_socket.hpp @@ -1,5 +1,4 @@ #pragma once -#include #include namespace fc { @@ -35,8 +34,8 @@ namespace fc { fc::ip::endpoint local_endpoint()const; private: - class impl; - fc::shared_ptr my; + class impl; + std::shared_ptr my; }; } diff --git a/include/fc/variant_object.hpp b/include/fc/variant_object.hpp index 73edd26..cebc31f 100644 --- a/include/fc/variant_object.hpp +++ b/include/fc/variant_object.hpp @@ -1,6 +1,6 @@ #pragma once #include -#include +#include namespace fc { diff --git a/src/io/fstream.cpp b/src/io/fstream.cpp index 5ebf790..1e6fffe 100644 --- a/src/io/fstream.cpp +++ b/src/io/fstream.cpp @@ -13,11 +13,11 @@ using namespace std; namespace fc { - class ofstream::impl : public fc::retainable { + class ofstream::impl { public: boost::filesystem::ofstream ofs; }; - class ifstream::impl : public fc::retainable { + class ifstream::impl { public: boost::filesystem::ifstream ifs; }; diff --git a/src/log/file_appender.cpp b/src/log/file_appender.cpp index 6cc1d7e..c2efebf 100644 --- a/src/log/file_appender.cpp +++ b/src/log/file_appender.cpp @@ -13,7 +13,7 @@ namespace fc { - class file_appender::impl : public fc::retainable + class file_appender::impl { public: config cfg; diff --git a/src/log/gelf_appender.cpp b/src/log/gelf_appender.cpp index 2d7f78a..c1828e5 100644 --- a/src/log/gelf_appender.cpp +++ b/src/log/gelf_appender.cpp @@ -20,7 +20,7 @@ namespace fc { - class gelf_appender::impl : public retainable + class gelf_appender::impl { public: config cfg; diff --git a/src/log/logger.cpp b/src/log/logger.cpp index 93241f3..b8743b9 100644 --- a/src/log/logger.cpp +++ b/src/log/logger.cpp @@ -11,7 +11,7 @@ namespace fc { - class logger::impl : public fc::retainable { + class logger::impl { public: impl() :_parent(nullptr),_enabled(true),_additivity(false),_level(log_level::warn){} @@ -54,8 +54,8 @@ namespace fc { std::swap(my,l.my); return *this; } - bool operator==( const logger& l, std::nullptr_t ) { return !l.my; } - bool operator!=( const logger& l, std::nullptr_t ) { return l.my; } + bool operator==( const logger& l, std::nullptr_t ) { return !(bool)l.my; } + bool operator!=( const logger& l, std::nullptr_t ) { return (bool)l.my; } bool logger::is_enabled( log_level e )const { return e >= my->_level; @@ -96,13 +96,10 @@ namespace fc { log_level logger::get_log_level()const { return my->_level; } logger& logger::set_log_level(log_level ll) { my->_level = ll; return *this; } - void logger::add_appender( const fc::shared_ptr& a ) + void logger::add_appender( const appender::ptr& a ) { my->_appenders.push_back(a); } -// void logger::remove_appender( const fc::shared_ptr& a ) - // { my->_appenders.erase(a); } - - std::vector > logger::get_appenders()const + std::vector logger::get_appenders()const { return my->_appenders; } diff --git a/src/network/http/http_server.cpp b/src/network/http/http_server.cpp index 8a63734..af06c6f 100644 --- a/src/network/http/http_server.cpp +++ b/src/network/http/http_server.cpp @@ -9,7 +9,7 @@ namespace fc { namespace http { - class server::response::impl : public fc::retainable + class server::response::impl { public: impl( const fc::http::connection_ptr& c, const std::function& cont = std::function() ) @@ -112,7 +112,7 @@ namespace fc { namespace http { { try { - http::server::response rep( fc::shared_ptr( new response::impl(c) ) ); + http::server::response rep( std::shared_ptr( new response::impl(c) ) ); request req = c->read_request(); if( do_on_req ) do_on_req( req, rep ); @@ -155,7 +155,7 @@ namespace fc { namespace http { server::response::response(){} server::response::response( const server::response& s ):my(s.my){} server::response::response( server::response&& s ):my(std::move(s.my)){} - server::response::response( const fc::shared_ptr& m ):my(m){} + server::response::response( const std::shared_ptr& m ):my(m){} server::response& server::response::operator=(const server::response& s) { my = s.my; return *this; } server::response& server::response::operator=(server::response&& s) { std::swap(my,s.my); return *this; } diff --git a/src/network/udp_socket.cpp b/src/network/udp_socket.cpp index 514e148..c813831 100644 --- a/src/network/udp_socket.cpp +++ b/src/network/udp_socket.cpp @@ -6,7 +6,7 @@ namespace fc { - class udp_socket::impl : public fc::retainable { + class udp_socket::impl { public: impl():_sock( fc::asio::default_io_service() ){} ~impl(){ From 7cf371736b3f06b769cfc0509f2f66afdbfaceaa Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Fri, 26 Apr 2019 14:21:11 +0200 Subject: [PATCH 002/110] Intermediate --- CMakeLists.txt | 1 - include/fc/asio.hpp | 18 +++---- include/fc/shared_ptr.hpp | 92 --------------------------------- include/fc/signals.hpp | 4 +- include/fc/thread/future.hpp | 83 +++++++++++++++++++---------- include/fc/thread/parallel.hpp | 12 ++--- include/fc/thread/task.hpp | 40 +++++++++----- include/fc/thread/thread.hpp | 20 +++---- src/asio.cpp | 4 +- src/io/iostream.cpp | 4 +- src/network/http/websocket.cpp | 16 +++--- src/network/rate_limiting.cpp | 8 +-- src/network/udp_socket.cpp | 8 +-- src/rpc/state.cpp | 2 +- src/shared_ptr.cpp | 30 ----------- src/thread/future.cpp | 15 ++++-- src/thread/parallel.cpp | 8 +-- src/thread/thread.cpp | 2 +- tests/thread/parallel_tests.cpp | 44 ++++++++-------- tests/thread/task_cancel.cpp | 2 +- 20 files changed, 173 insertions(+), 240 deletions(-) delete mode 100644 include/fc/shared_ptr.hpp delete mode 100644 src/shared_ptr.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f8fea3d..8fea7bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -211,7 +211,6 @@ set( fc_sources src/thread/non_preemptable_scope_check.cpp src/asio.cpp src/string.cpp - src/shared_ptr.cpp src/stacktrace.cpp src/time.cpp src/utf8.cpp diff --git a/include/fc/asio.hpp b/include/fc/asio.hpp index 06ba2f8..4c330c4 100644 --- a/include/fc/asio.hpp +++ b/include/fc/asio.hpp @@ -122,7 +122,7 @@ namespace asio { template future read_some(AsyncReadStream& s, const MutableBufferSequence& buf) { - promise::ptr completion_promise(new promise("fc::asio::async_read_some")); + promise::ptr completion_promise = promise::create("fc::asio::async_read_some"); s.async_read_some(buf, detail::read_write_handler(completion_promise)); return completion_promise;//->wait(); } @@ -130,7 +130,7 @@ namespace asio { template future read_some(AsyncReadStream& s, char* buffer, size_t length, size_t offset = 0) { - promise::ptr completion_promise(new promise("fc::asio::async_read_some")); + promise::ptr completion_promise = promise::create("fc::asio::async_read_some"); s.async_read_some(boost::asio::buffer(buffer + offset, length), detail::read_write_handler(completion_promise)); return completion_promise;//->wait(); @@ -139,7 +139,7 @@ namespace asio { template future read_some(AsyncReadStream& s, const std::shared_ptr& buffer, size_t length, size_t offset) { - promise::ptr completion_promise(new promise("fc::asio::async_read_some")); + promise::ptr completion_promise = promise::create("fc::asio::async_read_some"); s.async_read_some(boost::asio::buffer(buffer.get() + offset, length), detail::read_write_handler_with_buffer(completion_promise, buffer)); return completion_promise;//->wait(); @@ -179,7 +179,7 @@ namespace asio { */ template size_t write( AsyncWriteStream& s, const ConstBufferSequence& buf ) { - promise::ptr p(new promise("fc::asio::write")); + promise::ptr p = promise::create("fc::asio::write"); boost::asio::async_write(s, buf, detail::read_write_handler(p)); return p->wait(); } @@ -191,7 +191,7 @@ namespace asio { */ template future write_some( AsyncWriteStream& s, const ConstBufferSequence& buf ) { - promise::ptr p(new promise("fc::asio::write_some")); + promise::ptr p = promise::create("fc::asio::write_some"); s.async_write_some( buf, detail::read_write_handler(p)); return p; //->wait(); } @@ -199,7 +199,7 @@ namespace asio { template future write_some( AsyncWriteStream& s, const char* buffer, size_t length, size_t offset = 0) { - promise::ptr p(new promise("fc::asio::write_some")); + promise::ptr p = promise::create("fc::asio::write_some"); s.async_write_some( boost::asio::buffer(buffer + offset, length), detail::read_write_handler(p)); return p; //->wait(); } @@ -207,7 +207,7 @@ namespace asio { template future write_some( AsyncWriteStream& s, const std::shared_ptr& buffer, size_t length, size_t offset ) { - promise::ptr p(new promise("fc::asio::write_some")); + promise::ptr p = promise::create("fc::asio::write_some"); s.async_write_some( boost::asio::buffer(buffer.get() + offset, length), detail::read_write_handler_with_buffer(p, buffer)); return p; //->wait(); } @@ -250,7 +250,7 @@ namespace asio { template void accept( AcceptorType& acc, SocketType& sock ) { //promise::ptr p( new promise("fc::asio::tcp::accept") ); - promise::ptr p( new promise("fc::asio::tcp::accept") ); + promise::ptr p = promise::create("fc::asio::tcp::accept"); acc.async_accept( sock, boost::bind( fc::asio::detail::error_handler, p, _1 ) ); p->wait(); //if( ec ) BOOST_THROW_EXCEPTION( boost::system::system_error(ec) ); @@ -262,7 +262,7 @@ namespace asio { */ template void connect( AsyncSocket& sock, const EndpointType& ep ) { - promise::ptr p(new promise("fc::asio::tcp::connect")); + promise::ptr p = promise::create("fc::asio::tcp::connect"); sock.async_connect( ep, boost::bind( fc::asio::detail::error_handler, p, _1 ) ); p->wait(); //if( ec ) BOOST_THROW_EXCEPTION( boost::system::system_error(ec) ); diff --git a/include/fc/shared_ptr.hpp b/include/fc/shared_ptr.hpp deleted file mode 100644 index a07ec46..0000000 --- a/include/fc/shared_ptr.hpp +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once - -#include -#include - -namespace fc { - - /** - * @brief used to create reference counted types. - * - * Must be a virtual base class that is initialized with the - * - */ - class retainable { - public: - retainable(); - void retain(); - void release(); - int32_t retain_count()const; - - protected: - virtual ~retainable(); - private: - volatile int32_t _ref_count; - }; - - template - class shared_ptr { - public: - template - shared_ptr( const shared_ptr& o ) - :_ptr(o.get()) { - if(_ptr != nullptr ) _ptr->retain(); - } - shared_ptr( const shared_ptr& o ) - :_ptr(o.get()) { - if(_ptr != nullptr ) _ptr->retain(); - } - - shared_ptr( T* t, bool inc = false ) - :_ptr(t) { if( inc && t != nullptr) t->retain(); } - - shared_ptr():_ptr(nullptr){} - - - shared_ptr( shared_ptr&& p ) - :_ptr(p._ptr){ p._ptr = nullptr; } - - ~shared_ptr() { if( nullptr != _ptr ) { _ptr->release(); _ptr = nullptr; } } - - shared_ptr& reset( T* v = nullptr, bool inc = false ) { - if( v == _ptr ) return *this; - if( inc && nullptr != v ) v->retain(); - if( nullptr != _ptr ) _ptr->release(); - _ptr = v; - return *this; - } - - shared_ptr& operator=(const shared_ptr& p ) { - if( _ptr == p._ptr ) return *this; - if( p._ptr != nullptr ) p._ptr->retain(); - if( _ptr != nullptr ) _ptr->release(); - _ptr = p._ptr; - return *this; - } - shared_ptr& operator=(shared_ptr&& p ) { - std::swap(_ptr,p._ptr); - return *this; - } - T& operator* ()const { return *_ptr; } - T* operator-> ()const { return _ptr; } - - bool operator==( const shared_ptr& p )const { return get() == p.get(); } - bool operator<( const shared_ptr& p )const { return get() < p.get(); } - T * get() const { return _ptr; } - - bool operator!()const { return _ptr == 0; } - operator bool()const { return _ptr != 0; } - private: - T* _ptr; - }; - - template - fc::shared_ptr dynamic_pointer_cast( const fc::shared_ptr& t ) { - return fc::shared_ptr( dynamic_cast(t.get()), true ); - } - template - fc::shared_ptr static_pointer_cast( const fc::shared_ptr& t ) { - return fc::shared_ptr( static_cast(t.get()), true ); - } -} - diff --git a/include/fc/signals.hpp b/include/fc/signals.hpp index dd886a6..5fb4671 100644 --- a/include/fc/signals.hpp +++ b/include/fc/signals.hpp @@ -36,13 +36,13 @@ namespace fc { template inline T wait( boost::signals2::signal& sig, const microseconds& timeout_us=microseconds::maximum() ) { - typename promise::ptr p(new promise("fc::signal::wait")); + typename promise::ptr p = promise::create("fc::signal::wait"); boost::signals2::scoped_connection c( sig.connect( [=]( T t ) { p->set_value(t); } )); return p->wait( timeout_us ); } inline void wait( boost::signals2::signal& sig, const microseconds& timeout_us=microseconds::maximum() ) { - promise::ptr p(new promise("fc::signal::wait")); + promise::ptr p = promise::create("fc::signal::wait"); boost::signals2::scoped_connection c( sig.connect( [=]() { p->set_value(); } )); p->wait( timeout_us ); } diff --git a/include/fc/thread/future.hpp b/include/fc/thread/future.hpp index f0365ea..a6937c6 100644 --- a/include/fc/thread/future.hpp +++ b/include/fc/thread/future.hpp @@ -1,9 +1,11 @@ #pragma once #include -#include #include #include #include +#include + +#include //#define FC_TASK_NAMES_ARE_MANDATORY 1 #ifdef FC_TASK_NAMES_ARE_MANDATORY @@ -56,10 +58,10 @@ namespace fc { }; } - class promise_base : public virtual retainable{ + class promise_base : public std::enable_shared_from_this { public: - typedef fc::shared_ptr ptr; - promise_base(const char* desc FC_TASK_NAME_DEFAULT_ARG); + typedef std::shared_ptr ptr; + virtual ~promise_base(); const char* get_desc()const; @@ -70,7 +72,12 @@ namespace fc { void set_exception( const fc::exception_ptr& e ); + void retain(); + void release(); + protected: + promise_base(const char* desc FC_TASK_NAME_DEFAULT_ARG); + void _wait( const microseconds& timeout_us ); void _wait_until( const time_point& timeout_us ); void _enqueue_thread(); @@ -80,7 +87,6 @@ namespace fc { void _set_value(const void* v); void _on_complete( detail::completion_handler* c ); - ~promise_base(); private: friend class thread; @@ -99,18 +105,31 @@ namespace fc { const char* _cancellation_reason; private: #endif - const char* _desc; - detail::completion_handler* _compl; + const char* _desc; + detail::completion_handler* _compl; + std::shared_ptr _self; + boost::atomic _retain_count; }; template class promise : virtual public promise_base { public: - typedef fc::shared_ptr< promise > ptr; - promise( const char* desc FC_TASK_NAME_DEFAULT_ARG):promise_base(desc){} - promise( const T& val ){ set_value(val); } - promise( T&& val ){ set_value(std::move(val) ); } - + typedef std::shared_ptr< promise > ptr; + virtual ~promise(){} + + static ptr create( const char* desc FC_TASK_NAME_DEFAULT_ARG ) + { + return ptr( new promise( desc ) ); + } + static ptr create( const T& val ) + { + return ptr( new promise( val ) ); + } + static ptr create( T&& val ) + { + return ptr( new promise( std::move(val) ) ); + } + const T& wait(const microseconds& timeout = microseconds::maximum() ){ this->_wait( timeout ); return *result; @@ -135,19 +154,29 @@ namespace fc { _on_complete( new detail::completion_handler_impl(fc::forward(c)) ); } protected: + promise( const char* desc ):promise_base(desc){} + promise( const T& val ){ set_value(val); } + promise( T&& val ){ set_value(std::move(val) ); } + optional result; - ~promise(){} }; template<> class promise : virtual public promise_base { public: - typedef fc::shared_ptr< promise > ptr; - promise( const char* desc FC_TASK_NAME_DEFAULT_ARG):promise_base(desc){} - promise( bool fulfilled, const char* desc FC_TASK_NAME_DEFAULT_ARG ){ - if( fulfilled ) set_value(); - } + typedef std::shared_ptr< promise > ptr; + + virtual ~promise(){} + static ptr create( const char* desc FC_TASK_NAME_DEFAULT_ARG ) + { + return ptr( new promise( desc ) ); + } + static ptr create( bool fulfilled, const char* desc FC_TASK_NAME_DEFAULT_ARG ) + { + return ptr( new promise( fulfilled, desc ) ); + } + void wait(const microseconds& timeout = microseconds::maximum() ){ this->_wait( timeout ); } @@ -163,7 +192,10 @@ namespace fc { _on_complete( new detail::completion_handler_impl(fc::forward(c)) ); } protected: - ~promise(){} + promise( const char* desc ):promise_base(desc){} + promise( bool fulfilled, const char* desc ){ + if( fulfilled ) set_value(); + } }; /** @@ -184,8 +216,8 @@ namespace fc { template class future { public: - future( const fc::shared_ptr>& p ):m_prom(p){} - future( fc::shared_ptr>&& p ):m_prom(std::move(p)){} + future( const typename promise::ptr& p ):m_prom(p){} + future( typename promise::ptr&& p ):m_prom(std::move(p)){} future(const future& f ) : m_prom(f.m_prom){} future(){} @@ -194,7 +226,6 @@ namespace fc { return *this; } - operator const T&()const { return wait(); } /// @pre valid() @@ -251,14 +282,14 @@ namespace fc { } private: friend class thread; - fc::shared_ptr> m_prom; + typename promise::ptr m_prom; }; template<> class future { public: - future( const fc::shared_ptr>& p ):m_prom(p){} - future( fc::shared_ptr>&& p ):m_prom(std::move(p)){} + future( const typename promise::ptr& p ):m_prom(p){} + future( typename promise::ptr&& p ):m_prom(std::move(p)){} future(const future& f ) : m_prom(f.m_prom){} future(){} @@ -313,7 +344,7 @@ namespace fc { private: friend class thread; - fc::shared_ptr> m_prom; + typename promise::ptr m_prom; }; } diff --git a/include/fc/thread/parallel.hpp b/include/fc/thread/parallel.hpp index 59f9cf6..f66e1c6 100644 --- a/include/fc/thread/parallel.hpp +++ b/include/fc/thread/parallel.hpp @@ -55,8 +55,8 @@ namespace fc { ~ticket_guard(); void wait_for_my_turn(); private: - promise* my_promise; - future* ticket; + promise::ptr my_promise; + future* ticket; }; friend class ticket_guard; @@ -97,10 +97,10 @@ namespace fc { auto do_parallel( Functor&& f, const char* desc FC_TASK_NAME_DEFAULT_ARG ) -> fc::future { typedef decltype(f()) Result; typedef typename fc::deduce::type FunctorType; - fc::task* tsk = - new fc::task( fc::forward(f), desc ); - fc::future r(fc::shared_ptr< fc::promise >(tsk,true) ); - detail::get_worker_pool().post( tsk ); + typename task::ptr tsk = + task::create( fc::forward(f), desc ); + fc::future r( std::dynamic_pointer_cast< promise >(tsk) ); + detail::get_worker_pool().post( tsk.get() ); return r; } } diff --git a/include/fc/thread/task.hpp b/include/fc/thread/task.hpp index 987810b..a3162da 100644 --- a/include/fc/thread/task.hpp +++ b/include/fc/thread/task.hpp @@ -31,9 +31,9 @@ namespace fc { public: void run(); virtual void cancel(const char* reason FC_CANCELATION_REASON_DEFAULT_ARG) override; + ~task_base(); protected: - ~task_base(); /// Task priority looks like unsupported feature. uint64_t _posted_num; priority _prio; @@ -90,6 +90,19 @@ namespace fc { template class task : virtual public task_base, virtual public promise { public: + typedef std::shared_ptr> ptr; + + virtual ~task(){} + + template + static ptr create( Functor&& f, const char* desc ) + { + return ptr( new task( std::move(f), desc ) ); + } + virtual void cancel(const char* reason FC_CANCELATION_REASON_DEFAULT_ARG) override { task_base::cancel(reason); } + + alignas(double) char _functor[FunctorSize]; + private: template task( Functor&& f, const char* desc ):promise_base(desc), task_base(&_functor), promise(desc) { typedef typename fc::deduce::type FunctorType; @@ -100,16 +113,24 @@ namespace fc { _promise_impl = static_cast*>(this); _run_functor = &detail::functor_run::run; } - virtual void cancel(const char* reason FC_CANCELATION_REASON_DEFAULT_ARG) override { task_base::cancel(reason); } - - alignas(double) char _functor[FunctorSize]; - private: - ~task(){} }; template - class task : virtual public task_base, virtual public promise { + class task : public task_base, public promise { public: + typedef std::shared_ptr> ptr; + + virtual ~task(){} + + template + static ptr create( Functor&& f, const char* desc ) + { + return ptr( new task( std::move(f), desc ) ); + } + virtual void cancel(const char* reason FC_CANCELATION_REASON_DEFAULT_ARG) override { task_base::cancel(reason); } + + alignas(double) char _functor[FunctorSize]; + private: template task( Functor&& f, const char* desc ):promise_base(desc), task_base(&_functor), promise(desc) { typedef typename fc::deduce::type FunctorType; @@ -120,11 +141,6 @@ namespace fc { _promise_impl = static_cast*>(this); _run_functor = &detail::void_functor_run::run; } - virtual void cancel(const char* reason FC_CANCELATION_REASON_DEFAULT_ARG) override { task_base::cancel(reason); } - - alignas(double) char _functor[FunctorSize]; - private: - ~task(){} }; } diff --git a/include/fc/thread/thread.hpp b/include/fc/thread/thread.hpp index b71c066..5c08b71 100644 --- a/include/fc/thread/thread.hpp +++ b/include/fc/thread/thread.hpp @@ -87,10 +87,10 @@ namespace fc { auto async( Functor&& f, const char* desc FC_TASK_NAME_DEFAULT_ARG, priority prio = priority()) -> fc::future { typedef decltype(f()) Result; typedef typename fc::deduce::type FunctorType; - fc::task* tsk = - new fc::task( fc::forward(f), desc ); - fc::future r(fc::shared_ptr< fc::promise >(tsk,true) ); - async_task(tsk,prio); + typename task::ptr tsk = + task::create( fc::forward(f), desc ); + fc::future r( std::dynamic_pointer_cast< promise >(tsk) ); + async_task(tsk.get(),prio); return r; } void poke(); @@ -109,10 +109,10 @@ namespace fc { auto schedule( Functor&& f, const fc::time_point& when, const char* desc FC_TASK_NAME_DEFAULT_ARG, priority prio = priority()) -> fc::future { typedef decltype(f()) Result; - fc::task* tsk = - new fc::task( fc::forward(f), desc ); - fc::future r(fc::shared_ptr< fc::promise >(tsk,true) ); - async_task(tsk,prio,when); + typename task::ptr tsk = + task::create( fc::forward(f), desc ); + fc::future r( std::dynamic_pointer_cast< promise >(tsk) ); + async_task(tsk.get(),prio,when); return r; } @@ -147,8 +147,8 @@ namespace fc { template int wait_any( const fc::future& f1, const fc::future& f2, const microseconds& timeout_us = microseconds::maximum()) { std::vector proms(2); - proms[0] = fc::static_pointer_cast(f1.m_prom); - proms[1] = fc::static_pointer_cast(f2.m_prom); + proms[0] = std::static_pointer_cast(f1.m_prom); + proms[1] = std::static_pointer_cast(f2.m_prom); return wait_any_until(std::move(proms), fc::time_point::now()+timeout_us ); } private: diff --git a/src/asio.cpp b/src/asio.cpp index 35b2990..b56ec49 100644 --- a/src/asio.cpp +++ b/src/asio.cpp @@ -190,7 +190,7 @@ namespace fc { try { resolver res( fc::asio::default_io_service() ); - promise >::ptr p( new promise >("tcp::resolve completion") ); + promise >::ptr p = promise >::create("tcp::resolve completion"); res.async_resolve( boost::asio::ip::tcp::resolver::query(hostname,port), boost::bind( detail::resolve_handler, p, _1, _2 ) ); return p->wait(); @@ -204,7 +204,7 @@ namespace fc { try { resolver res( fc::asio::default_io_service() ); - promise >::ptr p( new promise >("udp::resolve completion") ); + promise >::ptr p = promise >::create("udp::resolve completion"); res.async_resolve( resolver::query(hostname,port), boost::bind( detail::resolve_handler, p, _1, _2 ) ); return p->wait(); diff --git a/src/io/iostream.cpp b/src/io/iostream.cpp index c44fc83..c7d364c 100644 --- a/src/io/iostream.cpp +++ b/src/io/iostream.cpp @@ -24,7 +24,7 @@ namespace fc { std::cin.read(&c,1); while( !std::cin.eof() ) { while( write_pos - read_pos > 0xfffff ) { - fc::promise::ptr wr( new fc::promise("cin_buffer::write_ready") ); + fc::promise::ptr wr = fc::promise::create("cin_buffer::write_ready"); write_ready = wr; if( write_pos - read_pos <= 0xfffff ) { wr->wait(); @@ -138,7 +138,7 @@ namespace fc { do { while( !b.eof && (b.write_pos - b.read_pos)==0 ){ // wait for more... - fc::promise::ptr rr( new fc::promise("cin_buffer::read_ready") ); + fc::promise::ptr rr = fc::promise::create("cin_buffer::read_ready"); { // copy read_ready because it is accessed from multiple threads fc::scoped_lock lock( b.read_ready_mutex ); b.read_ready = rr; diff --git a/src/network/http/websocket.cpp b/src/network/http/websocket.cpp index b32b863..5138fb0 100644 --- a/src/network/http/websocket.cpp +++ b/src/network/http/websocket.cpp @@ -292,8 +292,8 @@ namespace fc { namespace http { if( _server.is_listening() ) _server.stop_listening(); - if ( _connections.size() ) - _closed = new fc::promise(); + if( _connections.size() ) + _closed = promise::create(); auto cpy_con = _connections; for( auto item : cpy_con ) @@ -642,13 +642,13 @@ namespace fc { namespace http { websocketpp::lib::error_code ec; my->_uri = uri; - my->_connected = fc::promise::ptr( new fc::promise("websocket::connect") ); + my->_connected = promise::create("websocket::connect"); my->_client.set_open_handler( [=]( websocketpp::connection_hdl hdl ){ my->_hdl = hdl; auto con = my->_client.get_con_from_hdl(hdl); my->_connection = std::make_shared>( con ); - my->_closed = fc::promise::ptr( new fc::promise("websocket::closed") ); + my->_closed = promise::create("websocket::closed"); my->_connected->set_value(); }); @@ -670,12 +670,12 @@ namespace fc { namespace http { websocketpp::lib::error_code ec; smy->_uri = uri; - smy->_connected = fc::promise::ptr( new fc::promise("websocket::connect") ); + smy->_connected = promise::create("websocket::connect"); smy->_client.set_open_handler( [=]( websocketpp::connection_hdl hdl ){ auto con = smy->_client.get_con_from_hdl(hdl); smy->_connection = std::make_shared>( con ); - smy->_closed = fc::promise::ptr( new fc::promise("websocket::closed") ); + smy->_closed = promise::create("websocket::closed"); smy->_connected->set_value(); }); @@ -705,12 +705,12 @@ namespace fc { namespace http { // wlog( "connecting to ${uri}", ("uri",uri)); websocketpp::lib::error_code ec; - my->_connected = fc::promise::ptr( new fc::promise("websocket::connect") ); + my->_connected = promise::create("websocket::connect"); my->_client.set_open_handler( [=]( websocketpp::connection_hdl hdl ){ auto con = my->_client.get_con_from_hdl(hdl); my->_connection = std::make_shared>( con ); - my->_closed = fc::promise::ptr( new fc::promise("websocket::closed") ); + my->_closed = promise::create("websocket::closed"); my->_connected->set_value(); }); diff --git a/src/network/rate_limiting.cpp b/src/network/rate_limiting.cpp index ab7464e..38b8618 100644 --- a/src/network/rate_limiting.cpp +++ b/src/network/rate_limiting.cpp @@ -284,7 +284,7 @@ namespace fc size_t bytes_read; if (_download_bytes_per_second) { - promise::ptr completion_promise(new promise("rate_limiting_group_impl::readsome")); + promise::ptr completion_promise = promise::create("rate_limiting_group_impl::readsome"); rate_limited_tcp_read_operation read_operation(socket, buffer, length, offset, completion_promise); _read_operations_for_next_iteration.push_back(&read_operation); @@ -330,7 +330,7 @@ namespace fc size_t bytes_written; if (_upload_bytes_per_second) { - promise::ptr completion_promise(new promise("rate_limiting_group_impl::writesome")); + promise::ptr completion_promise = promise::create("rate_limiting_group_impl::writesome"); rate_limited_tcp_write_operation write_operation(socket, buffer, length, offset, completion_promise); _write_operations_for_next_iteration.push_back(&write_operation); @@ -367,7 +367,7 @@ namespace fc process_pending_operations(_last_read_iteration_time, _download_bytes_per_second, _read_operations_in_progress, _read_operations_for_next_iteration, _read_tokens, _unused_read_tokens); - _new_read_operation_available_promise = new promise("rate_limiting_group_impl::process_pending_reads"); + _new_read_operation_available_promise = promise::create("rate_limiting_group_impl::process_pending_reads"); try { if (_read_operations_in_progress.empty()) @@ -388,7 +388,7 @@ namespace fc process_pending_operations(_last_write_iteration_time, _upload_bytes_per_second, _write_operations_in_progress, _write_operations_for_next_iteration, _write_tokens, _unused_write_tokens); - _new_write_operation_available_promise = new promise("rate_limiting_group_impl::process_pending_writes"); + _new_write_operation_available_promise = promise::create("rate_limiting_group_impl::process_pending_writes"); try { if (_write_operations_in_progress.empty()) diff --git a/src/network/udp_socket.cpp b/src/network/udp_socket.cpp index c813831..66eb96d 100644 --- a/src/network/udp_socket.cpp +++ b/src/network/udp_socket.cpp @@ -56,7 +56,7 @@ namespace fc { throw; } - promise::ptr completion_promise(new promise("udp_socket::send_to")); + promise::ptr completion_promise = promise::create("udp_socket::send_to"); my->_sock.async_send_to( boost::asio::buffer(buffer, length), to_asio_ep(to), asio::detail::read_write_handler(completion_promise) ); @@ -76,7 +76,7 @@ namespace fc { throw; } - promise::ptr completion_promise(new promise("udp_socket::send_to")); + promise::ptr completion_promise = promise::create("udp_socket::send_to"); my->_sock.async_send_to( boost::asio::buffer(buffer.get(), length), to_asio_ep(to), asio::detail::read_write_handler_with_buffer(completion_promise, buffer) ); @@ -111,7 +111,7 @@ namespace fc { } boost::asio::ip::udp::endpoint boost_from_endpoint; - promise::ptr completion_promise(new promise("udp_socket::receive_from")); + promise::ptr completion_promise = promise::create("udp_socket::receive_from"); my->_sock.async_receive_from( boost::asio::buffer(receive_buffer.get(), receive_buffer_length), boost_from_endpoint, asio::detail::read_write_handler_with_buffer(completion_promise, receive_buffer) ); @@ -137,7 +137,7 @@ namespace fc { } boost::asio::ip::udp::endpoint boost_from_endpoint; - promise::ptr completion_promise(new promise("udp_socket::receive_from")); + promise::ptr completion_promise = promise::create("udp_socket::receive_from"); my->_sock.async_receive_from( boost::asio::buffer(receive_buffer, receive_buffer_length), boost_from_endpoint, asio::detail::read_write_handler(completion_promise) ); size_t bytes_read = completion_promise->wait(); diff --git a/src/rpc/state.cpp b/src/rpc/state.cpp index 97c9ba1..fe2879b 100644 --- a/src/rpc/state.cpp +++ b/src/rpc/state.cpp @@ -46,7 +46,7 @@ void state::handle_reply( const response& response ) request state::start_remote_call( const string& method_name, variants args ) { request request{ _next_id++, method_name, std::move(args) }; - _awaiting[*request.id] = fc::promise::ptr( new fc::promise("json_connection::async_call") ); + _awaiting[*request.id] = fc::promise::create("json_connection::async_call"); return request; } variant state::wait_for_response( const variant& request_id ) diff --git a/src/shared_ptr.cpp b/src/shared_ptr.cpp deleted file mode 100644 index 9e3a144..0000000 --- a/src/shared_ptr.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include -#include - -namespace fc { - retainable::retainable() - :_ref_count(1) { - static_assert( sizeof(_ref_count) == sizeof(boost::atomic), "failed to reserve enough space" ); - } - - retainable::~retainable() { - assert( _ref_count <= 0 ); - assert( _ref_count == 0 ); - } - void retainable::retain() { - ((boost::atomic*)&_ref_count)->fetch_add(1, boost::memory_order_relaxed ); - } - - void retainable::release() { - boost::atomic_thread_fence(boost::memory_order_acquire); - if( 1 == ((boost::atomic*)&_ref_count)->fetch_sub(1, boost::memory_order_release ) ) { - delete this; - } - } - - int32_t retainable::retain_count()const { - return _ref_count; - } -} diff --git a/src/thread/future.cpp b/src/thread/future.cpp index 2111584..d1c9a94 100644 --- a/src/thread/future.cpp +++ b/src/thread/future.cpp @@ -19,7 +19,8 @@ namespace fc { _cancellation_reason(nullptr), #endif _desc(desc), - _compl(nullptr) + _compl(nullptr), + _retain_count(0) { } const char* promise_base::get_desc()const{ @@ -72,7 +73,7 @@ namespace fc { // See https://github.com/cryptonomex/graphene/issues/597 // - ptr p_this = ptr( this, true ); + ptr p_this = shared_from_this(); try { @@ -123,7 +124,7 @@ namespace fc { blocked_thread = _blocked_thread; } if( blocked_thread ) - blocked_thread->notify(ptr(this,true)); + blocked_thread->notify( shared_from_this() ); } promise_base::~promise_base() { } void promise_base::_set_timeout(){ @@ -150,5 +151,13 @@ namespace fc { _compl = c; } } + void promise_base::retain() { + if( _retain_count.fetch_add(1, boost::memory_order_relaxed) == 0 ) + _self = shared_from_this(); + } + void promise_base::release() { + if( _retain_count.fetch_sub(1, boost::memory_order_release) == 1 ) + _self.reset(); + } } diff --git a/src/thread/parallel.cpp b/src/thread/parallel.cpp index 10b709e..10ef63b 100644 --- a/src/thread/parallel.cpp +++ b/src/thread/parallel.cpp @@ -158,8 +158,8 @@ namespace fc { serial_valve::ticket_guard::ticket_guard( boost::atomic*>& latch ) { - my_promise = new promise(); - future* my_future = new future( promise::ptr( my_promise, true ) ); + my_promise = promise::create(); + future* my_future = new future( my_promise ); try { do @@ -171,7 +171,7 @@ namespace fc { } catch (...) { - delete my_future; // this takes care of my_promise as well + delete my_future; throw; } } @@ -190,7 +190,7 @@ namespace fc { serial_valve::serial_valve() { - latch.store( new future( promise::ptr( new promise( true ), true ) ) ); + latch.store( new future( promise::create( true ) ) ); } serial_valve::~serial_valve() diff --git a/src/thread/thread.cpp b/src/thread/thread.cpp index 267ac62..00cd1d1 100644 --- a/src/thread/thread.cpp +++ b/src/thread/thread.cpp @@ -72,7 +72,7 @@ namespace fc { } thread::thread( const std::string& name, thread_idle_notifier* notifier ) { - promise::ptr p(new promise("thread start")); + promise::ptr p = promise::create("thread start"); boost::thread* t = new boost::thread( [this,p,name,notifier]() { try { set_thread_name(name.c_str()); // set thread's name for the debugger to display diff --git a/tests/thread/parallel_tests.cpp b/tests/thread/parallel_tests.cpp index 6e91da4..14dcb4d 100644 --- a/tests/thread/parallel_tests.cpp +++ b/tests/thread/parallel_tests.cpp @@ -200,25 +200,25 @@ BOOST_AUTO_TEST_CASE( serial_valve ) fc::serial_valve valve; { // Simple test, f2 finishes before f1 - fc::promise* syncer = new fc::promise(); - fc::promise* waiter = new fc::promise(); + fc::promise::ptr syncer = fc::promise::create(); + fc::promise::ptr waiter = fc::promise::create(); auto p1 = fc::async([&counter,&valve,syncer,waiter] () { valve.do_serial( [syncer,waiter](){ syncer->set_value(); - fc::future( fc::shared_ptr>( waiter, true ) ).wait(); }, + fc::future( waiter ).wait(); }, [&counter](){ BOOST_CHECK_EQUAL( 0u, counter.load() ); counter.fetch_add(1); } ); }); - fc::future( fc::shared_ptr>( syncer, true ) ).wait(); + fc::future( syncer ).wait(); // at this point, p1.f1 has started executing and is waiting on waiter - syncer = new fc::promise(); + syncer = fc::promise::create(); auto p2 = fc::async([&counter,&valve,syncer] () { valve.do_serial( [syncer](){ syncer->set_value(); }, [&counter](){ BOOST_CHECK_EQUAL( 1u, counter.load() ); counter.fetch_add(1); } ); }); - fc::future( fc::shared_ptr>( syncer, true ) ).wait(); + fc::future( syncer ).wait(); fc::usleep( fc::milliseconds(10) ); @@ -237,37 +237,37 @@ BOOST_AUTO_TEST_CASE( serial_valve ) } { // Triple test, f3 finishes first, then f1, finally f2 - fc::promise* syncer = new fc::promise(); - fc::promise* waiter = new fc::promise(); + fc::promise::ptr syncer = fc::promise::create(); + fc::promise::ptr waiter = fc::promise::create(); counter.store(0); auto p1 = fc::async([&counter,&valve,syncer,waiter] () { valve.do_serial( [&syncer,waiter](){ syncer->set_value(); - fc::future( fc::shared_ptr>( waiter, true ) ).wait(); }, + fc::future( waiter ).wait(); }, [&counter](){ BOOST_CHECK_EQUAL( 0u, counter.load() ); counter.fetch_add(1); } ); }); - fc::future( fc::shared_ptr>( syncer, true ) ).wait(); + fc::future( syncer ).wait(); // at this point, p1.f1 has started executing and is waiting on waiter - syncer = new fc::promise(); + syncer = fc::promise::create(); auto p2 = fc::async([&counter,&valve,syncer] () { valve.do_serial( [&syncer](){ syncer->set_value(); fc::usleep( fc::milliseconds(100) ); }, [&counter](){ BOOST_CHECK_EQUAL( 1u, counter.load() ); counter.fetch_add(1); } ); }); - fc::future( fc::shared_ptr>( syncer, true ) ).wait(); + fc::future( syncer ).wait(); // at this point, p2.f1 has started executing and is sleeping - syncer = new fc::promise(); + syncer = fc::promise::create(); auto p3 = fc::async([&counter,&valve,syncer] () { valve.do_serial( [syncer](){ syncer->set_value(); }, [&counter](){ BOOST_CHECK_EQUAL( 2u, counter.load() ); counter.fetch_add(1); } ); }); - fc::future( fc::shared_ptr>( syncer, true ) ).wait(); + fc::future( syncer ).wait(); fc::usleep( fc::milliseconds(10) ); @@ -288,37 +288,37 @@ BOOST_AUTO_TEST_CASE( serial_valve ) } { // Triple test again but with invocations from different threads - fc::promise* syncer = new fc::promise(); - fc::promise* waiter = new fc::promise(); + fc::promise::ptr syncer = fc::promise::create(); + fc::promise::ptr waiter = fc::promise::create(); counter.store(0); auto p1 = fc::do_parallel([&counter,&valve,syncer,waiter] () { valve.do_serial( [&syncer,waiter](){ syncer->set_value(); - fc::future( fc::shared_ptr>( waiter, true ) ).wait(); }, + fc::future( waiter ).wait(); }, [&counter](){ BOOST_CHECK_EQUAL( 0u, counter.load() ); counter.fetch_add(1); } ); }); - fc::future( fc::shared_ptr>( syncer, true ) ).wait(); + fc::future( syncer ).wait(); // at this point, p1.f1 has started executing and is waiting on waiter - syncer = new fc::promise(); + syncer = fc::promise::create(); auto p2 = fc::do_parallel([&counter,&valve,syncer] () { valve.do_serial( [&syncer](){ syncer->set_value(); fc::usleep( fc::milliseconds(100) ); }, [&counter](){ BOOST_CHECK_EQUAL( 1u, counter.load() ); counter.fetch_add(1); } ); }); - fc::future( fc::shared_ptr>( syncer, true ) ).wait(); + fc::future( syncer ).wait(); // at this point, p2.f1 has started executing and is sleeping - syncer = new fc::promise(); + syncer = fc::promise::create(); auto p3 = fc::do_parallel([&counter,&valve,syncer] () { valve.do_serial( [syncer](){ syncer->set_value(); }, [&counter](){ BOOST_CHECK_EQUAL( 2u, counter.load() ); counter.fetch_add(1); } ); }); - fc::future( fc::shared_ptr>( syncer, true ) ).wait(); + fc::future( syncer ).wait(); fc::usleep( fc::milliseconds(10) ); diff --git a/tests/thread/task_cancel.cpp b/tests/thread/task_cancel.cpp index 3435f39..2909ca7 100644 --- a/tests/thread/task_cancel.cpp +++ b/tests/thread/task_cancel.cpp @@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE( cancel_a_task_waiting_on_promise ) { enum task_result{task_completed, task_aborted}; - fc::promise::ptr promise_to_wait_on(new fc::promise()); + fc::promise::ptr promise_to_wait_on = fc::promise::create(); fc::future task = fc::async([promise_to_wait_on]() { BOOST_TEST_MESSAGE("Starting async task"); From 19bbc4080eb37b396a19286ffdb4fc889f301ef8 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sat, 27 Apr 2019 16:29:55 +0200 Subject: [PATCH 003/110] Added retain where applicable --- include/fc/thread/future.hpp | 1 + include/fc/thread/parallel.hpp | 1 + include/fc/thread/thread.hpp | 2 ++ 3 files changed, 4 insertions(+) diff --git a/include/fc/thread/future.hpp b/include/fc/thread/future.hpp index a6937c6..0adc69a 100644 --- a/include/fc/thread/future.hpp +++ b/include/fc/thread/future.hpp @@ -72,6 +72,7 @@ namespace fc { void set_exception( const fc::exception_ptr& e ); + // HERE BE DRAGONS void retain(); void release(); diff --git a/include/fc/thread/parallel.hpp b/include/fc/thread/parallel.hpp index f66e1c6..433dfbf 100644 --- a/include/fc/thread/parallel.hpp +++ b/include/fc/thread/parallel.hpp @@ -99,6 +99,7 @@ namespace fc { typedef typename fc::deduce::type FunctorType; typename task::ptr tsk = task::create( fc::forward(f), desc ); + tsk->retain(); // HERE BE DRAFONS fc::future r( std::dynamic_pointer_cast< promise >(tsk) ); detail::get_worker_pool().post( tsk.get() ); return r; diff --git a/include/fc/thread/thread.hpp b/include/fc/thread/thread.hpp index 5c08b71..a01dc20 100644 --- a/include/fc/thread/thread.hpp +++ b/include/fc/thread/thread.hpp @@ -89,6 +89,7 @@ namespace fc { typedef typename fc::deduce::type FunctorType; typename task::ptr tsk = task::create( fc::forward(f), desc ); + tsk->retain(); // HERE BE DRAFONS fc::future r( std::dynamic_pointer_cast< promise >(tsk) ); async_task(tsk.get(),prio); return r; @@ -111,6 +112,7 @@ namespace fc { typedef decltype(f()) Result; typename task::ptr tsk = task::create( fc::forward(f), desc ); + tsk->retain(); // HERE BE DRAFONS fc::future r( std::dynamic_pointer_cast< promise >(tsk) ); async_task(tsk.get(),prio,when); return r; From 7506aaefe7c83074328b959fc06c093680c0ce51 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Thu, 2 May 2019 16:25:23 +0200 Subject: [PATCH 004/110] Moved retain/release to task_base --- include/fc/thread/future.hpp | 6 ------ include/fc/thread/task.hpp | 22 ++++++++++++++++++++++ src/thread/future.cpp | 11 +---------- src/thread/task.cpp | 11 ++++++++++- src/thread/thread_d.hpp | 8 ++++---- 5 files changed, 37 insertions(+), 21 deletions(-) diff --git a/include/fc/thread/future.hpp b/include/fc/thread/future.hpp index 0adc69a..40dd62f 100644 --- a/include/fc/thread/future.hpp +++ b/include/fc/thread/future.hpp @@ -72,10 +72,6 @@ namespace fc { void set_exception( const fc::exception_ptr& e ); - // HERE BE DRAGONS - void retain(); - void release(); - protected: promise_base(const char* desc FC_TASK_NAME_DEFAULT_ARG); @@ -108,8 +104,6 @@ namespace fc { #endif const char* _desc; detail::completion_handler* _compl; - std::shared_ptr _self; - boost::atomic _retain_count; }; template diff --git a/include/fc/thread/task.hpp b/include/fc/thread/task.hpp index a3162da..e29cd14 100644 --- a/include/fc/thread/task.hpp +++ b/include/fc/thread/task.hpp @@ -33,6 +33,25 @@ namespace fc { virtual void cancel(const char* reason FC_CANCELATION_REASON_DEFAULT_ARG) override; ~task_base(); + /* HERE BE DRAGONS + * + * Tasks are handled by an fc::thread . To avoid concurrency issues, fc::thread keeps a reference to tha + * task in the form of a simple pointer. + * At the same time, a task is also a promise that will be fulfilled with the task result, so typically the + * creator of the task also keeps a reference to the task (but not necessarily always). + * + * Because effectively neither fc::thread nor the task creator are responsible for releasing resources + * associated with a task, and neither can delete the task without knowing if the other still needs it, + * the task object is managed by a shared_ptr. + * However, fc::thread doesn't hold a shared_ptr but a native pointer. To work around this, the task can + * be made to contain a shared_ptr holding itself (by calling retain()), which happens before the task + * is handed to an fc::thread, e. g. in fc::async(). Once the thread has processed the task, it calls + * release() which deletes the self-referencing shared_ptr and deletes the task object if it's no longer + * in use anywhere. + */ + void retain(); + void release(); + protected: /// Task priority looks like unsupported feature. uint64_t _posted_num; @@ -65,6 +84,9 @@ namespace fc { void run_impl(); void cleanup_task_specific_data(); + private: + std::shared_ptr _self; + boost::atomic _retain_count; }; namespace detail { diff --git a/src/thread/future.cpp b/src/thread/future.cpp index d1c9a94..c9dbffa 100644 --- a/src/thread/future.cpp +++ b/src/thread/future.cpp @@ -19,8 +19,7 @@ namespace fc { _cancellation_reason(nullptr), #endif _desc(desc), - _compl(nullptr), - _retain_count(0) + _compl(nullptr) { } const char* promise_base::get_desc()const{ @@ -151,13 +150,5 @@ namespace fc { _compl = c; } } - void promise_base::retain() { - if( _retain_count.fetch_add(1, boost::memory_order_relaxed) == 0 ) - _self = shared_from_this(); - } - void promise_base::release() { - if( _retain_count.fetch_sub(1, boost::memory_order_release) == 1 ) - _self.reset(); - } } diff --git a/src/thread/task.cpp b/src/thread/task.cpp index b081872..23027e0 100644 --- a/src/thread/task.cpp +++ b/src/thread/task.cpp @@ -22,7 +22,8 @@ namespace fc { _next(nullptr), _task_specific_data(nullptr), _promise_impl(nullptr), - _functor(func){ + _functor(func), + _retain_count(0){ } void task_base::run() { @@ -101,4 +102,12 @@ namespace fc { } } + void task_base::retain() { + if( _retain_count.fetch_add(1, boost::memory_order_relaxed) == 0 ) + _self = shared_from_this(); + } + void task_base::release() { + if( _retain_count.fetch_sub(1, boost::memory_order_release) == 1 ) + _self.reset(); + } } diff --git a/src/thread/thread_d.hpp b/src/thread/thread_d.hpp index b0b6916..055ae8b 100644 --- a/src/thread/thread_d.hpp +++ b/src/thread/thread_d.hpp @@ -335,7 +335,7 @@ namespace fc { if( (*task_itr)->canceled() ) { (*task_itr)->run(); - (*task_itr)->release(); + (*task_itr)->release(); // HERE BE DRAGONS task_itr = task_sch_queue.erase(task_itr); canceled_task = true; continue; @@ -531,10 +531,10 @@ namespace fc { next->_set_active_context( current ); current->cur_task = next; - fc::shared_ptr next_ptr(next); - next_ptr->run(); + next->run(); current->cur_task = 0; - next_ptr->_set_active_context(0); + next->_set_active_context(0); + next->release(); // HERE BE DRAGONS current->reinitialize(); } From 022c40dde277891d6597b068b49801c9fbe38137 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Thu, 2 May 2019 16:57:24 +0200 Subject: [PATCH 005/110] Removed unused real128 --- CMakeLists.txt | 1 - include/fc/real128.hpp | 61 ------------------- src/real128.cpp | 130 ----------------------------------------- tests/CMakeLists.txt | 4 -- tests/real128_test.cpp | 55 ----------------- 5 files changed, 251 deletions(-) delete mode 100644 include/fc/real128.hpp delete mode 100644 src/real128.cpp delete mode 100644 tests/real128_test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fea7bd..c6b730b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -195,7 +195,6 @@ option( UNITY_BUILD OFF ) set( fc_sources src/uint128.cpp - src/real128.cpp src/variant.cpp src/exception.cpp src/variant_object.cpp diff --git a/include/fc/real128.hpp b/include/fc/real128.hpp deleted file mode 100644 index 995c006..0000000 --- a/include/fc/real128.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once -#include - -#define FC_REAL128_PRECISION (uint64_t(1000000) * uint64_t(1000000) * uint64_t(1000000)) - -namespace fc { - class variant; - - /** - * Provides fixed point math operations based on decimal fractions - * with 18 places. - * Delegates to fc::bigint for multiplication and division. - */ - class real128 - { - public: - real128( uint64_t integer = 0); - explicit real128( const std::string& str ); - operator std::string()const; - - friend real128 operator * ( real128 a, const real128& b ) { a *= b; return a; } - friend real128 operator / ( real128 a, const real128& b ) { a /= b; return a; } - friend real128 operator + ( real128 a, const real128& b ) { a += b; return a; } - friend real128 operator - ( real128 a, const real128& b ) { a -= b; return a; } - - real128& operator += ( const real128& o ); - 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; - - template - inline void pack( Stream& s, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { - pack( s, fixed, _max_depth ); - } - private: - uint128 fixed; - }; - - void to_variant( const real128& var, variant& vo, uint32_t max_depth = 1 ); - void from_variant( const variant& var, real128& vo, uint32_t max_depth = 1 ); - - namespace raw - { - template - inline void pack( Stream& s, const real128& value_to_pack, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) - { value_to_pack.pack( s, _max_depth ); } - - template - inline void unpack( Stream& s, real128& value_to_unpack, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) - { - uint128_t delegate; - unpack( s, delegate, _max_depth ); - value_to_unpack = fc::real128::from_fixed( delegate ); - } - } - -} // namespace fc diff --git a/src/real128.cpp b/src/real128.cpp deleted file mode 100644 index f941359..0000000 --- a/src/real128.cpp +++ /dev/null @@ -1,130 +0,0 @@ -#include -#include -#include -#include -#include - -namespace fc -{ - uint64_t real128::to_uint64()const - { - return (fixed/ FC_REAL128_PRECISION).to_uint64(); - } - - real128::real128( uint64_t integer ) - { - fixed = uint128(integer) * FC_REAL128_PRECISION; - } - real128& real128::operator += ( const real128& o ) - { - fixed += o.fixed; - return *this; - } - real128& real128::operator -= ( const real128& o ) - { - fixed -= o.fixed; - return *this; - } - - real128& real128::operator /= ( const real128& o ) - { try { - FC_ASSERT( o.fixed > uint128(0), "Divide by Zero" ); - - fc::bigint self(fixed); - fc::bigint other(o.fixed); - self *= FC_REAL128_PRECISION; - self /= other; - fixed = self; - - return *this; - } FC_CAPTURE_AND_RETHROW( (*this)(o) ) } - - real128& real128::operator *= ( const real128& o ) - { try { - fc::bigint self(fixed); - fc::bigint other(o.fixed); - self *= other; - self /= FC_REAL128_PRECISION; - fixed = self; - return *this; - } FC_CAPTURE_AND_RETHROW( (*this)(o) ) } - - - real128::real128( const std::string& ratio_str ) - { - const char* c = ratio_str.c_str(); - int digit = *c - '0'; - if (digit >= 0 && digit <= 9) - { - uint64_t int_part = digit; - ++c; - digit = *c - '0'; - while (digit >= 0 && digit <= 9) - { - int_part = int_part * 10 + digit; - ++c; - digit = *c - '0'; - } - *this = real128(int_part); - } - else - { - // if the string doesn't look like "123.45" or ".45", this code isn't designed to parse it correctly - // in particular, we don't try to handle leading whitespace or '+'/'-' indicators at the beginning - assert(*c == '.'); - fixed = fc::uint128(); - } - - - if (*c == '.') - { - c++; - digit = *c - '0'; - if (digit >= 0 && digit <= 9) - { - int64_t frac_part = digit; - int64_t frac_magnitude = 10; - ++c; - digit = *c - '0'; - while (digit >= 0 && digit <= 9) - { - frac_part = frac_part * 10 + digit; - frac_magnitude *= 10; - ++c; - digit = *c - '0'; - } - *this += real128( frac_part ) / real128( frac_magnitude ); - } - } - } - real128::operator std::string()const - { - std::stringstream ss; - ss << std::string(fixed / FC_REAL128_PRECISION); - ss << '.'; - auto frac = (fixed % FC_REAL128_PRECISION) + FC_REAL128_PRECISION; - ss << std::string( frac ).substr(1); - - auto number = ss.str(); - while( number.back() == '0' ) number.pop_back(); - - return number; - } - - real128 real128::from_fixed( const uint128& fixed ) - { - real128 result; - result.fixed = fixed; - return result; - } - - void to_variant( const real128& var, variant& vo, uint32_t max_depth ) - { - vo = std::string(var); - } - void from_variant( const variant& var, real128& vo, uint32_t max_depth ) - { - vo = real128(var.as_string()); - } - -} // namespace fc diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9e395c3..01cf205 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,9 +10,6 @@ target_link_libraries( task_cancel_test fc ) add_executable( bloom_test all_tests.cpp bloom_test.cpp ) target_link_libraries( bloom_test fc ) -add_executable( real128_test all_tests.cpp real128_test.cpp ) -target_link_libraries( real128_test fc ) - add_executable( hmac_test hmac_test.cpp ) target_link_libraries( hmac_test fc ) @@ -44,7 +41,6 @@ add_executable( all_tests all_tests.cpp thread/thread_tests.cpp thread/parallel_tests.cpp bloom_test.cpp - real128_test.cpp serialization_test.cpp stacktrace_test.cpp time_test.cpp diff --git a/tests/real128_test.cpp b/tests/real128_test.cpp deleted file mode 100644 index 5020af9..0000000 --- a/tests/real128_test.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include -#include -#include - -BOOST_AUTO_TEST_SUITE(fc) - -using fc::real128; -using std::string; - -BOOST_AUTO_TEST_CASE(real128_test) -{ - BOOST_CHECK_EQUAL(string(real128()), string("0.")); - BOOST_CHECK_EQUAL(string(real128(0)), string("0.")); - BOOST_CHECK_EQUAL(real128(8).to_uint64(), 8u); - BOOST_CHECK_EQUAL(real128(6789).to_uint64(), 6789u); - BOOST_CHECK_EQUAL(real128(10000).to_uint64(), 10000u); - BOOST_CHECK_EQUAL(string(real128(1)), string("1.")); - BOOST_CHECK_EQUAL(string(real128(5)), string("5.")); - BOOST_CHECK_EQUAL(string(real128(12345)), string("12345.")); - BOOST_CHECK_EQUAL(string(real128(0)), string(real128("0"))); - - real128 ten(10); - real128 two(2); - real128 twenty(20); - real128 pi(31415926535); - pi /= 10000000000; - - BOOST_CHECK_EQUAL( string(ten), "10." ); - BOOST_CHECK_EQUAL( string(two), "2." ); - BOOST_CHECK_EQUAL( string(ten+two), "12." ); - BOOST_CHECK_EQUAL( string(ten-two), "8." ); - BOOST_CHECK_EQUAL( string(ten*two), "20." ); - BOOST_CHECK_EQUAL( string(ten/two), "5." ); - BOOST_CHECK_EQUAL( string(ten/two/two/two*two*two*two), "10." ); - BOOST_CHECK_EQUAL( string(ten/two/two/two*two*two*two), string(ten) ); - BOOST_CHECK_EQUAL( string(twenty/ten), string(two) ); - BOOST_CHECK_EQUAL( string(pi), "3.1415926535" ); - BOOST_CHECK_EQUAL( string(pi*10), "31.415926535" ); - BOOST_CHECK_EQUAL( string(pi*20), "62.83185307" ); - BOOST_CHECK_EQUAL( string(real128("62.83185307")/twenty), string(pi) ); - BOOST_CHECK_EQUAL( string(pi*1), "3.1415926535" ); - BOOST_CHECK_EQUAL( string(pi*0), "0." ); - - BOOST_CHECK_EQUAL(real128("12345.6789").to_uint64(), 12345u); - BOOST_CHECK_EQUAL((real128("12345.6789")*10000).to_uint64(), 123456789u); - BOOST_CHECK_EQUAL(string(real128("12345.6789")), string("12345.6789")); - - BOOST_CHECK_EQUAL( real128(uint64_t(-1)).to_uint64(), uint64_t(-1) ); - - wdump( (ten)(two)(twenty) ); - wdump((real128("12345.6789")) ); - wdump( (ten/3*3) ); -} - -BOOST_AUTO_TEST_SUITE_END() From 648d969fb9467f37e0955093f8a402d11ed2a1f9 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Thu, 2 May 2019 17:02:14 +0200 Subject: [PATCH 006/110] Remove unused header --- include/fc/utility.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/fc/utility.hpp b/include/fc/utility.hpp index e0e6371..184aaf7 100644 --- a/include/fc/utility.hpp +++ b/include/fc/utility.hpp @@ -1,6 +1,5 @@ #pragma once #include -#include #ifdef _MSC_VER #pragma warning(disable: 4482) // nonstandard extension used enum Name::Val, standard in C++11 From a3e2410091272b74ae4cd5b42bc14734e754583e Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Tue, 7 May 2019 08:23:47 +0200 Subject: [PATCH 007/110] Replace fc::uint128 with boost::multiprecision::uint128_t --- CMakeLists.txt | 2 +- include/fc/crypto/aes.hpp | 11 +- include/fc/crypto/city.hpp | 19 +- include/fc/crypto/sha512.hpp | 9 +- include/fc/io/raw.hpp | 19 ++ include/fc/io/raw_fwd.hpp | 7 +- include/fc/popcount.hpp | 40 ++++ include/fc/safe.hpp | 3 +- include/fc/uint128.hpp | 181 +++------------- include/fc/utility.hpp | 1 + include/fc/variant.hpp | 4 + src/crypto/aes.cpp | 14 +- src/crypto/city.cpp | 41 ++-- src/popcount.cpp | 54 +++++ src/uint128.cpp | 398 ----------------------------------- src/variant.cpp | 11 + 16 files changed, 207 insertions(+), 607 deletions(-) create mode 100644 include/fc/popcount.hpp create mode 100644 src/popcount.cpp delete mode 100644 src/uint128.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c6b730b..50c70f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -194,7 +194,7 @@ set( CMAKE_FIND_LIBRARY_SUFFIXES ${ORIGINAL_LIB_SUFFIXES} ) option( UNITY_BUILD OFF ) set( fc_sources - src/uint128.cpp + src/popcount.cpp src/variant.cpp src/exception.cpp src/variant_object.cpp diff --git a/include/fc/crypto/aes.hpp b/include/fc/crypto/aes.hpp index e9f26af..862c8f3 100644 --- a/include/fc/crypto/aes.hpp +++ b/include/fc/crypto/aes.hpp @@ -1,9 +1,10 @@ #pragma once -#include + #include #include -#include #include +#include + #include namespace fc { @@ -15,9 +16,8 @@ namespace fc { aes_encoder(); ~aes_encoder(); - void init( const fc::sha256& key, const fc::uint128& init_value ); + void init( const fc::sha256& key, const uint128_t& init_value ); uint32_t encode( const char* plaintxt, uint32_t len, char* ciphertxt ); - // uint32_t final_encode( char* ciphertxt ); private: struct impl; @@ -29,9 +29,8 @@ namespace fc { aes_decoder(); ~aes_decoder(); - void init( const fc::sha256& key, const fc::uint128& init_value ); + void init( const fc::sha256& key, const uint128_t& init_value ); uint32_t decode( const char* ciphertxt, uint32_t len, char* plaintext ); -// uint32_t final_decode( char* plaintext ); private: struct impl; diff --git a/include/fc/crypto/city.hpp b/include/fc/crypto/city.hpp index 7047ae8..323c4af 100644 --- a/include/fc/crypto/city.hpp +++ b/include/fc/crypto/city.hpp @@ -41,36 +41,25 @@ // doesn't hold for any hash functions in this file. #pragma once +#include + #include // for size_t. #include #include namespace fc { -template -class array; -class uint128; - // Hash function for a byte array. uint64_t city_hash64(const char *buf, size_t len); -uint32_t city_hash32(const char *buf, size_t len); - #if SIZE_MAX > UINT32_MAX inline size_t city_hash_size_t(const char *buf, size_t len) { return city_hash64(buf, len); } #else +uint32_t city_hash32(const char *buf, size_t len); inline size_t city_hash_size_t(const char *buf, size_t len) { return city_hash32(buf, len); } #endif // Hash function for a byte array. -uint128 city_hash128(const char *s, size_t len); - -// Hash function for a byte array. -uint64_t city_hash_crc_64(const char *buf, size_t len); - -// Hash function for a byte array. -uint128 city_hash_crc_128(const char *s, size_t len); -array city_hash_crc_256(const char *s, size_t len); - +uint128_t city_hash_crc_128(const char *s, size_t len); } // namespace fc diff --git a/include/fc/crypto/sha512.hpp b/include/fc/crypto/sha512.hpp index 10c9ea0..adb078c 100644 --- a/include/fc/crypto/sha512.hpp +++ b/include/fc/crypto/sha512.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include #include namespace fc @@ -9,16 +10,16 @@ class sha512 { public: sha512(); - explicit sha512( const string& hex_str ); + explicit sha512( const std::string& hex_str ); - string str()const; - operator string()const; + std::string str()const; + operator std::string()const; char* data()const; size_t data_size()const { return 512 / 8; } static sha512 hash( const char* d, uint32_t dlen ); - static sha512 hash( const string& ); + static sha512 hash( const std::string& ); template static sha512 hash( const T& t ) diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index ff2a10c..ca0fadb 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -1,5 +1,6 @@ #pragma once #include + #include #include #include @@ -24,6 +25,24 @@ namespace fc { pack( s, args..., _max_depth ); } + template + inline void pack( Stream& s, const uint128_t& v, uint32_t _max_depth ) + { + boost::endian::little_uint64_buf_at hilo[2]; + hilo[0] = static_cast(v >> 64); + hilo[1] = static_cast(v & 0xffffffffffffffffULL); + s.write( hilo[0].data(), sizeof(hilo) ); + } + template + inline void unpack( Stream& s, uint128_t& v, uint32_t _max_depth ) + { + boost::endian::little_uint64_buf_at hilo[2]; + s.read( (char*) hilo, sizeof(hilo) ); + v = hilo[0].value(); + v <<= 64; + v += hilo[1].value(); + } + template inline void pack( Stream& s, const fc::exception& e, uint32_t _max_depth ) { diff --git a/include/fc/io/raw_fwd.hpp b/include/fc/io/raw_fwd.hpp index f89ff8f..f54870a 100644 --- a/include/fc/io/raw_fwd.hpp +++ b/include/fc/io/raw_fwd.hpp @@ -1,10 +1,12 @@ #pragma once #include + #include #include #include #include #include +#include #include #include #include @@ -42,7 +44,10 @@ namespace fc { template inline void unpack( Stream& s, fc::enum_type& tp, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - + template + inline void pack( Stream& s, const uint128_t& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template + inline void unpack( Stream& s, uint128_t& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); 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 ); diff --git a/include/fc/popcount.hpp b/include/fc/popcount.hpp new file mode 100644 index 0000000..d7dfc26 --- /dev/null +++ b/include/fc/popcount.hpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019 BitShares Blockchain Foundation, and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include +#include + +namespace fc { + +#if _MSC_VER || __GNUC__ || __clang__ +inline uint8_t popcount( uint64_t v ) { return __builtin_popcountll(v); } +#else +uint8_t popcount( uint64_t v ); +#endif + +uint8_t popcount( const fc::uint128_t& v ); + +} // namespace fc diff --git a/include/fc/safe.hpp b/include/fc/safe.hpp index d9290b9..d7c8514 100644 --- a/include/fc/safe.hpp +++ b/include/fc/safe.hpp @@ -11,8 +11,7 @@ namespace fc { * integer overflow and default initialization. It will * throw an exception on overflow conditions. * - * It can only be used on built-in types. In particular, - * safe is buggy and should not be used. + * It can only be used on built-in types. * * Implemented using spec from: * https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow diff --git a/include/fc/uint128.hpp b/include/fc/uint128.hpp index 42c8e3d..58b8251 100644 --- a/include/fc/uint128.hpp +++ b/include/fc/uint128.hpp @@ -1,158 +1,33 @@ +/* + * Copyright (c) 2019 BitShares Blockchain Foundation, and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + #pragma once -#include -#include -#include -#include -#include -#include -#include +#include -#ifdef _MSC_VER - #pragma warning (push) - #pragma warning (disable : 4244) -#endif //// _MSC_VER +namespace fc { -namespace fc -{ - class bigint; - /** - * @brief an implementation of 128 bit unsigned integer - * - */ - class uint128 - { - - - public: - uint128():hi(0),lo(0){} - uint128( uint32_t l ):hi(0),lo(l){} - uint128( int32_t l ):hi( -(l<0) ),lo(l){} - uint128( int64_t l ):hi( -(l<0) ),lo(l){} - uint128( uint64_t l ):hi(0),lo(l){} - uint128( const std::string& s ); - uint128( uint64_t _h, uint64_t _l ) - :hi(_h),lo(_l){} - uint128( const fc::bigint& bi ); - - operator std::string()const; - operator fc::bigint()const; - - bool operator == ( const uint128& o )const{ return hi == o.hi && lo == o.lo; } - bool operator != ( const uint128& o )const{ return hi != o.hi || lo != o.lo; } - bool operator < ( const uint128& o )const { return (hi == o.hi) ? lo < o.lo : hi < o.hi; } - bool operator < ( const int64_t& o )const { return *this < uint128(o); } - bool operator !()const { return !(hi !=0 || lo != 0); } - uint128 operator -()const { return ++uint128( ~hi, ~lo ); } - uint128 operator ~()const { return uint128( ~hi, ~lo ); } - - uint128& operator++() { hi += (++lo == 0); return *this; } - uint128& operator--() { hi -= (lo-- == 0); return *this; } - uint128 operator++(int) { auto tmp = *this; ++(*this); return tmp; } - uint128 operator--(int) { auto tmp = *this; --(*this); return tmp; } - - uint128& operator |= ( const uint128& u ) { hi |= u.hi; lo |= u.lo; return *this; } - uint128& operator &= ( const uint128& u ) { hi &= u.hi; lo &= u.lo; return *this; } - uint128& operator ^= ( const uint128& u ) { hi ^= u.hi; lo ^= u.lo; return *this; } - uint128& operator <<= ( const uint128& u ); - uint128& operator >>= ( const uint128& u ); - - uint128& operator += ( const uint128& u ) { const uint64_t old = lo; lo += u.lo; hi += u.hi + (lo < old); return *this; } - uint128& operator -= ( const uint128& u ) { return *this += -u; } - uint128& operator *= ( const uint128& u ); - uint128& operator /= ( const uint128& u ); - uint128& operator %= ( const uint128& u ); - - - friend uint128 operator + ( const uint128& l, const uint128& r ) { return uint128(l)+=r; } - friend uint128 operator - ( const uint128& l, const uint128& r ) { return uint128(l)-=r; } - friend uint128 operator * ( const uint128& l, const uint128& r ) { return uint128(l)*=r; } - friend uint128 operator / ( const uint128& l, const uint128& r ) { return uint128(l)/=r; } - friend uint128 operator % ( const uint128& l, const uint128& r ) { return uint128(l)%=r; } - friend uint128 operator | ( const uint128& l, const uint128& r ) { return uint128(l)=(r); } - friend uint128 operator & ( const uint128& l, const uint128& r ) { return uint128(l)&=r; } - friend uint128 operator ^ ( const uint128& l, const uint128& r ) { return uint128(l)^=r; } - friend uint128 operator << ( const uint128& l, const uint128& r ) { return uint128(l)<<=r; } - friend uint128 operator >> ( const uint128& l, const uint128& r ) { return uint128(l)>>=r; } - friend bool operator > ( const uint128& l, const uint128& r ) { return r < l; } - friend bool operator > ( const uint128& l, const int64_t& r ) { return uint128(r) < l; } - friend bool operator > ( const int64_t& l, const uint128& r ) { return r < uint128(l); } - - friend bool operator >= ( const uint128& l, const uint128& r ) { return l == r || l > r; } - friend bool operator >= ( const uint128& l, const int64_t& r ) { return l >= uint128(r); } - friend bool operator >= ( const int64_t& l, const uint128& r ) { return uint128(l) >= r; } - friend bool operator <= ( const uint128& l, const uint128& r ) { return l == r || l < r; } - friend bool operator <= ( const uint128& l, const int64_t& r ) { return l <= uint128(r); } - friend bool operator <= ( const int64_t& l, const uint128& r ) { return uint128(l) <= r; } - - friend std::size_t hash_value( const uint128& v ) { return city_hash_size_t((const char*)&v, sizeof(v)); } - - uint32_t to_integer()const - { - FC_ASSERT( hi == 0 ); - uint32_t lo32 = (uint32_t) lo; - FC_ASSERT( lo == lo32 ); - return lo32; - } - uint64_t to_uint64()const - { - FC_ASSERT( hi == 0 ); - return lo; - } - uint32_t low_32_bits()const { return (uint32_t) lo; } - uint64_t low_bits()const { return lo; } - uint64_t high_bits()const { return hi; } - - static uint128 max_value() { - const uint64_t max64 = std::numeric_limits::max(); - return uint128( max64, max64 ); - } - - static void full_product( const uint128& a, const uint128& b, uint128& result_hi, uint128& result_lo ); - - uint8_t popcount() const; - - // fields must be public for serialization - uint64_t hi; - uint64_t lo; - }; - static_assert( sizeof(uint128) == 2*sizeof(uint64_t), "validate packing assumptions" ); - - typedef uint128 uint128_t; - - class variant; - - void to_variant( const uint128& var, variant& vo, uint32_t max_depth = 1 ); - void from_variant( const variant& var, uint128& vo, uint32_t max_depth = 1 ); - - namespace raw - { - template - inline void pack( Stream& s, const uint128& u, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { - pack( s, u.hi, _max_depth ); - pack( s, u.lo, _max_depth ); - } - template - inline void unpack( Stream& s, uint128& u, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { - unpack( s, u.hi, _max_depth ); - unpack( s, u.lo, _max_depth ); - } - } - - size_t city_hash_size_t(const char *buf, size_t len); +using boost::multiprecision::uint128_t; + } // namespace fc - -namespace std -{ - template<> - struct hash - { - size_t operator()( const fc::uint128& s )const; - }; -} - -FC_REFLECT( fc::uint128_t, (hi)(lo) ) - -#ifdef _MSC_VER - #pragma warning (pop) -#endif ///_MSC_VER diff --git a/include/fc/utility.hpp b/include/fc/utility.hpp index 184aaf7..0bc4d45 100644 --- a/include/fc/utility.hpp +++ b/include/fc/utility.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include #ifdef _MSC_VER #pragma warning(disable: 4482) // nonstandard extension used enum Name::Val, standard in C++11 diff --git a/include/fc/variant.hpp b/include/fc/variant.hpp index 2e08740..1f60962 100644 --- a/include/fc/variant.hpp +++ b/include/fc/variant.hpp @@ -11,6 +11,7 @@ #include // memset #include +#include #include #include #include @@ -146,6 +147,9 @@ namespace fc void to_variant( const microseconds& input_microseconds, variant& output_variant, uint32_t max_depth ); void from_variant( const variant& input_variant, microseconds& output_microseconds, uint32_t max_depth ); + void to_variant( const uint128_t& var, variant& vo, uint32_t max_depth = 1 ); + void from_variant( const variant& var, uint128_t& vo, uint32_t max_depth = 1 ); + #ifdef __APPLE__ void to_variant( size_t s, variant& v, uint32_t max_depth = 1 ); #elif !defined(_MSC_VER) diff --git a/src/crypto/aes.cpp b/src/crypto/aes.cpp index 7bb5d20..5e78915 100644 --- a/src/crypto/aes.cpp +++ b/src/crypto/aes.cpp @@ -4,11 +4,11 @@ #include #include -#include #include #include +#include #include #include #include @@ -38,7 +38,7 @@ aes_encoder::~aes_encoder() { } -void aes_encoder::init( const fc::sha256& key, const fc::uint128& init_value ) +void aes_encoder::init( const fc::sha256& key, const uint128_t& init_value ) { my->ctx.obj = EVP_CIPHER_CTX_new(); /* Create and initialise the context */ @@ -54,8 +54,8 @@ void aes_encoder::init( const fc::sha256& key, const fc::uint128& init_value ) * IV size for *most* modes is the same as the block size. For AES this * is 128 bits */ boost::endian::little_uint64_buf_t iv[2]; - iv[0] = init_value.hi; - iv[1] = init_value.lo; + iv[0] = static_cast( init_value >> 64 ); + iv[1] = static_cast( init_value & 0xffffffffffffffffULL ); if(1 != EVP_EncryptInit_ex(my->ctx, EVP_aes_256_cbc(), NULL, (unsigned char*)&key, (const unsigned char*)iv[0].data())) { FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc encryption init", @@ -106,7 +106,7 @@ aes_decoder::aes_decoder() (void)init; } -void aes_decoder::init( const fc::sha256& key, const fc::uint128& init_value ) +void aes_decoder::init( const fc::sha256& key, const uint128_t& init_value ) { my->ctx.obj = EVP_CIPHER_CTX_new(); /* Create and initialise the context */ @@ -122,8 +122,8 @@ void aes_decoder::init( const fc::sha256& key, const fc::uint128& init_value ) * IV size for *most* modes is the same as the block size. For AES this * is 128 bits */ boost::endian::little_uint64_buf_t iv[2]; - iv[0] = init_value.hi; - iv[1] = init_value.lo; + iv[0] = static_cast( init_value >> 64 ); + iv[1] = static_cast( init_value & 0xffffffffffffffffULL ); if(1 != EVP_DecryptInit_ex(my->ctx, EVP_aes_256_cbc(), NULL, (unsigned char*)&key, (const unsigned char*)iv[0].data())) { FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc encryption init", diff --git a/src/crypto/city.cpp b/src/crypto/city.cpp index af3a91b..5649dd6 100644 --- a/src/crypto/city.cpp +++ b/src/crypto/city.cpp @@ -33,8 +33,6 @@ #include #include // for memcpy and memset #include -#include -#include #include #if defined(__SSE4_2__) && defined(__x86_64__) @@ -47,13 +45,16 @@ namespace fc { using namespace std; - -inline uint64_t Uint128Low64(const uint128& x) { return x.low_bits(); } -inline uint64_t Uint128High64(const uint128& x) { return x.high_bits(); } +inline uint64_t Uint128Low64(const uint128_t& x) { + return static_cast(x & 0xffffffffffffffffULL); +} +inline uint64_t Uint128High64(const uint128_t& x) { + return static_cast( x >> 64 ); +} // Hash 128 input bits down to 64 bits of output. // This is intended to be a reasonably good hash function. -inline uint64_t Hash128to64(const uint128& x) { +inline uint64_t Hash128to64(const uint128_t& x) { // Murmur-inspired hashing. const uint64_t kMul = 0x9ddfea08eb382d69ULL; uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul; @@ -280,7 +281,7 @@ static uint64_t ShiftMix(uint64_t val) { } static uint64_t HashLen16(uint64_t u, uint64_t v) { - return Hash128to64(uint128(u, v)); + return Hash128to64( ( uint128_t(u) << 64 ) + v); } static uint64_t HashLen16(uint64_t u, uint64_t v, uint64_t mul) { @@ -425,7 +426,7 @@ uint64_t CityHash64WithSeed(const char *s, size_t len, uint64_t seed) { // A subroutine for CityHash128(). Returns a decent 128-bit hash for strings // of any length representable in signed long. Based on City and Murmur. -static uint128 CityMurmur(const char *s, size_t len, uint128 seed) { +uint128_t CityMurmur(const char *s, size_t len, uint128_t seed) { uint64_t a = Uint128Low64(seed); uint64_t b = Uint128High64(seed); uint64_t c = 0; @@ -452,10 +453,10 @@ static uint128 CityMurmur(const char *s, size_t len, uint128 seed) { } a = HashLen16(a, c); b = HashLen16(d, b); - return uint128(a ^ b, HashLen16(b, a)); + return ( uint128_t(a ^ b) << 64 ) + HashLen16(b, a); } -uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) { +uint128_t CityHash128WithSeed(const char *s, size_t len, uint128_t seed) { if (len < 128) { return CityMurmur(s, len, seed); } @@ -514,15 +515,15 @@ uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) { // different 56-byte-to-8-byte hashes to get a 16-byte final result. x = HashLen16(x, v.first); y = HashLen16(y + z, w.first); - return uint128(HashLen16(x + v.second, w.second) + y, - HashLen16(x + w.second, y + v.second)); + return ( uint128_t( HashLen16(x + v.second, w.second) + y ) << 64 ) + + HashLen16(x + w.second, y + v.second); } -uint128 city_hash128(const char *s, size_t len) { +uint128_t city_hash128(const char *s, size_t len) { return len >= 16 ? CityHash128WithSeed(s + 16, len - 16, - uint128(Fetch64(s), Fetch64(s + 8) + k0)) : - CityHash128WithSeed(s, len, uint128(k0, k1)); + ( uint128_t( Fetch64(s) ) << 64 ) + Fetch64(s + 8) + k0) : + CityHash128WithSeed(s, len, ( uint128_t(k0) << 64 ) + k1); } //#ifdef __SSE4_2__ @@ -640,7 +641,7 @@ array city_hash_crc_256(const char *s, size_t len) return buf; } -uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed) { +uint128_t CityHashCrc128WithSeed(const char *s, size_t len, uint128_t seed) { if (len <= 900) { return CityHash128WithSeed(s, len, seed); } else { @@ -648,18 +649,18 @@ uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed) { CityHashCrc256(s, len, result); uint64_t u = Uint128High64(seed) + result[0]; uint64_t v = Uint128Low64(seed) + result[1]; - return uint128(HashLen16(u, v + result[2]), - HashLen16(Rotate(v, 32), u * k0 + result[3])); + return ( uint128_t( HashLen16(u, v + result[2]) ) << 64 ) + + HashLen16(Rotate(v, 32), u * k0 + result[3]); } } -uint128 city_hash_crc_128(const char *s, size_t len) { +uint128_t city_hash_crc_128(const char *s, size_t len) { if (len <= 900) { return city_hash128(s, len); } else { uint64_t result[4]; CityHashCrc256(s, len, result); - return uint128(result[2], result[3]); + return ( uint128_t(result[2]) << 64 ) + result[3]; } } diff --git a/src/popcount.cpp b/src/popcount.cpp new file mode 100644 index 0000000..d4b5bc7 --- /dev/null +++ b/src/popcount.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019 BitShares Blockchain Foundation, and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +namespace fc { + +#if _MSC_VER || __GNUC__ || __clang__ +#else +uint8_t popcount( uint64_t v ) +{ + // Public Domain code taken from http://graphics.stanford.edu/~seander/bithacks.html + uint8_t c; + static const int S[] = {1, 2, 4, 8, 16, 32}; + static const uint64_t B[] = {0x5555555555555555, 0x3333333333333333, 0x0F0F0F0F0F0F0F0F, + 0x00FF00FF00FF00FF, 0x0000FFFF0000FFFF, 0x00000000FFFFFFFF }; + + c = v - ((v >> 1) & B[0]); + c = ((c >> S[1]) & B[1]) + (c & B[1]); + c = ((c >> S[2]) + c) & B[2]; + c = ((c >> S[3]) + c) & B[3]; + c = ((c >> S[4]) + c) & B[4]; + return ((c >> S[5]) + c) & B[5]; +} +#endif + +uint8_t popcount( const uint128_t& v ) +{ + return popcount( static_cast(v >> 64) ) + + popcount( static_cast(v & 0xffffffffffffffffULL) ); +} + +} // namespace fc diff --git a/src/uint128.cpp b/src/uint128.cpp deleted file mode 100644 index fa5b795..0000000 --- a/src/uint128.cpp +++ /dev/null @@ -1,398 +0,0 @@ -#include -#include -#include -#include -#include - -#include - -namespace fc -{ - typedef boost::multiprecision::uint128_t m128; - - template - static void divide(const T &numerator, const T &denominator, T "ient, T &remainder) - { - static const int bits = sizeof(T) * 8; - - if(denominator == 0) { - throw std::domain_error("divide by zero"); - } else { - T n = numerator; - T d = denominator; - T x = 1; - T answer = 0; - - - while((n >= d) && (((d >> (bits - 1)) & 1) == 0)) { - x <<= 1; - d <<= 1; - } - - while(x != 0) { - if(n >= d) { - n -= d; - answer |= x; - } - - x >>= 1; - d >>= 1; - } - - quotient = answer; - remainder = n; - } - } - - uint128::uint128(const std::string &sz) - :hi(0), lo(0) - { - // do we have at least one character? - if(!sz.empty()) { - // make some reasonable assumptions - int radix = 10; - bool minus = false; - - std::string::const_iterator i = sz.begin(); - - // check for minus sign, i suppose technically this should only apply - // to base 10, but who says that -0x1 should be invalid? - if(*i == '-') { - ++i; - minus = true; - } - - // check if there is radix changing prefix (0 or 0x) - if(i != sz.end()) { - if(*i == '0') { - radix = 8; - ++i; - if(i != sz.end()) { - if(*i == 'x') { - radix = 16; - ++i; - } - } - } - - while(i != sz.end()) { - unsigned int n = 0; - const char ch = *i; - - if(ch >= 'A' && ch <= 'Z') { - if(((ch - 'A') + 10) < radix) { - n = (ch - 'A') + 10; - } else { - break; - } - } else if(ch >= 'a' && ch <= 'z') { - if(((ch - 'a') + 10) < radix) { - n = (ch - 'a') + 10; - } else { - break; - } - } else if(ch >= '0' && ch <= '9') { - if((ch - '0') < radix) { - n = (ch - '0'); - } else { - break; - } - } else { - /* completely invalid character */ - break; - } - - (*this) *= radix; - (*this) += n; - - ++i; - } - } - - // if this was a negative number, do that two's compliment madness :-P - if(minus) { - *this = -*this; - } - } - } - - - uint128::operator bigint()const - { - boost::endian::big_uint64_buf_t tmp[2]; - tmp[0] = hi; - tmp[1] = lo; - bigint bi( (char*)&tmp, sizeof(tmp) ); - return bi; - } - uint128::uint128( const fc::bigint& bi ) - { - *this = uint128( std::string(bi) ); // TODO: optimize this... - } - - uint128::operator std::string ()const - { - if(*this == 0) { return "0"; } - - // at worst it will be size digits (base 2) so make our buffer - // that plus room for null terminator - static char sz [128 + 1]; - sz[sizeof(sz) - 1] = '\0'; - - uint128 ii(*this); - int i = 128 - 1; - - while (ii != 0 && i) { - - uint128 remainder; - divide(ii, uint128(10), ii, remainder); - sz [--i] = "0123456789abcdefghijklmnopqrstuvwxyz"[remainder.to_integer()]; - } - - return &sz[i]; - } - - - uint128& uint128::operator<<=(const uint128& rhs) - { - if(rhs >= 128) - { - hi = 0; - lo = 0; - } - else - { - unsigned int n = rhs.to_integer(); - const unsigned int halfsize = 128 / 2; - - if(n >= halfsize){ - n -= halfsize; - hi = lo; - lo = 0; - } - - if(n != 0) { - // shift high half - hi <<= n; - - const uint64_t mask(~(uint64_t(-1) >> n)); - - // and add them to high half - hi |= (lo & mask) >> (halfsize - n); - - // and finally shift also low half - lo <<= n; - } - } - - return *this; - } - - uint128 & uint128::operator>>=(const uint128& rhs) - { - if(rhs >= 128) - { - hi = 0; - lo = 0; - } - else - { - unsigned int n = rhs.to_integer(); - const unsigned int halfsize = 128 / 2; - - if(n >= halfsize) { - n -= halfsize; - lo = hi; - hi = 0; - } - - if(n != 0) { - // shift low half - lo >>= n; - - // get lower N bits of high half - const uint64_t mask(~(uint64_t(-1) << n)); - - // and add them to low qword - lo |= (hi & mask) << (halfsize - n); - - // and finally shift also high half - hi >>= n; - } - } - return *this; - } - - uint128& uint128::operator/=(const uint128 &b) - { - auto self = (m128(hi) << 64) + m128(lo); - auto other = (m128(b.hi) << 64) + m128(b.lo); - self /= other; - hi = static_cast(self >> 64); - lo = static_cast((self << 64 ) >> 64); - return *this; - } - - uint128& uint128::operator%=(const uint128 &b) - { - uint128 quotient; - divide(*this, b, quotient, *this); - return *this; - } - - uint128& uint128::operator*=(const uint128 &b) - { - uint64_t a0 = (uint32_t) (this->lo ); - uint64_t a1 = (uint32_t) (this->lo >> 0x20); - uint64_t a2 = (uint32_t) (this->hi ); - uint64_t a3 = (uint32_t) (this->hi >> 0x20); - - uint64_t b0 = (uint32_t) (b.lo ); - uint64_t b1 = (uint32_t) (b.lo >> 0x20); - uint64_t b2 = (uint32_t) (b.hi ); - uint64_t b3 = (uint32_t) (b.hi >> 0x20); - - // (a0 + (a1 << 0x20) + (a2 << 0x40) + (a3 << 0x60)) * - // (b0 + (b1 << 0x20) + (b2 << 0x40) + (b3 << 0x60)) = - // a0 * b0 - // - // (a1 * b0 + a0 * b1) << 0x20 - // (a2 * b0 + a1 * b1 + a0 * b2) << 0x40 - // (a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3) << 0x60 - // - // all other cross terms are << 0x80 or higher, thus do not appear in result - - this->hi = 0; - this->lo = a3*b0; - (*this) += a2*b1; - (*this) += a1*b2; - (*this) += a0*b3; - (*this) <<= 0x20; - (*this) += a2*b0; - (*this) += a1*b1; - (*this) += a0*b2; - (*this) <<= 0x20; - (*this) += a1*b0; - (*this) += a0*b1; - (*this) <<= 0x20; - (*this) += a0*b0; - - return *this; - } - - void uint128::full_product( const uint128& a, const uint128& b, uint128& result_hi, uint128& result_lo ) - { - // (ah * 2**64 + al) * (bh * 2**64 + bl) - // = (ah * bh * 2**128 + al * bh * 2**64 + ah * bl * 2**64 + al * bl - // = P * 2**128 + (Q + R) * 2**64 + S - // = Ph * 2**192 + Pl * 2**128 - // + Qh * 2**128 + Ql * 2**64 - // + Rh * 2**128 + Rl * 2**64 - // + Sh * 2**64 + Sl - // - - uint64_t ah = a.hi; - uint64_t al = a.lo; - uint64_t bh = b.hi; - uint64_t bl = b.lo; - - uint128 s = al; - s *= bl; - uint128 r = ah; - r *= bl; - uint128 q = al; - q *= bh; - uint128 p = ah; - p *= bh; - - uint64_t sl = s.lo; - uint64_t sh = s.hi; - uint64_t rl = r.lo; - uint64_t rh = r.hi; - uint64_t ql = q.lo; - uint64_t qh = q.hi; - uint64_t pl = p.lo; - uint64_t ph = p.hi; - - uint64_t y[4]; // final result - y[0] = sl; - - uint128_t acc = sh; - acc += ql; - acc += rl; - y[1] = acc.lo; - acc = acc.hi; - acc += qh; - acc += rh; - acc += pl; - y[2] = acc.lo; - y[3] = acc.hi + ph; - - result_hi = uint128( y[3], y[2] ); - result_lo = uint128( y[1], y[0] ); - } - - static uint8_t _popcount_64( uint64_t x ) - { - static const uint64_t m[] = { - 0x5555555555555555ULL, - 0x3333333333333333ULL, - 0x0F0F0F0F0F0F0F0FULL, - 0x00FF00FF00FF00FFULL, - 0x0000FFFF0000FFFFULL, - 0x00000000FFFFFFFFULL - }; - // TODO future optimization: replace slow, portable version - // with fast, non-portable __builtin_popcountll intrinsic - // (when available) - - for( int i=0, w=1; i<6; i++, w+=w ) - { - x = (x & m[i]) + ((x >> w) & m[i]); - } - return uint8_t(x); - } - - uint8_t uint128::popcount()const - { - return _popcount_64( lo ) + _popcount_64( hi ); - } - - void to_variant( const uint128& var, variant& vo, uint32_t max_depth ) - { - vo = std::string(var); - } - void from_variant( const variant& var, uint128& vo, uint32_t max_depth ) - { - vo = uint128(var.as_string()); - } - -} // namespace fc - -namespace std { - size_t hash::operator()( const fc::uint128& s )const - { - boost::endian::little_uint64_buf_t tmp[2]; - tmp[0] = s.hi; - tmp[1] = s.lo; - return fc::city_hash_size_t((char*)&tmp, sizeof(tmp)); - } -} - -/* - * Portions of the above code were adapted from the work of Evan Teran. - * - * Copyright (c) 2008 - * Evan Teran - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose and without fee is hereby granted, provided - * that the above copyright notice appears in all copies and that both the - * copyright notice and this permission notice appear in supporting - * documentation, and that the same name not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. We make no representations about the - * suitability this software for any purpose. It is provided "as is" - * without express or implied warranty. - */ - diff --git a/src/variant.cpp b/src/variant.cpp index 4e52ec9..026e2ab 100644 --- a/src/variant.cpp +++ b/src/variant.cpp @@ -13,6 +13,7 @@ namespace fc { + /** * The TypeID is stored in the 'last byte' of the variant. */ @@ -672,6 +673,16 @@ void from_variant( const variant& var, std::vector& vo, uint32_t max_depth } } +void to_variant( const uint128_t& var, variant& vo, uint32_t max_depth ) +{ + vo = var.str(); +} + +void from_variant( const variant& var, uint128_t& vo, uint32_t max_depth ) +{ + vo = uint128_t( var.as_string() ); +} + #ifdef __APPLE__ #elif !defined(_MSC_VER) void to_variant( long long int s, variant& v, uint32_t max_depth ) { v = variant( int64_t(s) ); } From 632a90709ed518e58bd36780acdca5e60d672058 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Wed, 22 May 2019 12:53:26 +0200 Subject: [PATCH 008/110] Replace fc::array with std::array --- include/fc/array.hpp | 145 ------------------------------ include/fc/crypto/elliptic.hpp | 21 ++--- include/fc/io/raw.hpp | 20 ++--- include/fc/io/raw_fwd.hpp | 19 ++-- include/fc/reflect/typename.hpp | 12 ++- include/fc/static_variant.hpp | 18 ++-- include/fc/variant.hpp | 31 +++++++ src/crypto/elliptic_common.cpp | 40 ++++----- src/crypto/elliptic_secp256k1.cpp | 59 ++++++------ tests/crypto/ecc_test.cpp | 4 +- tests/hmac_test.cpp | 7 +- 11 files changed, 140 insertions(+), 236 deletions(-) delete mode 100644 include/fc/array.hpp diff --git a/include/fc/array.hpp b/include/fc/array.hpp deleted file mode 100644 index 687b175..0000000 --- a/include/fc/array.hpp +++ /dev/null @@ -1,145 +0,0 @@ -#pragma once -#include -#include -#include - -namespace fc { - - /** - * Provides a fixed size array that is easier for templates to specialize - * against or overload than T[N]. - */ - template - class array { - public: - /** - * Checked indexing (when in debug build) that also simplifies dereferencing - * when you have an array*. - */ - ///@{ - T& at( size_t pos ) { assert( pos < N); return data[pos]; } - const T& at( size_t pos )const { assert( pos < N); return data[pos]; } - ///@} - - T& operator[]( size_t pos ) { assert( pos < N); return data[pos]; } - const T& operator[]( size_t pos )const { assert( pos < N); return data[pos]; } - - - const T* begin()const { return &data[0]; } - const T* end()const { return &data[N]; } - - T* begin() { return &data[0]; } - T* end() { return &data[N]; } - - size_t size()const { return N; } - - T data[N]; - }; - - /** provided for default 0 init */ - template - class array - { - public: - typedef unsigned char T; - array(){ memset( data, 0, sizeof(data) ); } - /** - * Checked indexing (when in debug build) that also simplifies dereferencing - * when you have an array*. - */ - ///@{ - T& at( size_t pos ) { assert( pos < N); return data[pos]; } - const T& at( size_t pos )const { assert( pos < N); return data[pos]; } - ///@} - - T* begin() { return &data[0]; } - const T* begin()const { return &data[0]; } - const T* end()const { return &data[N]; } - - size_t size()const { return N; } - - T data[N]; - }; - - /** provided for default 0 init */ - template - class array - { - public: - typedef char T; - array(){ memset( data, 0, sizeof(data) ); } - /** - * Checked indexing (when in debug build) that also simplifies dereferencing - * when you have an array*. - */ - ///@{ - T& at( size_t pos ) { assert( pos < N); return data[pos]; } - const T& at( size_t pos )const { assert( pos < N); return data[pos]; } - ///@} - - T* begin() { return &data[0]; } - const T* begin()const { return &data[0]; } - const T* end()const { return &data[N]; } - - size_t size()const { return N; } - - T data[N]; - }; - - template - bool operator == ( const array& a, const array& b ) - { return 0 == memcmp( a.data, b.data, N*sizeof(T) ); } - template - bool operator < ( const array& a, const array& b ) - { return memcmp( a.data, b.data, N*sizeof(T) ) < 0 ; } - - template - bool operator > ( const array& a, const array& b ) - { return memcmp( a.data, b.data, N*sizeof(T) ) > 0 ; } - - template - bool operator != ( const array& a, const array& b ) - { return 0 != memcmp( a.data, b.data, N*sizeof(T) ); } - - template - void to_variant( const array& bi, variant& v, uint32_t max_depth = 1 ) - { - to_variant( std::vector( (const char*)&bi, ((const char*)&bi) + sizeof(bi) ), v, 1 ); - } - template - void from_variant( const variant& v, array& bi, uint32_t max_depth = 1 ) - { - std::vector ve = v.as< std::vector >( 1 ); - if( ve.size() ) - { - memcpy(&bi, ve.data(), std::min(ve.size(),sizeof(bi)) ); - } - else - memset( &bi, char(0), sizeof(bi) ); - } - - - template struct get_typename< fc::array > - { - static const char* name() - { - static std::string _name = std::string("fc::array<")+std::string(fc::get_typename::name())+","+ fc::to_string(N) + ">"; - return _name.c_str(); - } - }; -} - -#include -#include -namespace std -{ - template - struct hash > - { - size_t operator()( const fc::array& e )const - { - return fc::city_hash_size_t( (char*)&e, sizeof(e) ); - } - }; -} - diff --git a/include/fc/crypto/elliptic.hpp b/include/fc/crypto/elliptic.hpp index 7ca2ec6..3784299 100644 --- a/include/fc/crypto/elliptic.hpp +++ b/include/fc/crypto/elliptic.hpp @@ -4,9 +4,10 @@ #include #include #include -#include #include +#include + namespace fc { namespace ecc { @@ -16,15 +17,15 @@ namespace fc { class private_key_impl; } - typedef fc::sha256 blind_factor_type; - typedef fc::array commitment_type; - typedef fc::array public_key_data; - typedef fc::sha256 private_key_secret; - typedef fc::array public_key_point_data; ///< the full non-compressed version of the ECC point - typedef fc::array signature; - typedef fc::array compact_signature; - typedef std::vector range_proof_type; - typedef fc::array extended_key_data; + typedef fc::sha256 blind_factor_type; + typedef std::array commitment_type; + typedef std::array public_key_data; + typedef fc::sha256 private_key_secret; + typedef std::array public_key_point_data; ///< the full non-compressed version of the ECC point + typedef std::array signature; + typedef std::array compact_signature; + typedef std::vector range_proof_type; + typedef std::array extended_key_data; /** * @class public_key diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index ca0fadb..4b46086 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -146,22 +146,22 @@ namespace fc { } FC_RETHROW_EXCEPTIONS( warn, "" ) } template - inline void pack( Stream& s, const fc::array& v, uint32_t _max_depth ) { - s.write( &v.data[0], N ); + inline void pack( Stream& s, const std::array& v, uint32_t _max_depth ) { + s.write( v.data(), N ); } template - inline void pack( Stream& s, const fc::array& v, uint32_t _max_depth ) { - s.write( (char*)&v.data[0], N ); + inline void pack( Stream& s, const std::array& v, uint32_t _max_depth ) { + s.write( (char*)v.data(), N ); } template - inline void unpack( Stream& s, fc::array& v, uint32_t _max_depth ) { try { - s.read( &v.data[0], N ); - } FC_RETHROW_EXCEPTIONS( warn, "fc::array", ("length",N) ) } + inline void unpack( Stream& s, std::array& v, uint32_t _max_depth ) { try { + s.read( v.data(), N ); + } FC_RETHROW_EXCEPTIONS( warn, "std::array", ("length",N) ) } template - inline void unpack( Stream& s, fc::array& v, uint32_t _max_depth ) { try { - s.read( (char*)&v.data[0], N ); - } FC_RETHROW_EXCEPTIONS( warn, "fc::array", ("length",N) ) } + inline void unpack( Stream& s, std::array& v, uint32_t _max_depth ) { try { + s.read( (char*)v.data(), N ); + } FC_RETHROW_EXCEPTIONS( warn, "std::array", ("length",N) ) } template inline void pack( Stream& s, const std::shared_ptr& v, uint32_t _max_depth ) diff --git a/include/fc/io/raw_fwd.hpp b/include/fc/io/raw_fwd.hpp index f54870a..e82fe44 100644 --- a/include/fc/io/raw_fwd.hpp +++ b/include/fc/io/raw_fwd.hpp @@ -4,9 +4,10 @@ #include #include #include -#include #include #include + +#include #include #include #include @@ -130,13 +131,17 @@ namespace fc { inline void unpack( Stream& s, boost::endian::endian_buffer& v, uint32_t _max_depth ); template - inline void pack( Stream& s, const fc::array& v, uint32_t _max_depth ) = delete; + inline void pack( Stream& s, const std::array& v, uint32_t _max_depth ) = delete; template - inline void unpack( Stream& s, fc::array& v, uint32_t _max_depth ) = delete; - 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 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); + inline void unpack( Stream& s, std::array& v, uint32_t _max_depth ) = delete; + template + inline void pack( Stream& s, const std::array& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template + inline void unpack( Stream& s, std::array& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH); + template + inline void pack( Stream& s, const std::array& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template + inline void unpack( Stream& s, std::array& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH); template inline void pack( Stream& s, const std::shared_ptr& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); diff --git a/include/fc/reflect/typename.hpp b/include/fc/reflect/typename.hpp index e61f79b..3fe9a83 100644 --- a/include/fc/reflect/typename.hpp +++ b/include/fc/reflect/typename.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -7,7 +8,7 @@ #include #include - +#include #include namespace fc { @@ -92,6 +93,15 @@ namespace fc { return n.c_str(); } }; + template struct get_typename< std::array > + { + static const char* name() + { + static std::string _name = std::string("std::array<") + std::string(fc::get_typename::name()) + + "," + fc::to_string(N) + ">"; + return _name.c_str(); + } + }; struct unsigned_int; class variant_object; diff --git a/include/fc/static_variant.hpp b/include/fc/static_variant.hpp index 4a440a2..5451168 100644 --- a/include/fc/static_variant.hpp +++ b/include/fc/static_variant.hpp @@ -11,11 +11,11 @@ **/ #pragma once +#include #include #include #include -#include #include namespace fc { @@ -216,17 +216,17 @@ public: } // namespace impl template -static const fc::array +static const std::array init_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0) { - return fc::array(); + return std::array(); } template -static const fc::array +static const std::array init_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0 ) { - fc::array result{}; + std::array result{}; if( !funcs ) funcs = result.begin(); *funcs++ = [] ( Visitor& v, Data d ) { return v( *reinterpret_cast( d ) ); }; init_wrappers( v, d, funcs ); @@ -234,17 +234,17 @@ static const fc::array } template -static const fc::array +static const std::array init_const_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0 ) { - return fc::array(); + return std::array(); } template -static const fc::array +static const std::array init_const_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0 ) { - fc::array result{}; + std::array result{}; if( !funcs ) funcs = result.begin(); *funcs++ = [] ( Visitor& v, Data d ) { return v( *reinterpret_cast( d ) ); }; init_const_wrappers( v, d, funcs ); diff --git a/include/fc/variant.hpp b/include/fc/variant.hpp index 1f60962..4da4f52 100644 --- a/include/fc/variant.hpp +++ b/include/fc/variant.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -658,6 +659,36 @@ namespace fc c.insert( item.as( max_depth - 1 ) ); } + template + void to_variant( const std::array& bi, variant& v, uint32_t max_depth = 1 ) + { + to_variant( std::vector( bi.begin(), bi.end() ), v, 1 ); + } + template + void from_variant( const variant& v, std::array& bi, uint32_t max_depth = 1 ) + { + std::vector ve = v.as< std::vector >( 1 ); + if( ve.size() ) + memcpy( bi.data(), ve.data(), std::min( ve.size(), bi.size() ) ); + else + memset( bi.data(), 0, bi.size() ); + } + + template + void to_variant( const std::array& bi, variant& v, uint32_t max_depth = 1 ) + { + to_variant( std::vector( bi.begin(), bi.end() ), v, 1 ); + } + template + void from_variant( const variant& v, std::array& bi, uint32_t max_depth = 1 ) + { + std::vector ve = v.as< std::vector >( 1 ); + if( ve.size() ) + memcpy( bi.data(), ve.data(), std::min( ve.size(), bi.size() ) ); + else + memset( bi.data(), 0, bi.size() ); + } + variant operator + ( const variant& a, const variant& b ); variant operator - ( const variant& a, const variant& b ); variant operator * ( const variant& a, const variant& b ); diff --git a/src/crypto/elliptic_common.cpp b/src/crypto/elliptic_common.cpp index 13bf256..56eeebc 100644 --- a/src/crypto/elliptic_common.cpp +++ b/src/crypto/elliptic_common.cpp @@ -19,7 +19,7 @@ namespace fc { namespace ecc { namespace detail { - typedef fc::array chr37; + typedef std::array chr37; fc::sha256 _left( const fc::sha512& v ) { @@ -52,10 +52,10 @@ namespace fc { namespace ecc { return result; } - static chr37 _derive_message( char first, const char* key32, int i ) + static chr37 _derive_message( unsigned char first, const unsigned char* key32, int i ) { chr37 result; - unsigned char* dest = (unsigned char*) result.begin(); + unsigned char* dest = result.begin(); *dest++ = first; memcpy( dest, key32, 32 ); dest += 32; _put( &dest, i ); @@ -69,7 +69,7 @@ namespace fc { namespace ecc { static chr37 _derive_message( const private_key_secret& key, int i ) { - return _derive_message( 0, key.data(), i ); + return _derive_message( 0, (unsigned char*) key.data(), i ); } const ec_group& get_curve() @@ -139,40 +139,40 @@ namespace fc { namespace ecc { std::string public_key::to_base58( const public_key_data &key ) { - sha256 check = sha256::hash(key.data, sizeof(key)); + sha256 check = sha256::hash((char*) key.data(), sizeof(key)); static_assert(sizeof(key) + 4 == 37, "Elliptic public key size (or its hash) is incorrect"); - array data; - memcpy(data.data, key.begin(), key.size()); + detail::chr37 data; + memcpy(data.data(), key.begin(), key.size()); memcpy(data.begin() + key.size(), (const char*)check._hash, 4); - return fc::to_base58(data.begin(), data.size()); + return fc::to_base58((char*) data.begin(), data.size()); } public_key public_key::from_base58( const std::string& b58 ) { - array data; + detail::chr37 data; size_t s = fc::from_base58(b58, (char*)&data, sizeof(data) ); FC_ASSERT( s == sizeof(data) ); public_key_data key; - sha256 check = sha256::hash(data.data, sizeof(key)); - FC_ASSERT( memcmp( (char*)check._hash, data.data + sizeof(key), 4 ) == 0 ); - memcpy( (char*)key.data, data.data, sizeof(key) ); + sha256 check = sha256::hash((char*) data.data(), sizeof(key)); + FC_ASSERT( memcmp( (char*)check._hash, data.data() + key.size(), 4 ) == 0 ); + memcpy( (char*)key.data(), data.data(), key.size() ); return from_key_data(key); } unsigned int public_key::fingerprint() const { public_key_data key = serialize(); - ripemd160 hash = ripemd160::hash( sha256::hash( key.begin(), key.size() ) ); + ripemd160 hash = ripemd160::hash( sha256::hash( (char*) key.begin(), key.size() ) ); unsigned char* fp = (unsigned char*) hash._hash; return (fp[0] << 24) | (fp[1] << 16) | (fp[2] << 8) | fp[3]; } bool public_key::is_canonical( const compact_signature& c ) { - return !(c.data[1] & 0x80) - && !(c.data[1] == 0 && !(c.data[2] & 0x80)) - && !(c.data[33] & 0x80) - && !(c.data[33] == 0 && !(c.data[34] & 0x80)); + return !(c[1] & 0x80) + && !(c[1] == 0 && !(c[2] & 0x80)) + && !(c[33] & 0x80) + && !(c[33] == 0 && !(c[34] & 0x80)); } private_key private_key::generate_from_seed( const fc::sha256& seed, const fc::sha256& offset ) @@ -234,7 +234,7 @@ namespace fc { namespace ecc { size_t buf_len = key.size() + 4; char *buffer = (char*)alloca(buf_len); memcpy( buffer, key.begin(), key.size() ); - fc::sha256 double_hash = fc::sha256::hash( fc::sha256::hash( key.begin(), key.size() )); + fc::sha256 double_hash = fc::sha256::hash( fc::sha256::hash( (char*) key.begin(), key.size() )); memcpy( buffer + key.size(), double_hash.data(), 4 ); return fc::to_base58( buffer, buf_len ); } @@ -311,7 +311,7 @@ namespace fc { namespace ecc { { const detail::chr37 data = detail::_derive_message( get_public_key().serialize(), i ); hmac_sha512 mac; - fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() ); + fc::sha512 l = mac.digest( c.data(), c.data_size(), (char*) data.begin(), data.size() ); return private_derive_rest( l, i ); } @@ -320,7 +320,7 @@ namespace fc { namespace ecc { hmac_sha512 mac; private_key_secret key = get_secret(); const detail::chr37 data = detail::_derive_message( key, i ); - fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() ); + fc::sha512 l = mac.digest( c.data(), c.data_size(), (char*) data.begin(), data.size() ); return private_derive_rest( l, i ); } diff --git a/src/crypto/elliptic_secp256k1.cpp b/src/crypto/elliptic_secp256k1.cpp index b80ace3..7f8d841 100644 --- a/src/crypto/elliptic_secp256k1.cpp +++ b/src/crypto/elliptic_secp256k1.cpp @@ -41,6 +41,7 @@ namespace fc { namespace ecc { public_key_impl() BOOST_NOEXCEPT { _init_lib(); + memset( _key.data(), 0, _key.size() ); } public_key_impl( const public_key_impl& cpy ) BOOST_NOEXCEPT @@ -52,16 +53,16 @@ namespace fc { namespace ecc { public_key_data _key; }; - typedef fc::array chr37; + typedef std::array chr37; chr37 _derive_message( const public_key_data& key, int i ); fc::sha256 _left( const fc::sha512& v ); fc::sha256 _right( const fc::sha512& v ); const ec_group& get_curve(); const private_key_secret& get_curve_order(); const private_key_secret& get_half_curve_order(); - } + } // detail - static const public_key_data empty_pub; + static const public_key_data empty_pub = detail::public_key_impl()._key; static const private_key_secret empty_priv; fc::sha512 private_key::get_shared_secret( const public_key& other )const @@ -69,8 +70,8 @@ namespace fc { namespace ecc { FC_ASSERT( my->_key != empty_priv ); FC_ASSERT( other.my->_key != empty_pub ); public_key_data pub(other.my->_key); - FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), (unsigned char*) pub.begin(), pub.size(), (unsigned char*) my->_key.data() ) ); - return fc::sha512::hash( pub.begin() + 1, pub.size() - 1 ); + FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), pub.begin(), pub.size(), (unsigned char*) my->_key.data() ) ); + return fc::sha512::hash( (char*) pub.begin() + 1, pub.size() - 1 ); } @@ -104,7 +105,7 @@ namespace fc { namespace ecc { FC_ASSERT( my->_key != empty_pub ); public_key_data new_key; memcpy( new_key.begin(), my->_key.begin(), new_key.size() ); - FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), (unsigned char*) new_key.begin(), new_key.size(), (unsigned char*) digest.data() ) ); + FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), new_key.begin(), new_key.size(), (unsigned char*) digest.data() ) ); return public_key( new_key ); } @@ -126,22 +127,22 @@ namespace fc { namespace ecc { public_key_point_data dat; unsigned int pk_len = my->_key.size(); memcpy( dat.begin(), my->_key.begin(), pk_len ); - FC_ASSERT( secp256k1_ec_pubkey_decompress( detail::_get_context(), (unsigned char *) dat.begin(), (int*) &pk_len ) ); + FC_ASSERT( secp256k1_ec_pubkey_decompress( detail::_get_context(), dat.begin(), (int*) &pk_len ) ); FC_ASSERT( pk_len == dat.size() ); return dat; } public_key::public_key( const public_key_point_data& dat ) { - const char* front = &dat.data[0]; + const unsigned char* front = dat.data(); if( *front == 0 ){} else { EC_KEY *key = EC_KEY_new_by_curve_name( NID_secp256k1 ); - key = o2i_ECPublicKey( &key, (const unsigned char**)&front, sizeof(dat) ); + key = o2i_ECPublicKey( &key, &front, sizeof(dat) ); FC_ASSERT( key ); EC_KEY_set_conv_form( key, POINT_CONVERSION_COMPRESSED ); - unsigned char* buffer = (unsigned char*) my->_key.begin(); + unsigned char* buffer = my->_key.begin(); i2o_ECPublicKey( key, &buffer ); // FIXME: questionable memory handling EC_KEY_free( key ); } @@ -154,7 +155,7 @@ namespace fc { namespace ecc { public_key::public_key( const compact_signature& c, const fc::sha256& digest, bool check_canonical ) { - int nV = c.data[0]; + int nV = c[0]; if (nV<27 || nV>=35) FC_THROW_EXCEPTION( exception, "unable to reconstruct public key from signature" ); @@ -164,7 +165,7 @@ namespace fc { namespace ecc { } unsigned int pk_len; - FC_ASSERT( secp256k1_ecdsa_recover_compact( detail::_get_context(), (unsigned char*) digest.data(), (unsigned char*) c.begin() + 1, (unsigned char*) my->_key.begin(), (int*) &pk_len, 1, (*c.begin() - 27) & 3 ) ); + FC_ASSERT( secp256k1_ecdsa_recover_compact( detail::_get_context(), (unsigned char*) digest.data(), c.begin() + 1, my->_key.begin(), (int*) &pk_len, 1, (*c.begin() - 27) & 3 ) ); FC_ASSERT( pk_len == my->_key.size() ); } @@ -180,7 +181,7 @@ namespace fc { namespace ecc { fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() ); fc::sha256 left = detail::_left(l); FC_ASSERT( left < detail::get_curve_order() ); - FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), (unsigned char*) key.begin(), key.size(), (unsigned char*) left.data() ) > 0 ); + FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), key.begin(), key.size(), (unsigned char*) left.data() ) > 0 ); // FIXME: check validity - if left + key == infinity then invalid extended_public_key result( key, detail::_right(l), i, fingerprint(), depth + 1 ); return result; @@ -204,7 +205,7 @@ namespace fc { namespace ecc { commitment_type blind( const blind_factor_type& blind, uint64_t value ) { commitment_type result; - FC_ASSERT( secp256k1_pedersen_commit( detail::_get_context(), (unsigned char*)&result, (unsigned char*)&blind, value ) ); + FC_ASSERT( secp256k1_pedersen_commit( detail::_get_context(), result.data(), (unsigned char*) blind.data(), value ) ); return result; } @@ -212,8 +213,8 @@ namespace fc { namespace ecc { { blind_factor_type result; std::vector blinds(blinds_in.size()); - for( uint32_t i = 0; i < blinds_in.size(); ++i ) blinds[i] = (const unsigned char*)&blinds_in[i]; - FC_ASSERT( secp256k1_pedersen_blind_sum( detail::_get_context(), (unsigned char*)&result, blinds.data(), blinds_in.size(), non_neg ) ); + for( uint32_t i = 0; i < blinds_in.size(); ++i ) blinds[i] = (unsigned char*) blinds_in[i].data(); + FC_ASSERT( secp256k1_pedersen_blind_sum( detail::_get_context(), (unsigned char*) result.data(), blinds.data(), blinds_in.size(), non_neg ) ); return result; } @@ -221,16 +222,16 @@ namespace fc { namespace ecc { bool verify_sum( const std::vector& commits_in, const std::vector& neg_commits_in, int64_t excess ) { std::vector commits(commits_in.size()); - for( uint32_t i = 0; i < commits_in.size(); ++i ) commits[i] = (const unsigned char*)&commits_in[i]; + for( uint32_t i = 0; i < commits_in.size(); ++i ) commits[i] = commits_in[i].data(); std::vector neg_commits(neg_commits_in.size()); - for( uint32_t i = 0; i < neg_commits_in.size(); ++i ) neg_commits[i] = (const unsigned char*)&neg_commits_in[i]; + for( uint32_t i = 0; i < neg_commits_in.size(); ++i ) neg_commits[i] = neg_commits_in[i].data(); return secp256k1_pedersen_verify_tally( detail::_get_context(), commits.data(), commits.size(), neg_commits.data(), neg_commits.size(), excess ); } bool verify_range( uint64_t& min_val, uint64_t& max_val, const commitment_type& commit, const std::vector& proof ) { - return secp256k1_rangeproof_verify( detail::_get_context(), &min_val, &max_val, (const unsigned char*)&commit, (const unsigned char*)proof.data(), proof.size() ); + return secp256k1_rangeproof_verify( detail::_get_context(), &min_val, &max_val, commit.data(), (const unsigned char*)proof.data(), proof.size() ); } std::vector range_proof_sign( uint64_t min_value, @@ -245,12 +246,12 @@ namespace fc { namespace ecc { int proof_len = 5134; std::vector proof(proof_len); - FC_ASSERT( secp256k1_rangeproof_sign( detail::_get_context(), - (unsigned char*)proof.data(), - &proof_len, min_value, - (const unsigned char*)&commit, - (const unsigned char*)&commit_blind, - (const unsigned char*)&nonce, + FC_ASSERT( secp256k1_rangeproof_sign( detail::_get_context(), + (unsigned char*)proof.data(), + &proof_len, min_value, + commit.data(), + (unsigned char*) commit_blind.data(), + (unsigned char*) nonce.data(), base10_exp, min_bits, actual_value ) ); proof.resize(proof_len); return proof; @@ -269,14 +270,14 @@ namespace fc { namespace ecc { char msg[4096]; int mlen = 0; FC_ASSERT( secp256k1_rangeproof_rewind( detail::_get_context(), - (unsigned char*)&blind_out, + (unsigned char*) blind_out.data(), &value_out, - (unsigned char*)msg, + (unsigned char*) msg, &mlen, - (const unsigned char*)&nonce, + (unsigned char*) nonce.data(), &min_val, &max_val, - (const unsigned char*)&commit, + commit.data(), (const unsigned char*)proof.data(), proof.size() ) ); diff --git a/tests/crypto/ecc_test.cpp b/tests/crypto/ecc_test.cpp index df809ee..94028ae 100644 --- a/tests/crypto/ecc_test.cpp +++ b/tests/crypto/ecc_test.cpp @@ -23,7 +23,7 @@ static void interop_do(const char * const data, size_t len) { } static void interop_do(const fc::ecc::public_key_data &data) { - interop_do(data.begin(), data.size()); + interop_do((char*) data.begin(), data.size()); } static void interop_do(const fc::ecc::private_key_secret &data) { @@ -31,7 +31,7 @@ static void interop_do(const fc::ecc::private_key_secret &data) { } static void interop_do(const fc::ecc::public_key_point_data &data) { - interop_do(data.begin(), data.size()); + interop_do((char*) data.begin(), data.size()); } static void interop_do(const std::string &data) { diff --git a/tests/hmac_test.cpp b/tests/hmac_test.cpp index ea3e54b..82079be 100644 --- a/tests/hmac_test.cpp +++ b/tests/hmac_test.cpp @@ -1,12 +1,13 @@ #define BOOST_TEST_MODULE HmacTest #include -#include #include #include #include #include #include +#include + // See http://tools.ietf.org/html/rfc4231 static const std::string TEST1_KEY = "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"; @@ -77,9 +78,9 @@ static void run_test( const std::string& key, const std::string& data, const std const std::string& expect_256, const std::string& expect_512 ) { - fc::array key_arr; + std::array key_arr; BOOST_CHECK_EQUAL( fc::from_hex( key, key_arr.begin(), key_arr.size() ), N ); - fc::array data_arr; + std::array data_arr; BOOST_CHECK_EQUAL( fc::from_hex( data, data_arr.begin(), data_arr.size() ), M ); BOOST_CHECK_EQUAL( mac_224.digest( key_arr.begin(), N, data_arr.begin(), M ).str(), expect_224 ); From a8337ecc426b70b336298f10c528429636a98fe0 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Fri, 31 May 2019 22:09:06 +0200 Subject: [PATCH 009/110] Added constexpr where applicable --- include/fc/bloom_filter.hpp | 2 +- include/fc/crypto/ripemd160.hpp | 2 +- include/fc/crypto/sha1.hpp | 2 +- include/fc/crypto/sha224.hpp | 2 +- include/fc/crypto/sha256.hpp | 2 +- include/fc/crypto/sha512.hpp | 2 +- include/fc/safe.hpp | 6 ++--- include/fc/static_variant.hpp | 45 +++++++++++++++------------------ 8 files changed, 29 insertions(+), 34 deletions(-) diff --git a/include/fc/bloom_filter.hpp b/include/fc/bloom_filter.hpp index a52f2da..940dfbd 100644 --- a/include/fc/bloom_filter.hpp +++ b/include/fc/bloom_filter.hpp @@ -31,7 +31,7 @@ namespace fc { -static const std::size_t bits_per_char = 0x08; // 8 bits in 1 char(unsigned) +static constexpr std::size_t bits_per_char = 0x08; // 8 bits in 1 char(unsigned) static const unsigned char bit_mask[bits_per_char] = { 0x01, //00000001 0x02, //00000010 diff --git a/include/fc/crypto/ripemd160.hpp b/include/fc/crypto/ripemd160.hpp index 58d8b18..faea983 100644 --- a/include/fc/crypto/ripemd160.hpp +++ b/include/fc/crypto/ripemd160.hpp @@ -18,7 +18,7 @@ class ripemd160 explicit operator string()const; char* data()const; - size_t data_size()const { return 160/8; } + constexpr size_t data_size()const { return 160/8; } static ripemd160 hash( const fc::sha512& h ); static ripemd160 hash( const fc::sha256& h ); diff --git a/include/fc/crypto/sha1.hpp b/include/fc/crypto/sha1.hpp index 737eecf..68fe77d 100644 --- a/include/fc/crypto/sha1.hpp +++ b/include/fc/crypto/sha1.hpp @@ -17,7 +17,7 @@ class sha1 operator std::string()const; char* data()const; - size_t data_size()const { return 20; } + constexpr size_t data_size()const { return 20; } static sha1 hash( const char* d, uint32_t dlen ); static sha1 hash( const std::string& ); diff --git a/include/fc/crypto/sha224.hpp b/include/fc/crypto/sha224.hpp index 772e9f6..923c623 100644 --- a/include/fc/crypto/sha224.hpp +++ b/include/fc/crypto/sha224.hpp @@ -16,7 +16,7 @@ class sha224 operator string()const; char* data()const; - size_t data_size()const { return 224 / 8; } + constexpr size_t data_size()const { return 224 / 8; } static sha224 hash( const char* d, uint32_t dlen ); static sha224 hash( const string& ); diff --git a/include/fc/crypto/sha256.hpp b/include/fc/crypto/sha256.hpp index a382ad0..dcc6159 100644 --- a/include/fc/crypto/sha256.hpp +++ b/include/fc/crypto/sha256.hpp @@ -18,7 +18,7 @@ class sha256 operator string()const; char* data()const; - size_t data_size()const { return 256 / 8; } + constexpr size_t data_size()const { return 256 / 8; } static sha256 hash( const char* d, uint32_t dlen ); static sha256 hash( const string& ); diff --git a/include/fc/crypto/sha512.hpp b/include/fc/crypto/sha512.hpp index adb078c..0eb5715 100644 --- a/include/fc/crypto/sha512.hpp +++ b/include/fc/crypto/sha512.hpp @@ -16,7 +16,7 @@ class sha512 operator std::string()const; char* data()const; - size_t data_size()const { return 512 / 8; } + constexpr size_t data_size()const { return 512 / 8; } static sha512 hash( const char* d, uint32_t dlen ); static sha512 hash( const std::string& ); diff --git a/include/fc/safe.hpp b/include/fc/safe.hpp index d7c8514..42ab676 100644 --- a/include/fc/safe.hpp +++ b/include/fc/safe.hpp @@ -26,11 +26,11 @@ namespace fc { safe(){} safe( const safe& o ):value(o.value){} - static safe min() + static constexpr safe min() { return std::numeric_limits::min(); } - static safe max() + static constexpr safe max() { return std::numeric_limits::max(); } @@ -91,7 +91,7 @@ namespace fc { safe operator - ()const { - if( value == std::numeric_limits::min() ) FC_CAPTURE_AND_THROW( overflow_exception, (*this) ); + if( value == min() ) FC_CAPTURE_AND_THROW( overflow_exception, (*this) ); return safe( -value ); } diff --git a/include/fc/static_variant.hpp b/include/fc/static_variant.hpp index 5451168..59e6213 100644 --- a/include/fc/static_variant.hpp +++ b/include/fc/static_variant.hpp @@ -141,58 +141,53 @@ struct storage_ops { template struct position { - static const int pos = -1; + static constexpr int pos = -1; }; template struct position { - static const int pos = 0; + static constexpr int pos = 0; }; template struct position { - static const int pos = position::pos != -1 ? position::pos + 1 : -1; + static constexpr int pos = position::pos != -1 ? position::pos + 1 : -1; }; template struct type_info { - static const bool no_reference_types = false; - static const bool no_duplicates = position::pos == -1 && type_info::no_duplicates; - static const size_t size = type_info::size > sizeof(T&) ? type_info::size : sizeof(T&); - static const size_t count = 1 + type_info::count; + static constexpr bool no_reference_types = false; + static constexpr bool no_duplicates = position::pos == -1 && type_info::no_duplicates; + static constexpr size_t size = type_info::size > sizeof(T&) ? type_info::size : sizeof(T&); + static constexpr size_t count = 1 + type_info::count; }; template struct type_info { - static const bool no_reference_types = type_info::no_reference_types; - static const bool no_duplicates = position::pos == -1 && type_info::no_duplicates; - static const size_t size = type_info::size > sizeof(T) ? type_info::size : sizeof(T&); - static const size_t count = 1 + type_info::count; + static constexpr bool no_reference_types = type_info::no_reference_types; + static constexpr bool no_duplicates = position::pos == -1 && type_info::no_duplicates; + static constexpr size_t size = type_info::size > sizeof(T) ? type_info::size : sizeof(T&); + static constexpr size_t count = 1 + type_info::count; }; template<> struct type_info<> { - static const bool no_reference_types = true; - static const bool no_duplicates = true; - static const size_t count = 0; - static const size_t size = 0; + static constexpr bool no_reference_types = true; + static constexpr bool no_duplicates = true; + static constexpr size_t count = 0; + static constexpr size_t size = 0; }; template -size_t size( TTag ) +constexpr size_t size( TTag ) { return 0; } template -size_t size( TTag tag ) +constexpr size_t size( TTag tag ) { - if (tag <= 0) - { - return sizeof(A); - } - - return size( --tag ); + return tag <= 0 ? sizeof(A) : size( --tag ); } @@ -304,7 +299,7 @@ public: template> struct tag { - static const int value = impl::position::pos; + static constexpr int value = impl::position::pos; }; static_variant() @@ -434,7 +429,7 @@ public: return wrappers[tag]( v, data ); } - static int count() { return impl::type_info::count; } + static constexpr int count() { return impl::type_info::count; } void set_which( tag_type w ) { FC_ASSERT( w >= 0 ); FC_ASSERT( w < count() ); From 0aac8a4afc15bce0aa75bd8a0882483eef03b4c1 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 3 Jun 2019 12:06:55 +0200 Subject: [PATCH 010/110] Replaced fc::forward with std::forward --- include/fc/exception/exception.hpp | 5 ++--- include/fc/fwd_impl.hpp | 14 +++++++------- include/fc/optional.hpp | 6 ++---- include/fc/thread/future.hpp | 8 ++++---- include/fc/thread/parallel.hpp | 2 +- include/fc/thread/task.hpp | 4 ++-- include/fc/thread/thread.hpp | 8 ++++---- include/fc/utility.hpp | 3 --- include/fc/variant.hpp | 2 +- include/fc/variant_object.hpp | 10 +++++----- 10 files changed, 28 insertions(+), 34 deletions(-) diff --git a/include/fc/exception/exception.hpp b/include/fc/exception/exception.hpp index 3d728ed..e5b54a4 100644 --- a/include/fc/exception/exception.hpp +++ b/include/fc/exception/exception.hpp @@ -5,7 +5,6 @@ */ #include #include -#include #include #include #include @@ -167,10 +166,10 @@ namespace fc { #if defined(_MSC_VER) && (_MSC_VER < 1700) return std::make_shared( log_message(), - std::copy_exception(fc::forward(e)) ); + std::copy_exception(std::forward(e)) ); #else return std::make_shared( log_message(), - std::make_exception_ptr(fc::forward(e)) ); + std::make_exception_ptr(std::forward(e)) ); #endif } diff --git a/include/fc/fwd_impl.hpp b/include/fc/fwd_impl.hpp index 53a4440..df2f0f8 100644 --- a/include/fc/fwd_impl.hpp +++ b/include/fc/fwd_impl.hpp @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include #include #include @@ -41,10 +41,10 @@ namespace fc { template - auto operator + ( const fwd& x, U&& u ) -> typename detail::add::type { return *x+fc::forward(u); } + auto operator + ( const fwd& x, U&& u ) -> typename detail::add::type { return *x+std::forward(u); } template - auto operator - ( const fwd& x, U&& u ) -> typename detail::sub::type { return *x-fc::forward(u); } + auto operator - ( const fwd& x, U&& u ) -> typename detail::sub::type { return *x-std::forward(u); } template auto operator << ( U& u, const fwd& f ) -> typename detail::insert_op::type { return u << *f; } @@ -63,20 +63,20 @@ namespace fc { template fwd::fwd( U&& u ) { check_size(); - new (this) T( fc::forward(u) ); + new (this) T( std::forward(u) ); } template template fwd::fwd( U&& u, V&& v ) { check_size(); - new (this) T( fc::forward(u), fc::forward(v) ); + new (this) T( std::forward(u), std::forward(v) ); } template template fwd::fwd( U&& u, V&& v, X&& x, Y&& y ) { check_size(); - new (this) T( fc::forward(u), fc::forward(v), fc::forward(x), fc::forward(y) ); + new (this) T( std::forward(u), std::forward(v), std::forward(x), std::forward(y) ); } @@ -121,7 +121,7 @@ namespace fc { template template T& fwd::operator = ( U&& u ) { - return **this = fc::forward(u); + return **this = std::forward(u); } template diff --git a/include/fc/optional.hpp b/include/fc/optional.hpp index ff6c789..04145b4 100644 --- a/include/fc/optional.hpp +++ b/include/fc/optional.hpp @@ -1,9 +1,7 @@ #pragma once -#include #include #include - namespace fc { #ifdef _MSC_VER # pragma warning(push) @@ -81,14 +79,14 @@ namespace fc { optional( U&& u ) :_valid(true) { - new ((char*)ptr()) T( fc::forward(u) ); + new ((char*)ptr()) T( std::forward(u) ); } template optional& operator=( U&& u ) { reset(); - new (ptr()) T( fc::forward(u) ); + new (ptr()) T( std::forward(u) ); _valid = true; return *this; } diff --git a/include/fc/thread/future.hpp b/include/fc/thread/future.hpp index 40dd62f..4e98c3d 100644 --- a/include/fc/thread/future.hpp +++ b/include/fc/thread/future.hpp @@ -146,7 +146,7 @@ namespace fc { template void on_complete( CompletionHandler&& c ) { - _on_complete( new detail::completion_handler_impl(fc::forward(c)) ); + _on_complete( new detail::completion_handler_impl(std::forward(c)) ); } protected: promise( const char* desc ):promise_base(desc){} @@ -184,7 +184,7 @@ namespace fc { template void on_complete( CompletionHandler&& c ) { - _on_complete( new detail::completion_handler_impl(fc::forward(c)) ); + _on_complete( new detail::completion_handler_impl(std::forward(c)) ); } protected: promise( const char* desc ):promise_base(desc){} @@ -273,7 +273,7 @@ namespace fc { */ template void on_complete( CompletionHandler&& c ) { - m_prom->on_complete( fc::forward(c) ); + m_prom->on_complete( std::forward(c) ); } private: friend class thread; @@ -334,7 +334,7 @@ namespace fc { template void on_complete( CompletionHandler&& c ) { - m_prom->on_complete( fc::forward(c) ); + m_prom->on_complete( std::forward(c) ); } private: diff --git a/include/fc/thread/parallel.hpp b/include/fc/thread/parallel.hpp index 433dfbf..a1eece5 100644 --- a/include/fc/thread/parallel.hpp +++ b/include/fc/thread/parallel.hpp @@ -98,7 +98,7 @@ namespace fc { typedef decltype(f()) Result; typedef typename fc::deduce::type FunctorType; typename task::ptr tsk = - task::create( fc::forward(f), desc ); + task::create( std::forward(f), desc ); tsk->retain(); // HERE BE DRAFONS fc::future r( std::dynamic_pointer_cast< promise >(tsk) ); detail::get_worker_pool().post( tsk.get() ); diff --git a/include/fc/thread/task.hpp b/include/fc/thread/task.hpp index e29cd14..db5bc66 100644 --- a/include/fc/thread/task.hpp +++ b/include/fc/thread/task.hpp @@ -129,7 +129,7 @@ namespace fc { task( Functor&& f, const char* desc ):promise_base(desc), task_base(&_functor), promise(desc) { typedef typename fc::deduce::type FunctorType; static_assert( sizeof(f) <= sizeof(_functor), "sizeof(Functor) is larger than FunctorSize" ); - new ((char*)&_functor) FunctorType( fc::forward(f) ); + new ((char*)&_functor) FunctorType( std::forward(f) ); _destroy_functor = &detail::functor_destructor::destroy; _promise_impl = static_cast*>(this); @@ -157,7 +157,7 @@ namespace fc { task( Functor&& f, const char* desc ):promise_base(desc), task_base(&_functor), promise(desc) { typedef typename fc::deduce::type FunctorType; static_assert( sizeof(f) <= sizeof(_functor), "sizeof(Functor) is larger than FunctorSize" ); - new ((char*)&_functor) FunctorType( fc::forward(f) ); + new ((char*)&_functor) FunctorType( std::forward(f) ); _destroy_functor = &detail::functor_destructor::destroy; _promise_impl = static_cast*>(this); diff --git a/include/fc/thread/thread.hpp b/include/fc/thread/thread.hpp index a01dc20..eb54959 100644 --- a/include/fc/thread/thread.hpp +++ b/include/fc/thread/thread.hpp @@ -88,7 +88,7 @@ namespace fc { typedef decltype(f()) Result; typedef typename fc::deduce::type FunctorType; typename task::ptr tsk = - task::create( fc::forward(f), desc ); + task::create( std::forward(f), desc ); tsk->retain(); // HERE BE DRAFONS fc::future r( std::dynamic_pointer_cast< promise >(tsk) ); async_task(tsk.get(),prio); @@ -111,7 +111,7 @@ namespace fc { const char* desc FC_TASK_NAME_DEFAULT_ARG, priority prio = priority()) -> fc::future { typedef decltype(f()) Result; typename task::ptr tsk = - task::create( fc::forward(f), desc ); + task::create( std::forward(f), desc ); tsk->retain(); // HERE BE DRAFONS fc::future r( std::dynamic_pointer_cast< promise >(tsk) ); async_task(tsk.get(),prio,when); @@ -225,11 +225,11 @@ namespace fc { template auto async( Functor&& f, const char* desc FC_TASK_NAME_DEFAULT_ARG, priority prio = priority()) -> fc::future { - return fc::thread::current().async( fc::forward(f), desc, prio ); + return fc::thread::current().async( std::forward(f), desc, prio ); } template auto schedule( Functor&& f, const fc::time_point& t, const char* desc FC_TASK_NAME_DEFAULT_ARG, priority prio = priority()) -> fc::future { - return fc::thread::current().schedule( fc::forward(f), t, desc, prio ); + return fc::thread::current().schedule( std::forward(f), t, desc, prio ); } /** diff --git a/include/fc/utility.hpp b/include/fc/utility.hpp index 0bc4d45..c08160c 100644 --- a/include/fc/utility.hpp +++ b/include/fc/utility.hpp @@ -25,9 +25,6 @@ namespace fc { template struct deduce { typedef T type; }; template struct deduce{ typedef T type; }; - template - inline T&& forward( U&& u ) { return static_cast(u); } - struct true_type { enum _value { value = 1 }; }; struct false_type { enum _value { value = 0 }; }; diff --git a/include/fc/variant.hpp b/include/fc/variant.hpp index 4da4f52..58e54ad 100644 --- a/include/fc/variant.hpp +++ b/include/fc/variant.hpp @@ -350,7 +350,7 @@ namespace fc template variant& operator=( T&& v ) { - return *this = variant( fc::forward(v) ); + return *this = variant( std::forward(v) ); } template diff --git a/include/fc/variant_object.hpp b/include/fc/variant_object.hpp index cebc31f..477c1c9 100644 --- a/include/fc/variant_object.hpp +++ b/include/fc/variant_object.hpp @@ -70,7 +70,7 @@ namespace fc variant_object( string key, T&& val ) :_key_value( std::make_shared >() ) { - *this = variant_object( std::move(key), variant(forward(val)) ); + *this = variant_object( std::move(key), variant(std::forward(val)) ); } variant_object( const variant_object& ); variant_object( variant_object&& ); @@ -173,7 +173,7 @@ namespace fc mutable_variant_object& operator()( string key, T&& var, uint32_t max_depth ) { _FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" ); - set( std::move(key), variant( fc::forward(var), max_depth - 1 ) ); + set( std::move(key), variant( std::forward(var), max_depth - 1 ) ); return *this; } /** @@ -191,7 +191,7 @@ namespace fc explicit mutable_variant_object( T&& v ) :_key_value( new std::vector() ) { - *this = variant(fc::forward(v)).get_object(); + *this = variant(std::forward(v)).get_object(); } mutable_variant_object(); @@ -202,7 +202,7 @@ namespace fc mutable_variant_object( string key, T&& val ) :_key_value( new std::vector() ) { - set( std::move(key), variant(forward(val)) ); + set( std::move(key), variant(std::forward(val)) ); } mutable_variant_object( mutable_variant_object&& ); @@ -232,7 +232,7 @@ namespace fc optional v; try { - v = variant( fc::forward(var), _max_depth ); + v = variant( std::forward(var), _max_depth ); } catch( ... ) { From 8ad041cea02ebe722d29aa82e887e9aa7a2591c1 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 3 Jun 2019 12:21:50 +0200 Subject: [PATCH 011/110] Replaced fc::deduce with std::remove_reference> --- include/fc/thread/parallel.hpp | 2 +- include/fc/thread/task.hpp | 5 +++-- include/fc/thread/thread.hpp | 2 +- include/fc/utility.hpp | 6 ------ 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/include/fc/thread/parallel.hpp b/include/fc/thread/parallel.hpp index a1eece5..6ad88c2 100644 --- a/include/fc/thread/parallel.hpp +++ b/include/fc/thread/parallel.hpp @@ -96,7 +96,7 @@ namespace fc { template auto do_parallel( Functor&& f, const char* desc FC_TASK_NAME_DEFAULT_ARG ) -> fc::future { typedef decltype(f()) Result; - typedef typename fc::deduce::type FunctorType; + typedef typename std::remove_const_t< std::remove_reference_t > FunctorType; typename task::ptr tsk = task::create( std::forward(f), desc ); tsk->retain(); // HERE BE DRAFONS diff --git a/include/fc/thread/task.hpp b/include/fc/thread/task.hpp index db5bc66..3da124d 100644 --- a/include/fc/thread/task.hpp +++ b/include/fc/thread/task.hpp @@ -2,6 +2,7 @@ #include #include #include +#include namespace fc { struct context; @@ -127,7 +128,7 @@ namespace fc { private: template task( Functor&& f, const char* desc ):promise_base(desc), task_base(&_functor), promise(desc) { - typedef typename fc::deduce::type FunctorType; + typedef typename std::remove_const_t< std::remove_reference_t > FunctorType; static_assert( sizeof(f) <= sizeof(_functor), "sizeof(Functor) is larger than FunctorSize" ); new ((char*)&_functor) FunctorType( std::forward(f) ); _destroy_functor = &detail::functor_destructor::destroy; @@ -155,7 +156,7 @@ namespace fc { private: template task( Functor&& f, const char* desc ):promise_base(desc), task_base(&_functor), promise(desc) { - typedef typename fc::deduce::type FunctorType; + typedef typename std::remove_const_t< std::remove_reference_t > FunctorType; static_assert( sizeof(f) <= sizeof(_functor), "sizeof(Functor) is larger than FunctorSize" ); new ((char*)&_functor) FunctorType( std::forward(f) ); _destroy_functor = &detail::functor_destructor::destroy; diff --git a/include/fc/thread/thread.hpp b/include/fc/thread/thread.hpp index eb54959..2e275e6 100644 --- a/include/fc/thread/thread.hpp +++ b/include/fc/thread/thread.hpp @@ -86,7 +86,7 @@ namespace fc { template auto async( Functor&& f, const char* desc FC_TASK_NAME_DEFAULT_ARG, priority prio = priority()) -> fc::future { typedef decltype(f()) Result; - typedef typename fc::deduce::type FunctorType; + typedef typename std::remove_const_t< std::remove_reference_t > FunctorType; typename task::ptr tsk = task::create( std::forward(f), desc ); tsk->retain(); // HERE BE DRAFONS diff --git a/include/fc/utility.hpp b/include/fc/utility.hpp index c08160c..7c7983c 100644 --- a/include/fc/utility.hpp +++ b/include/fc/utility.hpp @@ -19,12 +19,6 @@ namespace fc { using std::size_t; typedef decltype(nullptr) nullptr_t; - template struct deduce { typedef T type; }; - template struct deduce { typedef T type; }; - template struct deduce { typedef T type; }; - template struct deduce { typedef T type; }; - template struct deduce{ typedef T type; }; - struct true_type { enum _value { value = 1 }; }; struct false_type { enum _value { value = 0 }; }; From 1025c361539856bc5fe2bc6f3b1c7aa90d9b5ed9 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 3 Jun 2019 13:57:21 +0200 Subject: [PATCH 012/110] Replaced fc::nullptr_t with std::nullptr_t --- include/fc/log/logger.hpp | 5 +++-- include/fc/utility.hpp | 1 - include/fc/variant.hpp | 3 ++- src/log/logger.cpp | 2 +- src/variant.cpp | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/include/fc/log/logger.hpp b/include/fc/log/logger.hpp index 0d29eb8..2ddfebf 100644 --- a/include/fc/log/logger.hpp +++ b/include/fc/log/logger.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include namespace fc @@ -30,8 +31,8 @@ namespace fc ~logger(); logger& operator=(const logger&); logger& operator=(logger&&); - friend bool operator==( const logger&, nullptr_t ); - friend bool operator!=( const logger&, nullptr_t ); + friend bool operator==( const logger&, std::nullptr_t ); + friend bool operator!=( const logger&, std::nullptr_t ); logger& set_log_level( log_level e ); log_level get_log_level()const; diff --git a/include/fc/utility.hpp b/include/fc/utility.hpp index 7c7983c..ff3c604 100644 --- a/include/fc/utility.hpp +++ b/include/fc/utility.hpp @@ -17,7 +17,6 @@ namespace fc { using std::size_t; - typedef decltype(nullptr) nullptr_t; struct true_type { enum _value { value = 1 }; }; struct false_type { enum _value { value = 0 }; }; diff --git a/include/fc/variant.hpp b/include/fc/variant.hpp index 58e54ad..279b7de 100644 --- a/include/fc/variant.hpp +++ b/include/fc/variant.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -212,7 +213,7 @@ namespace fc /// Constructs a null_type variant variant(); /// Constructs a null_type variant - variant( nullptr_t, uint32_t max_depth = 1 ); + variant( std::nullptr_t, uint32_t max_depth = 1 ); /// @param str - UTF8 string variant( const char* str, uint32_t max_depth = 1 ); diff --git a/src/log/logger.cpp b/src/log/logger.cpp index b8743b9..019793b 100644 --- a/src/log/logger.cpp +++ b/src/log/logger.cpp @@ -28,7 +28,7 @@ namespace fc { logger::logger() :my( new impl() ){} - logger::logger(nullptr_t){} + logger::logger(std::nullptr_t){} logger::logger( const string& name, const logger& parent ) :my( new impl() ) diff --git a/src/variant.cpp b/src/variant.cpp index 026e2ab..d823f32 100644 --- a/src/variant.cpp +++ b/src/variant.cpp @@ -28,7 +28,7 @@ variant::variant() set_variant_type( this, null_type ); } -variant::variant( fc::nullptr_t, uint32_t max_depth ) +variant::variant( std::nullptr_t, uint32_t max_depth ) { set_variant_type( this, null_type ); } From f732a587d710150417c32b19586ce8881a80f4bd Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 3 Jun 2019 14:13:12 +0200 Subject: [PATCH 013/110] Replace NO_RETURN with [[noreturn]] standard attribute --- include/fc/exception/exception.hpp | 14 +++++++------- include/fc/io/datastream.hpp | 3 +-- include/fc/utility.hpp | 13 ------------- src/exception.cpp | 6 +++--- src/io/datastream.cpp | 2 +- 5 files changed, 12 insertions(+), 26 deletions(-) diff --git a/include/fc/exception/exception.hpp b/include/fc/exception/exception.hpp index e5b54a4..e61e92f 100644 --- a/include/fc/exception/exception.hpp +++ b/include/fc/exception/exception.hpp @@ -106,7 +106,7 @@ namespace fc * * @note does not return. */ - virtual NO_RETURN void dynamic_rethrow_exception()const; + [[noreturn]] virtual void dynamic_rethrow_exception()const; /** * This is equivalent to: @@ -155,7 +155,7 @@ namespace fc std::exception_ptr get_inner_exception()const; - virtual NO_RETURN void dynamic_rethrow_exception()const; + [[noreturn]] virtual void dynamic_rethrow_exception()const; virtual std::shared_ptr dynamic_copy_exception()const; private: std::exception_ptr _inner; @@ -179,13 +179,13 @@ namespace fc public: struct base_exception_builder { - virtual NO_RETURN void rethrow( const exception& e )const = 0; + [[noreturn]] virtual void rethrow( const exception& e )const = 0; }; template struct exception_builder : public base_exception_builder { - virtual NO_RETURN void rethrow( const exception& e )const override + [[noreturn]] virtual void rethrow( const exception& e )const override { throw T( e ); } @@ -201,7 +201,7 @@ namespace fc _registered_exceptions[T::code_value] = &builder; } - void NO_RETURN rethrow( const exception& e )const; + [[noreturn]] void rethrow( const exception& e )const; static exception_factory& instance() { @@ -243,7 +243,7 @@ namespace fc explicit TYPE();\ \ virtual std::shared_ptr dynamic_copy_exception()const;\ - virtual NO_RETURN void dynamic_rethrow_exception()const; \ + [[noreturn]] virtual void dynamic_rethrow_exception()const; \ }; #define FC_IMPLEMENT_DERIVED_EXCEPTION( TYPE, BASE, CODE, WHAT ) \ @@ -269,7 +269,7 @@ namespace fc { \ return std::make_shared( *this ); \ } \ - NO_RETURN void TYPE::dynamic_rethrow_exception()const \ + [[noreturn]] void TYPE::dynamic_rethrow_exception()const \ { \ if( code() == CODE ) throw *this;\ else fc::exception::dynamic_rethrow_exception(); \ diff --git a/include/fc/io/datastream.hpp b/include/fc/io/datastream.hpp index 0bf36a1..87b432e 100644 --- a/include/fc/io/datastream.hpp +++ b/include/fc/io/datastream.hpp @@ -1,5 +1,4 @@ #pragma once -#include #include #include @@ -7,7 +6,7 @@ namespace fc { namespace detail { - NO_RETURN void throw_datastream_range_error( const char* file, size_t len, int64_t over ); + [[noreturn]] void throw_datastream_range_error( const char* file, size_t len, int64_t over ); } /** diff --git a/include/fc/utility.hpp b/include/fc/utility.hpp index ff3c604..ce46946 100644 --- a/include/fc/utility.hpp +++ b/include/fc/utility.hpp @@ -2,19 +2,6 @@ #include #include -#ifdef _MSC_VER -#pragma warning(disable: 4482) // nonstandard extension used enum Name::Val, standard in C++11 -#define NO_RETURN __declspec(noreturn) -#else -#define NO_RETURN __attribute__((noreturn)) -#endif - - -//namespace std { -// typedef decltype(sizeof(int)) size_t; -// typedef decltype(nullptr) nullptr_t; -//} - namespace fc { using std::size_t; diff --git a/src/exception.cpp b/src/exception.cpp index 79b2135..d3fadbb 100644 --- a/src/exception.cpp +++ b/src/exception.cpp @@ -96,7 +96,7 @@ namespace fc std::exception_ptr unhandled_exception::get_inner_exception()const { return _inner; } - NO_RETURN void unhandled_exception::dynamic_rethrow_exception()const + [[noreturn]] void unhandled_exception::dynamic_rethrow_exception()const { if( !(_inner == std::exception_ptr()) ) std::rethrow_exception( _inner ); else { fc::exception::dynamic_rethrow_exception(); } @@ -217,7 +217,7 @@ namespace fc return ss.str(); } - void NO_RETURN exception_factory::rethrow( const exception& e )const + [[noreturn]] void exception_factory::rethrow( const exception& e )const { auto itr = _registered_exceptions.find( e.code() ); if( itr != _registered_exceptions.end() ) @@ -229,7 +229,7 @@ namespace fc * the error code. This is used to propagate exception types * across conversions to/from JSON */ - NO_RETURN void exception::dynamic_rethrow_exception()const + [[noreturn]] void exception::dynamic_rethrow_exception()const { exception_factory::instance().rethrow( *this ); } diff --git a/src/io/datastream.cpp b/src/io/datastream.cpp index 69fda0d..5ece65f 100644 --- a/src/io/datastream.cpp +++ b/src/io/datastream.cpp @@ -1,7 +1,7 @@ #include #include -NO_RETURN void fc::detail::throw_datastream_range_error(char const* method, size_t len, int64_t over) +[[noreturn]] void fc::detail::throw_datastream_range_error(char const* method, size_t len, int64_t over) { FC_THROW_EXCEPTION( out_of_range_exception, "${method} datastream of length ${len} over by ${over}", ("method",std::string(method))("len",len)("over",over) ); } From a11a50d4e11797c2a37bfb9b07c3eef522cf561d Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 3 Jun 2019 18:33:39 +0200 Subject: [PATCH 014/110] Replaced true_type, false_type, is_class, is_enum with std type_traits --- include/fc/io/raw.hpp | 74 +++++++++++++++++++++++++--------- include/fc/reflect/reflect.hpp | 16 +++----- include/fc/reflect/variant.hpp | 18 ++++----- include/fc/utility.hpp | 18 --------- 4 files changed, 68 insertions(+), 58 deletions(-) delete mode 100644 include/fc/utility.hpp diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index 4b46086..2369d6c 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -358,17 +358,21 @@ namespace fc { const uint32_t max_depth; }; - // Default pack/unpack functions for classes (if_class) are removed due to recursion issue. + // Default pack/unpack functions for classes are removed due to recursion issue. // Classes should implement pack/unpack functions explicitly. - template + template struct if_class; - template<> - struct if_class { - template + template + struct if_class::value>> { + template static inline void pack( Stream& s, const T v, uint32_t _max_depth ) = delete; - template + template static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) = delete; + }; + + template<> + struct if_class { template static inline void pack( Stream& s, const int64_t v, uint32_t _max_depth ) { boost::endian::little_int64_buf_t tmp; @@ -381,6 +385,10 @@ namespace fc { s.read( (char*)&tmp, sizeof(tmp) ); v = tmp.value(); } + }; + + template<> + struct if_class { template static inline void pack( Stream& s, const uint64_t v, uint32_t _max_depth ) { boost::endian::little_uint64_buf_t tmp; @@ -393,6 +401,10 @@ namespace fc { s.read( (char*)&tmp, sizeof(tmp) ); v = tmp.value(); } + }; + + template<> + struct if_class { template static inline void pack( Stream& s, const int32_t v, uint32_t _max_depth ) { boost::endian::little_int32_buf_t tmp; @@ -405,6 +417,10 @@ namespace fc { s.read( (char*)&tmp, sizeof(tmp) ); v = tmp.value(); } + }; + + template<> + struct if_class { template static inline void pack( Stream& s, const uint32_t v, uint32_t _max_depth ) { boost::endian::little_uint32_buf_t tmp; @@ -417,6 +433,10 @@ namespace fc { s.read( (char*)&tmp, sizeof(tmp) ); v = tmp.value(); } + }; + + template<> + struct if_class { template static inline void pack( Stream& s, const int16_t v, uint32_t _max_depth ) { boost::endian::little_int16_buf_t tmp; @@ -429,6 +449,10 @@ namespace fc { s.read( (char*)&tmp, sizeof(tmp) ); v = tmp.value(); } + }; + + template<> + struct if_class { template static inline void pack( Stream& s, const uint16_t v, uint32_t _max_depth ) { boost::endian::little_uint16_buf_t tmp; @@ -441,6 +465,10 @@ namespace fc { s.read( (char*)&tmp, sizeof(tmp) ); v = tmp.value(); } + }; + + template<> + struct if_class { template static inline void pack( Stream& s, const int8_t v, uint32_t _max_depth ) { s.write( (char*)&v, 1 ); @@ -449,6 +477,10 @@ namespace fc { static inline void unpack( Stream& s, int8_t& v, uint32_t _max_depth ) { s.read( (char*)&v, 1 ); } + }; + + template<> + struct if_class { template static inline void pack( Stream& s, const uint8_t v, uint32_t _max_depth ) { s.write( (char*)&v, 1 ); @@ -459,27 +491,29 @@ namespace fc { } }; - template - struct if_enum { - template + template + struct if_enum; + template + struct if_enum::value>> { + template 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 + template 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 + template + struct if_enum::value>> { + template 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 + template static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); int64_t temp; @@ -488,30 +522,30 @@ namespace fc { } }; - template + template struct if_reflected { template 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 ); + if_class::pack( s, v, _max_depth - 1 ); } template 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 ); + if_class::unpack( s, v, _max_depth - 1 ); } }; template<> - struct if_reflected { + struct if_reflected { template 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 ); + if_enum::pack( s, v, _max_depth - 1 ); } template 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 ); + if_enum::unpack( s, v, _max_depth - 1 ); } }; diff --git a/include/fc/reflect/reflect.hpp b/include/fc/reflect/reflect.hpp index a5122d9..3bf0ef7 100644 --- a/include/fc/reflect/reflect.hpp +++ b/include/fc/reflect/reflect.hpp @@ -7,7 +7,6 @@ */ #include -#include #include #include #include @@ -16,6 +15,7 @@ #include #include #include +#include #include @@ -33,8 +33,7 @@ namespace fc { template struct reflector{ typedef T type; - typedef fc::false_type is_defined; - typedef fc::false_type is_enum; + typedef std::false_type is_defined; /** * @tparam Visitor a function object of the form: @@ -137,8 +136,7 @@ void fc::reflector::visit( const Visitor& v ) { \ #define FC_REFLECT_ENUM( ENUM, FIELDS ) \ namespace fc { \ template<> struct reflector { \ - typedef fc::true_type is_defined; \ - typedef fc::true_type is_enum; \ + typedef std::true_type is_defined; \ static const char* to_string(ENUM elem) { \ switch( elem ) { \ BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_ENUM_TO_STRING, ENUM, FIELDS ) \ @@ -215,8 +213,7 @@ namespace fc { \ template<> struct get_typename { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \ template<> struct reflector {\ typedef TYPE type; \ - typedef fc::true_type is_defined; \ - typedef fc::false_type is_enum; \ + typedef std::true_type is_defined; \ enum member_count_enum { \ local_member_count = 0 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_MEMBER_COUNT, +, MEMBERS ),\ total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\ @@ -228,8 +225,7 @@ namespace fc { \ template struct get_typename { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \ template struct reflector {\ typedef TYPE type; \ - typedef fc::true_type is_defined; \ - typedef fc::false_type is_enum; \ + typedef std::true_type is_defined; \ enum member_count_enum { \ local_member_count = 0 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_MEMBER_COUNT, +, MEMBERS ),\ total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\ @@ -266,7 +262,7 @@ namespace fc { \ template<> struct get_typename { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \ template<> struct reflector {\ typedef TYPE type; \ - typedef fc::true_type is_defined; \ + typedef std::true_type is_defined; \ enum member_count_enum { \ local_member_count = BOOST_PP_SEQ_SIZE(MEMBERS), \ total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\ diff --git a/include/fc/reflect/variant.hpp b/include/fc/reflect/variant.hpp index b47de30..8f88dc9 100644 --- a/include/fc/reflect/variant.hpp +++ b/include/fc/reflect/variant.hpp @@ -63,17 +63,17 @@ namespace fc const uint32_t _max_depth; }; - template - struct if_enum + template + struct if_enum; + template + struct if_enum::value>> { - template static inline void to_variant( const T& v, fc::variant& vo, uint32_t max_depth ) { mutable_variant_object mvo; fc::reflector::visit( to_variant_visitor( mvo, v, max_depth ) ); vo = std::move(mvo); } - template static inline void from_variant( const fc::variant& v, T& o, uint32_t max_depth ) { const variant_object& vo = v.get_object(); @@ -81,15 +81,13 @@ namespace fc } }; - template<> - struct if_enum + template + struct if_enum::value>> { - template static inline void to_variant( const T& o, fc::variant& v, uint32_t max_depth = 1 ) { v = fc::reflector::to_fc_string(o); } - template static inline void from_variant( const fc::variant& v, T& o, uint32_t max_depth = 1 ) { if( v.is_string() ) @@ -103,12 +101,12 @@ namespace fc template void to_variant( const T& o, variant& v, uint32_t max_depth ) { - if_enum::is_enum>::to_variant( o, v, max_depth ); + if_enum::to_variant( o, v, max_depth ); } template void from_variant( const variant& v, T& o, uint32_t max_depth ) { - if_enum::is_enum>::from_variant( v, o, max_depth ); + if_enum::from_variant( v, o, max_depth ); } } diff --git a/include/fc/utility.hpp b/include/fc/utility.hpp deleted file mode 100644 index ce46946..0000000 --- a/include/fc/utility.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include -#include - -namespace fc { - using std::size_t; - - struct true_type { enum _value { value = 1 }; }; - struct false_type { enum _value { value = 0 }; }; - - namespace detail { - template fc::true_type is_class_helper(void(T::*)()); - template fc::false_type is_class_helper(...); - } - - template - struct is_class { typedef decltype(detail::is_class_helper(0)) type; enum value_enum { value = type::value }; }; -} From 8196eb98c82b9b374d0243bcbe1217398b5200e9 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Thu, 6 Jun 2019 14:36:43 +0200 Subject: [PATCH 015/110] Added fc::int128_t --- include/fc/uint128.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/fc/uint128.hpp b/include/fc/uint128.hpp index 58b8251..fa9ae07 100644 --- a/include/fc/uint128.hpp +++ b/include/fc/uint128.hpp @@ -28,6 +28,7 @@ namespace fc { +using boost::multiprecision::int128_t; using boost::multiprecision::uint128_t; } // namespace fc From 7649f1f47d19657da32c48208aa22c3c02fc5d8f Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Thu, 6 Jun 2019 14:54:48 +0200 Subject: [PATCH 016/110] Removed broken http_server + unused http_api --- CMakeLists.txt | 2 - include/fc/network/http/server.hpp | 61 --------- include/fc/rpc/http_api.hpp | 35 ----- src/network/http/http_server.cpp | 207 ----------------------------- src/rpc/http_api.cpp | 141 -------------------- 5 files changed, 446 deletions(-) delete mode 100644 include/fc/network/http/server.hpp delete mode 100644 include/fc/rpc/http_api.hpp delete mode 100644 src/network/http/http_server.cpp delete mode 100644 src/rpc/http_api.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 50c70f2..9769e66 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,7 +224,6 @@ set( fc_sources src/interprocess/signals.cpp src/interprocess/file_mapping.cpp src/rpc/cli.cpp - src/rpc/http_api.cpp src/rpc/state.cpp src/rpc/websocket_api.cpp src/log/log_message.cpp @@ -256,7 +255,6 @@ set( fc_sources src/network/tcp_socket.cpp src/network/udp_socket.cpp src/network/http/http_connection.cpp - src/network/http/http_server.cpp src/network/http/websocket.cpp src/network/ip.cpp src/network/rate_limiting.cpp diff --git a/include/fc/network/http/server.hpp b/include/fc/network/http/server.hpp deleted file mode 100644 index a7dc3a3..0000000 --- a/include/fc/network/http/server.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once -#include -#include -#include - -namespace fc { namespace http { - - /** - * Listens on a given port for incomming http - * connections and then calls a user provided callback - * function for every http request. - * - */ - class server - { - public: - server(); - server( uint16_t port ); - server( server&& s ); - ~server(); - - server& operator=(server&& s); - - class response - { - public: - class impl; - - response(); - response( const std::shared_ptr& my); - response( const response& r); - response( response&& r ); - ~response(); - response& operator=(const response& ); - response& operator=( response&& ); - - void add_header( const std::string& key, const std::string& val )const; - void set_status( const http::reply::status_code& s )const; - void set_length( uint64_t s )const; - - void write( const char* data, uint64_t len )const; - - private: - std::shared_ptr my; - }; - - void listen( const fc::ip::endpoint& p ); - fc::ip::endpoint get_local_endpoint() const; - - /** - * Set the callback to be called for every http request made. - */ - void on_request( const std::function& cb ); - - private: - class impl; - std::unique_ptr my; - }; - typedef std::shared_ptr server_ptr; - -} } diff --git a/include/fc/rpc/http_api.hpp b/include/fc/rpc/http_api.hpp deleted file mode 100644 index a693655..0000000 --- a/include/fc/rpc/http_api.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include - -namespace fc { namespace rpc { - - class http_api_connection : public api_connection - { - public: - http_api_connection(uint32_t max_conversion_depth); - ~http_api_connection(); - - virtual variant send_call( - api_id_type api_id, - string method_name, - variants args = variants() ) override; - virtual variant send_callback( - uint64_t callback_id, - variants args = variants() ) override; - virtual void send_notice( - uint64_t callback_id, - variants args = variants() ) override; - - void on_request( - const fc::http::request& req, - const fc::http::server::response& resp ); - - fc::rpc::state _rpc_state; - }; - -} } // namespace fc::rpc diff --git a/src/network/http/http_server.cpp b/src/network/http/http_server.cpp deleted file mode 100644 index af06c6f..0000000 --- a/src/network/http/http_server.cpp +++ /dev/null @@ -1,207 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - - -namespace fc { namespace http { - - class server::response::impl - { - public: - impl( const fc::http::connection_ptr& c, const std::function& cont = std::function() ) - :body_bytes_sent(0),body_length(0),con(c),handle_next_req(cont) - {} - - void send_header() { - //ilog( "sending header..." ); - fc::stringstream ss; - ss << "HTTP/1.1 " << rep.status << " "; - switch( rep.status ) { - case fc::http::reply::OK: ss << "OK\r\n"; break; - case fc::http::reply::RecordCreated: ss << "Record Created\r\n"; break; - case fc::http::reply::NotFound: ss << "Not Found\r\n"; break; - case fc::http::reply::Found: ss << "Found\r\n"; break; - default: ss << "Internal Server Error\r\n"; break; - } - for( uint32_t i = 0; i < rep.headers.size(); ++i ) { - ss << rep.headers[i].key <<": "<get_socket().write( s.c_str(), s.size() ); - } - - http::reply rep; - int64_t body_bytes_sent; - uint64_t body_length; - http::connection_ptr con; - std::function handle_next_req; - }; - - - class server::impl - { - public: - impl(){} - - impl(const fc::ip::endpoint& p ) - { - tcp_serv.set_reuse_address(); - tcp_serv.listen(p); - accept_complete = fc::async([this](){ this->accept_loop(); }, "http_server accept_loop"); - } - - ~impl() - { - try - { - tcp_serv.close(); - if (accept_complete.valid()) - accept_complete.wait(); - } - catch (...) - { - } - - for (fc::future& request_in_progress : requests_in_progress) - { - try - { - request_in_progress.cancel_and_wait(); - } - catch (const fc::exception& e) - { - wlog("Caught exception while canceling http request task: ${error}", ("error", e)); - } - catch (const std::exception& e) - { - wlog("Caught exception while canceling http request task: ${error}", ("error", e.what())); - } - catch (...) - { - wlog("Caught unknown exception while canceling http request task"); - } - } - requests_in_progress.clear(); - } - - void accept_loop() - { - while( !accept_complete.canceled() ) - { - http::connection_ptr con = std::make_shared(); - tcp_serv.accept( con->get_socket() ); - //ilog( "Accept Connection" ); - // clean up futures for any completed requests - for (auto iter = requests_in_progress.begin(); iter != requests_in_progress.end();) - if (!iter->valid() || iter->ready()) - iter = requests_in_progress.erase(iter); - else - ++iter; - requests_in_progress.emplace_back(fc::async([=](){ handle_connection(con, on_req); }, "http_server handle_connection")); - } - } - - void handle_connection( const http::connection_ptr& c, - std::function do_on_req ) - { - try - { - http::server::response rep( std::shared_ptr( new response::impl(c) ) ); - request req = c->read_request(); - if( do_on_req ) - do_on_req( req, rep ); - c->get_socket().close(); - } - catch ( fc::exception& e ) - { - wlog( "unable to read request ${1}", ("1", e.to_detail_string() ) );//fc::except_str().c_str()); - } - //wlog( "done handle connection" ); - } - - fc::future accept_complete; - std::function on_req; - std::vector > requests_in_progress; - fc::tcp_server tcp_serv; - }; - - - - server::server():my( new impl() ){} - server::server( uint16_t port ) :my( new impl(fc::ip::endpoint( fc::ip::address(),port)) ){} - server::server( server&& s ):my(std::move(s.my)){} - - server& server::operator=(server&& s) { std::swap(my,s.my); return *this; } - - server::~server(){} - - void server::listen( const fc::ip::endpoint& p ) - { - my.reset( new impl(p) ); - } - - fc::ip::endpoint server::get_local_endpoint() const - { - return my->tcp_serv.get_local_endpoint(); - } - - - server::response::response(){} - server::response::response( const server::response& s ):my(s.my){} - server::response::response( server::response&& s ):my(std::move(s.my)){} - server::response::response( const std::shared_ptr& m ):my(m){} - - server::response& server::response::operator=(const server::response& s) { my = s.my; return *this; } - server::response& server::response::operator=(server::response&& s) { std::swap(my,s.my); return *this; } - - void server::response::add_header( const std::string& key, const std::string& val )const { - my->rep.headers.push_back( fc::http::header( key, val ) ); - } - void server::response::set_status( const http::reply::status_code& s )const { - if( my->body_bytes_sent != 0 ) { - wlog( "Attempt to set status after sending headers" ); - } - my->rep.status = s; - } - void server::response::set_length( uint64_t s )const { - if( my->body_bytes_sent != 0 ) { - wlog( "Attempt to set length after sending headers" ); - } - my->body_length = s; - } - void server::response::write( const char* data, uint64_t len )const { - if( my->body_bytes_sent + len > my->body_length ) { - wlog( "Attempt to send to many bytes.." ); - len = my->body_bytes_sent + len - my->body_length; - } - if( my->body_bytes_sent == 0 ) { - my->send_header(); - } - my->body_bytes_sent += len; - my->con->get_socket().write( data, static_cast(len) ); - if( my->body_bytes_sent == int64_t(my->body_length) ) { - if( false || my->handle_next_req ) { - ilog( "handle next request..." ); - //fc::async( std::function(my->handle_next_req) ); - fc::async( my->handle_next_req, "http_server handle_next_req" ); - } - } - } - - server::response::~response(){} - - void server::on_request( const std::function& cb ) - { - my->on_req = cb; - } - - - - -} } diff --git a/src/rpc/http_api.cpp b/src/rpc/http_api.cpp deleted file mode 100644 index b8a299a..0000000 --- a/src/rpc/http_api.cpp +++ /dev/null @@ -1,141 +0,0 @@ - -#include - -namespace fc { namespace rpc { - -http_api_connection::~http_api_connection() -{ -} - -http_api_connection::http_api_connection(uint32_t max_depth) -:api_connection(max_depth) -{ - _rpc_state.add_method( "call", [this]( const variants& args ) -> variant - { - // TODO: This logic is duplicated between http_api_connection and websocket_api_connection - // it should be consolidated into one place instead of copy-pasted - FC_ASSERT( args.size() == 3 && args[2].is_array() ); - api_id_type api_id; - if( args[0].is_string() ) - { - variant subresult = this->receive_call( 1, args[0].as_string() ); - api_id = subresult.as_uint64(); - } - else - api_id = args[0].as_uint64(); - - return this->receive_call( - api_id, - args[1].as_string(), - args[2].get_array() ); - } ); - - _rpc_state.add_method( "notice", [this]( const variants& args ) -> variant - { - FC_ASSERT( args.size() == 2 && args[1].is_array() ); - this->receive_notice( - args[0].as_uint64(), - args[1].get_array() ); - return variant(); - } ); - - _rpc_state.add_method( "callback", [this]( const variants& args ) -> variant - { - FC_ASSERT( args.size() == 2 && args[1].is_array() ); - this->receive_callback( - args[0].as_uint64(), - args[1].get_array() ); - return variant(); - } ); - - _rpc_state.on_unhandled( [&]( const std::string& method_name, const variants& args ) - { - return this->receive_call( 0, method_name, args ); - } ); -} - -variant http_api_connection::send_call( - api_id_type api_id, - string method_name, - variants args /* = variants() */ ) -{ - // HTTP has no way to do this, so do nothing - return variant(); -} - -variant http_api_connection::send_callback( - uint64_t callback_id, - variants args /* = variants() */ ) -{ - // HTTP has no way to do this, so do nothing - return variant(); -} - -void http_api_connection::send_notice( - uint64_t callback_id, - variants args /* = variants() */ ) -{ - // HTTP has no way to do this, so do nothing - return; -} - -void http_api_connection::on_request( const fc::http::request& req, const fc::http::server::response& resp ) -{ - // this must be called by outside HTTP server's on_request method - std::string resp_body; - http::reply::status_code resp_status; - - try - { - resp.add_header( "Content-Type", "application/json" ); - std::string req_body( req.body.begin(), req.body.end() ); - auto var = fc::json::from_string( req_body, fc::json::legacy_parser, _max_conversion_depth ); - const auto& var_obj = var.get_object(); - - if( var_obj.contains( "method" ) ) - { - auto call = var.as(_max_conversion_depth); - try - { - try - { - fc::variant result( _rpc_state.local_call( call.method, call.params ), _max_conversion_depth ); - resp_body = fc::json::to_string( fc::variant( fc::rpc::response( *call.id, result ), _max_conversion_depth), - fc::json::stringify_large_ints_and_doubles, _max_conversion_depth ); - resp_status = http::reply::OK; - } - FC_CAPTURE_AND_RETHROW( (call.method)(call.params) ); - } - catch ( const fc::exception& e ) - { - resp_body = fc::json::to_string( fc::variant( fc::rpc::response( *call.id, error_object{ 1, e.to_detail_string(), fc::variant(e, _max_conversion_depth)} ), _max_conversion_depth), - fc::json::stringify_large_ints_and_doubles, _max_conversion_depth ); - resp_status = http::reply::InternalServerError; - } - } - else - { - resp_status = http::reply::BadRequest; - resp_body = ""; - } - } - catch ( const fc::exception& e ) - { - resp_status = http::reply::InternalServerError; - resp_body = ""; - wdump((e.to_detail_string())); - } - try - { - resp.set_status( resp_status ); - resp.set_length( resp_body.length() ); - resp.write( resp_body.c_str(), resp_body.length() ); - } - catch( const fc::exception& e ) - { - wdump((e.to_detail_string())); - } - return; -} - -} } // namespace fc::rpc From 79b2a0d634a9c8d51d00e2c4b9462b3b4529e108 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sat, 8 Jun 2019 10:25:52 +0200 Subject: [PATCH 017/110] Add support for native 128bit types --- CMakeLists.txt | 7 ++++++- include/fc/uint128.hpp | 15 +++++++++++++++ src/crypto/city.cpp | 1 + src/variant.cpp | 4 ++-- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9769e66..fd83397 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,12 @@ CMAKE_MINIMUM_REQUIRED( VERSION 3.1 ) set( CMAKE_CXX_STANDARD 14 ) SET( CMAKE_CXX_STANDARD_REQUIRED ON ) -set( CMAKE_CXX_EXTENSIONS OFF ) + +if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" ) + set( CMAKE_CXX_EXTENSIONS ON ) # for __int128 support +else( GNU ) + set( CMAKE_CXX_EXTENSIONS OFF ) +endif( GNU ) MESSAGE(STATUS "Configuring project fc located in: ${CMAKE_CURRENT_SOURCE_DIR}") SET( CMAKE_AUTOMOC OFF ) diff --git a/include/fc/uint128.hpp b/include/fc/uint128.hpp index fa9ae07..741676e 100644 --- a/include/fc/uint128.hpp +++ b/include/fc/uint128.hpp @@ -24,6 +24,19 @@ #pragma once +#ifdef __SIZEOF_INT128__ + +#include + +namespace fc { + +using int128_t = __int128_t; +using uint128_t = __uint128_t; + +} // namespace fc + +#else // __SIZEOF_INT128__ + #include namespace fc { @@ -32,3 +45,5 @@ using boost::multiprecision::int128_t; using boost::multiprecision::uint128_t; } // namespace fc + +#endif // __SIZEOF_INT128__ diff --git a/src/crypto/city.cpp b/src/crypto/city.cpp index 5649dd6..ef5469d 100644 --- a/src/crypto/city.cpp +++ b/src/crypto/city.cpp @@ -31,6 +31,7 @@ //#include #include +#include #include // for memcpy and memset #include #include diff --git a/src/variant.cpp b/src/variant.cpp index d823f32..a472ddf 100644 --- a/src/variant.cpp +++ b/src/variant.cpp @@ -675,12 +675,12 @@ void from_variant( const variant& var, std::vector& vo, uint32_t max_depth void to_variant( const uint128_t& var, variant& vo, uint32_t max_depth ) { - vo = var.str(); + vo = boost::lexical_cast( var ); } void from_variant( const variant& var, uint128_t& vo, uint32_t max_depth ) { - vo = uint128_t( var.as_string() ); + vo = boost::lexical_cast( var.as_string() ); } #ifdef __APPLE__ From 40797b1026c69fd1a463a0712a29e5a2913da940 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 10 Jun 2019 18:52:46 +0200 Subject: [PATCH 018/110] Fixed typo --- include/fc/thread/parallel.hpp | 2 +- include/fc/thread/thread.hpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/fc/thread/parallel.hpp b/include/fc/thread/parallel.hpp index 6ad88c2..14d4bbf 100644 --- a/include/fc/thread/parallel.hpp +++ b/include/fc/thread/parallel.hpp @@ -99,7 +99,7 @@ namespace fc { typedef typename std::remove_const_t< std::remove_reference_t > FunctorType; typename task::ptr tsk = task::create( std::forward(f), desc ); - tsk->retain(); // HERE BE DRAFONS + tsk->retain(); // HERE BE DRAGONS fc::future r( std::dynamic_pointer_cast< promise >(tsk) ); detail::get_worker_pool().post( tsk.get() ); return r; diff --git a/include/fc/thread/thread.hpp b/include/fc/thread/thread.hpp index 2e275e6..bd02d09 100644 --- a/include/fc/thread/thread.hpp +++ b/include/fc/thread/thread.hpp @@ -89,7 +89,7 @@ namespace fc { typedef typename std::remove_const_t< std::remove_reference_t > FunctorType; typename task::ptr tsk = task::create( std::forward(f), desc ); - tsk->retain(); // HERE BE DRAFONS + tsk->retain(); // HERE BE DRAGONS fc::future r( std::dynamic_pointer_cast< promise >(tsk) ); async_task(tsk.get(),prio); return r; @@ -112,7 +112,7 @@ namespace fc { typedef decltype(f()) Result; typename task::ptr tsk = task::create( std::forward(f), desc ); - tsk->retain(); // HERE BE DRAFONS + tsk->retain(); // HERE BE DRAGONS fc::future r( std::dynamic_pointer_cast< promise >(tsk) ); async_task(tsk.get(),prio,when); return r; From f1746b705abb0c9483d469846d106c1463213451 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 10 Jun 2019 23:24:09 +0200 Subject: [PATCH 019/110] Make data_size static in hash classes --- include/fc/crypto/ripemd160.hpp | 2 +- include/fc/crypto/sha1.hpp | 2 +- include/fc/crypto/sha224.hpp | 2 +- include/fc/crypto/sha256.hpp | 2 +- include/fc/crypto/sha512.hpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/fc/crypto/ripemd160.hpp b/include/fc/crypto/ripemd160.hpp index faea983..ac48d16 100644 --- a/include/fc/crypto/ripemd160.hpp +++ b/include/fc/crypto/ripemd160.hpp @@ -18,7 +18,7 @@ class ripemd160 explicit operator string()const; char* data()const; - constexpr size_t data_size()const { return 160/8; } + static constexpr size_t data_size() { return 160/8; } static ripemd160 hash( const fc::sha512& h ); static ripemd160 hash( const fc::sha256& h ); diff --git a/include/fc/crypto/sha1.hpp b/include/fc/crypto/sha1.hpp index 68fe77d..0050146 100644 --- a/include/fc/crypto/sha1.hpp +++ b/include/fc/crypto/sha1.hpp @@ -17,7 +17,7 @@ class sha1 operator std::string()const; char* data()const; - constexpr size_t data_size()const { return 20; } + static constexpr size_t data_size() { return 20; } static sha1 hash( const char* d, uint32_t dlen ); static sha1 hash( const std::string& ); diff --git a/include/fc/crypto/sha224.hpp b/include/fc/crypto/sha224.hpp index 923c623..c35c98f 100644 --- a/include/fc/crypto/sha224.hpp +++ b/include/fc/crypto/sha224.hpp @@ -16,7 +16,7 @@ class sha224 operator string()const; char* data()const; - constexpr size_t data_size()const { return 224 / 8; } + static constexpr size_t data_size() { return 224 / 8; } static sha224 hash( const char* d, uint32_t dlen ); static sha224 hash( const string& ); diff --git a/include/fc/crypto/sha256.hpp b/include/fc/crypto/sha256.hpp index dcc6159..840d38f 100644 --- a/include/fc/crypto/sha256.hpp +++ b/include/fc/crypto/sha256.hpp @@ -18,7 +18,7 @@ class sha256 operator string()const; char* data()const; - constexpr size_t data_size()const { return 256 / 8; } + static constexpr size_t data_size() { return 256 / 8; } static sha256 hash( const char* d, uint32_t dlen ); static sha256 hash( const string& ); diff --git a/include/fc/crypto/sha512.hpp b/include/fc/crypto/sha512.hpp index 0eb5715..521c93b 100644 --- a/include/fc/crypto/sha512.hpp +++ b/include/fc/crypto/sha512.hpp @@ -16,7 +16,7 @@ class sha512 operator std::string()const; char* data()const; - constexpr size_t data_size()const { return 512 / 8; } + static constexpr size_t data_size() { return 512 / 8; } static sha512 hash( const char* d, uint32_t dlen ); static sha512 hash( const std::string& ); From b16bf00a10d394f781d9b3996fc4c21da48a9f7c Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 10 Jun 2019 23:25:56 +0200 Subject: [PATCH 020/110] Made task_base destructor virtual --- include/fc/thread/task.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fc/thread/task.hpp b/include/fc/thread/task.hpp index 3da124d..ed8c208 100644 --- a/include/fc/thread/task.hpp +++ b/include/fc/thread/task.hpp @@ -32,7 +32,7 @@ namespace fc { public: void run(); virtual void cancel(const char* reason FC_CANCELATION_REASON_DEFAULT_ARG) override; - ~task_base(); + virtual ~task_base(); /* HERE BE DRAGONS * From 1bda001b8cf8c0f795423d1eb4d8a2dd40d100e4 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Tue, 11 Jun 2019 08:40:46 +0200 Subject: [PATCH 021/110] Use common inline functions for splitting/combining uint128 to/from two uint64 values --- include/fc/io/raw.hpp | 8 +++----- include/fc/uint128.hpp | 22 ++++++++++++++++++++++ src/crypto/aes.cpp | 8 ++++---- src/crypto/city.cpp | 40 +++++++++++++++------------------------- 4 files changed, 44 insertions(+), 34 deletions(-) diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index 2369d6c..6b0371b 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -29,8 +29,8 @@ namespace fc { inline void pack( Stream& s, const uint128_t& v, uint32_t _max_depth ) { boost::endian::little_uint64_buf_at hilo[2]; - hilo[0] = static_cast(v >> 64); - hilo[1] = static_cast(v & 0xffffffffffffffffULL); + hilo[0] = uint128_hi64( v ); + hilo[1] = uint128_lo64( v ); s.write( hilo[0].data(), sizeof(hilo) ); } template @@ -38,9 +38,7 @@ namespace fc { { boost::endian::little_uint64_buf_at hilo[2]; s.read( (char*) hilo, sizeof(hilo) ); - v = hilo[0].value(); - v <<= 64; - v += hilo[1].value(); + v = uint128( hilo[0].value(), hilo[1].value() ); } template diff --git a/include/fc/uint128.hpp b/include/fc/uint128.hpp index 741676e..46a18bd 100644 --- a/include/fc/uint128.hpp +++ b/include/fc/uint128.hpp @@ -33,6 +33,13 @@ namespace fc { using int128_t = __int128_t; using uint128_t = __uint128_t; +inline uint64_t uint128_lo64(const uint128_t x) { + return static_cast(x & 0xffffffffffffffffULL); +} +inline uint64_t uint128_hi64(const uint128_t x) { + return static_cast( x >> 64 ); +} + } // namespace fc #else // __SIZEOF_INT128__ @@ -44,6 +51,21 @@ namespace fc { using boost::multiprecision::int128_t; using boost::multiprecision::uint128_t; +inline uint64_t uint128_lo64(const uint128_t& x) { + return static_cast(x & 0xffffffffffffffffULL); +} +inline uint64_t uint128_hi64(const uint128_t& x) { + return static_cast( x >> 64 ); +} + } // namespace fc #endif // __SIZEOF_INT128__ + +namespace fc { + +inline uint128_t uint128( const uint64_t hi, const uint64_t lo ) { + return ( uint128_t(hi) << 64 ) + lo; +} + +} // namespace fc diff --git a/src/crypto/aes.cpp b/src/crypto/aes.cpp index 5e78915..55464a7 100644 --- a/src/crypto/aes.cpp +++ b/src/crypto/aes.cpp @@ -54,8 +54,8 @@ void aes_encoder::init( const fc::sha256& key, const uint128_t& init_value ) * IV size for *most* modes is the same as the block size. For AES this * is 128 bits */ boost::endian::little_uint64_buf_t iv[2]; - iv[0] = static_cast( init_value >> 64 ); - iv[1] = static_cast( init_value & 0xffffffffffffffffULL ); + iv[0] = uint128_hi64( init_value ); + iv[1] = uint128_lo64( init_value ); if(1 != EVP_EncryptInit_ex(my->ctx, EVP_aes_256_cbc(), NULL, (unsigned char*)&key, (const unsigned char*)iv[0].data())) { FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc encryption init", @@ -122,8 +122,8 @@ void aes_decoder::init( const fc::sha256& key, const uint128_t& init_value ) * IV size for *most* modes is the same as the block size. For AES this * is 128 bits */ boost::endian::little_uint64_buf_t iv[2]; - iv[0] = static_cast( init_value >> 64 ); - iv[1] = static_cast( init_value & 0xffffffffffffffffULL ); + iv[0] = uint128_hi64( init_value ); + iv[1] = uint128_lo64( init_value ); if(1 != EVP_DecryptInit_ex(my->ctx, EVP_aes_256_cbc(), NULL, (unsigned char*)&key, (const unsigned char*)iv[0].data())) { FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc encryption init", diff --git a/src/crypto/city.cpp b/src/crypto/city.cpp index ef5469d..3ed4cd0 100644 --- a/src/crypto/city.cpp +++ b/src/crypto/city.cpp @@ -46,21 +46,14 @@ namespace fc { using namespace std; -inline uint64_t Uint128Low64(const uint128_t& x) { - return static_cast(x & 0xffffffffffffffffULL); -} -inline uint64_t Uint128High64(const uint128_t& x) { - return static_cast( x >> 64 ); -} - // Hash 128 input bits down to 64 bits of output. // This is intended to be a reasonably good hash function. inline uint64_t Hash128to64(const uint128_t& x) { // Murmur-inspired hashing. const uint64_t kMul = 0x9ddfea08eb382d69ULL; - uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul; + uint64_t a = (uint128_lo64(x) ^ uint128_hi64(x)) * kMul; a ^= (a >> 47); - uint64_t b = (Uint128High64(x) ^ a) * kMul; + uint64_t b = (uint128_hi64(x) ^ a) * kMul; b ^= (b >> 47); b *= kMul; return b; @@ -282,7 +275,7 @@ static uint64_t ShiftMix(uint64_t val) { } static uint64_t HashLen16(uint64_t u, uint64_t v) { - return Hash128to64( ( uint128_t(u) << 64 ) + v); + return Hash128to64( uint128( u, v) ); } static uint64_t HashLen16(uint64_t u, uint64_t v, uint64_t mul) { @@ -428,8 +421,8 @@ uint64_t CityHash64WithSeed(const char *s, size_t len, uint64_t seed) { // A subroutine for CityHash128(). Returns a decent 128-bit hash for strings // of any length representable in signed long. Based on City and Murmur. uint128_t CityMurmur(const char *s, size_t len, uint128_t seed) { - uint64_t a = Uint128Low64(seed); - uint64_t b = Uint128High64(seed); + uint64_t a = uint128_lo64(seed); + uint64_t b = uint128_hi64(seed); uint64_t c = 0; uint64_t d = 0; signed long l = len - 16; @@ -454,7 +447,7 @@ uint128_t CityMurmur(const char *s, size_t len, uint128_t seed) { } a = HashLen16(a, c); b = HashLen16(d, b); - return ( uint128_t(a ^ b) << 64 ) + HashLen16(b, a); + return uint128( a ^ b, HashLen16(b, a) ); } uint128_t CityHash128WithSeed(const char *s, size_t len, uint128_t seed) { @@ -465,8 +458,8 @@ uint128_t CityHash128WithSeed(const char *s, size_t len, uint128_t seed) { // We expect len >= 128 to be the common case. Keep 56 bytes of state: // v, w, x, y, and z. pair v, w; - uint64_t x = Uint128Low64(seed); - uint64_t y = Uint128High64(seed); + uint64_t x = uint128_lo64(seed); + uint64_t y = uint128_hi64(seed); uint64_t z = len * k1; v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s); v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8); @@ -516,15 +509,13 @@ uint128_t CityHash128WithSeed(const char *s, size_t len, uint128_t seed) { // different 56-byte-to-8-byte hashes to get a 16-byte final result. x = HashLen16(x, v.first); y = HashLen16(y + z, w.first); - return ( uint128_t( HashLen16(x + v.second, w.second) + y ) << 64 ) - + HashLen16(x + w.second, y + v.second); + return uint128( HashLen16(x + v.second, w.second) + y, HashLen16(x + w.second, y + v.second) ); } uint128_t city_hash128(const char *s, size_t len) { return len >= 16 ? - CityHash128WithSeed(s + 16, len - 16, - ( uint128_t( Fetch64(s) ) << 64 ) + Fetch64(s + 8) + k0) : - CityHash128WithSeed(s, len, ( uint128_t(k0) << 64 ) + k1); + CityHash128WithSeed( s + 16, len - 16, uint128( Fetch64(s), Fetch64(s + 8) + k0 ) ) : + CityHash128WithSeed( s, len, uint128( k0, k1 ) ); } //#ifdef __SSE4_2__ @@ -648,10 +639,9 @@ uint128_t CityHashCrc128WithSeed(const char *s, size_t len, uint128_t seed) { } else { uint64_t result[4]; CityHashCrc256(s, len, result); - uint64_t u = Uint128High64(seed) + result[0]; - uint64_t v = Uint128Low64(seed) + result[1]; - return ( uint128_t( HashLen16(u, v + result[2]) ) << 64 ) - + HashLen16(Rotate(v, 32), u * k0 + result[3]); + uint64_t u = uint128_hi64(seed) + result[0]; + uint64_t v = uint128_lo64(seed) + result[1]; + return uint128( HashLen16(u, v + result[2]), HashLen16(Rotate(v, 32), u * k0 + result[3]) ); } } @@ -661,7 +651,7 @@ uint128_t city_hash_crc_128(const char *s, size_t len) { } else { uint64_t result[4]; CityHashCrc256(s, len, result); - return ( uint128_t(result[2]) << 64 ) + result[3]; + return uint128( result[2], result[3] ); } } From ed7eefec673eba7a7393c3d469627f7bc0b067d2 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Tue, 11 Jun 2019 08:52:44 +0200 Subject: [PATCH 022/110] Avoid array copy --- include/fc/variant.hpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/include/fc/variant.hpp b/include/fc/variant.hpp index 279b7de..2098a70 100644 --- a/include/fc/variant.hpp +++ b/include/fc/variant.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -663,14 +664,14 @@ namespace fc template void to_variant( const std::array& bi, variant& v, uint32_t max_depth = 1 ) { - to_variant( std::vector( bi.begin(), bi.end() ), v, 1 ); + v = variant( to_hex( bi.data(), N ) ); } template void from_variant( const variant& v, std::array& bi, uint32_t max_depth = 1 ) { - std::vector ve = v.as< std::vector >( 1 ); + std::string ve = v.as_string(); if( ve.size() ) - memcpy( bi.data(), ve.data(), std::min( ve.size(), bi.size() ) ); + from_hex( ve, bi.data(), std::min( ve.size() / 2, bi.size() ) ); else memset( bi.data(), 0, bi.size() ); } @@ -678,14 +679,14 @@ namespace fc template void to_variant( const std::array& bi, variant& v, uint32_t max_depth = 1 ) { - to_variant( std::vector( bi.begin(), bi.end() ), v, 1 ); + v = variant( to_hex( (char*) bi.data(), N ) ); } template void from_variant( const variant& v, std::array& bi, uint32_t max_depth = 1 ) { - std::vector ve = v.as< std::vector >( 1 ); + std::string ve = v.as_string(); if( ve.size() ) - memcpy( bi.data(), ve.data(), std::min( ve.size(), bi.size() ) ); + from_hex( ve, (char*)bi.data(), std::min( ve.size() / 2, bi.size() ) ); else memset( bi.data(), 0, bi.size() ); } From d5fb99b41fc83e7229328bc39dc5e6c78ffd239b Mon Sep 17 00:00:00 2001 From: crypto-ape <43807588+crypto-ape@users.noreply.github.com> Date: Thu, 4 Apr 2019 17:35:02 +0200 Subject: [PATCH 023/110] SSE intrinsic rename --- src/crypto/city.cpp | 11 ++++++----- src/crypto/crc.cpp | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/crypto/city.cpp b/src/crypto/city.cpp index af3a91b..cfd72e0 100644 --- a/src/crypto/city.cpp +++ b/src/crypto/city.cpp @@ -38,9 +38,10 @@ #include #if defined(__SSE4_2__) && defined(__x86_64__) -#include + #include + #define _mm_crc32_u64_impl _mm_crc32_u64 #else -uint64_t _mm_crc32_u64(uint64_t a, uint64_t b ); + uint64_t _mm_crc32_u64_impl(uint64_t a, uint64_t b ); #endif namespace fc { @@ -563,9 +564,9 @@ static void CityHashCrc256Long(const char *s, size_t len, g += e; \ e += z; \ g += x; \ - z = _mm_crc32_u64(z, b + g); \ - y = _mm_crc32_u64(y, e + h); \ - x = _mm_crc32_u64(x, f + a); \ + z = _mm_crc32_u64_impl(z, b + g); \ + y = _mm_crc32_u64_impl(y, e + h); \ + x = _mm_crc32_u64_impl(x, f + a); \ e = Rotate(e, r); \ c += e; \ s += 40 diff --git a/src/crypto/crc.cpp b/src/crypto/crc.cpp index 7fa8cb1..28e99c9 100644 --- a/src/crypto/crc.cpp +++ b/src/crypto/crc.cpp @@ -604,7 +604,7 @@ static const uint32_t crc_c[256] = { #if !defined __SSE4_2__ || (defined __SSE4_2__ && !defined __x86_64__) -uint64_t _mm_crc32_u64(uint64_t a, uint64_t b ) +uint64_t _mm_crc32_u64_impl(uint64_t a, uint64_t b ) { // Squelch warning about unusued variable crc_c (void)(crc_c); @@ -619,7 +619,7 @@ int main( int argc, char** argv ) { uint64_t f = 0x1234; uint64_t a = 0x5678; - uint32_t f1 = _mm_crc32_u64(f, a); + uint32_t f1 = _mm_crc32_u64_impl(f, a); uint32_t f4 = crc32cSlicingBy8(f, (unsigned char*)&a, sizeof(a)); std::cout< Date: Wed, 19 Jun 2019 17:31:54 +0200 Subject: [PATCH 024/110] Fixed typo --- include/fc/thread/task.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fc/thread/task.hpp b/include/fc/thread/task.hpp index ed8c208..9ddf4b3 100644 --- a/include/fc/thread/task.hpp +++ b/include/fc/thread/task.hpp @@ -36,7 +36,7 @@ namespace fc { /* HERE BE DRAGONS * - * Tasks are handled by an fc::thread . To avoid concurrency issues, fc::thread keeps a reference to tha + * Tasks are handled by an fc::thread . To avoid concurrency issues, fc::thread keeps a reference to the * task in the form of a simple pointer. * At the same time, a task is also a promise that will be fulfilled with the task result, so typically the * creator of the task also keeps a reference to the task (but not necessarily always). From 491fd317343a2937cbe9bd1f9f9af9c57cfe9d3a Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Wed, 19 Jun 2019 17:39:45 +0200 Subject: [PATCH 025/110] Replace 0 with nullptr --- src/thread/thread_d.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/thread/thread_d.hpp b/src/thread/thread_d.hpp index 055ae8b..77e8fb7 100644 --- a/src/thread/thread_d.hpp +++ b/src/thread/thread_d.hpp @@ -532,8 +532,8 @@ namespace fc { next->_set_active_context( current ); current->cur_task = next; next->run(); - current->cur_task = 0; - next->_set_active_context(0); + current->cur_task = nullptr; + next->_set_active_context(nullptr); next->release(); // HERE BE DRAGONS current->reinitialize(); } From deb9d4f0a69ad70fd556f8eee075cc61adc98a9e Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Wed, 19 Jun 2019 17:40:22 +0200 Subject: [PATCH 026/110] Make task internal storage private --- include/fc/thread/task.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/fc/thread/task.hpp b/include/fc/thread/task.hpp index 9ddf4b3..f7c2ec5 100644 --- a/include/fc/thread/task.hpp +++ b/include/fc/thread/task.hpp @@ -123,8 +123,6 @@ namespace fc { return ptr( new task( std::move(f), desc ) ); } virtual void cancel(const char* reason FC_CANCELATION_REASON_DEFAULT_ARG) override { task_base::cancel(reason); } - - alignas(double) char _functor[FunctorSize]; private: template task( Functor&& f, const char* desc ):promise_base(desc), task_base(&_functor), promise(desc) { @@ -136,6 +134,8 @@ namespace fc { _promise_impl = static_cast*>(this); _run_functor = &detail::functor_run::run; } + + alignas(double) char _functor[FunctorSize]; }; template @@ -151,8 +151,6 @@ namespace fc { return ptr( new task( std::move(f), desc ) ); } virtual void cancel(const char* reason FC_CANCELATION_REASON_DEFAULT_ARG) override { task_base::cancel(reason); } - - alignas(double) char _functor[FunctorSize]; private: template task( Functor&& f, const char* desc ):promise_base(desc), task_base(&_functor), promise(desc) { @@ -164,6 +162,8 @@ namespace fc { _promise_impl = static_cast*>(this); _run_functor = &detail::void_functor_run::run; } + + alignas(double) char _functor[FunctorSize]; }; } From e0dd942875bd72b9af15c90960bf76c3166061f3 Mon Sep 17 00:00:00 2001 From: crypto-ape <43807588+crypto-ape@users.noreply.github.com> Date: Thu, 4 Apr 2019 17:36:04 +0200 Subject: [PATCH 027/110] Update build system for MinGW --- CMakeLists.txt | 100 +++++++++++------------------------------ include/fc/variant.hpp | 2 +- src/variant.cpp | 2 +- 3 files changed, 29 insertions(+), 75 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d28877..01fe9d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ # Defines fc library target. PROJECT( fc ) -CMAKE_MINIMUM_REQUIRED( VERSION 3.1 ) +CMAKE_MINIMUM_REQUIRED( VERSION 3.2 ) set( CMAKE_CXX_STANDARD 14 ) SET( CMAKE_CXX_STANDARD_REQUIRED ON ) @@ -22,6 +22,10 @@ INCLUDE(GetGitRevisionDescription) INCLUDE(CheckLibraryExists) INCLUDE(CheckLibcxxAtomic) +if (APPLE) + INCLUDE(Legacy) +endif (APPLE) + get_git_head_revision(GIT_REFSPEC FC_GIT_REVISION_SHA) get_git_unix_timestamp(FC_GIT_REVISION_UNIX_TIMESTAMP) @@ -39,7 +43,7 @@ endif() SET (ORIGINAL_LIB_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) SET(BOOST_COMPONENTS) -LIST(APPEND BOOST_COMPONENTS thread date_time filesystem system program_options chrono unit_test_framework context iostreams regex) +LIST(APPEND BOOST_COMPONENTS coroutine thread date_time filesystem system program_options chrono unit_test_framework context iostreams regex) # boost::endian is also required, but FindBoost can't handle header-only libs SET( Boost_USE_STATIC_LIBS ON CACHE STRING "ON or OFF" ) @@ -98,17 +102,7 @@ endif ( MSVC ) # End configure secp256k1-zkp # Configure editline -if ( MSVC ) -# # autoconf won't work here, hard code the defines -# set( EDITLINE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline" ) -# -# file( GLOB EDITLINE_SOURCES "${EDITLINE_DIR}/src/editline.c" ) -# add_library( editline ${EDITLINE_SOURCES} ) -# -# target_include_directories( editline PRIVATE "${EDITLINE_DIR}" PUBLIC "${EDITLINE_DIR}/include" ) -# -# set_target_properties( editline PROPERTIES COMPILE_DEFINITIONS LINKER_LANGUAGE C ) -else ( MSVC ) +if ( NOT WIN32 ) include(ExternalProject) if ( MINGW ) # Editline is not avalible in MINGW @@ -120,7 +114,7 @@ else ( MSVC ) BUILD_COMMAND make INSTALL_COMMAND true BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline/src/project_editline-build/src/.libs/libeditline.a - ) + ) ExternalProject_Add_Step(project_editline autogen WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/autogen.sh @@ -133,7 +127,7 @@ else ( MSVC ) add_dependencies(editline project_editline) install( FILES ${binary_dir}/src/.libs/libeditline${CMAKE_STATIC_LIBRARY_SUFFIX} DESTINATION lib/cryptonomex ) endif ( MINGW ) -endif ( MSVC ) +endif ( NOT WIN32 ) # End configure editline IF( WIN32 ) @@ -142,30 +136,21 @@ IF( WIN32 ) set( RPCRT4 rpcrt4 ) #boost - SET(BOOST_ROOT $ENV{BOOST_ROOT}) -# set(Boost_USE_DEBUG_PYTHON ON) + if ($ENV{BOOST_ROOT}) + SET(BOOST_ROOT $ENV{BOOST_ROOT}) + endif() + + set(Boost_USE_DEBUG_PYTHON ON) set(Boost_USE_MULTITHREADED ON) set(BOOST_ALL_DYN_LINK OFF) # force dynamic linking for all libraries - FIND_PACKAGE(Boost 1.53 REQUIRED COMPONENTS ${BOOST_COMPONENTS}) - # For Boost 1.53 on windows, coroutine was not in BOOST_LIBRARYDIR and do not need it to build, but if boost versin >= 1.54, find coroutine otherwise will cause link errors - IF(NOT "${Boost_VERSION}" MATCHES "1.53(.*)") - SET(BOOST_LIBRARIES_TEMP ${Boost_LIBRARIES}) - FIND_PACKAGE(Boost 1.54 REQUIRED COMPONENTS coroutine) - LIST(APPEND BOOST_COMPONENTS coroutine) - SET(Boost_LIBRARIES ${BOOST_LIBRARIES_TEMP} ${Boost_LIBRARIES}) - ENDIF() + LIST(APPEND PLATFORM_SPECIFIC_LIBS ws2_32 crypt32 mswsock userenv) - LIST(APPEND PLATFORM_SPECIFIC_LIBS wsock32.lib ws2_32.lib userenv.lib) # iphlpapi.lib ELSE(WIN32) MESSAGE(STATUS "Configuring fc to build on Unix/Apple") - LIST(APPEND BOOST_COMPONENTS coroutine) - - FIND_PACKAGE(Boost 1.53 REQUIRED COMPONENTS ${BOOST_COMPONENTS}) - SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a;.so") IF(NOT APPLE) @@ -175,9 +160,10 @@ ELSE(WIN32) ENDIF(NOT APPLE) ENDIF(WIN32) +FIND_PACKAGE(Boost 1.57 REQUIRED COMPONENTS ${BOOST_COMPONENTS}) -IF(NOT "$ENV{OPENSSL_ROOT_DIR}" STREQUAL "") +IF($ENV{OPENSSL_ROOT_DIR}) set(OPENSSL_ROOT_DIR $ENV{OPENSSL_ROOT_DIR} ) set(OPENSSL_INCLUDE_DIR ${OPENSSL_ROOT_DIR}/include) message(STATUS "Setting up OpenSSL root and include vars to ${OPENSSL_ROOT_DIR}, ${OPENSSL_INCLUDE_DIR}") @@ -283,12 +269,11 @@ setup_library( fc SOURCES ${sources} LIBRARY_TYPE STATIC ) install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION include ) # begin editline stuff -if(NOT (MSVC OR MINGW)) - target_compile_definitions (fc PRIVATE HAVE_EDITLINE) - set(editline_libraries editline) -endif(NOT (MSVC OR MINGW)) if(WIN32) target_compile_definitions( fc PRIVATE _CRT_NONSTDC_NO_DEPRECATE ) +elseif(WIN32) + target_compile_definitions (fc PRIVATE HAVE_EDITLINE) + set(editline_libraries editline) endif(WIN32) # end editline stuff @@ -383,9 +368,11 @@ target_link_libraries( fc PUBLIC ${LINK_USR_LOCAL_LIB} ${OPENSSL_LIBRARIES} ${Z ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${editline_libraries} secp256k1 ${CMAKE_REQUIRED_LIBRARIES} ) -if(MSVC) - set_source_files_properties( src/network/http/websocket.cpp PROPERTIES COMPILE_FLAGS "/bigobj" ) -endif(MSVC) +if(WIN32 AND MSVC) + set_source_files_properties( src/network/http/websocket.cpp PROPERTIES COMPILE_FLAGS "/bigobj" ) +elseif(WIN32 AND MINGW) + set_source_files_properties( src/network/http/websocket.cpp PROPERTIES LINK_FLAGS "-mbig-obj" ) +endif() IF(NOT Boost_UNIT_TEST_FRAMEWORK_LIBRARY MATCHES "\\.(a|lib)$") @@ -400,18 +387,10 @@ include_directories( vendor/websocketpp ) add_subdirectory(tests) -if(WIN32) +if(MSVC) # add addtional import library on windows platform target_link_libraries( fc PUBLIC crypt32.lib) - # now generate a list of the DLLs we're using to use during the install process - include (ParseLibraryList) - PARSE_LIBRARY_LIST(${Boost_LIBRARIES} - FOUND parseOk - DEBUG Boost_LIBRARIES_DEBUG - OPT Boost_LIBRARIES_RELEASE - GENERAL Boost_LIBRARIES_GENERAL) - #Variable will hold list of .pdb files generated for libraries the 'fc' module is linked to set(INTERFACE_LINK_PDB_RELEASE) @@ -480,31 +459,6 @@ if(WIN32) set_property(TARGET fc PROPERTY SHARED_LIBRARIES_DEBUG ${SHARED_LIBRARIES_DEBUG}) set_property(TARGET fc PROPERTY SHARED_LIBRARIES_RELEASE ${SHARED_LIBRARIES_RELEASE}) -endif(WIN32) - -SET(OPENSSL_CONF_TARGET ) -IF(DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY) - SET (OPENSSL_CONF_TARGET ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) -ELSE() - SET (OPENSSL_CONF_TARGET ${CMAKE_CURRENT_BINARY_DIR}) -ENDIF() - - IF(WIN32) - IF("${OPENSSL_ROOT_DIR}" STREQUAL "") - get_filename_component(OPENSSL_ROOT_DIR "${OPENSSL_INCLUDE_DIR}/.." REALPATH) - ENDIF() - IF("${OPENSSL_CONF_SOURCE}" STREQUAL "") - SET(OPENSSL_CONF_SOURCE "${OPENSSL_ROOT_DIR}/ssl/openssl.cnf") - IF(MINGW) - SET(OPENSSL_CONF_SOURCE "${OPENSSL_ROOT_DIR}/openssl.cnf") - ENDIF(MINGW) - ENDIF() - SET(POST_BUILD_STEP_COMMANDS ${POST_BUILD_STEP_COMMANDS} - COMMAND ${CMAKE_COMMAND} -E copy_if_different "${OPENSSL_CONF_SOURCE}" "${OPENSSL_CONF_TARGET}/openssl.cnf") - ENDIF(WIN32) - -ADD_CUSTOM_COMMAND(TARGET fc POST_BUILD ${POST_BUILD_STEP_COMMANDS} - COMMENT "Copying OpenSSL/ssl/openssl.cnf into target directory." -) +endif(MSVC) MESSAGE(STATUS "Finished fc module configuration...") diff --git a/include/fc/variant.hpp b/include/fc/variant.hpp index 2e08740..5f1ce5b 100644 --- a/include/fc/variant.hpp +++ b/include/fc/variant.hpp @@ -148,7 +148,7 @@ namespace fc #ifdef __APPLE__ void to_variant( size_t s, variant& v, uint32_t max_depth = 1 ); - #elif !defined(_MSC_VER) + #elif !defined(_WIN32) void to_variant( long long int s, variant& v, uint32_t max_depth = 1 ); void to_variant( unsigned long long int s, variant& v, uint32_t max_depth = 1 ); #endif diff --git a/src/variant.cpp b/src/variant.cpp index 4e52ec9..3d24e28 100644 --- a/src/variant.cpp +++ b/src/variant.cpp @@ -673,7 +673,7 @@ void from_variant( const variant& var, std::vector& vo, uint32_t max_depth } #ifdef __APPLE__ -#elif !defined(_MSC_VER) +#elif !defined(_WIN32) void to_variant( long long int s, variant& v, uint32_t max_depth ) { v = variant( int64_t(s) ); } void to_variant( unsigned long long int s, variant& v, uint32_t max_depth ) { v = variant( uint64_t(s)); } #endif From c9b3d57b0e0ac0eddbdd673316943cb6db19d8bf Mon Sep 17 00:00:00 2001 From: crypto-ape <43807588+crypto-ape@users.noreply.github.com> Date: Tue, 9 Apr 2019 16:37:32 +0200 Subject: [PATCH 028/110] Updated Boost searching --- CMakeLists.txt | 8 +- CMakeModules/Boost/BoostConfig.cmake | 18 + .../{ => Legacy/Boost}/FindBoost.cmake | 2360 ++++++++--------- CMakeModules/Legacy/CMakeLists.txt | 27 + 4 files changed, 1228 insertions(+), 1185 deletions(-) create mode 100644 CMakeModules/Boost/BoostConfig.cmake rename CMakeModules/{ => Legacy/Boost}/FindBoost.cmake (97%) create mode 100644 CMakeModules/Legacy/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 01fe9d0..37dae09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,8 @@ # # Defines fc library target. +CMAKE_MINIMUM_REQUIRED( VERSION 3.1.2 FATAL_ERROR ) PROJECT( fc ) -CMAKE_MINIMUM_REQUIRED( VERSION 3.2 ) set( CMAKE_CXX_STANDARD 14 ) SET( CMAKE_CXX_STANDARD_REQUIRED ON ) @@ -22,9 +22,7 @@ INCLUDE(GetGitRevisionDescription) INCLUDE(CheckLibraryExists) INCLUDE(CheckLibcxxAtomic) -if (APPLE) - INCLUDE(Legacy) -endif (APPLE) +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/Legacy) get_git_head_revision(GIT_REFSPEC FC_GIT_REVISION_SHA) get_git_unix_timestamp(FC_GIT_REVISION_UNIX_TIMESTAMP) @@ -160,7 +158,7 @@ ELSE(WIN32) ENDIF(NOT APPLE) ENDIF(WIN32) -FIND_PACKAGE(Boost 1.57 REQUIRED COMPONENTS ${BOOST_COMPONENTS}) +FIND_PACKAGE(Boost CONFIG COMPONENTS ${BOOST_COMPONENTS}) IF($ENV{OPENSSL_ROOT_DIR}) diff --git a/CMakeModules/Boost/BoostConfig.cmake b/CMakeModules/Boost/BoostConfig.cmake new file mode 100644 index 0000000..5a6bac8 --- /dev/null +++ b/CMakeModules/Boost/BoostConfig.cmake @@ -0,0 +1,18 @@ +# This overrides `find_package(Boost ... CONFIG ... )` calls +# - calls the CMAke's built-in `FindBoost.cmake` and adds `pthread` library dependency + +MESSAGE(STATUS "Using custom FindBoost config") + +find_package(Boost 1.57 REQUIRED COMPONENTS ${Boost_FIND_COMPONENTS}) + +# Inject `pthread` dependency to Boost if needed +if (UNIX AND NOT CYGWIN) + list(FIND Boost_FIND_COMPONENTS thread _using_boost_thread) + if (_using_boost_thread GREATER -1) + find_library(BOOST_THREAD_LIBRARY NAMES pthread DOC "The threading library used by boost-thread") + if (BOOST_THREAD_LIBRARY) + MESSAGE(STATUS "Adding Boost thread lib dependency: ${BOOST_THREAD_LIBRARY}") + list(APPEND Boost_LIBRARIES ${BOOST_THREAD_LIBRARY}) + endif () + endif () +endif () \ No newline at end of file diff --git a/CMakeModules/FindBoost.cmake b/CMakeModules/Legacy/Boost/FindBoost.cmake similarity index 97% rename from CMakeModules/FindBoost.cmake rename to CMakeModules/Legacy/Boost/FindBoost.cmake index 4c37f5f..b8276af 100644 --- a/CMakeModules/FindBoost.cmake +++ b/CMakeModules/Legacy/Boost/FindBoost.cmake @@ -1,1180 +1,1180 @@ -# - Find Boost include dirs and libraries -# Use this module by invoking find_package with the form: -# find_package(Boost -# [version] [EXACT] # Minimum or EXACT version e.g. 1.36.0 -# [REQUIRED] # Fail with error if Boost is not found -# [COMPONENTS ...] # Boost libraries by their canonical name -# ) # e.g. "date_time" for "libboost_date_time" -# This module finds headers and requested component libraries OR a CMake -# package configuration file provided by a "Boost CMake" build. For the -# latter case skip to the "Boost CMake" section below. For the former -# case results are reported in variables: -# Boost_FOUND - True if headers and requested libraries were found -# Boost_INCLUDE_DIRS - Boost include directories -# Boost_LIBRARY_DIRS - Link directories for Boost libraries -# Boost_LIBRARIES - Boost component libraries to be linked -# Boost__FOUND - True if component was found ( is upper-case) -# Boost__LIBRARY - Libraries to link for component (may include -# target_link_libraries debug/optimized keywords) -# Boost_VERSION - BOOST_VERSION value from boost/version.hpp -# Boost_LIB_VERSION - Version string appended to library filenames -# Boost_MAJOR_VERSION - Boost major version number (X in X.y.z) -# Boost_MINOR_VERSION - Boost minor version number (Y in x.Y.z) -# Boost_SUBMINOR_VERSION - Boost subminor version number (Z in x.y.Z) -# Boost_LIB_DIAGNOSTIC_DEFINITIONS (Windows) -# - Pass to add_definitions() to have diagnostic -# information about Boost's automatic linking -# displayed during compilation -# -# This module reads hints about search locations from variables: -# BOOST_ROOT - Preferred installation prefix -# (or BOOSTROOT) -# BOOST_INCLUDEDIR - Preferred include directory e.g. /include -# BOOST_LIBRARYDIR - Preferred library directory e.g. /lib -# Boost_NO_SYSTEM_PATHS - Set to ON to disable searching in locations not -# specified by these hint variables. Default is OFF. -# Boost_ADDITIONAL_VERSIONS -# - List of Boost versions not known to this module -# (Boost install locations may contain the version) -# and saves search results persistently in CMake cache entries: -# Boost_INCLUDE_DIR - Directory containing Boost headers -# Boost_LIBRARY_DIR - Directory containing Boost libraries -# Boost__LIBRARY_DEBUG - Component library debug variant -# Boost__LIBRARY_RELEASE - Component library release variant -# Users may set the these hints or results as cache entries. Projects should -# not read these entries directly but instead use the above result variables. -# Note that some hint names start in upper-case "BOOST". One may specify -# these as environment variables if they are not specified as CMake variables -# or cache entries. -# -# This module first searches for the Boost header files using the above hint -# variables (excluding BOOST_LIBRARYDIR) and saves the result in -# Boost_INCLUDE_DIR. Then it searches for requested component libraries using -# the above hints (excluding BOOST_INCLUDEDIR and Boost_ADDITIONAL_VERSIONS), -# "lib" directories near Boost_INCLUDE_DIR, and the library name configuration -# settings below. It saves the library directory in Boost_LIBRARY_DIR and -# individual library locations in Boost__LIBRARY_DEBUG and -# Boost__LIBRARY_RELEASE. When one changes settings used by previous -# searches in the same build tree (excluding environment variables) this -# module discards previous search results affected by the changes and searches -# again. -# -# Boost libraries come in many variants encoded in their file name. Users or -# projects may tell this module which variant to find by setting variables: -# Boost_USE_MULTITHREADED - Set to OFF to use the non-multithreaded -# libraries ('mt' tag). Default is ON. -# Boost_USE_STATIC_LIBS - Set to ON to force the use of the static -# libraries. Default is OFF. -# Boost_USE_STATIC_RUNTIME - Set to ON or OFF to specify whether to use -# libraries linked statically to the C++ runtime -# ('s' tag). Default is platform dependent. -# Boost_USE_DEBUG_PYTHON - Set to ON to use libraries compiled with a -# debug Python build ('y' tag). Default is OFF. -# Boost_USE_STLPORT - Set to ON to use libraries compiled with -# STLPort ('p' tag). Default is OFF. -# Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS -# - Set to ON to use libraries compiled with -# STLPort deprecated "native iostreams" -# ('n' tag). Default is OFF. -# Boost_COMPILER - Set to the compiler-specific library suffix -# (e.g. "-gcc43"). Default is auto-computed -# for the C++ compiler in use. -# Boost_THREADAPI - Suffix for "thread" component library name, -# such as "pthread" or "win32". Names with -# and without this suffix will both be tried. -# Other variables one may set to control this module are: -# Boost_DEBUG - Set to ON to enable debug output from FindBoost. -# Please enable this before filing any bug report. -# Boost_DETAILED_FAILURE_MSG -# - Set to ON to add detailed information to the -# failure message even when the REQUIRED option -# is not given to the find_package call. -# Boost_REALPATH - Set to ON to resolve symlinks for discovered -# libraries to assist with packaging. For example, -# the "system" component library may be resolved to -# "/usr/lib/libboost_system.so.1.42.0" instead of -# "/usr/lib/libboost_system.so". This does not -# affect linking and should not be enabled unless -# the user needs this information. -# On Visual Studio and Borland compilers Boost headers request automatic -# linking to corresponding libraries. This requires matching libraries to be -# linked explicitly or available in the link library search path. In this -# case setting Boost_USE_STATIC_LIBS to OFF may not achieve dynamic linking. -# Boost automatic linking typically requests static libraries with a few -# exceptions (such as Boost.Python). Use -# add_definitions(${Boost_LIB_DIAGNOSTIC_DEFINITIONS}) -# to ask Boost to report information about automatic linking requests. -# -# Example to find Boost headers only: -# find_package(Boost 1.36.0) -# if(Boost_FOUND) -# include_directories(${Boost_INCLUDE_DIRS}) -# add_executable(foo foo.cc) -# endif() -# Example to find Boost headers and some libraries: -# set(Boost_USE_STATIC_LIBS ON) -# set(Boost_USE_MULTITHREADED ON) -# set(Boost_USE_STATIC_RUNTIME OFF) -# find_package(Boost 1.36.0 COMPONENTS date_time filesystem system ...) -# if(Boost_FOUND) -# include_directories(${Boost_INCLUDE_DIRS}) -# add_executable(foo foo.cc) -# target_link_libraries(foo ${Boost_LIBRARIES}) -# endif() -# -# Boost CMake ---------------------------------------------------------- -# -# If Boost was built using the boost-cmake project it provides a package -# configuration file for use with find_package's Config mode. This module -# looks for the package configuration file called BoostConfig.cmake or -# boost-config.cmake and stores the result in cache entry "Boost_DIR". If -# found, the package configuration file is loaded and this module returns with -# no further action. See documentation of the Boost CMake package -# configuration for details on what it provides. -# -# Set Boost_NO_BOOST_CMAKE to ON to disable the search for boost-cmake. - -#============================================================================= -# Copyright 2006-2012 Kitware, Inc. -# Copyright 2006-2008 Andreas Schneider -# Copyright 2007 Wengo -# Copyright 2007 Mike Jackson -# Copyright 2008 Andreas Pakulat -# Copyright 2008-2012 Philip Lowman -# -# Distributed under the OSI-approved BSD License (the "License"); -# see accompanying file Copyright.txt for details. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= -# (To distribute this file outside of CMake, substitute the full -# License text for the above reference.) - - -#------------------------------------------------------------------------------- -# Before we go searching, check whether boost-cmake is avaialble, unless the -# user specifically asked NOT to search for boost-cmake. -# -# If Boost_DIR is set, this behaves as any find_package call would. If not, -# it looks at BOOST_ROOT and BOOSTROOT to find Boost. -# - -message(STATUS "Using custom FindBoost.cmake") - -if (NOT Boost_NO_BOOST_CMAKE) - # If Boost_DIR is not set, look for BOOSTROOT and BOOST_ROOT as alternatives, - # since these are more conventional for Boost. - if ("$ENV{Boost_DIR}" STREQUAL "") - if (NOT "$ENV{BOOST_ROOT}" STREQUAL "") - set(ENV{Boost_DIR} $ENV{BOOST_ROOT}) - elseif (NOT "$ENV{BOOSTROOT}" STREQUAL "") - set(ENV{Boost_DIR} $ENV{BOOSTROOT}) - endif() - endif() - - # Do the same find_package call but look specifically for the CMake version. - # Note that args are passed in the Boost_FIND_xxxxx variables, so there is no - # need to delegate them to this find_package call. - find_package(Boost QUIET NO_MODULE) - mark_as_advanced(Boost_DIR) - - # If we found boost-cmake, then we're done. Print out what we found. - # Otherwise let the rest of the module try to find it. - if (Boost_FOUND) - message("Boost ${Boost_FIND_VERSION} found.") - if (Boost_FIND_COMPONENTS) - message("Found Boost components:") - message(" ${Boost_FIND_COMPONENTS}") - endif() - return() - endif() -endif() - - -#------------------------------------------------------------------------------- -# FindBoost functions & macros -# - -############################################ -# -# Check the existence of the libraries. -# -############################################ -# This macro was taken directly from the FindQt4.cmake file that is included -# with the CMake distribution. This is NOT my work. All work was done by the -# original authors of the FindQt4.cmake file. Only minor modifications were -# made to remove references to Qt and make this file more generally applicable -# And ELSE/ENDIF pairs were removed for readability. -######################################################################### - -macro(_Boost_ADJUST_LIB_VARS basename) - if(Boost_INCLUDE_DIR ) - if(Boost_${basename}_LIBRARY_DEBUG AND Boost_${basename}_LIBRARY_RELEASE) - # if the generator supports configuration types then set - # optimized and debug libraries, or if the CMAKE_BUILD_TYPE has a value - if(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) - set(Boost_${basename}_LIBRARY optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG}) - else() - # if there are no configuration types and CMAKE_BUILD_TYPE has no value - # then just use the release libraries - set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE} ) - endif() - # FIXME: This probably should be set for both cases - set(Boost_${basename}_LIBRARIES optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG}) - endif() - - # if only the release version was found, set the debug variable also to the release version - if(Boost_${basename}_LIBRARY_RELEASE AND NOT Boost_${basename}_LIBRARY_DEBUG) - set(Boost_${basename}_LIBRARY_DEBUG ${Boost_${basename}_LIBRARY_RELEASE}) - set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE}) - set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_RELEASE}) - endif() - - # if only the debug version was found, set the release variable also to the debug version - if(Boost_${basename}_LIBRARY_DEBUG AND NOT Boost_${basename}_LIBRARY_RELEASE) - set(Boost_${basename}_LIBRARY_RELEASE ${Boost_${basename}_LIBRARY_DEBUG}) - set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_DEBUG}) - set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_DEBUG}) - endif() - - # If the debug & release library ends up being the same, omit the keywords - if(${Boost_${basename}_LIBRARY_RELEASE} STREQUAL ${Boost_${basename}_LIBRARY_DEBUG}) - set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE} ) - set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_RELEASE} ) - endif() - - if(Boost_${basename}_LIBRARY) - set(Boost_${basename}_FOUND ON) - endif() - - endif() - # Make variables changeble to the advanced user - mark_as_advanced( - Boost_${basename}_LIBRARY_RELEASE - Boost_${basename}_LIBRARY_DEBUG - ) -endmacro() - -macro(_Boost_CHANGE_DETECT changed_var) - set(${changed_var} 0) - foreach(v ${ARGN}) - if(DEFINED _Boost_COMPONENTS_SEARCHED) - if(${v}) - if(_${v}_LAST) - string(COMPARE NOTEQUAL "${${v}}" "${_${v}_LAST}" _${v}_CHANGED) - else() - set(_${v}_CHANGED 1) - endif() - elseif(_${v}_LAST) - set(_${v}_CHANGED 1) - endif() - if(_${v}_CHANGED) - set(${changed_var} 1) - endif() - else() - set(_${v}_CHANGED 0) - endif() - endforeach() -endmacro() - -macro(_Boost_FIND_LIBRARY var) - find_library(${var} ${ARGN}) - - # If we found the first library save Boost_LIBRARY_DIR. - if(${var} AND NOT Boost_LIBRARY_DIR) - get_filename_component(_dir "${${var}}" PATH) - set(Boost_LIBRARY_DIR "${_dir}" CACHE PATH "Boost library directory" FORCE) - endif() - - # If Boost_LIBRARY_DIR is known then search only there. - if(Boost_LIBRARY_DIR) - set(_boost_LIBRARY_SEARCH_DIRS ${Boost_LIBRARY_DIR} NO_DEFAULT_PATH) - endif() -endmacro() - -#------------------------------------------------------------------------------- - -# -# Runs compiler with "-dumpversion" and parses major/minor -# version with a regex. -# -function(_Boost_COMPILER_DUMPVERSION _OUTPUT_VERSION) - - exec_program(${CMAKE_CXX_COMPILER} - ARGS ${CMAKE_CXX_COMPILER_ARG1} -dumpversion - OUTPUT_VARIABLE _boost_COMPILER_VERSION - ) - string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2" - _boost_COMPILER_VERSION ${_boost_COMPILER_VERSION}) - - set(${_OUTPUT_VERSION} ${_boost_COMPILER_VERSION} PARENT_SCOPE) -endfunction() - -# -# Take a list of libraries with "thread" in it -# and prepend duplicates with "thread_${Boost_THREADAPI}" -# at the front of the list -# -function(_Boost_PREPEND_LIST_WITH_THREADAPI _output) - set(_orig_libnames ${ARGN}) - string(REPLACE "thread" "thread_${Boost_THREADAPI}" _threadapi_libnames "${_orig_libnames}") - set(${_output} ${_threadapi_libnames} ${_orig_libnames} PARENT_SCOPE) -endfunction() - -# -# If a library is found, replace its cache entry with its REALPATH -# -function(_Boost_SWAP_WITH_REALPATH _library _docstring) - if(${_library}) - get_filename_component(_boost_filepathreal ${${_library}} REALPATH) - unset(${_library} CACHE) - set(${_library} ${_boost_filepathreal} CACHE FILEPATH "${_docstring}") - endif() -endfunction() - -function(_Boost_CHECK_SPELLING _var) - if(${_var}) - string(TOUPPER ${_var} _var_UC) - message(FATAL_ERROR "ERROR: ${_var} is not the correct spelling. The proper spelling is ${_var_UC}.") - endif() -endfunction() - -# Guesses Boost's compiler prefix used in built library names -# Returns the guess by setting the variable pointed to by _ret -function(_Boost_GUESS_COMPILER_PREFIX _ret) - if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel" - OR "${CMAKE_CXX_COMPILER}" MATCHES "icl" - OR "${CMAKE_CXX_COMPILER}" MATCHES "icpc") - if(WIN32) - set (_boost_COMPILER "-iw") - else() - set (_boost_COMPILER "-il") - endif() - elseif (MSVC12) - set(_boost_COMPILER "-vc120") - elseif (MSVC11) - set(_boost_COMPILER "-vc110") - elseif (MSVC10) - set(_boost_COMPILER "-vc100") - elseif (MSVC90) - set(_boost_COMPILER "-vc90") - elseif (MSVC80) - set(_boost_COMPILER "-vc80") - elseif (MSVC71) - set(_boost_COMPILER "-vc71") - elseif (MSVC70) # Good luck! - set(_boost_COMPILER "-vc7") # yes, this is correct - elseif (MSVC60) # Good luck! - set(_boost_COMPILER "-vc6") # yes, this is correct - elseif (BORLAND) - set(_boost_COMPILER "-bcb") - elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "SunPro") - set(_boost_COMPILER "-sw") - elseif (MINGW) - if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34) - set(_boost_COMPILER "-mgw") # no GCC version encoding prior to 1.34 - else() - _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION) - set(_boost_COMPILER "-mgw${_boost_COMPILER_VERSION}") - endif() - elseif (UNIX) - if (CMAKE_COMPILER_IS_GNUCXX) - if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34) - set(_boost_COMPILER "-gcc") # no GCC version encoding prior to 1.34 - else() - _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION) - # Determine which version of GCC we have. - if(APPLE) - if(Boost_MINOR_VERSION) - if(${Boost_MINOR_VERSION} GREATER 35) - # In Boost 1.36.0 and newer, the mangled compiler name used - # on Mac OS X/Darwin is "xgcc". - set(_boost_COMPILER "-xgcc${_boost_COMPILER_VERSION}") - else() - # In Boost <= 1.35.0, there is no mangled compiler name for - # the Mac OS X/Darwin version of GCC. - set(_boost_COMPILER "") - endif() - else() - # We don't know the Boost version, so assume it's - # pre-1.36.0. - set(_boost_COMPILER "") - endif() - else() - set(_boost_COMPILER "-gcc${_boost_COMPILER_VERSION}") - endif() - endif() - endif () - else() - # TODO at least Boost_DEBUG here? - set(_boost_COMPILER "") - endif() - set(${_ret} ${_boost_COMPILER} PARENT_SCOPE) -endfunction() - -function(_Boost_consider_adding_pthreads _outvar) - # On Unix platforms (excluding cygwin) add pthreads to Boost_LIBRARIES - # if the user is searching for the boost-thread component. - if(UNIX AND NOT CYGWIN) - list(FIND Boost_FIND_COMPONENTS thread _using_boost_thread) - if(_using_boost_thread GREATER -1) - find_library(BOOST_THREAD_LIBRARY NAMES pthread - DOC "The threading library used by boost-thread" - ) - if(BOOST_THREAD_LIBRARY) - set(${_outvar} ${ARGN} ${BOOST_THREAD_LIBRARY} PARENT_SCOPE) - endif() - endif() - endif() -endfunction() - -# -# End functions/macros -# -#------------------------------------------------------------------------------- - -#------------------------------------------------------------------------------- -# main. -#------------------------------------------------------------------------------- - -if(NOT DEFINED Boost_USE_MULTITHREADED) - set(Boost_USE_MULTITHREADED TRUE) -endif() - -# Check the version of Boost against the requested version. -if(Boost_FIND_VERSION AND NOT Boost_FIND_VERSION_MINOR) - message(SEND_ERROR "When requesting a specific version of Boost, you must provide at least the major and minor version numbers, e.g., 1.34") -endif() - -if(Boost_FIND_VERSION_EXACT) - # The version may appear in a directory with or without the patch - # level, even when the patch level is non-zero. - set(_boost_TEST_VERSIONS - "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}.${Boost_FIND_VERSION_PATCH}" - "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") -else() - # The user has not requested an exact version. Among known - # versions, find those that are acceptable to the user request. - set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS} - "1.56.0" "1.56" "1.55.0" "1.55" "1.54.0" "1.54" - "1.53.0" "1.53" "1.52.0" "1.52" "1.51.0" "1.51" - "1.50.0" "1.50" "1.49.0" "1.49" "1.48.0" "1.48" "1.47.0" "1.47" "1.46.1" - "1.46.0" "1.46" "1.45.0" "1.45" "1.44.0" "1.44" "1.43.0" "1.43" "1.42.0" "1.42" - "1.41.0" "1.41" "1.40.0" "1.40" "1.39.0" "1.39" "1.38.0" "1.38" "1.37.0" "1.37" - "1.36.1" "1.36.0" "1.36" "1.35.1" "1.35.0" "1.35" "1.34.1" "1.34.0" - "1.34" "1.33.1" "1.33.0" "1.33") - set(_boost_TEST_VERSIONS) - if(Boost_FIND_VERSION) - set(_Boost_FIND_VERSION_SHORT "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") - # Select acceptable versions. - foreach(version ${_Boost_KNOWN_VERSIONS}) - if(NOT "${version}" VERSION_LESS "${Boost_FIND_VERSION}") - # This version is high enough. - list(APPEND _boost_TEST_VERSIONS "${version}") - elseif("${version}.99" VERSION_EQUAL "${_Boost_FIND_VERSION_SHORT}.99") - # This version is a short-form for the requested version with - # the patch level dropped. - list(APPEND _boost_TEST_VERSIONS "${version}") - endif() - endforeach() - else() - # Any version is acceptable. - set(_boost_TEST_VERSIONS "${_Boost_KNOWN_VERSIONS}") - endif() -endif() - -# The reason that we failed to find Boost. This will be set to a -# user-friendly message when we fail to find some necessary piece of -# Boost. -set(Boost_ERROR_REASON) - -if(Boost_DEBUG) - # Output some of their choices - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_TEST_VERSIONS = ${_boost_TEST_VERSIONS}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_USE_MULTITHREADED = ${Boost_USE_MULTITHREADED}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_USE_STATIC_LIBS = ${Boost_USE_STATIC_LIBS}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_USE_STATIC_RUNTIME = ${Boost_USE_STATIC_RUNTIME}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_ADDITIONAL_VERSIONS = ${Boost_ADDITIONAL_VERSIONS}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_NO_SYSTEM_PATHS = ${Boost_NO_SYSTEM_PATHS}") -endif() - -if(WIN32) - # In windows, automatic linking is performed, so you do not have - # to specify the libraries. If you are linking to a dynamic - # runtime, then you can choose to link to either a static or a - # dynamic Boost library, the default is to do a static link. You - # can alter this for a specific library "whatever" by defining - # BOOST_WHATEVER_DYN_LINK to force Boost library "whatever" to be - # linked dynamically. Alternatively you can force all Boost - # libraries to dynamic link by defining BOOST_ALL_DYN_LINK. - - # This feature can be disabled for Boost library "whatever" by - # defining BOOST_WHATEVER_NO_LIB, or for all of Boost by defining - # BOOST_ALL_NO_LIB. - - # If you want to observe which libraries are being linked against - # then defining BOOST_LIB_DIAGNOSTIC will cause the auto-linking - # code to emit a #pragma message each time a library is selected - # for linking. - set(Boost_LIB_DIAGNOSTIC_DEFINITIONS "-DBOOST_LIB_DIAGNOSTIC") -endif() - -_Boost_CHECK_SPELLING(Boost_ROOT) -_Boost_CHECK_SPELLING(Boost_LIBRARYDIR) -_Boost_CHECK_SPELLING(Boost_INCLUDEDIR) - -# Collect environment variable inputs as hints. Do not consider changes. -foreach(v BOOSTROOT BOOST_ROOT BOOST_INCLUDEDIR BOOST_LIBRARYDIR) - set(_env $ENV{${v}}) - if(_env) - file(TO_CMAKE_PATH "${_env}" _ENV_${v}) - else() - set(_ENV_${v} "") - endif() -endforeach() -if(NOT _ENV_BOOST_ROOT AND _ENV_BOOSTROOT) - set(_ENV_BOOST_ROOT "${_ENV_BOOSTROOT}") -endif() - -# Collect inputs and cached results. Detect changes since the last run. -if(NOT BOOST_ROOT AND BOOSTROOT) - set(BOOST_ROOT "${BOOSTROOT}") -endif() -set(_Boost_VARS_DIR - BOOST_ROOT - Boost_NO_SYSTEM_PATHS - ) - -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Declared as CMake or Environmental Variables:") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " BOOST_ROOT = ${BOOST_ROOT}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " BOOST_INCLUDEDIR = ${BOOST_INCLUDEDIR}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " BOOST_LIBRARYDIR = ${BOOST_LIBRARYDIR}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_TEST_VERSIONS = ${_boost_TEST_VERSIONS}") -endif() - -# ------------------------------------------------------------------------ -# Search for Boost include DIR -# ------------------------------------------------------------------------ - -set(_Boost_VARS_INC BOOST_INCLUDEDIR Boost_INCLUDE_DIR Boost_ADDITIONAL_VERSIONS) -_Boost_CHANGE_DETECT(_Boost_CHANGE_INCDIR ${_Boost_VARS_DIR} ${_Boost_VARS_INC}) -# Clear Boost_INCLUDE_DIR if it did not change but other input affecting the -# location did. We will find a new one based on the new inputs. -if(_Boost_CHANGE_INCDIR AND NOT _Boost_INCLUDE_DIR_CHANGED) - unset(Boost_INCLUDE_DIR CACHE) -endif() - -if(NOT Boost_INCLUDE_DIR) - set(_boost_INCLUDE_SEARCH_DIRS "") - if(BOOST_INCLUDEDIR) - list(APPEND _boost_INCLUDE_SEARCH_DIRS ${BOOST_INCLUDEDIR}) - elseif(_ENV_BOOST_INCLUDEDIR) - list(APPEND _boost_INCLUDE_SEARCH_DIRS ${_ENV_BOOST_INCLUDEDIR}) - endif() - - if( BOOST_ROOT ) - list(APPEND _boost_INCLUDE_SEARCH_DIRS ${BOOST_ROOT}/include ${BOOST_ROOT}) - elseif( _ENV_BOOST_ROOT ) - list(APPEND _boost_INCLUDE_SEARCH_DIRS ${_ENV_BOOST_ROOT}/include ${_ENV_BOOST_ROOT}) - endif() - - if( Boost_NO_SYSTEM_PATHS) - list(APPEND _boost_INCLUDE_SEARCH_DIRS NO_CMAKE_SYSTEM_PATH) - else() - list(APPEND _boost_INCLUDE_SEARCH_DIRS PATHS - C:/boost/include - C:/boost - /sw/local/include - ) - endif() - - # Try to find Boost by stepping backwards through the Boost versions - # we know about. - # Build a list of path suffixes for each version. - set(_boost_PATH_SUFFIXES) - foreach(_boost_VER ${_boost_TEST_VERSIONS}) - # Add in a path suffix, based on the required version, ideally - # we could read this from version.hpp, but for that to work we'd - # need to know the include dir already - set(_boost_BOOSTIFIED_VERSION) - - # Transform 1.35 => 1_35 and 1.36.0 => 1_36_0 - if(_boost_VER MATCHES "[0-9]+\\.[0-9]+\\.[0-9]+") - string(REGEX REPLACE "([0-9]+)\\.([0-9]+)\\.([0-9]+)" "\\1_\\2_\\3" - _boost_BOOSTIFIED_VERSION ${_boost_VER}) - elseif(_boost_VER MATCHES "[0-9]+\\.[0-9]+") - string(REGEX REPLACE "([0-9]+)\\.([0-9]+)" "\\1_\\2" - _boost_BOOSTIFIED_VERSION ${_boost_VER}) - endif() - - list(APPEND _boost_PATH_SUFFIXES - "boost-${_boost_BOOSTIFIED_VERSION}" - "boost_${_boost_BOOSTIFIED_VERSION}" - "boost/boost-${_boost_BOOSTIFIED_VERSION}" - "boost/boost_${_boost_BOOSTIFIED_VERSION}" - ) - - endforeach() - - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Include debugging info:") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " _boost_INCLUDE_SEARCH_DIRS = ${_boost_INCLUDE_SEARCH_DIRS}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " _boost_PATH_SUFFIXES = ${_boost_PATH_SUFFIXES}") - endif() - - # Look for a standard boost header file. - find_path(Boost_INCLUDE_DIR - NAMES boost/config.hpp - HINTS ${_boost_INCLUDE_SEARCH_DIRS} - PATH_SUFFIXES ${_boost_PATH_SUFFIXES} - ) -endif() - -# ------------------------------------------------------------------------ -# Extract version information from version.hpp -# ------------------------------------------------------------------------ - -# Set Boost_FOUND based only on header location and version. -# It will be updated below for component libraries. -if(Boost_INCLUDE_DIR) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "location of version.hpp: ${Boost_INCLUDE_DIR}/boost/version.hpp") - endif() - - # Extract Boost_VERSION and Boost_LIB_VERSION from version.hpp - set(Boost_VERSION 0) - set(Boost_LIB_VERSION "") - file(STRINGS "${Boost_INCLUDE_DIR}/boost/version.hpp" _boost_VERSION_HPP_CONTENTS REGEX "#define BOOST_(LIB_)?VERSION ") - set(_Boost_VERSION_REGEX "([0-9]+)") - set(_Boost_LIB_VERSION_REGEX "\"([0-9_]+)\"") - foreach(v VERSION LIB_VERSION) - if("${_boost_VERSION_HPP_CONTENTS}" MATCHES ".*#define BOOST_${v} ${_Boost_${v}_REGEX}.*") - set(Boost_${v} "${CMAKE_MATCH_1}") - endif() - endforeach() - unset(_boost_VERSION_HPP_CONTENTS) - - math(EXPR Boost_MAJOR_VERSION "${Boost_VERSION} / 100000") - math(EXPR Boost_MINOR_VERSION "${Boost_VERSION} / 100 % 1000") - math(EXPR Boost_SUBMINOR_VERSION "${Boost_VERSION} % 100") - - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}\nBoost include path: ${Boost_INCLUDE_DIR}") - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "version.hpp reveals boost " - "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") - endif() - - if(Boost_FIND_VERSION) - # Set Boost_FOUND based on requested version. - set(_Boost_VERSION "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") - if("${_Boost_VERSION}" VERSION_LESS "${Boost_FIND_VERSION}") - set(Boost_FOUND 0) - set(_Boost_VERSION_AGE "old") - elseif(Boost_FIND_VERSION_EXACT AND - NOT "${_Boost_VERSION}" VERSION_EQUAL "${Boost_FIND_VERSION}") - set(Boost_FOUND 0) - set(_Boost_VERSION_AGE "new") - else() - set(Boost_FOUND 1) - endif() - if(NOT Boost_FOUND) - # State that we found a version of Boost that is too new or too old. - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}\nDetected version of Boost is too ${_Boost_VERSION_AGE}. Requested version was ${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") - if (Boost_FIND_VERSION_PATCH) - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}.${Boost_FIND_VERSION_PATCH}") - endif () - if (NOT Boost_FIND_VERSION_EXACT) - set(Boost_ERROR_REASON "${Boost_ERROR_REASON} (or newer)") - endif () - set(Boost_ERROR_REASON "${Boost_ERROR_REASON}.") - endif () - else() - # Caller will accept any Boost version. - set(Boost_FOUND 1) - endif() -else() - set(Boost_FOUND 0) - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}Unable to find the Boost header files. Please set BOOST_ROOT to the root directory containing Boost or BOOST_INCLUDEDIR to the directory containing Boost's headers.") -endif() - -# ------------------------------------------------------------------------ -# Suffix initialization and compiler suffix detection. -# ------------------------------------------------------------------------ - -set(_Boost_VARS_NAME - Boost_COMPILER - Boost_THREADAPI - Boost_USE_DEBUG_PYTHON - Boost_USE_MULTITHREADED - Boost_USE_STATIC_LIBS - Boost_USE_STATIC_RUNTIME - Boost_USE_STLPORT - Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS - ) -_Boost_CHANGE_DETECT(_Boost_CHANGE_LIBNAME ${_Boost_VARS_NAME}) - -# Setting some more suffixes for the library -set(Boost_LIB_PREFIX "") -if ( WIN32 AND Boost_USE_STATIC_LIBS AND NOT CYGWIN) - set(Boost_LIB_PREFIX "lib") -endif() - -if (Boost_COMPILER) - set(_boost_COMPILER ${Boost_COMPILER}) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "using user-specified Boost_COMPILER = ${_boost_COMPILER}") - endif() -else() - # Attempt to guess the compiler suffix - # NOTE: this is not perfect yet, if you experience any issues - # please report them and use the Boost_COMPILER variable - # to work around the problems. - _Boost_GUESS_COMPILER_PREFIX(_boost_COMPILER) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "guessed _boost_COMPILER = ${_boost_COMPILER}") - endif() -endif() - -set (_boost_MULTITHREADED "-mt") -if( NOT Boost_USE_MULTITHREADED ) - set (_boost_MULTITHREADED "") -endif() -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_MULTITHREADED = ${_boost_MULTITHREADED}") -endif() - -#====================== -# Systematically build up the Boost ABI tag -# http://boost.org/doc/libs/1_41_0/more/getting_started/windows.html#library-naming -set( _boost_RELEASE_ABI_TAG "-") -set( _boost_DEBUG_ABI_TAG "-") -# Key Use this library when: -# s linking statically to the C++ standard library and -# compiler runtime support libraries. -if(Boost_USE_STATIC_RUNTIME) - set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}s") - set( _boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}s") -endif() -# g using debug versions of the standard and runtime -# support libraries -if(WIN32) - if(MSVC OR "${CMAKE_CXX_COMPILER}" MATCHES "icl" - OR "${CMAKE_CXX_COMPILER}" MATCHES "icpc") - set(_boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}g") - endif() -endif() -# y using special debug build of python -if(Boost_USE_DEBUG_PYTHON) - set(_boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}y") -endif() -# d using a debug version of your code -set(_boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}d") -# p using the STLport standard library rather than the -# default one supplied with your compiler -if(Boost_USE_STLPORT) - set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}p") - set( _boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}p") -endif() -# n using the STLport deprecated "native iostreams" feature -if(Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS) - set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}n") - set( _boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}n") -endif() - -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_RELEASE_ABI_TAG = ${_boost_RELEASE_ABI_TAG}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_DEBUG_ABI_TAG = ${_boost_DEBUG_ABI_TAG}") -endif() - -# ------------------------------------------------------------------------ -# Begin finding boost libraries -# ------------------------------------------------------------------------ -set(_Boost_VARS_LIB BOOST_LIBRARYDIR Boost_LIBRARY_DIR) -_Boost_CHANGE_DETECT(_Boost_CHANGE_LIBDIR ${_Boost_VARS_DIR} ${_Boost_VARS_LIB} Boost_INCLUDE_DIR) -# Clear Boost_LIBRARY_DIR if it did not change but other input affecting the -# location did. We will find a new one based on the new inputs. -if(_Boost_CHANGE_LIBDIR AND NOT _Boost_LIBRARY_DIR_CHANGED) - unset(Boost_LIBRARY_DIR CACHE) -endif() - -if(Boost_LIBRARY_DIR) - set(_boost_LIBRARY_SEARCH_DIRS ${Boost_LIBRARY_DIR} NO_DEFAULT_PATH) -else() - set(_boost_LIBRARY_SEARCH_DIRS "") - if(BOOST_LIBRARYDIR) - list(APPEND _boost_LIBRARY_SEARCH_DIRS ${BOOST_LIBRARYDIR}) - elseif(_ENV_BOOST_LIBRARYDIR) - list(APPEND _boost_LIBRARY_SEARCH_DIRS ${_ENV_BOOST_LIBRARYDIR}) - endif() - - if(BOOST_ROOT) - list(APPEND _boost_LIBRARY_SEARCH_DIRS ${BOOST_ROOT}/lib ${BOOST_ROOT}/stage/lib) - elseif(_ENV_BOOST_ROOT) - list(APPEND _boost_LIBRARY_SEARCH_DIRS ${_ENV_BOOST_ROOT}/lib ${_ENV_BOOST_ROOT}/stage/lib) - endif() - - list(APPEND _boost_LIBRARY_SEARCH_DIRS - ${Boost_INCLUDE_DIR}/lib - ${Boost_INCLUDE_DIR}/../lib - ${Boost_INCLUDE_DIR}/../lib/${CMAKE_LIBRARY_ARCHITECTURE} - ${Boost_INCLUDE_DIR}/stage/lib - ) - if( Boost_NO_SYSTEM_PATHS ) - list(APPEND _boost_LIBRARY_SEARCH_DIRS NO_CMAKE_SYSTEM_PATH) - else() - list(APPEND _boost_LIBRARY_SEARCH_DIRS PATHS - C:/boost/lib - C:/boost - /sw/local/lib - ) - endif() -endif() - -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_LIBRARY_SEARCH_DIRS = ${_boost_LIBRARY_SEARCH_DIRS}") -endif() - -# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES -if( Boost_USE_STATIC_LIBS ) - set( _boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) - if(WIN32) - set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) - else() - set(CMAKE_FIND_LIBRARY_SUFFIXES .a ) - endif() -endif() - -# We want to use the tag inline below without risking double dashes -if(_boost_RELEASE_ABI_TAG) - if(${_boost_RELEASE_ABI_TAG} STREQUAL "-") - set(_boost_RELEASE_ABI_TAG "") - endif() -endif() -if(_boost_DEBUG_ABI_TAG) - if(${_boost_DEBUG_ABI_TAG} STREQUAL "-") - set(_boost_DEBUG_ABI_TAG "") - endif() -endif() - -# The previous behavior of FindBoost when Boost_USE_STATIC_LIBS was enabled -# on WIN32 was to: -# 1. Search for static libs compiled against a SHARED C++ standard runtime library (use if found) -# 2. Search for static libs compiled against a STATIC C++ standard runtime library (use if found) -# We maintain this behavior since changing it could break people's builds. -# To disable the ambiguous behavior, the user need only -# set Boost_USE_STATIC_RUNTIME either ON or OFF. -set(_boost_STATIC_RUNTIME_WORKAROUND false) -if(WIN32 AND Boost_USE_STATIC_LIBS) - if(NOT DEFINED Boost_USE_STATIC_RUNTIME) - set(_boost_STATIC_RUNTIME_WORKAROUND true) - endif() -endif() - -# On versions < 1.35, remove the System library from the considered list -# since it wasn't added until 1.35. -if(Boost_VERSION AND Boost_FIND_COMPONENTS) - if(Boost_VERSION LESS 103500) - list(REMOVE_ITEM Boost_FIND_COMPONENTS system) - endif() -endif() - -# If the user changed any of our control inputs flush previous results. -if(_Boost_CHANGE_LIBDIR OR _Boost_CHANGE_LIBNAME) - foreach(COMPONENT ${_Boost_COMPONENTS_SEARCHED}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - foreach(c DEBUG RELEASE) - set(_var Boost_${UPPERCOMPONENT}_LIBRARY_${c}) - unset(${_var} CACHE) - set(${_var} "${_var}-NOTFOUND") - endforeach() - endforeach() - set(_Boost_COMPONENTS_SEARCHED "") -endif() - -foreach(COMPONENT ${Boost_FIND_COMPONENTS}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - - set( _boost_docstring_release "Boost ${COMPONENT} library (release)") - set( _boost_docstring_debug "Boost ${COMPONENT} library (debug)") - - # - # Find RELEASE libraries - # - set(_boost_RELEASE_NAMES - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} - ${Boost_LIB_PREFIX}boost_${COMPONENT} ) - if(_boost_STATIC_RUNTIME_WORKAROUND) - set(_boost_RELEASE_STATIC_ABI_TAG "-s${_boost_RELEASE_ABI_TAG}") - list(APPEND _boost_RELEASE_NAMES - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} ) - endif() - if(Boost_THREADAPI AND ${COMPONENT} STREQUAL "thread") - _Boost_PREPEND_LIST_WITH_THREADAPI(_boost_RELEASE_NAMES ${_boost_RELEASE_NAMES}) - endif() - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Searching for ${UPPERCOMPONENT}_LIBRARY_RELEASE: ${_boost_RELEASE_NAMES}") - endif() - - # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing. - string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS}") - - _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE - NAMES ${_boost_RELEASE_NAMES} - HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp} - NAMES_PER_DIR - DOC "${_boost_docstring_release}" - ) - - # - # Find DEBUG libraries - # - set(_boost_DEBUG_NAMES - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED} - ${Boost_LIB_PREFIX}boost_${COMPONENT} ) - if(_boost_STATIC_RUNTIME_WORKAROUND) - set(_boost_DEBUG_STATIC_ABI_TAG "-s${_boost_DEBUG_ABI_TAG}") - list(APPEND _boost_DEBUG_NAMES - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} ) - endif() - if(Boost_THREADAPI AND ${COMPONENT} STREQUAL "thread") - _Boost_PREPEND_LIST_WITH_THREADAPI(_boost_DEBUG_NAMES ${_boost_DEBUG_NAMES}) - endif() - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Searching for ${UPPERCOMPONENT}_LIBRARY_DEBUG: ${_boost_DEBUG_NAMES}") - endif() - - # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing. - string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS}") - - _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG - NAMES ${_boost_DEBUG_NAMES} - HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp} - NAMES_PER_DIR - DOC "${_boost_docstring_debug}" - ) - - if(Boost_REALPATH) - _Boost_SWAP_WITH_REALPATH(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE "${_boost_docstring_release}") - _Boost_SWAP_WITH_REALPATH(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG "${_boost_docstring_debug}" ) - endif() - - _Boost_ADJUST_LIB_VARS(${UPPERCOMPONENT}) - -endforeach() - -# Restore the original find library ordering -if( Boost_USE_STATIC_LIBS ) - set(CMAKE_FIND_LIBRARY_SUFFIXES ${_boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) -endif() - -# ------------------------------------------------------------------------ -# End finding boost libraries -# ------------------------------------------------------------------------ - -set(Boost_INCLUDE_DIRS ${Boost_INCLUDE_DIR}) -set(Boost_LIBRARY_DIRS ${Boost_LIBRARY_DIR}) - -# The above setting of Boost_FOUND was based only on the header files. -# Update it for the requested component libraries. -if(Boost_FOUND) - # The headers were found. Check for requested component libs. - set(_boost_CHECKED_COMPONENT FALSE) - set(_Boost_MISSING_COMPONENTS "") - foreach(COMPONENT ${Boost_FIND_COMPONENTS}) - string(TOUPPER ${COMPONENT} COMPONENT) - set(_boost_CHECKED_COMPONENT TRUE) - if(NOT Boost_${COMPONENT}_FOUND) - string(TOLOWER ${COMPONENT} COMPONENT) - list(APPEND _Boost_MISSING_COMPONENTS ${COMPONENT}) - endif() - endforeach() - - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] Boost_FOUND = ${Boost_FOUND}") - endif() - - if (_Boost_MISSING_COMPONENTS) - set(Boost_FOUND 0) - # We were unable to find some libraries, so generate a sensible - # error message that lists the libraries we were unable to find. - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}\nThe following Boost libraries could not be found:\n") - foreach(COMPONENT ${_Boost_MISSING_COMPONENTS}) - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON} boost_${COMPONENT}\n") - endforeach() - - list(LENGTH Boost_FIND_COMPONENTS Boost_NUM_COMPONENTS_WANTED) - list(LENGTH _Boost_MISSING_COMPONENTS Boost_NUM_MISSING_COMPONENTS) - if (${Boost_NUM_COMPONENTS_WANTED} EQUAL ${Boost_NUM_MISSING_COMPONENTS}) - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}No Boost libraries were found. You may need to set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") - else () - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}Some (but not all) of the required Boost libraries were found. You may need to install these additional Boost libraries. Alternatively, set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") - endif () - endif () - - if( NOT Boost_LIBRARY_DIRS AND NOT _boost_CHECKED_COMPONENT ) - # Compatibility Code for backwards compatibility with CMake - # 2.4's FindBoost module. - - # Look for the boost library path. - # Note that the user may not have installed any libraries - # so it is quite possible the Boost_LIBRARY_DIRS may not exist. - set(_boost_LIB_DIR ${Boost_INCLUDE_DIR}) - - if("${_boost_LIB_DIR}" MATCHES "boost-[0-9]+") - get_filename_component(_boost_LIB_DIR ${_boost_LIB_DIR} PATH) - endif() - - if("${_boost_LIB_DIR}" MATCHES "/include$") - # Strip off the trailing "/include" in the path. - get_filename_component(_boost_LIB_DIR ${_boost_LIB_DIR} PATH) - endif() - - if(EXISTS "${_boost_LIB_DIR}/lib") - set(_boost_LIB_DIR ${_boost_LIB_DIR}/lib) - else() - if(EXISTS "${_boost_LIB_DIR}/stage/lib") - set(_boost_LIB_DIR ${_boost_LIB_DIR}/stage/lib) - else() - set(_boost_LIB_DIR "") - endif() - endif() - - if(_boost_LIB_DIR AND EXISTS "${_boost_LIB_DIR}") - set(Boost_LIBRARY_DIRS ${_boost_LIB_DIR}) - endif() - - endif() -else() - # Boost headers were not found so no components were found. - foreach(COMPONENT ${Boost_FIND_COMPONENTS}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - set(Boost_${UPPERCOMPONENT}_FOUND 0) - endforeach() -endif() - -# ------------------------------------------------------------------------ -# Notification to end user about what was found -# ------------------------------------------------------------------------ - -set(Boost_LIBRARIES "") -if(Boost_FOUND) - if(NOT Boost_FIND_QUIETLY) - message(STATUS "Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") - if(Boost_FIND_COMPONENTS) - message(STATUS "Found the following Boost libraries:") - endif() - endif() - foreach( COMPONENT ${Boost_FIND_COMPONENTS} ) - string( TOUPPER ${COMPONENT} UPPERCOMPONENT ) - if( Boost_${UPPERCOMPONENT}_FOUND ) - if(NOT Boost_FIND_QUIETLY) - message (STATUS " ${COMPONENT}") - endif() - list(APPEND Boost_LIBRARIES ${Boost_${UPPERCOMPONENT}_LIBRARY}) - endif() - endforeach() - - # Add pthread library on UNIX if thread component was found - _Boost_consider_adding_pthreads(Boost_LIBRARIES ${Boost_LIBRARIES}) -else() - if(Boost_FIND_REQUIRED) - message(SEND_ERROR "Unable to find the requested Boost libraries.\n${Boost_ERROR_REASON}") - else() - if(NOT Boost_FIND_QUIETLY) - # we opt not to automatically output Boost_ERROR_REASON here as - # it could be quite lengthy and somewhat imposing in its requests - # Since Boost is not always a required dependency we'll leave this - # up to the end-user. - if(Boost_DEBUG OR Boost_DETAILED_FAILURE_MSG) - message(STATUS "Could NOT find Boost\n${Boost_ERROR_REASON}") - else() - message(STATUS "Could NOT find Boost") - endif() - endif() - endif() -endif() - -# Configure display of cache entries in GUI. -foreach(v BOOSTROOT BOOST_ROOT ${_Boost_VARS_INC} ${_Boost_VARS_LIB}) - get_property(_type CACHE ${v} PROPERTY TYPE) - if(_type) - set_property(CACHE ${v} PROPERTY ADVANCED 1) - if("x${_type}" STREQUAL "xUNINITIALIZED") - if("x${v}" STREQUAL "xBoost_ADDITIONAL_VERSIONS") - set_property(CACHE ${v} PROPERTY TYPE STRING) - else() - set_property(CACHE ${v} PROPERTY TYPE PATH) - endif() - endif() - endif() -endforeach() - -# Record last used values of input variables so we can -# detect on the next run if the user changed them. -foreach(v - ${_Boost_VARS_INC} ${_Boost_VARS_LIB} - ${_Boost_VARS_DIR} ${_Boost_VARS_NAME} - ) - if(DEFINED ${v}) - set(_${v}_LAST "${${v}}" CACHE INTERNAL "Last used ${v} value.") - else() - unset(_${v}_LAST CACHE) - endif() -endforeach() - -# Maintain a persistent list of components requested anywhere since -# the last flush. -set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}") -list(APPEND _Boost_COMPONENTS_SEARCHED ${Boost_FIND_COMPONENTS}) -list(REMOVE_DUPLICATES _Boost_COMPONENTS_SEARCHED) -list(SORT _Boost_COMPONENTS_SEARCHED) -set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}" - CACHE INTERNAL "Components requested for this build tree.") +# - Find Boost include dirs and libraries +# Use this module by invoking find_package with the form: +# find_package(Boost +# [version] [EXACT] # Minimum or EXACT version e.g. 1.36.0 +# [REQUIRED] # Fail with error if Boost is not found +# [COMPONENTS ...] # Boost libraries by their canonical name +# ) # e.g. "date_time" for "libboost_date_time" +# This module finds headers and requested component libraries OR a CMake +# package configuration file provided by a "Boost CMake" build. For the +# latter case skip to the "Boost CMake" section below. For the former +# case results are reported in variables: +# Boost_FOUND - True if headers and requested libraries were found +# Boost_INCLUDE_DIRS - Boost include directories +# Boost_LIBRARY_DIRS - Link directories for Boost libraries +# Boost_LIBRARIES - Boost component libraries to be linked +# Boost__FOUND - True if component was found ( is upper-case) +# Boost__LIBRARY - Libraries to link for component (may include +# target_link_libraries debug/optimized keywords) +# Boost_VERSION - BOOST_VERSION value from boost/version.hpp +# Boost_LIB_VERSION - Version string appended to library filenames +# Boost_MAJOR_VERSION - Boost major version number (X in X.y.z) +# Boost_MINOR_VERSION - Boost minor version number (Y in x.Y.z) +# Boost_SUBMINOR_VERSION - Boost subminor version number (Z in x.y.Z) +# Boost_LIB_DIAGNOSTIC_DEFINITIONS (Windows) +# - Pass to add_definitions() to have diagnostic +# information about Boost's automatic linking +# displayed during compilation +# +# This module reads hints about search locations from variables: +# BOOST_ROOT - Preferred installation prefix +# (or BOOSTROOT) +# BOOST_INCLUDEDIR - Preferred include directory e.g. /include +# BOOST_LIBRARYDIR - Preferred library directory e.g. /lib +# Boost_NO_SYSTEM_PATHS - Set to ON to disable searching in locations not +# specified by these hint variables. Default is OFF. +# Boost_ADDITIONAL_VERSIONS +# - List of Boost versions not known to this module +# (Boost install locations may contain the version) +# and saves search results persistently in CMake cache entries: +# Boost_INCLUDE_DIR - Directory containing Boost headers +# Boost_LIBRARY_DIR - Directory containing Boost libraries +# Boost__LIBRARY_DEBUG - Component library debug variant +# Boost__LIBRARY_RELEASE - Component library release variant +# Users may set the these hints or results as cache entries. Projects should +# not read these entries directly but instead use the above result variables. +# Note that some hint names start in upper-case "BOOST". One may specify +# these as environment variables if they are not specified as CMake variables +# or cache entries. +# +# This module first searches for the Boost header files using the above hint +# variables (excluding BOOST_LIBRARYDIR) and saves the result in +# Boost_INCLUDE_DIR. Then it searches for requested component libraries using +# the above hints (excluding BOOST_INCLUDEDIR and Boost_ADDITIONAL_VERSIONS), +# "lib" directories near Boost_INCLUDE_DIR, and the library name configuration +# settings below. It saves the library directory in Boost_LIBRARY_DIR and +# individual library locations in Boost__LIBRARY_DEBUG and +# Boost__LIBRARY_RELEASE. When one changes settings used by previous +# searches in the same build tree (excluding environment variables) this +# module discards previous search results affected by the changes and searches +# again. +# +# Boost libraries come in many variants encoded in their file name. Users or +# projects may tell this module which variant to find by setting variables: +# Boost_USE_MULTITHREADED - Set to OFF to use the non-multithreaded +# libraries ('mt' tag). Default is ON. +# Boost_USE_STATIC_LIBS - Set to ON to force the use of the static +# libraries. Default is OFF. +# Boost_USE_STATIC_RUNTIME - Set to ON or OFF to specify whether to use +# libraries linked statically to the C++ runtime +# ('s' tag). Default is platform dependent. +# Boost_USE_DEBUG_PYTHON - Set to ON to use libraries compiled with a +# debug Python build ('y' tag). Default is OFF. +# Boost_USE_STLPORT - Set to ON to use libraries compiled with +# STLPort ('p' tag). Default is OFF. +# Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS +# - Set to ON to use libraries compiled with +# STLPort deprecated "native iostreams" +# ('n' tag). Default is OFF. +# Boost_COMPILER - Set to the compiler-specific library suffix +# (e.g. "-gcc43"). Default is auto-computed +# for the C++ compiler in use. +# Boost_THREADAPI - Suffix for "thread" component library name, +# such as "pthread" or "win32". Names with +# and without this suffix will both be tried. +# Other variables one may set to control this module are: +# Boost_DEBUG - Set to ON to enable debug output from FindBoost. +# Please enable this before filing any bug report. +# Boost_DETAILED_FAILURE_MSG +# - Set to ON to add detailed information to the +# failure message even when the REQUIRED option +# is not given to the find_package call. +# Boost_REALPATH - Set to ON to resolve symlinks for discovered +# libraries to assist with packaging. For example, +# the "system" component library may be resolved to +# "/usr/lib/libboost_system.so.1.42.0" instead of +# "/usr/lib/libboost_system.so". This does not +# affect linking and should not be enabled unless +# the user needs this information. +# On Visual Studio and Borland compilers Boost headers request automatic +# linking to corresponding libraries. This requires matching libraries to be +# linked explicitly or available in the link library search path. In this +# case setting Boost_USE_STATIC_LIBS to OFF may not achieve dynamic linking. +# Boost automatic linking typically requests static libraries with a few +# exceptions (such as Boost.Python). Use +# add_definitions(${Boost_LIB_DIAGNOSTIC_DEFINITIONS}) +# to ask Boost to report information about automatic linking requests. +# +# Example to find Boost headers only: +# find_package(Boost 1.36.0) +# if(Boost_FOUND) +# include_directories(${Boost_INCLUDE_DIRS}) +# add_executable(foo foo.cc) +# endif() +# Example to find Boost headers and some libraries: +# set(Boost_USE_STATIC_LIBS ON) +# set(Boost_USE_MULTITHREADED ON) +# set(Boost_USE_STATIC_RUNTIME OFF) +# find_package(Boost 1.36.0 COMPONENTS date_time filesystem system ...) +# if(Boost_FOUND) +# include_directories(${Boost_INCLUDE_DIRS}) +# add_executable(foo foo.cc) +# target_link_libraries(foo ${Boost_LIBRARIES}) +# endif() +# +# Boost CMake ---------------------------------------------------------- +# +# If Boost was built using the boost-cmake project it provides a package +# configuration file for use with find_package's Config mode. This module +# looks for the package configuration file called BoostConfig.cmake or +# boost-config.cmake and stores the result in cache entry "Boost_DIR". If +# found, the package configuration file is loaded and this module returns with +# no further action. See documentation of the Boost CMake package +# configuration for details on what it provides. +# +# Set Boost_NO_BOOST_CMAKE to ON to disable the search for boost-cmake. + +#============================================================================= +# Copyright 2006-2012 Kitware, Inc. +# Copyright 2006-2008 Andreas Schneider +# Copyright 2007 Wengo +# Copyright 2007 Mike Jackson +# Copyright 2008 Andreas Pakulat +# Copyright 2008-2012 Philip Lowman +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + + +#------------------------------------------------------------------------------- +# Before we go searching, check whether boost-cmake is avaialble, unless the +# user specifically asked NOT to search for boost-cmake. +# +# If Boost_DIR is set, this behaves as any find_package call would. If not, +# it looks at BOOST_ROOT and BOOSTROOT to find Boost. +# + +message(STATUS "Using custom FindBoost.cmake") + +if (NOT Boost_NO_BOOST_CMAKE) + # If Boost_DIR is not set, look for BOOSTROOT and BOOST_ROOT as alternatives, + # since these are more conventional for Boost. + if ("$ENV{Boost_DIR}" STREQUAL "") + if (NOT "$ENV{BOOST_ROOT}" STREQUAL "") + set(ENV{Boost_DIR} $ENV{BOOST_ROOT}) + elseif (NOT "$ENV{BOOSTROOT}" STREQUAL "") + set(ENV{Boost_DIR} $ENV{BOOSTROOT}) + endif() + endif() + + # Do the same find_package call but look specifically for the CMake version. + # Note that args are passed in the Boost_FIND_xxxxx variables, so there is no + # need to delegate them to this find_package call. + find_package(Boost QUIET NO_MODULE) + mark_as_advanced(Boost_DIR) + + # If we found boost-cmake, then we're done. Print out what we found. + # Otherwise let the rest of the module try to find it. + if (Boost_FOUND) + message("Boost ${Boost_FIND_VERSION} found.") + if (Boost_FIND_COMPONENTS) + message("Found Boost components:") + message(" ${Boost_FIND_COMPONENTS}") + endif() + return() + endif() +endif() + + +#------------------------------------------------------------------------------- +# FindBoost functions & macros +# + +############################################ +# +# Check the existence of the libraries. +# +############################################ +# This macro was taken directly from the FindQt4.cmake file that is included +# with the CMake distribution. This is NOT my work. All work was done by the +# original authors of the FindQt4.cmake file. Only minor modifications were +# made to remove references to Qt and make this file more generally applicable +# And ELSE/ENDIF pairs were removed for readability. +######################################################################### + +macro(_Boost_ADJUST_LIB_VARS basename) + if(Boost_INCLUDE_DIR ) + if(Boost_${basename}_LIBRARY_DEBUG AND Boost_${basename}_LIBRARY_RELEASE) + # if the generator supports configuration types then set + # optimized and debug libraries, or if the CMAKE_BUILD_TYPE has a value + if(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) + set(Boost_${basename}_LIBRARY optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG}) + else() + # if there are no configuration types and CMAKE_BUILD_TYPE has no value + # then just use the release libraries + set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE} ) + endif() + # FIXME: This probably should be set for both cases + set(Boost_${basename}_LIBRARIES optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG}) + endif() + + # if only the release version was found, set the debug variable also to the release version + if(Boost_${basename}_LIBRARY_RELEASE AND NOT Boost_${basename}_LIBRARY_DEBUG) + set(Boost_${basename}_LIBRARY_DEBUG ${Boost_${basename}_LIBRARY_RELEASE}) + set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE}) + set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_RELEASE}) + endif() + + # if only the debug version was found, set the release variable also to the debug version + if(Boost_${basename}_LIBRARY_DEBUG AND NOT Boost_${basename}_LIBRARY_RELEASE) + set(Boost_${basename}_LIBRARY_RELEASE ${Boost_${basename}_LIBRARY_DEBUG}) + set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_DEBUG}) + set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_DEBUG}) + endif() + + # If the debug & release library ends up being the same, omit the keywords + if(${Boost_${basename}_LIBRARY_RELEASE} STREQUAL ${Boost_${basename}_LIBRARY_DEBUG}) + set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE} ) + set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_RELEASE} ) + endif() + + if(Boost_${basename}_LIBRARY) + set(Boost_${basename}_FOUND ON) + endif() + + endif() + # Make variables changeble to the advanced user + mark_as_advanced( + Boost_${basename}_LIBRARY_RELEASE + Boost_${basename}_LIBRARY_DEBUG + ) +endmacro() + +macro(_Boost_CHANGE_DETECT changed_var) + set(${changed_var} 0) + foreach(v ${ARGN}) + if(DEFINED _Boost_COMPONENTS_SEARCHED) + if(${v}) + if(_${v}_LAST) + string(COMPARE NOTEQUAL "${${v}}" "${_${v}_LAST}" _${v}_CHANGED) + else() + set(_${v}_CHANGED 1) + endif() + elseif(_${v}_LAST) + set(_${v}_CHANGED 1) + endif() + if(_${v}_CHANGED) + set(${changed_var} 1) + endif() + else() + set(_${v}_CHANGED 0) + endif() + endforeach() +endmacro() + +macro(_Boost_FIND_LIBRARY var) + find_library(${var} ${ARGN}) + + # If we found the first library save Boost_LIBRARY_DIR. + if(${var} AND NOT Boost_LIBRARY_DIR) + get_filename_component(_dir "${${var}}" PATH) + set(Boost_LIBRARY_DIR "${_dir}" CACHE PATH "Boost library directory" FORCE) + endif() + + # If Boost_LIBRARY_DIR is known then search only there. + if(Boost_LIBRARY_DIR) + set(_boost_LIBRARY_SEARCH_DIRS ${Boost_LIBRARY_DIR} NO_DEFAULT_PATH) + endif() +endmacro() + +#------------------------------------------------------------------------------- + +# +# Runs compiler with "-dumpversion" and parses major/minor +# version with a regex. +# +function(_Boost_COMPILER_DUMPVERSION _OUTPUT_VERSION) + + exec_program(${CMAKE_CXX_COMPILER} + ARGS ${CMAKE_CXX_COMPILER_ARG1} -dumpversion + OUTPUT_VARIABLE _boost_COMPILER_VERSION + ) + string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2" + _boost_COMPILER_VERSION ${_boost_COMPILER_VERSION}) + + set(${_OUTPUT_VERSION} ${_boost_COMPILER_VERSION} PARENT_SCOPE) +endfunction() + +# +# Take a list of libraries with "thread" in it +# and prepend duplicates with "thread_${Boost_THREADAPI}" +# at the front of the list +# +function(_Boost_PREPEND_LIST_WITH_THREADAPI _output) + set(_orig_libnames ${ARGN}) + string(REPLACE "thread" "thread_${Boost_THREADAPI}" _threadapi_libnames "${_orig_libnames}") + set(${_output} ${_threadapi_libnames} ${_orig_libnames} PARENT_SCOPE) +endfunction() + +# +# If a library is found, replace its cache entry with its REALPATH +# +function(_Boost_SWAP_WITH_REALPATH _library _docstring) + if(${_library}) + get_filename_component(_boost_filepathreal ${${_library}} REALPATH) + unset(${_library} CACHE) + set(${_library} ${_boost_filepathreal} CACHE FILEPATH "${_docstring}") + endif() +endfunction() + +function(_Boost_CHECK_SPELLING _var) + if(${_var}) + string(TOUPPER ${_var} _var_UC) + message(FATAL_ERROR "ERROR: ${_var} is not the correct spelling. The proper spelling is ${_var_UC}.") + endif() +endfunction() + +# Guesses Boost's compiler prefix used in built library names +# Returns the guess by setting the variable pointed to by _ret +function(_Boost_GUESS_COMPILER_PREFIX _ret) + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel" + OR "${CMAKE_CXX_COMPILER}" MATCHES "icl" + OR "${CMAKE_CXX_COMPILER}" MATCHES "icpc") + if(WIN32) + set (_boost_COMPILER "-iw") + else() + set (_boost_COMPILER "-il") + endif() + elseif (MSVC12) + set(_boost_COMPILER "-vc120") + elseif (MSVC11) + set(_boost_COMPILER "-vc110") + elseif (MSVC10) + set(_boost_COMPILER "-vc100") + elseif (MSVC90) + set(_boost_COMPILER "-vc90") + elseif (MSVC80) + set(_boost_COMPILER "-vc80") + elseif (MSVC71) + set(_boost_COMPILER "-vc71") + elseif (MSVC70) # Good luck! + set(_boost_COMPILER "-vc7") # yes, this is correct + elseif (MSVC60) # Good luck! + set(_boost_COMPILER "-vc6") # yes, this is correct + elseif (BORLAND) + set(_boost_COMPILER "-bcb") + elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "SunPro") + set(_boost_COMPILER "-sw") + elseif (MINGW) + if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34) + set(_boost_COMPILER "-mgw") # no GCC version encoding prior to 1.34 + else() + _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION) + set(_boost_COMPILER "-mgw${_boost_COMPILER_VERSION}") + endif() + elseif (UNIX) + if (CMAKE_COMPILER_IS_GNUCXX) + if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34) + set(_boost_COMPILER "-gcc") # no GCC version encoding prior to 1.34 + else() + _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION) + # Determine which version of GCC we have. + if(APPLE) + if(Boost_MINOR_VERSION) + if(${Boost_MINOR_VERSION} GREATER 35) + # In Boost 1.36.0 and newer, the mangled compiler name used + # on Mac OS X/Darwin is "xgcc". + set(_boost_COMPILER "-xgcc${_boost_COMPILER_VERSION}") + else() + # In Boost <= 1.35.0, there is no mangled compiler name for + # the Mac OS X/Darwin version of GCC. + set(_boost_COMPILER "") + endif() + else() + # We don't know the Boost version, so assume it's + # pre-1.36.0. + set(_boost_COMPILER "") + endif() + else() + set(_boost_COMPILER "-gcc${_boost_COMPILER_VERSION}") + endif() + endif() + endif () + else() + # TODO at least Boost_DEBUG here? + set(_boost_COMPILER "") + endif() + set(${_ret} ${_boost_COMPILER} PARENT_SCOPE) +endfunction() + +function(_Boost_consider_adding_pthreads _outvar) + # On Unix platforms (excluding cygwin) add pthreads to Boost_LIBRARIES + # if the user is searching for the boost-thread component. + if(UNIX AND NOT CYGWIN) + list(FIND Boost_FIND_COMPONENTS thread _using_boost_thread) + if(_using_boost_thread GREATER -1) + find_library(BOOST_THREAD_LIBRARY NAMES pthread + DOC "The threading library used by boost-thread" + ) + if(BOOST_THREAD_LIBRARY) + set(${_outvar} ${ARGN} ${BOOST_THREAD_LIBRARY} PARENT_SCOPE) + endif() + endif() + endif() +endfunction() + +# +# End functions/macros +# +#------------------------------------------------------------------------------- + +#------------------------------------------------------------------------------- +# main. +#------------------------------------------------------------------------------- + +if(NOT DEFINED Boost_USE_MULTITHREADED) + set(Boost_USE_MULTITHREADED TRUE) +endif() + +# Check the version of Boost against the requested version. +if(Boost_FIND_VERSION AND NOT Boost_FIND_VERSION_MINOR) + message(SEND_ERROR "When requesting a specific version of Boost, you must provide at least the major and minor version numbers, e.g., 1.34") +endif() + +if(Boost_FIND_VERSION_EXACT) + # The version may appear in a directory with or without the patch + # level, even when the patch level is non-zero. + set(_boost_TEST_VERSIONS + "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}.${Boost_FIND_VERSION_PATCH}" + "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") +else() + # The user has not requested an exact version. Among known + # versions, find those that are acceptable to the user request. + set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS} + "1.56.0" "1.56" "1.55.0" "1.55" "1.54.0" "1.54" + "1.53.0" "1.53" "1.52.0" "1.52" "1.51.0" "1.51" + "1.50.0" "1.50" "1.49.0" "1.49" "1.48.0" "1.48" "1.47.0" "1.47" "1.46.1" + "1.46.0" "1.46" "1.45.0" "1.45" "1.44.0" "1.44" "1.43.0" "1.43" "1.42.0" "1.42" + "1.41.0" "1.41" "1.40.0" "1.40" "1.39.0" "1.39" "1.38.0" "1.38" "1.37.0" "1.37" + "1.36.1" "1.36.0" "1.36" "1.35.1" "1.35.0" "1.35" "1.34.1" "1.34.0" + "1.34" "1.33.1" "1.33.0" "1.33") + set(_boost_TEST_VERSIONS) + if(Boost_FIND_VERSION) + set(_Boost_FIND_VERSION_SHORT "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") + # Select acceptable versions. + foreach(version ${_Boost_KNOWN_VERSIONS}) + if(NOT "${version}" VERSION_LESS "${Boost_FIND_VERSION}") + # This version is high enough. + list(APPEND _boost_TEST_VERSIONS "${version}") + elseif("${version}.99" VERSION_EQUAL "${_Boost_FIND_VERSION_SHORT}.99") + # This version is a short-form for the requested version with + # the patch level dropped. + list(APPEND _boost_TEST_VERSIONS "${version}") + endif() + endforeach() + else() + # Any version is acceptable. + set(_boost_TEST_VERSIONS "${_Boost_KNOWN_VERSIONS}") + endif() +endif() + +# The reason that we failed to find Boost. This will be set to a +# user-friendly message when we fail to find some necessary piece of +# Boost. +set(Boost_ERROR_REASON) + +if(Boost_DEBUG) + # Output some of their choices + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "_boost_TEST_VERSIONS = ${_boost_TEST_VERSIONS}") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "Boost_USE_MULTITHREADED = ${Boost_USE_MULTITHREADED}") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "Boost_USE_STATIC_LIBS = ${Boost_USE_STATIC_LIBS}") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "Boost_USE_STATIC_RUNTIME = ${Boost_USE_STATIC_RUNTIME}") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "Boost_ADDITIONAL_VERSIONS = ${Boost_ADDITIONAL_VERSIONS}") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "Boost_NO_SYSTEM_PATHS = ${Boost_NO_SYSTEM_PATHS}") +endif() + +if(WIN32) + # In windows, automatic linking is performed, so you do not have + # to specify the libraries. If you are linking to a dynamic + # runtime, then you can choose to link to either a static or a + # dynamic Boost library, the default is to do a static link. You + # can alter this for a specific library "whatever" by defining + # BOOST_WHATEVER_DYN_LINK to force Boost library "whatever" to be + # linked dynamically. Alternatively you can force all Boost + # libraries to dynamic link by defining BOOST_ALL_DYN_LINK. + + # This feature can be disabled for Boost library "whatever" by + # defining BOOST_WHATEVER_NO_LIB, or for all of Boost by defining + # BOOST_ALL_NO_LIB. + + # If you want to observe which libraries are being linked against + # then defining BOOST_LIB_DIAGNOSTIC will cause the auto-linking + # code to emit a #pragma message each time a library is selected + # for linking. + set(Boost_LIB_DIAGNOSTIC_DEFINITIONS "-DBOOST_LIB_DIAGNOSTIC") +endif() + +_Boost_CHECK_SPELLING(Boost_ROOT) +_Boost_CHECK_SPELLING(Boost_LIBRARYDIR) +_Boost_CHECK_SPELLING(Boost_INCLUDEDIR) + +# Collect environment variable inputs as hints. Do not consider changes. +foreach(v BOOSTROOT BOOST_ROOT BOOST_INCLUDEDIR BOOST_LIBRARYDIR) + set(_env $ENV{${v}}) + if(_env) + file(TO_CMAKE_PATH "${_env}" _ENV_${v}) + else() + set(_ENV_${v} "") + endif() +endforeach() +if(NOT _ENV_BOOST_ROOT AND _ENV_BOOSTROOT) + set(_ENV_BOOST_ROOT "${_ENV_BOOSTROOT}") +endif() + +# Collect inputs and cached results. Detect changes since the last run. +if(NOT BOOST_ROOT AND BOOSTROOT) + set(BOOST_ROOT "${BOOSTROOT}") +endif() +set(_Boost_VARS_DIR + BOOST_ROOT + Boost_NO_SYSTEM_PATHS + ) + +if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "Declared as CMake or Environmental Variables:") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + " BOOST_ROOT = ${BOOST_ROOT}") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + " BOOST_INCLUDEDIR = ${BOOST_INCLUDEDIR}") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + " BOOST_LIBRARYDIR = ${BOOST_LIBRARYDIR}") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "_boost_TEST_VERSIONS = ${_boost_TEST_VERSIONS}") +endif() + +# ------------------------------------------------------------------------ +# Search for Boost include DIR +# ------------------------------------------------------------------------ + +set(_Boost_VARS_INC BOOST_INCLUDEDIR Boost_INCLUDE_DIR Boost_ADDITIONAL_VERSIONS) +_Boost_CHANGE_DETECT(_Boost_CHANGE_INCDIR ${_Boost_VARS_DIR} ${_Boost_VARS_INC}) +# Clear Boost_INCLUDE_DIR if it did not change but other input affecting the +# location did. We will find a new one based on the new inputs. +if(_Boost_CHANGE_INCDIR AND NOT _Boost_INCLUDE_DIR_CHANGED) + unset(Boost_INCLUDE_DIR CACHE) +endif() + +if(NOT Boost_INCLUDE_DIR) + set(_boost_INCLUDE_SEARCH_DIRS "") + if(BOOST_INCLUDEDIR) + list(APPEND _boost_INCLUDE_SEARCH_DIRS ${BOOST_INCLUDEDIR}) + elseif(_ENV_BOOST_INCLUDEDIR) + list(APPEND _boost_INCLUDE_SEARCH_DIRS ${_ENV_BOOST_INCLUDEDIR}) + endif() + + if( BOOST_ROOT ) + list(APPEND _boost_INCLUDE_SEARCH_DIRS ${BOOST_ROOT}/include ${BOOST_ROOT}) + elseif( _ENV_BOOST_ROOT ) + list(APPEND _boost_INCLUDE_SEARCH_DIRS ${_ENV_BOOST_ROOT}/include ${_ENV_BOOST_ROOT}) + endif() + + if( Boost_NO_SYSTEM_PATHS) + list(APPEND _boost_INCLUDE_SEARCH_DIRS NO_CMAKE_SYSTEM_PATH) + else() + list(APPEND _boost_INCLUDE_SEARCH_DIRS PATHS + C:/boost/include + C:/boost + /sw/local/include + ) + endif() + + # Try to find Boost by stepping backwards through the Boost versions + # we know about. + # Build a list of path suffixes for each version. + set(_boost_PATH_SUFFIXES) + foreach(_boost_VER ${_boost_TEST_VERSIONS}) + # Add in a path suffix, based on the required version, ideally + # we could read this from version.hpp, but for that to work we'd + # need to know the include dir already + set(_boost_BOOSTIFIED_VERSION) + + # Transform 1.35 => 1_35 and 1.36.0 => 1_36_0 + if(_boost_VER MATCHES "[0-9]+\\.[0-9]+\\.[0-9]+") + string(REGEX REPLACE "([0-9]+)\\.([0-9]+)\\.([0-9]+)" "\\1_\\2_\\3" + _boost_BOOSTIFIED_VERSION ${_boost_VER}) + elseif(_boost_VER MATCHES "[0-9]+\\.[0-9]+") + string(REGEX REPLACE "([0-9]+)\\.([0-9]+)" "\\1_\\2" + _boost_BOOSTIFIED_VERSION ${_boost_VER}) + endif() + + list(APPEND _boost_PATH_SUFFIXES + "boost-${_boost_BOOSTIFIED_VERSION}" + "boost_${_boost_BOOSTIFIED_VERSION}" + "boost/boost-${_boost_BOOSTIFIED_VERSION}" + "boost/boost_${_boost_BOOSTIFIED_VERSION}" + ) + + endforeach() + + if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "Include debugging info:") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + " _boost_INCLUDE_SEARCH_DIRS = ${_boost_INCLUDE_SEARCH_DIRS}") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + " _boost_PATH_SUFFIXES = ${_boost_PATH_SUFFIXES}") + endif() + + # Look for a standard boost header file. + find_path(Boost_INCLUDE_DIR + NAMES boost/config.hpp + HINTS ${_boost_INCLUDE_SEARCH_DIRS} + PATH_SUFFIXES ${_boost_PATH_SUFFIXES} + ) +endif() + +# ------------------------------------------------------------------------ +# Extract version information from version.hpp +# ------------------------------------------------------------------------ + +# Set Boost_FOUND based only on header location and version. +# It will be updated below for component libraries. +if(Boost_INCLUDE_DIR) + if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "location of version.hpp: ${Boost_INCLUDE_DIR}/boost/version.hpp") + endif() + + # Extract Boost_VERSION and Boost_LIB_VERSION from version.hpp + set(Boost_VERSION 0) + set(Boost_LIB_VERSION "") + file(STRINGS "${Boost_INCLUDE_DIR}/boost/version.hpp" _boost_VERSION_HPP_CONTENTS REGEX "#define BOOST_(LIB_)?VERSION ") + set(_Boost_VERSION_REGEX "([0-9]+)") + set(_Boost_LIB_VERSION_REGEX "\"([0-9_]+)\"") + foreach(v VERSION LIB_VERSION) + if("${_boost_VERSION_HPP_CONTENTS}" MATCHES ".*#define BOOST_${v} ${_Boost_${v}_REGEX}.*") + set(Boost_${v} "${CMAKE_MATCH_1}") + endif() + endforeach() + unset(_boost_VERSION_HPP_CONTENTS) + + math(EXPR Boost_MAJOR_VERSION "${Boost_VERSION} / 100000") + math(EXPR Boost_MINOR_VERSION "${Boost_VERSION} / 100 % 1000") + math(EXPR Boost_SUBMINOR_VERSION "${Boost_VERSION} % 100") + + set(Boost_ERROR_REASON + "${Boost_ERROR_REASON}Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}\nBoost include path: ${Boost_INCLUDE_DIR}") + if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "version.hpp reveals boost " + "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") + endif() + + if(Boost_FIND_VERSION) + # Set Boost_FOUND based on requested version. + set(_Boost_VERSION "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") + if("${_Boost_VERSION}" VERSION_LESS "${Boost_FIND_VERSION}") + set(Boost_FOUND 0) + set(_Boost_VERSION_AGE "old") + elseif(Boost_FIND_VERSION_EXACT AND + NOT "${_Boost_VERSION}" VERSION_EQUAL "${Boost_FIND_VERSION}") + set(Boost_FOUND 0) + set(_Boost_VERSION_AGE "new") + else() + set(Boost_FOUND 1) + endif() + if(NOT Boost_FOUND) + # State that we found a version of Boost that is too new or too old. + set(Boost_ERROR_REASON + "${Boost_ERROR_REASON}\nDetected version of Boost is too ${_Boost_VERSION_AGE}. Requested version was ${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") + if (Boost_FIND_VERSION_PATCH) + set(Boost_ERROR_REASON + "${Boost_ERROR_REASON}.${Boost_FIND_VERSION_PATCH}") + endif () + if (NOT Boost_FIND_VERSION_EXACT) + set(Boost_ERROR_REASON "${Boost_ERROR_REASON} (or newer)") + endif () + set(Boost_ERROR_REASON "${Boost_ERROR_REASON}.") + endif () + else() + # Caller will accept any Boost version. + set(Boost_FOUND 1) + endif() +else() + set(Boost_FOUND 0) + set(Boost_ERROR_REASON + "${Boost_ERROR_REASON}Unable to find the Boost header files. Please set BOOST_ROOT to the root directory containing Boost or BOOST_INCLUDEDIR to the directory containing Boost's headers.") +endif() + +# ------------------------------------------------------------------------ +# Suffix initialization and compiler suffix detection. +# ------------------------------------------------------------------------ + +set(_Boost_VARS_NAME + Boost_COMPILER + Boost_THREADAPI + Boost_USE_DEBUG_PYTHON + Boost_USE_MULTITHREADED + Boost_USE_STATIC_LIBS + Boost_USE_STATIC_RUNTIME + Boost_USE_STLPORT + Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS + ) +_Boost_CHANGE_DETECT(_Boost_CHANGE_LIBNAME ${_Boost_VARS_NAME}) + +# Setting some more suffixes for the library +set(Boost_LIB_PREFIX "") +if ( WIN32 AND Boost_USE_STATIC_LIBS AND NOT CYGWIN) + set(Boost_LIB_PREFIX "lib") +endif() + +if (Boost_COMPILER) + set(_boost_COMPILER ${Boost_COMPILER}) + if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "using user-specified Boost_COMPILER = ${_boost_COMPILER}") + endif() +else() + # Attempt to guess the compiler suffix + # NOTE: this is not perfect yet, if you experience any issues + # please report them and use the Boost_COMPILER variable + # to work around the problems. + _Boost_GUESS_COMPILER_PREFIX(_boost_COMPILER) + if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "guessed _boost_COMPILER = ${_boost_COMPILER}") + endif() +endif() + +set (_boost_MULTITHREADED "-mt") +if( NOT Boost_USE_MULTITHREADED ) + set (_boost_MULTITHREADED "") +endif() +if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "_boost_MULTITHREADED = ${_boost_MULTITHREADED}") +endif() + +#====================== +# Systematically build up the Boost ABI tag +# http://boost.org/doc/libs/1_41_0/more/getting_started/windows.html#library-naming +set( _boost_RELEASE_ABI_TAG "-") +set( _boost_DEBUG_ABI_TAG "-") +# Key Use this library when: +# s linking statically to the C++ standard library and +# compiler runtime support libraries. +if(Boost_USE_STATIC_RUNTIME) + set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}s") + set( _boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}s") +endif() +# g using debug versions of the standard and runtime +# support libraries +if(WIN32) + if(MSVC OR "${CMAKE_CXX_COMPILER}" MATCHES "icl" + OR "${CMAKE_CXX_COMPILER}" MATCHES "icpc") + set(_boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}g") + endif() +endif() +# y using special debug build of python +if(Boost_USE_DEBUG_PYTHON) + set(_boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}y") +endif() +# d using a debug version of your code +set(_boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}d") +# p using the STLport standard library rather than the +# default one supplied with your compiler +if(Boost_USE_STLPORT) + set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}p") + set( _boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}p") +endif() +# n using the STLport deprecated "native iostreams" feature +if(Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS) + set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}n") + set( _boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}n") +endif() + +if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "_boost_RELEASE_ABI_TAG = ${_boost_RELEASE_ABI_TAG}") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "_boost_DEBUG_ABI_TAG = ${_boost_DEBUG_ABI_TAG}") +endif() + +# ------------------------------------------------------------------------ +# Begin finding boost libraries +# ------------------------------------------------------------------------ +set(_Boost_VARS_LIB BOOST_LIBRARYDIR Boost_LIBRARY_DIR) +_Boost_CHANGE_DETECT(_Boost_CHANGE_LIBDIR ${_Boost_VARS_DIR} ${_Boost_VARS_LIB} Boost_INCLUDE_DIR) +# Clear Boost_LIBRARY_DIR if it did not change but other input affecting the +# location did. We will find a new one based on the new inputs. +if(_Boost_CHANGE_LIBDIR AND NOT _Boost_LIBRARY_DIR_CHANGED) + unset(Boost_LIBRARY_DIR CACHE) +endif() + +if(Boost_LIBRARY_DIR) + set(_boost_LIBRARY_SEARCH_DIRS ${Boost_LIBRARY_DIR} NO_DEFAULT_PATH) +else() + set(_boost_LIBRARY_SEARCH_DIRS "") + if(BOOST_LIBRARYDIR) + list(APPEND _boost_LIBRARY_SEARCH_DIRS ${BOOST_LIBRARYDIR}) + elseif(_ENV_BOOST_LIBRARYDIR) + list(APPEND _boost_LIBRARY_SEARCH_DIRS ${_ENV_BOOST_LIBRARYDIR}) + endif() + + if(BOOST_ROOT) + list(APPEND _boost_LIBRARY_SEARCH_DIRS ${BOOST_ROOT}/lib ${BOOST_ROOT}/stage/lib) + elseif(_ENV_BOOST_ROOT) + list(APPEND _boost_LIBRARY_SEARCH_DIRS ${_ENV_BOOST_ROOT}/lib ${_ENV_BOOST_ROOT}/stage/lib) + endif() + + list(APPEND _boost_LIBRARY_SEARCH_DIRS + ${Boost_INCLUDE_DIR}/lib + ${Boost_INCLUDE_DIR}/../lib + ${Boost_INCLUDE_DIR}/../lib/${CMAKE_LIBRARY_ARCHITECTURE} + ${Boost_INCLUDE_DIR}/stage/lib + ) + if( Boost_NO_SYSTEM_PATHS ) + list(APPEND _boost_LIBRARY_SEARCH_DIRS NO_CMAKE_SYSTEM_PATH) + else() + list(APPEND _boost_LIBRARY_SEARCH_DIRS PATHS + C:/boost/lib + C:/boost + /sw/local/lib + ) + endif() +endif() + +if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "_boost_LIBRARY_SEARCH_DIRS = ${_boost_LIBRARY_SEARCH_DIRS}") +endif() + +# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES +if( Boost_USE_STATIC_LIBS ) + set( _boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + if(WIN32) + set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) + else() + set(CMAKE_FIND_LIBRARY_SUFFIXES .a ) + endif() +endif() + +# We want to use the tag inline below without risking double dashes +if(_boost_RELEASE_ABI_TAG) + if(${_boost_RELEASE_ABI_TAG} STREQUAL "-") + set(_boost_RELEASE_ABI_TAG "") + endif() +endif() +if(_boost_DEBUG_ABI_TAG) + if(${_boost_DEBUG_ABI_TAG} STREQUAL "-") + set(_boost_DEBUG_ABI_TAG "") + endif() +endif() + +# The previous behavior of FindBoost when Boost_USE_STATIC_LIBS was enabled +# on WIN32 was to: +# 1. Search for static libs compiled against a SHARED C++ standard runtime library (use if found) +# 2. Search for static libs compiled against a STATIC C++ standard runtime library (use if found) +# We maintain this behavior since changing it could break people's builds. +# To disable the ambiguous behavior, the user need only +# set Boost_USE_STATIC_RUNTIME either ON or OFF. +set(_boost_STATIC_RUNTIME_WORKAROUND false) +if(WIN32 AND Boost_USE_STATIC_LIBS) + if(NOT DEFINED Boost_USE_STATIC_RUNTIME) + set(_boost_STATIC_RUNTIME_WORKAROUND true) + endif() +endif() + +# On versions < 1.35, remove the System library from the considered list +# since it wasn't added until 1.35. +if(Boost_VERSION AND Boost_FIND_COMPONENTS) + if(Boost_VERSION LESS 103500) + list(REMOVE_ITEM Boost_FIND_COMPONENTS system) + endif() +endif() + +# If the user changed any of our control inputs flush previous results. +if(_Boost_CHANGE_LIBDIR OR _Boost_CHANGE_LIBNAME) + foreach(COMPONENT ${_Boost_COMPONENTS_SEARCHED}) + string(TOUPPER ${COMPONENT} UPPERCOMPONENT) + foreach(c DEBUG RELEASE) + set(_var Boost_${UPPERCOMPONENT}_LIBRARY_${c}) + unset(${_var} CACHE) + set(${_var} "${_var}-NOTFOUND") + endforeach() + endforeach() + set(_Boost_COMPONENTS_SEARCHED "") +endif() + +foreach(COMPONENT ${Boost_FIND_COMPONENTS}) + string(TOUPPER ${COMPONENT} UPPERCOMPONENT) + + set( _boost_docstring_release "Boost ${COMPONENT} library (release)") + set( _boost_docstring_debug "Boost ${COMPONENT} library (debug)") + + # + # Find RELEASE libraries + # + set(_boost_RELEASE_NAMES + ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} + ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} + ${Boost_LIB_PREFIX}boost_${COMPONENT} ) + if(_boost_STATIC_RUNTIME_WORKAROUND) + set(_boost_RELEASE_STATIC_ABI_TAG "-s${_boost_RELEASE_ABI_TAG}") + list(APPEND _boost_RELEASE_NAMES + ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} + ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} ) + endif() + if(Boost_THREADAPI AND ${COMPONENT} STREQUAL "thread") + _Boost_PREPEND_LIST_WITH_THREADAPI(_boost_RELEASE_NAMES ${_boost_RELEASE_NAMES}) + endif() + if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "Searching for ${UPPERCOMPONENT}_LIBRARY_RELEASE: ${_boost_RELEASE_NAMES}") + endif() + + # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing. + string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS}") + + _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE + NAMES ${_boost_RELEASE_NAMES} + HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp} + NAMES_PER_DIR + DOC "${_boost_docstring_release}" + ) + + # + # Find DEBUG libraries + # + set(_boost_DEBUG_NAMES + ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} + ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} + ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED} + ${Boost_LIB_PREFIX}boost_${COMPONENT} ) + if(_boost_STATIC_RUNTIME_WORKAROUND) + set(_boost_DEBUG_STATIC_ABI_TAG "-s${_boost_DEBUG_ABI_TAG}") + list(APPEND _boost_DEBUG_NAMES + ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} + ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} ) + endif() + if(Boost_THREADAPI AND ${COMPONENT} STREQUAL "thread") + _Boost_PREPEND_LIST_WITH_THREADAPI(_boost_DEBUG_NAMES ${_boost_DEBUG_NAMES}) + endif() + if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "Searching for ${UPPERCOMPONENT}_LIBRARY_DEBUG: ${_boost_DEBUG_NAMES}") + endif() + + # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing. + string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS}") + + _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG + NAMES ${_boost_DEBUG_NAMES} + HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp} + NAMES_PER_DIR + DOC "${_boost_docstring_debug}" + ) + + if(Boost_REALPATH) + _Boost_SWAP_WITH_REALPATH(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE "${_boost_docstring_release}") + _Boost_SWAP_WITH_REALPATH(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG "${_boost_docstring_debug}" ) + endif() + + _Boost_ADJUST_LIB_VARS(${UPPERCOMPONENT}) + +endforeach() + +# Restore the original find library ordering +if( Boost_USE_STATIC_LIBS ) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${_boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) +endif() + +# ------------------------------------------------------------------------ +# End finding boost libraries +# ------------------------------------------------------------------------ + +set(Boost_INCLUDE_DIRS ${Boost_INCLUDE_DIR}) +set(Boost_LIBRARY_DIRS ${Boost_LIBRARY_DIR}) + +# The above setting of Boost_FOUND was based only on the header files. +# Update it for the requested component libraries. +if(Boost_FOUND) + # The headers were found. Check for requested component libs. + set(_boost_CHECKED_COMPONENT FALSE) + set(_Boost_MISSING_COMPONENTS "") + foreach(COMPONENT ${Boost_FIND_COMPONENTS}) + string(TOUPPER ${COMPONENT} COMPONENT) + set(_boost_CHECKED_COMPONENT TRUE) + if(NOT Boost_${COMPONENT}_FOUND) + string(TOLOWER ${COMPONENT} COMPONENT) + list(APPEND _Boost_MISSING_COMPONENTS ${COMPONENT}) + endif() + endforeach() + + if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] Boost_FOUND = ${Boost_FOUND}") + endif() + + if (_Boost_MISSING_COMPONENTS) + set(Boost_FOUND 0) + # We were unable to find some libraries, so generate a sensible + # error message that lists the libraries we were unable to find. + set(Boost_ERROR_REASON + "${Boost_ERROR_REASON}\nThe following Boost libraries could not be found:\n") + foreach(COMPONENT ${_Boost_MISSING_COMPONENTS}) + set(Boost_ERROR_REASON + "${Boost_ERROR_REASON} boost_${COMPONENT}\n") + endforeach() + + list(LENGTH Boost_FIND_COMPONENTS Boost_NUM_COMPONENTS_WANTED) + list(LENGTH _Boost_MISSING_COMPONENTS Boost_NUM_MISSING_COMPONENTS) + if (${Boost_NUM_COMPONENTS_WANTED} EQUAL ${Boost_NUM_MISSING_COMPONENTS}) + set(Boost_ERROR_REASON + "${Boost_ERROR_REASON}No Boost libraries were found. You may need to set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") + else () + set(Boost_ERROR_REASON + "${Boost_ERROR_REASON}Some (but not all) of the required Boost libraries were found. You may need to install these additional Boost libraries. Alternatively, set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") + endif () + endif () + + if( NOT Boost_LIBRARY_DIRS AND NOT _boost_CHECKED_COMPONENT ) + # Compatibility Code for backwards compatibility with CMake + # 2.4's FindBoost module. + + # Look for the boost library path. + # Note that the user may not have installed any libraries + # so it is quite possible the Boost_LIBRARY_DIRS may not exist. + set(_boost_LIB_DIR ${Boost_INCLUDE_DIR}) + + if("${_boost_LIB_DIR}" MATCHES "boost-[0-9]+") + get_filename_component(_boost_LIB_DIR ${_boost_LIB_DIR} PATH) + endif() + + if("${_boost_LIB_DIR}" MATCHES "/include$") + # Strip off the trailing "/include" in the path. + get_filename_component(_boost_LIB_DIR ${_boost_LIB_DIR} PATH) + endif() + + if(EXISTS "${_boost_LIB_DIR}/lib") + set(_boost_LIB_DIR ${_boost_LIB_DIR}/lib) + else() + if(EXISTS "${_boost_LIB_DIR}/stage/lib") + set(_boost_LIB_DIR ${_boost_LIB_DIR}/stage/lib) + else() + set(_boost_LIB_DIR "") + endif() + endif() + + if(_boost_LIB_DIR AND EXISTS "${_boost_LIB_DIR}") + set(Boost_LIBRARY_DIRS ${_boost_LIB_DIR}) + endif() + + endif() +else() + # Boost headers were not found so no components were found. + foreach(COMPONENT ${Boost_FIND_COMPONENTS}) + string(TOUPPER ${COMPONENT} UPPERCOMPONENT) + set(Boost_${UPPERCOMPONENT}_FOUND 0) + endforeach() +endif() + +# ------------------------------------------------------------------------ +# Notification to end user about what was found +# ------------------------------------------------------------------------ + +set(Boost_LIBRARIES "") +if(Boost_FOUND) + if(NOT Boost_FIND_QUIETLY) + message(STATUS "Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") + if(Boost_FIND_COMPONENTS) + message(STATUS "Found the following Boost libraries:") + endif() + endif() + foreach( COMPONENT ${Boost_FIND_COMPONENTS} ) + string( TOUPPER ${COMPONENT} UPPERCOMPONENT ) + if( Boost_${UPPERCOMPONENT}_FOUND ) + if(NOT Boost_FIND_QUIETLY) + message (STATUS " ${COMPONENT}") + endif() + list(APPEND Boost_LIBRARIES ${Boost_${UPPERCOMPONENT}_LIBRARY}) + endif() + endforeach() + + # Add pthread library on UNIX if thread component was found + _Boost_consider_adding_pthreads(Boost_LIBRARIES ${Boost_LIBRARIES}) +else() + if(Boost_FIND_REQUIRED) + message(SEND_ERROR "Unable to find the requested Boost libraries.\n${Boost_ERROR_REASON}") + else() + if(NOT Boost_FIND_QUIETLY) + # we opt not to automatically output Boost_ERROR_REASON here as + # it could be quite lengthy and somewhat imposing in its requests + # Since Boost is not always a required dependency we'll leave this + # up to the end-user. + if(Boost_DEBUG OR Boost_DETAILED_FAILURE_MSG) + message(STATUS "Could NOT find Boost\n${Boost_ERROR_REASON}") + else() + message(STATUS "Could NOT find Boost") + endif() + endif() + endif() +endif() + +# Configure display of cache entries in GUI. +foreach(v BOOSTROOT BOOST_ROOT ${_Boost_VARS_INC} ${_Boost_VARS_LIB}) + get_property(_type CACHE ${v} PROPERTY TYPE) + if(_type) + set_property(CACHE ${v} PROPERTY ADVANCED 1) + if("x${_type}" STREQUAL "xUNINITIALIZED") + if("x${v}" STREQUAL "xBoost_ADDITIONAL_VERSIONS") + set_property(CACHE ${v} PROPERTY TYPE STRING) + else() + set_property(CACHE ${v} PROPERTY TYPE PATH) + endif() + endif() + endif() +endforeach() + +# Record last used values of input variables so we can +# detect on the next run if the user changed them. +foreach(v + ${_Boost_VARS_INC} ${_Boost_VARS_LIB} + ${_Boost_VARS_DIR} ${_Boost_VARS_NAME} + ) + if(DEFINED ${v}) + set(_${v}_LAST "${${v}}" CACHE INTERNAL "Last used ${v} value.") + else() + unset(_${v}_LAST CACHE) + endif() +endforeach() + +# Maintain a persistent list of components requested anywhere since +# the last flush. +set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}") +list(APPEND _Boost_COMPONENTS_SEARCHED ${Boost_FIND_COMPONENTS}) +list(REMOVE_DUPLICATES _Boost_COMPONENTS_SEARCHED) +list(SORT _Boost_COMPONENTS_SEARCHED) +set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}" + CACHE INTERNAL "Components requested for this build tree.") diff --git a/CMakeModules/Legacy/CMakeLists.txt b/CMakeModules/Legacy/CMakeLists.txt new file mode 100644 index 0000000..353391d --- /dev/null +++ b/CMakeModules/Legacy/CMakeLists.txt @@ -0,0 +1,27 @@ +# If you are running recent enough version of CMake you shall consider updating/removing these lines ... +MESSAGE(STATUS "Configuring build scripts for older CMake versions") + +# This patches your current boost searching routine so that `pthread` library is included if needed +# - this is here to fix some older CMake + Boost configurations +set(Boost_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Boost" PARENT_SCOPE) + +if (APPLE OR USE_LEGACY_FIND_BOOST) + MESSAGE(STATUS "Configuring for custom FindBoost.cmake") + # Custom FindBoost.cmake + # - overrides `find_package( Boost )` functionality + # - it's a modified https://github.com/Kitware/CMake/blob/363825cd55595b7de62fcf610836f6156a9f1a31/Modules/FindBoost.cmake + # - adds additional Boost search path + # - adds pthread as an dependency if needed + ###### + # This is using an old version of FindBoost.cmake irregardless of your CMake version + # - this will be removed in future release + # - improves Boost library search in some Apple OS configrations + # - this can be fixed with properly setting BOOST_LIBRARYDIR + ##### + + MESSAGE(DEPRECATION "Custom FindBoost.cmake will be deprecated in some future release. If you are using some of the affected configurations try setting the BOOST_LIBRARYDIR variable.") + + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Boost") + + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} PARENT_SCOPE) +endif () \ No newline at end of file From 8d33bb844d04d7e59092ea4b8823aa62400d9d29 Mon Sep 17 00:00:00 2001 From: crypto-ape <43807588+crypto-ape@users.noreply.github.com> Date: Tue, 23 Apr 2019 13:45:18 +0200 Subject: [PATCH 029/110] Fixed `pthread` dependency --- CMakeLists.txt | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 37dae09..b5a3808 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,8 +38,6 @@ if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(platformBitness 64) endif() -SET (ORIGINAL_LIB_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) - SET(BOOST_COMPONENTS) LIST(APPEND BOOST_COMPONENTS coroutine thread date_time filesystem system program_options chrono unit_test_framework context iostreams regex) # boost::endian is also required, but FindBoost can't handle header-only libs @@ -145,21 +143,18 @@ IF( WIN32 ) LIST(APPEND PLATFORM_SPECIFIC_LIBS ws2_32 crypt32 mswsock userenv) # iphlpapi.lib - -ELSE(WIN32) - MESSAGE(STATUS "Configuring fc to build on Unix/Apple") - - SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a;.so") - - IF(NOT APPLE) - # Linux or other unix - SET(rt_library rt ) - SET(pthread_library pthread) - ENDIF(NOT APPLE) ENDIF(WIN32) FIND_PACKAGE(Boost CONFIG COMPONENTS ${BOOST_COMPONENTS}) +IF(NOT WIN32) + MESSAGE(STATUS "Configuring fc to build on Unix/Apple") + + if(NOT APPLE) + SET(rt_library rt) + SET(pthread_library pthread) + endif(NOT APPLE) +ENDIF(NOT WIN32) IF($ENV{OPENSSL_ROOT_DIR}) set(OPENSSL_ROOT_DIR $ENV{OPENSSL_ROOT_DIR} ) @@ -173,8 +168,6 @@ ENDIF( LIBCXX_HAVE_CXX_ATOMICS_WITH_LIB ) find_package(OpenSSL REQUIRED) -set( CMAKE_FIND_LIBRARY_SUFFIXES ${ORIGINAL_LIB_SUFFIXES} ) - option( UNITY_BUILD OFF ) set( fc_sources From c453db886bec1984f9d691325c2ca8569a51e6d7 Mon Sep 17 00:00:00 2001 From: crypto-ape <43807588+crypto-ape@users.noreply.github.com> Date: Tue, 23 Apr 2019 17:23:00 +0200 Subject: [PATCH 030/110] CMake version bump --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b5a3808..79bf995 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # # Defines fc library target. -CMAKE_MINIMUM_REQUIRED( VERSION 3.1.2 FATAL_ERROR ) +CMAKE_MINIMUM_REQUIRED( VERSION 3.2 FATAL_ERROR ) PROJECT( fc ) set( CMAKE_CXX_STANDARD 14 ) From b8a87bde7630464478398c7fe3d0ede72a9866cf Mon Sep 17 00:00:00 2001 From: crypto-ape <43807588+crypto-ape@users.noreply.github.com> Date: Tue, 23 Apr 2019 17:23:37 +0200 Subject: [PATCH 031/110] BoostConfig EOF newline --- CMakeModules/Boost/BoostConfig.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeModules/Boost/BoostConfig.cmake b/CMakeModules/Boost/BoostConfig.cmake index 5a6bac8..b0d9323 100644 --- a/CMakeModules/Boost/BoostConfig.cmake +++ b/CMakeModules/Boost/BoostConfig.cmake @@ -15,4 +15,4 @@ if (UNIX AND NOT CYGWIN) list(APPEND Boost_LIBRARIES ${BOOST_THREAD_LIBRARY}) endif () endif () -endif () \ No newline at end of file +endif () From a2303d35282fb402854164e9923777ada79a7c29 Mon Sep 17 00:00:00 2001 From: crypto-ape <43807588+crypto-ape@users.noreply.github.com> Date: Thu, 25 Apr 2019 11:51:21 +0200 Subject: [PATCH 032/110] Updated CMake for MinGW --- CMakeLists.txt | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 79bf995..a154c9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,7 +44,7 @@ LIST(APPEND BOOST_COMPONENTS coroutine thread date_time filesystem system progra SET( Boost_USE_STATIC_LIBS ON CACHE STRING "ON or OFF" ) # Configure secp256k1-zkp -if ( MSVC ) +if ( WIN32 ) # autoconf won't work here, hard code the defines set( SECP256K1_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp" ) @@ -60,18 +60,9 @@ if ( MSVC ) USE_SCALAR_8X32 USE_SCALAR_INV_BUILTIN ) set_target_properties( secp256k1 PROPERTIES COMPILE_DEFINITIONS "${SECP256K1_BUILD_DEFINES}" LINKER_LANGUAGE C ) -else ( MSVC ) +else ( WIN32 ) include(ExternalProject) - if ( MINGW ) - ExternalProject_Add( project_secp256k1 - PREFIX ${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp - SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp - CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp/configure --prefix=${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp --with-bignum=no --host=x86_64-w64-mingw32 - BUILD_COMMAND make - INSTALL_COMMAND true - BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp/src/project_secp256k1-build/.libs/libsecp256k1.a - ) - else ( MINGW ) + ExternalProject_Add( project_secp256k1 PREFIX ${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp @@ -80,7 +71,7 @@ else ( MSVC ) INSTALL_COMMAND true BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp/src/project_secp256k1-build/.libs/libsecp256k1.a ) - endif ( MINGW ) + ExternalProject_Add_Step(project_secp256k1 autogen WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp/autogen.sh @@ -94,15 +85,13 @@ else ( MSVC ) set_property(TARGET secp256k1 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp/include) add_dependencies(secp256k1 project_secp256k1) install( FILES ${binary_dir}/.libs/libsecp256k1${CMAKE_STATIC_LIBRARY_SUFFIX} DESTINATION lib/cryptonomex ) -endif ( MSVC ) +endif ( WIN32 ) # End configure secp256k1-zkp # Configure editline if ( NOT WIN32 ) include(ExternalProject) - if ( MINGW ) -# Editline is not avalible in MINGW - else ( MINGW ) + ExternalProject_Add( project_editline PREFIX ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline @@ -111,6 +100,7 @@ if ( NOT WIN32 ) INSTALL_COMMAND true BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline/src/project_editline-build/src/.libs/libeditline.a ) + ExternalProject_Add_Step(project_editline autogen WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/autogen.sh @@ -122,7 +112,6 @@ if ( NOT WIN32 ) set_property(TARGET editline PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/include) add_dependencies(editline project_editline) install( FILES ${binary_dir}/src/.libs/libeditline${CMAKE_STATIC_LIBRARY_SUFFIX} DESTINATION lib/cryptonomex ) - endif ( MINGW ) endif ( NOT WIN32 ) # End configure editline @@ -316,6 +305,7 @@ ENDIF(APPLE) if( ZLIB_FOUND ) MESSAGE( STATUS "zlib found" ) + target_include_directories(fc PUBLIC ${ZLIB_INCLUDE_DIRS}) add_definitions( -DHAS_ZLIB ) else() MESSAGE( STATUS "zlib not found" ) From 241f1f2f0d9090ebbd693225b85c2a680432192f Mon Sep 17 00:00:00 2001 From: crypto-ape <43807588+crypto-ape@users.noreply.github.com> Date: Fri, 26 Apr 2019 09:25:05 +0200 Subject: [PATCH 033/110] Legacy/CMakeLists.txt EOF newline --- CMakeModules/Legacy/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeModules/Legacy/CMakeLists.txt b/CMakeModules/Legacy/CMakeLists.txt index 353391d..56c115f 100644 --- a/CMakeModules/Legacy/CMakeLists.txt +++ b/CMakeModules/Legacy/CMakeLists.txt @@ -24,4 +24,4 @@ if (APPLE OR USE_LEGACY_FIND_BOOST) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Boost") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} PARENT_SCOPE) -endif () \ No newline at end of file +endif () From 86b025007a4e1b6a9d5d3679e6625973f33b27f5 Mon Sep 17 00:00:00 2001 From: crypto-ape <43807588+crypto-ape@users.noreply.github.com> Date: Mon, 20 May 2019 14:59:30 +0200 Subject: [PATCH 034/110] Bumped Boost version --- CMakeModules/Boost/BoostConfig.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeModules/Boost/BoostConfig.cmake b/CMakeModules/Boost/BoostConfig.cmake index b0d9323..a5e01f2 100644 --- a/CMakeModules/Boost/BoostConfig.cmake +++ b/CMakeModules/Boost/BoostConfig.cmake @@ -1,9 +1,9 @@ # This overrides `find_package(Boost ... CONFIG ... )` calls -# - calls the CMAke's built-in `FindBoost.cmake` and adds `pthread` library dependency +# - calls the CMake's built-in `FindBoost.cmake` and adds `pthread` library dependency MESSAGE(STATUS "Using custom FindBoost config") -find_package(Boost 1.57 REQUIRED COMPONENTS ${Boost_FIND_COMPONENTS}) +find_package(Boost 1.58 REQUIRED COMPONENTS ${Boost_FIND_COMPONENTS}) # Inject `pthread` dependency to Boost if needed if (UNIX AND NOT CYGWIN) From ab617200a5052c07315ba93c2fa34f5b26463a92 Mon Sep 17 00:00:00 2001 From: crypto-ape <43807588+crypto-ape@users.noreply.github.com> Date: Mon, 20 May 2019 15:00:02 +0200 Subject: [PATCH 035/110] Removed unneeded definitions --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a154c9b..c722b18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -141,7 +141,6 @@ IF(NOT WIN32) if(NOT APPLE) SET(rt_library rt) - SET(pthread_library pthread) endif(NOT APPLE) ENDIF(NOT WIN32) From dfc0a357d379f1c497d8a5e9cc9401f48999bc6a Mon Sep 17 00:00:00 2001 From: crypto-ape <43807588+crypto-ape@users.noreply.github.com> Date: Mon, 20 May 2019 15:01:00 +0200 Subject: [PATCH 036/110] Updated Boost Lockfree compilation test --- CMakeModules/CheckLibcxxAtomic.cmake | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeModules/CheckLibcxxAtomic.cmake b/CMakeModules/CheckLibcxxAtomic.cmake index 0e55627..7239d6f 100644 --- a/CMakeModules/CheckLibcxxAtomic.cmake +++ b/CMakeModules/CheckLibcxxAtomic.cmake @@ -18,11 +18,15 @@ function(check_cxx_atomics varname) if (CMAKE_C_FLAGS MATCHES -fsanitize-coverage OR CMAKE_CXX_FLAGS MATCHES -fsanitize-coverage) set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters") endif() + + set(OLD_CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES}) + set(CMAKE_REQUIRED_INCLUDES ${Boost_INCLUDE_DIRS}) + check_cxx_source_compiles(" #include #include -boost::lockfree::queue q; +boost::lockfree::queue> q; int main(int, char**) { uint32_t* a; uint32_t* b; @@ -31,6 +35,7 @@ int main(int, char**) { } " ${varname}) set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) + set(CMAKE_REQUIRED_INCLUDES ${OLD_CMAKE_REQUIRED_INCLUDES}) endfunction(check_cxx_atomics) # Perform the check for 64bit atomics without libatomic. From b2c2a475210b5347e9e90b8c18d1af0e6abf4abd Mon Sep 17 00:00:00 2001 From: crypto-ape <43807588+crypto-ape@users.noreply.github.com> Date: Mon, 8 Jul 2019 13:41:44 +0200 Subject: [PATCH 037/110] CheckLibcxxAtomic after Boost --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c722b18..f5c3995 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,6 @@ INCLUDE( VersionMacros ) INCLUDE( SetupTargetMacros ) INCLUDE(GetGitRevisionDescription) INCLUDE(CheckLibraryExists) -INCLUDE(CheckLibcxxAtomic) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/Legacy) @@ -441,4 +440,6 @@ if(MSVC) endif(MSVC) +INCLUDE(CheckLibcxxAtomic) + MESSAGE(STATUS "Finished fc module configuration...") From e4b35e4a42cbd1c53a945ff0f8cd28d3ab4a2138 Mon Sep 17 00:00:00 2001 From: Abit Date: Thu, 18 Jul 2019 23:15:22 +0200 Subject: [PATCH 038/110] Update a comment to avoid confusing doxygen --- include/fc/utf8.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fc/utf8.hpp b/include/fc/utf8.hpp index c573029..8dd934e 100644 --- a/include/fc/utf8.hpp +++ b/include/fc/utf8.hpp @@ -3,7 +3,7 @@ #include -/// This file contains general purpose utilities related to UTF-8 <-> Unicode conversions +// This file contains general purpose utilities related to UTF-8 <-> Unicode conversions namespace fc { From 2c5c30848a2d1cdd774ecaef2b051565f6f151f9 Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 19 Jul 2019 15:55:35 -0400 Subject: [PATCH 039/110] Correctly close websocket API connection --- src/rpc/websocket_api.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/rpc/websocket_api.cpp b/src/rpc/websocket_api.cpp index 0798f8f..da97a9e 100644 --- a/src/rpc/websocket_api.cpp +++ b/src/rpc/websocket_api.cpp @@ -74,7 +74,10 @@ websocket_api_connection::websocket_api_connection( const std::shared_ptrclosed.connect( [this](){ closed(); } ); + _connection->closed.connect( [this](){ + closed(); + _connection = nullptr; + } ); } variant websocket_api_connection::send_call( From 451ed46ecc7ca60c108e446cc0b7c9d6aa29c1dc Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 24 Jun 2019 13:01:45 +0200 Subject: [PATCH 040/110] Replace one more "new promise" with "promise::create" --- include/fc/asio.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/fc/asio.hpp b/include/fc/asio.hpp index 4c330c4..bc9377d 100644 --- a/include/fc/asio.hpp +++ b/include/fc/asio.hpp @@ -102,7 +102,7 @@ namespace asio { */ template size_t read( AsyncReadStream& s, const MutableBufferSequence& buf ) { - promise::ptr p(new promise("fc::asio::read")); + promise::ptr p = promise::create("fc::asio::read"); boost::asio::async_read( s, buf, detail::read_write_handler(p) ); return p->wait(); } @@ -249,7 +249,6 @@ namespace asio { */ template void accept( AcceptorType& acc, SocketType& sock ) { - //promise::ptr p( new promise("fc::asio::tcp::accept") ); promise::ptr p = promise::create("fc::asio::tcp::accept"); acc.async_accept( sock, boost::bind( fc::asio::detail::error_handler, p, _1 ) ); p->wait(); From e160afce1693f1c582b6b1a7e38ee87c6d443dd9 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 24 Jun 2019 13:16:53 +0200 Subject: [PATCH 041/110] Attempt to fix uint128 for mac --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6daae58..af06637 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ PROJECT( fc ) set( CMAKE_CXX_STANDARD 14 ) SET( CMAKE_CXX_STANDARD_REQUIRED ON ) -if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" ) +if( "${CMAKE_CXX_COMPILER_ID}" MATCHES "^(Apple)?Clang|GNU$" ) set( CMAKE_CXX_EXTENSIONS ON ) # for __int128 support else( GNU ) set( CMAKE_CXX_EXTENSIONS OFF ) From c8f3e452d34ecf38806fc87c426492e84a43f829 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 24 Jun 2019 13:25:33 +0200 Subject: [PATCH 042/110] Use array::data instead of array::begin --- src/crypto/elliptic_common.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/crypto/elliptic_common.cpp b/src/crypto/elliptic_common.cpp index 56eeebc..dd89c3a 100644 --- a/src/crypto/elliptic_common.cpp +++ b/src/crypto/elliptic_common.cpp @@ -55,7 +55,7 @@ namespace fc { namespace ecc { static chr37 _derive_message( unsigned char first, const unsigned char* key32, int i ) { chr37 result; - unsigned char* dest = result.begin(); + unsigned char* dest = result.data(); *dest++ = first; memcpy( dest, key32, 32 ); dest += 32; _put( &dest, i ); @@ -64,7 +64,7 @@ namespace fc { namespace ecc { chr37 _derive_message( const public_key_data& key, int i ) { - return _derive_message( *key.begin(), key.begin() + 1, i ); + return _derive_message( *key.data(), key.data() + 1, i ); } static chr37 _derive_message( const private_key_secret& key, int i ) @@ -142,9 +142,9 @@ namespace fc { namespace ecc { sha256 check = sha256::hash((char*) key.data(), sizeof(key)); static_assert(sizeof(key) + 4 == 37, "Elliptic public key size (or its hash) is incorrect"); detail::chr37 data; - memcpy(data.data(), key.begin(), key.size()); - memcpy(data.begin() + key.size(), (const char*)check._hash, 4); - return fc::to_base58((char*) data.begin(), data.size()); + memcpy(data.data(), key.data(), key.size()); + memcpy(data.data() + key.size(), (const char*)check._hash, 4); + return fc::to_base58((char*) data.data(), data.size()); } public_key public_key::from_base58( const std::string& b58 ) @@ -163,7 +163,7 @@ namespace fc { namespace ecc { unsigned int public_key::fingerprint() const { public_key_data key = serialize(); - ripemd160 hash = ripemd160::hash( sha256::hash( (char*) key.begin(), key.size() ) ); + ripemd160 hash = ripemd160::hash( sha256::hash( (char*) key.data(), key.size() ) ); unsigned char* fp = (unsigned char*) hash._hash; return (fp[0] << 24) | (fp[1] << 16) | (fp[2] << 8) | fp[3]; } @@ -233,8 +233,8 @@ namespace fc { namespace ecc { { size_t buf_len = key.size() + 4; char *buffer = (char*)alloca(buf_len); - memcpy( buffer, key.begin(), key.size() ); - fc::sha256 double_hash = fc::sha256::hash( fc::sha256::hash( (char*) key.begin(), key.size() )); + memcpy( buffer, key.data(), key.size() ); + fc::sha256 double_hash = fc::sha256::hash( fc::sha256::hash( (char*) key.data(), key.size() )); memcpy( buffer + key.size(), double_hash.data(), 4 ); return fc::to_base58( buffer, buf_len ); } @@ -260,14 +260,14 @@ namespace fc { namespace ecc { extended_key_data extended_public_key::serialize_extended() const { extended_key_data result; - unsigned char* dest = (unsigned char*) result.begin(); + unsigned char* dest = (unsigned char*) result.data(); detail::_put( &dest, BTC_EXT_PUB_MAGIC ); *dest++ = depth; detail::_put( &dest, parent_fp ); detail::_put( &dest, child_num ); memcpy( dest, c.data(), c.data_size() ); dest += 32; public_key_data key = serialize(); - memcpy( dest, key.begin(), key.size() ); + memcpy( dest, key.data(), key.size() ); return result; } @@ -293,7 +293,7 @@ namespace fc { namespace ecc { fc::sha256 chain; memcpy( chain.data(), ptr, chain.data_size() ); ptr += chain.data_size(); public_key_data key; - memcpy( key.begin(), ptr, key.size() ); + memcpy( key.data(), ptr, key.size() ); return extended_public_key( key, chain, cn, fp, d ); } @@ -311,7 +311,7 @@ namespace fc { namespace ecc { { const detail::chr37 data = detail::_derive_message( get_public_key().serialize(), i ); hmac_sha512 mac; - fc::sha512 l = mac.digest( c.data(), c.data_size(), (char*) data.begin(), data.size() ); + fc::sha512 l = mac.digest( c.data(), c.data_size(), (char*) data.data(), data.size() ); return private_derive_rest( l, i ); } @@ -320,14 +320,14 @@ namespace fc { namespace ecc { hmac_sha512 mac; private_key_secret key = get_secret(); const detail::chr37 data = detail::_derive_message( key, i ); - fc::sha512 l = mac.digest( c.data(), c.data_size(), (char*) data.begin(), data.size() ); + fc::sha512 l = mac.digest( c.data(), c.data_size(), (char*) data.data(), data.size() ); return private_derive_rest( l, i ); } extended_key_data extended_private_key::serialize_extended() const { extended_key_data result; - unsigned char* dest = (unsigned char*) result.begin(); + unsigned char* dest = (unsigned char*) result.data(); detail::_put( &dest, BTC_EXT_PRIV_MAGIC ); *dest++ = depth; detail::_put( &dest, parent_fp ); From 6008c96c1a6324b5706e50454f97a41449c851af Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 24 Jun 2019 13:30:24 +0200 Subject: [PATCH 043/110] Allow more space for windows sockets due to fc::future changes --- include/fc/network/tcp_socket.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fc/network/tcp_socket.hpp b/include/fc/network/tcp_socket.hpp index fe6b837..9bb6ea5 100644 --- a/include/fc/network/tcp_socket.hpp +++ b/include/fc/network/tcp_socket.hpp @@ -51,7 +51,7 @@ namespace fc { friend class tcp_server; class impl; #ifdef _WIN64 - fc::fwd my; + fc::fwd my; #else fc::fwd my; #endif From ce79181dcf688a820e8f5feda6fe747e5e0495bf Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Fri, 26 Jul 2019 15:03:22 +0200 Subject: [PATCH 044/110] Replaced more instances of array::begin with array::data --- src/crypto/elliptic_impl_priv.cpp | 7 +++++-- src/crypto/elliptic_secp256k1.cpp | 25 +++++++++++++++---------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/crypto/elliptic_impl_priv.cpp b/src/crypto/elliptic_impl_priv.cpp index 585ffde..96ce6e4 100644 --- a/src/crypto/elliptic_impl_priv.cpp +++ b/src/crypto/elliptic_impl_priv.cpp @@ -72,7 +72,8 @@ namespace fc { namespace ecc { FC_ASSERT( my->_key != empty_priv ); public_key_data pub; unsigned int pk_len; - FC_ASSERT( secp256k1_ec_pubkey_create( detail::_get_context(), (unsigned char*) pub.begin(), (int*) &pk_len, (unsigned char*) my->_key.data(), 1 ) ); + FC_ASSERT( secp256k1_ec_pubkey_create( detail::_get_context(), pub.data(), (int*) &pk_len, + (unsigned char*) my->_key.data(), 1 ) ); FC_ASSERT( pk_len == pub.size() ); return public_key(pub); } @@ -93,7 +94,9 @@ namespace fc { namespace ecc { unsigned int counter = 0; do { - FC_ASSERT( secp256k1_ecdsa_sign_compact( detail::_get_context(), (unsigned char*) digest.data(), (unsigned char*) result.begin() + 1, (unsigned char*) my->_key.data(), extended_nonce_function, &counter, &recid )); + FC_ASSERT( secp256k1_ecdsa_sign_compact( detail::_get_context(), (unsigned char*) digest.data(), + result.data() + 1, (unsigned char*) my->_key.data(), + extended_nonce_function, &counter, &recid )); } while( require_canonical && !public_key::is_canonical( result ) ); result.begin()[0] = 27 + 4 + recid; return result; diff --git a/src/crypto/elliptic_secp256k1.cpp b/src/crypto/elliptic_secp256k1.cpp index 7f8d841..a8e29ed 100644 --- a/src/crypto/elliptic_secp256k1.cpp +++ b/src/crypto/elliptic_secp256k1.cpp @@ -70,8 +70,9 @@ namespace fc { namespace ecc { FC_ASSERT( my->_key != empty_priv ); FC_ASSERT( other.my->_key != empty_pub ); public_key_data pub(other.my->_key); - FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), pub.begin(), pub.size(), (unsigned char*) my->_key.data() ) ); - return fc::sha512::hash( (char*) pub.begin() + 1, pub.size() - 1 ); + FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), pub.data(), pub.size(), + (unsigned char*) my->_key.data() ) ); + return fc::sha512::hash( (char*) pub.data() + 1, pub.size() - 1 ); } @@ -104,8 +105,9 @@ namespace fc { namespace ecc { { FC_ASSERT( my->_key != empty_pub ); public_key_data new_key; - memcpy( new_key.begin(), my->_key.begin(), new_key.size() ); - FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), new_key.begin(), new_key.size(), (unsigned char*) digest.data() ) ); + memcpy( new_key.begin(), my->_key.data(), new_key.size() ); + FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), new_key.data(), new_key.size(), + (unsigned char*) digest.data() ) ); return public_key( new_key ); } @@ -126,8 +128,8 @@ namespace fc { namespace ecc { FC_ASSERT( my->_key != empty_pub ); public_key_point_data dat; unsigned int pk_len = my->_key.size(); - memcpy( dat.begin(), my->_key.begin(), pk_len ); - FC_ASSERT( secp256k1_ec_pubkey_decompress( detail::_get_context(), dat.begin(), (int*) &pk_len ) ); + memcpy( dat.begin(), my->_key.data(), pk_len ); + FC_ASSERT( secp256k1_ec_pubkey_decompress( detail::_get_context(), dat.data(), (int*) &pk_len ) ); FC_ASSERT( pk_len == dat.size() ); return dat; } @@ -142,7 +144,7 @@ namespace fc { namespace ecc { key = o2i_ECPublicKey( &key, &front, sizeof(dat) ); FC_ASSERT( key ); EC_KEY_set_conv_form( key, POINT_CONVERSION_COMPRESSED ); - unsigned char* buffer = my->_key.begin(); + unsigned char* buffer = my->_key.data(); i2o_ECPublicKey( key, &buffer ); // FIXME: questionable memory handling EC_KEY_free( key ); } @@ -165,7 +167,9 @@ namespace fc { namespace ecc { } unsigned int pk_len; - FC_ASSERT( secp256k1_ecdsa_recover_compact( detail::_get_context(), (unsigned char*) digest.data(), c.begin() + 1, my->_key.begin(), (int*) &pk_len, 1, (*c.begin() - 27) & 3 ) ); + FC_ASSERT( secp256k1_ecdsa_recover_compact( detail::_get_context(), (unsigned char*) digest.data(), + c.data() + 1, my->_key.data(), (int*) &pk_len, 1, + (*c.data() - 27) & 3 ) ); FC_ASSERT( pk_len == my->_key.size() ); } @@ -178,10 +182,11 @@ namespace fc { namespace ecc { hmac_sha512 mac; public_key_data key = serialize(); const detail::chr37 data = detail::_derive_message( key, i ); - fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() ); + fc::sha512 l = mac.digest( c.data(), c.data_size(), data.data(), data.size() ); fc::sha256 left = detail::_left(l); FC_ASSERT( left < detail::get_curve_order() ); - FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), key.begin(), key.size(), (unsigned char*) left.data() ) > 0 ); + FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), key.data(), key.size(), + (unsigned char*) left.data() ) > 0 ); // FIXME: check validity - if left + key == infinity then invalid extended_public_key result( key, detail::_right(l), i, fingerprint(), depth + 1 ); return result; From a9a6cb94d173d0c51a708d8cf2e3ff22b97eb31e Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 29 Jul 2019 12:21:15 +0200 Subject: [PATCH 045/110] Replaced more begin() with data() --- src/crypto/elliptic_secp256k1.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/crypto/elliptic_secp256k1.cpp b/src/crypto/elliptic_secp256k1.cpp index a8e29ed..2edf5f8 100644 --- a/src/crypto/elliptic_secp256k1.cpp +++ b/src/crypto/elliptic_secp256k1.cpp @@ -105,7 +105,7 @@ namespace fc { namespace ecc { { FC_ASSERT( my->_key != empty_pub ); public_key_data new_key; - memcpy( new_key.begin(), my->_key.data(), new_key.size() ); + memcpy( new_key.data(), my->_key.data(), new_key.size() ); FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), new_key.data(), new_key.size(), (unsigned char*) digest.data() ) ); return public_key( new_key ); @@ -128,7 +128,7 @@ namespace fc { namespace ecc { FC_ASSERT( my->_key != empty_pub ); public_key_point_data dat; unsigned int pk_len = my->_key.size(); - memcpy( dat.begin(), my->_key.data(), pk_len ); + memcpy( dat.data(), my->_key.data(), pk_len ); FC_ASSERT( secp256k1_ec_pubkey_decompress( detail::_get_context(), dat.data(), (int*) &pk_len ) ); FC_ASSERT( pk_len == dat.size() ); return dat; From cabab23e2c4a57d525aecd65dab0805a1c753714 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Fri, 2 Aug 2019 17:17:13 +0200 Subject: [PATCH 046/110] Replaced more array::begin() with data() --- src/crypto/elliptic_impl_priv.cpp | 2 +- tests/crypto/ecc_test.cpp | 8 ++++---- tests/hmac_test.cpp | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/crypto/elliptic_impl_priv.cpp b/src/crypto/elliptic_impl_priv.cpp index 96ce6e4..3263927 100644 --- a/src/crypto/elliptic_impl_priv.cpp +++ b/src/crypto/elliptic_impl_priv.cpp @@ -98,7 +98,7 @@ namespace fc { namespace ecc { result.data() + 1, (unsigned char*) my->_key.data(), extended_nonce_function, &counter, &recid )); } while( require_canonical && !public_key::is_canonical( result ) ); - result.begin()[0] = 27 + 4 + recid; + result.data()[0] = 27 + 4 + recid; return result; } diff --git a/tests/crypto/ecc_test.cpp b/tests/crypto/ecc_test.cpp index 94028ae..79ac1e1 100644 --- a/tests/crypto/ecc_test.cpp +++ b/tests/crypto/ecc_test.cpp @@ -23,7 +23,7 @@ static void interop_do(const char * const data, size_t len) { } static void interop_do(const fc::ecc::public_key_data &data) { - interop_do((char*) data.begin(), data.size()); + interop_do((char*) data.data(), data.size()); } static void interop_do(const fc::ecc::private_key_secret &data) { @@ -31,7 +31,7 @@ static void interop_do(const fc::ecc::private_key_secret &data) { } static void interop_do(const fc::ecc::public_key_point_data &data) { - interop_do((char*) data.begin(), data.size()); + interop_do((char*) data.data(), data.size()); } static void interop_do(const std::string &data) { @@ -44,11 +44,11 @@ static void interop_do(const fc::sha512 &data) { static void interop_do(fc::ecc::compact_signature &data) { if (write_mode) { - interop_data.write((char*) data.begin(), data.size()); + interop_data.write((char*) data.data(), data.size()); return; } - interop_data.read((char*) data.begin(), data.size()); + interop_data.read((char*) data.data(), data.size()); } static void interop_file(const char * const name) { diff --git a/tests/hmac_test.cpp b/tests/hmac_test.cpp index 82079be..fdd1e4c 100644 --- a/tests/hmac_test.cpp +++ b/tests/hmac_test.cpp @@ -79,13 +79,13 @@ static void run_test( const std::string& key, const std::string& data, const std { std::array key_arr; - BOOST_CHECK_EQUAL( fc::from_hex( key, key_arr.begin(), key_arr.size() ), N ); + BOOST_CHECK_EQUAL( fc::from_hex( key, key_arr.data(), key_arr.size() ), N ); std::array data_arr; - BOOST_CHECK_EQUAL( fc::from_hex( data, data_arr.begin(), data_arr.size() ), M ); + BOOST_CHECK_EQUAL( fc::from_hex( data, data_arr.data(), data_arr.size() ), M ); - BOOST_CHECK_EQUAL( mac_224.digest( key_arr.begin(), N, data_arr.begin(), M ).str(), expect_224 ); - BOOST_CHECK_EQUAL( mac_256.digest( key_arr.begin(), N, data_arr.begin(), M ).str(), expect_256 ); - BOOST_CHECK_EQUAL( mac_512.digest( key_arr.begin(), N, data_arr.begin(), M ).str(), expect_512 ); + BOOST_CHECK_EQUAL( mac_224.digest( key_arr.data(), N, data_arr.data(), M ).str(), expect_224 ); + BOOST_CHECK_EQUAL( mac_256.digest( key_arr.data(), N, data_arr.data(), M ).str(), expect_256 ); + BOOST_CHECK_EQUAL( mac_512.digest( key_arr.data(), N, data_arr.data(), M ).str(), expect_512 ); } BOOST_AUTO_TEST_CASE(hmac_test_1) From 42be69c3f7d3130ebb1867f46abb1cc06c36b0ae Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Fri, 2 Aug 2019 17:31:28 +0200 Subject: [PATCH 047/110] Removed unused var --- include/fc/reflect/reflect.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fc/reflect/reflect.hpp b/include/fc/reflect/reflect.hpp index 3bf0ef7..7578360 100644 --- a/include/fc/reflect/reflect.hpp +++ b/include/fc/reflect/reflect.hpp @@ -175,7 +175,7 @@ template<> struct reflector { \ { \ i = boost::lexical_cast(s); \ } \ - catch( const boost::bad_lexical_cast& e ) \ + catch( const boost::bad_lexical_cast& ) \ { \ fc::throw_bad_enum_cast( s, BOOST_PP_STRINGIZE(ENUM) ); \ } \ From fd0b1979001cb2a2e3f358f7f9f8adf62c70777c Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 5 Aug 2019 10:24:12 -0500 Subject: [PATCH 048/110] bump websocketpp for Boost 1.70 --- vendor/websocketpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/websocketpp b/vendor/websocketpp index 4543c5f..969c993 160000 --- a/vendor/websocketpp +++ b/vendor/websocketpp @@ -1 +1 @@ -Subproject commit 4543c5f9860333e9c73552362ae74239f98e80fe +Subproject commit 969c9939112cd9f8a99e9d051cadc406ee634140 From 2dc5ad8bac8d4af7fe87fc458387881993850928 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 5 Aug 2019 21:18:17 +0200 Subject: [PATCH 049/110] Try to work around __int128 problem on mac --- src/variant.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/variant.cpp b/src/variant.cpp index 9eb6251..7a527e9 100644 --- a/src/variant.cpp +++ b/src/variant.cpp @@ -11,6 +11,10 @@ #include #include +#ifdef __APPLE__ +#include +#endif + namespace fc { @@ -675,12 +679,26 @@ void from_variant( const variant& var, std::vector& vo, uint32_t max_depth void to_variant( const uint128_t& var, variant& vo, uint32_t max_depth ) { +#ifdef __APPLE__ + boost::multiprecision::uint128_t helper = uint128_hi64( var ); + helper <<= 64; + helper += uint128_lo64( var ); + vo = boost::lexical_cast( helper ); +#else vo = boost::lexical_cast( var ); +#endif } void from_variant( const variant& var, uint128_t& vo, uint32_t max_depth ) { +#ifdef __APPLE__ + boost::multiprecision::uint128_t helper = boost::lexical_cast( var.as_string() ); + vo = static_cast( helper >> 64 ); + vo <<= 64; + vo += static_cast( helper & 0xffffffffffffffffULL ); +#else vo = boost::lexical_cast( var.as_string() ); +#endif } #ifdef __APPLE__ From d8bec3d8470dd11066d3713ddee0cd3c25b364d1 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 5 Aug 2019 21:27:53 +0200 Subject: [PATCH 050/110] Resolved another begin/data inconsistency --- include/fc/static_variant.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/fc/static_variant.hpp b/include/fc/static_variant.hpp index 7ed4d90..6f1841c 100644 --- a/include/fc/static_variant.hpp +++ b/include/fc/static_variant.hpp @@ -222,7 +222,7 @@ static const std::array init_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0 ) { std::array result{}; - if( !funcs ) funcs = result.begin(); + if( !funcs ) funcs = result.data(); *funcs++ = [] ( Visitor& v, Data d ) { return v( *reinterpret_cast( d ) ); }; init_wrappers( v, d, funcs ); return result; @@ -240,7 +240,7 @@ static const std::array init_const_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0 ) { std::array result{}; - if( !funcs ) funcs = result.begin(); + if( !funcs ) funcs = result.data(); *funcs++ = [] ( Visitor& v, Data d ) { return v( *reinterpret_cast( d ) ); }; init_const_wrappers( v, d, funcs ); return result; From e45a44970144bdedf44a1e077b2caa508a644816 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 5 Aug 2019 21:28:12 +0200 Subject: [PATCH 051/110] Fixed type of chr37 --- src/crypto/elliptic_secp256k1.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/crypto/elliptic_secp256k1.cpp b/src/crypto/elliptic_secp256k1.cpp index 2edf5f8..b180d44 100644 --- a/src/crypto/elliptic_secp256k1.cpp +++ b/src/crypto/elliptic_secp256k1.cpp @@ -53,7 +53,7 @@ namespace fc { namespace ecc { public_key_data _key; }; - typedef std::array chr37; + typedef std::array chr37; chr37 _derive_message( const public_key_data& key, int i ); fc::sha256 _left( const fc::sha512& v ); fc::sha256 _right( const fc::sha512& v ); @@ -182,7 +182,7 @@ namespace fc { namespace ecc { hmac_sha512 mac; public_key_data key = serialize(); const detail::chr37 data = detail::_derive_message( key, i ); - fc::sha512 l = mac.digest( c.data(), c.data_size(), data.data(), data.size() ); + fc::sha512 l = mac.digest( c.data(), c.data_size(), (const char*) data.data(), data.size() ); fc::sha256 left = detail::_left(l); FC_ASSERT( left < detail::get_curve_order() ); FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), key.data(), key.size(), From d3c85a841501e60db475fa6a2bc13ea6d913d759 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sun, 11 Aug 2019 12:15:54 +0200 Subject: [PATCH 052/110] Fix cmake warning --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index af06637..bad2407 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,9 +9,9 @@ SET( CMAKE_CXX_STANDARD_REQUIRED ON ) if( "${CMAKE_CXX_COMPILER_ID}" MATCHES "^(Apple)?Clang|GNU$" ) set( CMAKE_CXX_EXTENSIONS ON ) # for __int128 support -else( GNU ) +else( "${CMAKE_CXX_COMPILER_ID}" MATCHES "^(Apple)?Clang|GNU$" ) set( CMAKE_CXX_EXTENSIONS OFF ) -endif( GNU ) +endif( "${CMAKE_CXX_COMPILER_ID}" MATCHES "^(Apple)?Clang|GNU$" ) MESSAGE(STATUS "Configuring project fc located in: ${CMAKE_CURRENT_SOURCE_DIR}") SET( CMAKE_AUTOMOC OFF ) From 06f88979a09364ff9e88c1de681786c79ed1ca8b Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Sun, 11 Aug 2019 13:44:18 -0500 Subject: [PATCH 053/110] Resolve #1898: Fix crash in API We were getting the moral equivalent of a null pointer dereference by incrementing an iterator past its past-the-end position, then dereferencing it. This is now fixed. --- include/fc/rpc/api_connection.hpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/include/fc/rpc/api_connection.hpp b/include/fc/rpc/api_connection.hpp index 71eaf80..281f1d2 100644 --- a/include/fc/rpc/api_connection.hpp +++ b/include/fc/rpc/api_connection.hpp @@ -44,13 +44,18 @@ namespace fc { } template - R call_generic( const std::function& f, variants::const_iterator a0, variants::const_iterator e, uint32_t max_depth ) + R call_generic( const std::function& f, variants::const_iterator a0, + variants::const_iterator e, uint32_t max_depth ) { bool optional_args = all_optionals, std::decay_t...>::value; FC_ASSERT( a0 != e || optional_args ); FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" ); - auto arg = (a0 == e)? std::decay_t() : a0->as>(max_depth - 1); - return call_generic( bind_first_arg( f, arg ), a0+1, e, max_depth - 1 ); + if (a0==e) + return call_generic( bind_first_arg( f, std::decay_t() ), a0, + e, max_depth - 1 ); + auto arg = a0->as>(max_depth - 1); + return call_generic( bind_first_arg( f, std::move(arg) ), a0+1, e, + max_depth - 1 ); } template @@ -180,13 +185,18 @@ namespace fc { } template - R call_generic( const std::function& f, variants::const_iterator a0, variants::const_iterator e, uint32_t max_depth ) + R call_generic( const std::function& f, variants::const_iterator a0, + variants::const_iterator e, uint32_t max_depth ) { bool optional_args = detail::all_optionals, std::decay_t...>::value; FC_ASSERT( a0 != e || optional_args, "too few arguments passed to method" ); FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" ); - auto arg = (a0 == e)? std::decay_t() : a0->as>(max_depth - 1); - return call_generic( this->bind_first_arg( f, arg ), a0+1, e, max_depth - 1 ); + if (a0==e) + return call_generic( this->bind_first_arg( f, std::decay_t() ), a0, + e, max_depth - 1 ); + auto arg = a0->as>(max_depth - 1); + return call_generic( this->bind_first_arg( f, std::move(arg) ), a0+1, e, + max_depth - 1 ); } struct api_visitor From 7b6c359a327f42312444a7bcafddf30a214c016b Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 13 Aug 2019 13:09:31 -0400 Subject: [PATCH 054/110] Update test case for optional API arguments Reproduces https://github.com/bitshares/bitshares-core/issues/1898 --- tests/api_tests.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/tests/api_tests.cpp b/tests/api_tests.cpp index dff5350..ef42b8d 100644 --- a/tests/api_tests.cpp +++ b/tests/api_tests.cpp @@ -39,8 +39,12 @@ public: const fc::optional& third ) { return fc::json::to_string(fc::variants{first, {second, 2}, {third, 2}}); } + std::string bar( fc::optional first, fc::optional second, + fc::optional third ) { + return fc::json::to_string(fc::variants{{first,2}, {second, 2}, {third, 2}}); + } }; -FC_API( optionals_api, (foo) ); +FC_API( optionals_api, (foo)(bar) ); using namespace fc; @@ -106,6 +110,12 @@ BOOST_AUTO_TEST_CASE(optionals_test) { BOOST_CHECK_EQUAL(oapi->foo("a", "b", "c"), "[\"a\",\"b\",\"c\"]"); BOOST_CHECK_EQUAL(oapi->foo("a", {}, "c"), "[\"a\",null,\"c\"]"); + BOOST_CHECK_EQUAL(oapi->bar(), "[null,null,null]"); + BOOST_CHECK_EQUAL(oapi->bar("a"), "[\"a\",null,null]"); + BOOST_CHECK_EQUAL(oapi->bar("a", "b"), "[\"a\",\"b\",null]"); + BOOST_CHECK_EQUAL(oapi->bar("a", "b", "c"), "[\"a\",\"b\",\"c\"]"); + BOOST_CHECK_EQUAL(oapi->bar("a", {}, "c"), "[\"a\",null,\"c\"]"); + auto server = std::make_shared(); server->on_connection([&]( const websocket_connection_ptr& c ){ auto wsc = std::make_shared(c, MAX_DEPTH); @@ -119,7 +129,6 @@ BOOST_AUTO_TEST_CASE(optionals_test) { auto client = std::make_shared(); auto con = client->connect( "ws://localhost:" + std::to_string(listen_port) ); - server->stop_listening(); auto apic = std::make_shared(con, MAX_DEPTH); auto remote_optionals = apic->get_remote_api(); @@ -128,6 +137,37 @@ BOOST_AUTO_TEST_CASE(optionals_test) { BOOST_CHECK_EQUAL(remote_optionals->foo("a", "b", "c"), "[\"a\",\"b\",\"c\"]"); BOOST_CHECK_EQUAL(remote_optionals->foo("a", {}, "c"), "[\"a\",null,\"c\"]"); + BOOST_CHECK_EQUAL(remote_optionals->bar(), "[null,null,null]"); + BOOST_CHECK_EQUAL(remote_optionals->bar("a"), "[\"a\",null,null]"); + BOOST_CHECK_EQUAL(remote_optionals->bar("a", "b"), "[\"a\",\"b\",null]"); + BOOST_CHECK_EQUAL(remote_optionals->bar("a", "b", "c"), "[\"a\",\"b\",\"c\"]"); + BOOST_CHECK_EQUAL(remote_optionals->bar("a", {}, "c"), "[\"a\",null,\"c\"]"); + + auto client2 = std::make_shared(); + auto con2 = client2->connect( "ws://localhost:" + std::to_string(listen_port) ); + string response; + con2->on_message_handler([&](const std::string& s){ + response = s; + }); + + con2->send_message( "{\"id\":1,\"method\":\"call\",\"params\":[0,\"bar\",[\"a\",\"b\",\"c\"]]}" ); + fc::usleep(fc::milliseconds(50)); + BOOST_CHECK_EQUAL( response, "{\"id\":1,\"result\":\"[\\\"a\\\",\\\"b\\\",\\\"c\\\"]\"}" ); + + con2->send_message( "{\"id\":2,\"method\":\"call\",\"params\":[0,\"bar\",[\"a\",\"b\"]]}" ); + fc::usleep(fc::milliseconds(50)); + BOOST_CHECK_EQUAL( response, "{\"id\":2,\"result\":\"[\\\"a\\\",\\\"b\\\",null]\"}" ); + + con2->send_message( "{\"id\":3,\"method\":\"call\",\"params\":[0,\"bar\",[\"a\"]]}" ); + fc::usleep(fc::milliseconds(50)); + BOOST_CHECK_EQUAL( response, "{\"id\":3,\"result\":\"[\\\"a\\\",null,null]\"}" ); + + con2->send_message( "{\"id\":4,\"method\":\"call\",\"params\":[0,\"bar\",[]]}" ); + fc::usleep(fc::milliseconds(50)); + BOOST_CHECK_EQUAL( response, "{\"id\":4,\"result\":\"[null,null,null]\"}" ); + + server->stop_listening(); + client->synchronous_close(); server->close(); fc::usleep(fc::milliseconds(50)); From 8426b45d6c84f6d8c3160da3bb5daa19373bf17f Mon Sep 17 00:00:00 2001 From: John Jones Date: Tue, 13 Aug 2019 13:11:36 -0500 Subject: [PATCH 055/110] Increase size for Boost 1.70 --- include/fc/network/tcp_socket.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fc/network/tcp_socket.hpp b/include/fc/network/tcp_socket.hpp index 9bb6ea5..160df37 100644 --- a/include/fc/network/tcp_socket.hpp +++ b/include/fc/network/tcp_socket.hpp @@ -51,7 +51,7 @@ namespace fc { friend class tcp_server; class impl; #ifdef _WIN64 - fc::fwd my; + fc::fwd my; #else fc::fwd my; #endif From a1c2ff99434977a6a66d3e11089a3613f6973893 Mon Sep 17 00:00:00 2001 From: crypto-ape <43807588+crypto-ape@users.noreply.github.com> Date: Tue, 13 Aug 2019 17:31:22 +0200 Subject: [PATCH 056/110] support openbsd // make code compliant with clang --- CMakeLists.txt | 8 ++++---- include/fc/string.hpp | 2 +- include/fc/variant.hpp | 6 +++--- src/stacktrace.cpp | 3 +++ src/variant.cpp | 12 +++++++----- 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bad2407..e391325 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -141,11 +141,11 @@ ENDIF(WIN32) FIND_PACKAGE(Boost CONFIG COMPONENTS ${BOOST_COMPONENTS}) IF(NOT WIN32) - MESSAGE(STATUS "Configuring fc to build on Unix/Apple") + MESSAGE(STATUS "Configuring fc to build on Unix/Apple") - if(NOT APPLE) - SET(rt_library rt) - endif(NOT APPLE) + IF(NOT APPLE AND NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "OpenBSD") + SET(rt_library rt ) + ENDIF(NOT APPLE AND NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "OpenBSD") ENDIF(NOT WIN32) IF($ENV{OPENSSL_ROOT_DIR}) diff --git a/include/fc/string.hpp b/include/fc/string.hpp index 7fbe2e5..8f269f0 100644 --- a/include/fc/string.hpp +++ b/include/fc/string.hpp @@ -17,7 +17,7 @@ namespace fc std::string to_pretty_string( int64_t ); inline std::string to_string( int32_t v ) { return to_string( int64_t(v) ); } inline std::string to_string( uint32_t v ){ return to_string( uint64_t(v) ); } -#ifdef __APPLE__ +#if defined(__APPLE__) or defined(__OpenBSD__) inline std::string to_string( size_t s) { return to_string(uint64_t(s)); } #endif diff --git a/include/fc/variant.hpp b/include/fc/variant.hpp index f7ef613..66c422e 100644 --- a/include/fc/variant.hpp +++ b/include/fc/variant.hpp @@ -153,7 +153,7 @@ namespace fc void to_variant( const uint128_t& var, variant& vo, uint32_t max_depth = 1 ); void from_variant( const variant& var, uint128_t& vo, uint32_t max_depth = 1 ); - #ifdef __APPLE__ + #if defined(__APPLE__) or defined(__OpenBSD__) void to_variant( size_t s, variant& v, uint32_t max_depth = 1 ); #elif !defined(_WIN32) void to_variant( long long int s, variant& v, uint32_t max_depth = 1 ); @@ -229,7 +229,7 @@ namespace fc variant( uint32_t val, uint32_t max_depth = 1 ); variant( int32_t val, uint32_t max_depth = 1 ); variant( uint64_t val, uint32_t max_depth = 1 ); -#ifdef __APPLE__ +#if defined(__APPLE__) or defined(__OpenBSD__) variant( size_t val, uint32_t max_depth = 1 ); #endif variant( int64_t val, uint32_t max_depth = 1 ); @@ -632,7 +632,7 @@ namespace fc template void to_variant( const safe& s, variant& v, uint32_t max_depth ) { - to_variant( s.value, v, max_depth ); + to_variant( static_cast(s.value), v, max_depth ); } template diff --git a/src/stacktrace.cpp b/src/stacktrace.cpp index 126691f..910b48f 100644 --- a/src/stacktrace.cpp +++ b/src/stacktrace.cpp @@ -8,6 +8,9 @@ #if BOOST_VERSION / 100 >= 1065 && !defined(__APPLE__) #include #include +#if defined(__OpenBSD__) + #define BOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED +#endif #include namespace fc diff --git a/src/variant.cpp b/src/variant.cpp index 7a527e9..eaa12d3 100644 --- a/src/variant.cpp +++ b/src/variant.cpp @@ -11,7 +11,7 @@ #include #include -#ifdef __APPLE__ +#if defined(__APPLE__) or defined(__OpenBSD__) #include #endif @@ -79,7 +79,7 @@ variant::variant( uint64_t val, uint32_t max_depth ) set_variant_type( this, uint64_type ); } -#ifdef __APPLE__ +#if defined(__APPLE__) or defined(__OpenBSD__) variant::variant( size_t val, uint32_t max_depth ) { *reinterpret_cast(this) = val; @@ -679,7 +679,7 @@ void from_variant( const variant& var, std::vector& vo, uint32_t max_depth void to_variant( const uint128_t& var, variant& vo, uint32_t max_depth ) { -#ifdef __APPLE__ +#if defined(__APPLE__) or defined(__OpenBSD__) boost::multiprecision::uint128_t helper = uint128_hi64( var ); helper <<= 64; helper += uint128_lo64( var ); @@ -691,7 +691,7 @@ void to_variant( const uint128_t& var, variant& vo, uint32_t max_depth ) void from_variant( const variant& var, uint128_t& vo, uint32_t max_depth ) { -#ifdef __APPLE__ +#if defined(__APPLE__) or defined(__OpenBSD__) boost::multiprecision::uint128_t helper = boost::lexical_cast( var.as_string() ); vo = static_cast( helper >> 64 ); vo <<= 64; @@ -701,7 +701,9 @@ void from_variant( const variant& var, uint128_t& vo, uint32_t max_depth ) #endif } -#ifdef __APPLE__ +#if defined(__APPLE__) +#elif defined(__OpenBSD__) + void to_variant( size_t s, variant& v, uint32_t max_depth ) { v = variant( int64_t(s) ); } #elif !defined(_WIN32) void to_variant( long long int s, variant& v, uint32_t max_depth ) { v = variant( int64_t(s) ); } void to_variant( unsigned long long int s, variant& v, uint32_t max_depth ) { v = variant( uint64_t(s)); } From cb5f7d3cddbcad3b9a42de5b66f0b4af06791b34 Mon Sep 17 00:00:00 2001 From: crypto-ape <43807588+crypto-ape@users.noreply.github.com> Date: Tue, 13 Aug 2019 17:32:17 +0200 Subject: [PATCH 057/110] support openbsd // get rid of alloca --- src/crypto/elliptic_common.cpp | 9 +++------ src/crypto/elliptic_secp256k1.cpp | 2 -- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/crypto/elliptic_common.cpp b/src/crypto/elliptic_common.cpp index dd89c3a..8e4f802 100644 --- a/src/crypto/elliptic_common.cpp +++ b/src/crypto/elliptic_common.cpp @@ -7,8 +7,6 @@ #ifdef _WIN32 # include -#else -# include #endif /* stuff common to all ecc implementations */ @@ -231,12 +229,11 @@ namespace fc { namespace ecc { static std::string _to_base58( const extended_key_data& key ) { - size_t buf_len = key.size() + 4; - char *buffer = (char*)alloca(buf_len); + char buffer[key.size() + 4]; // it's a small static array => allocate on stack memcpy( buffer, key.data(), key.size() ); - fc::sha256 double_hash = fc::sha256::hash( fc::sha256::hash( (char*) key.data(), key.size() )); + fc::sha256 double_hash = fc::sha256::hash( fc::sha256::hash( (char*)key.data(), key.size() )); memcpy( buffer + key.size(), double_hash.data(), 4 ); - return fc::to_base58( buffer, buf_len ); + return fc::to_base58( buffer, sizeof(buffer) ); } static void _parse_extended_data( unsigned char* buffer, std::string base58 ) diff --git a/src/crypto/elliptic_secp256k1.cpp b/src/crypto/elliptic_secp256k1.cpp index b180d44..11969fc 100644 --- a/src/crypto/elliptic_secp256k1.cpp +++ b/src/crypto/elliptic_secp256k1.cpp @@ -14,8 +14,6 @@ #if _WIN32 # include -#else -# include #endif #include "_elliptic_impl_priv.hpp" From 4ac6887deb99ce2e26bd34688deaafa23fe4dd03 Mon Sep 17 00:00:00 2001 From: crypto-ape <43807588+crypto-ape@users.noreply.github.com> Date: Tue, 13 Aug 2019 17:33:12 +0200 Subject: [PATCH 058/110] support openbsd // compile with libressl --- src/crypto/openssl.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/crypto/openssl.cpp b/src/crypto/openssl.cpp index 3f8df03..e4c0e88 100644 --- a/src/crypto/openssl.cpp +++ b/src/crypto/openssl.cpp @@ -39,7 +39,11 @@ namespace fc ~openssl_scope() { +#if not defined(LIBRESSL_VERSION_NUMBER) + // No FIPS in LibreSSL. + // https://marc.info/?l=openbsd-misc&m=139819485423701&w=2 FIPS_mode_set(0); +#endif CONF_modules_unload(1); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); From 727e09ebe7be57672d3a3f11b0b7cfebaea2675b Mon Sep 17 00:00:00 2001 From: crypto-ape <43807588+crypto-ape@users.noreply.github.com> Date: Tue, 13 Aug 2019 17:37:58 +0200 Subject: [PATCH 059/110] support openbsd // implement tcp keep-alive polling --- src/network/tcp_socket.cpp | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/network/tcp_socket.cpp b/src/network/tcp_socket.cpp index 0012ba6..1152496 100644 --- a/src/network/tcp_socket.cpp +++ b/src/network/tcp_socket.cpp @@ -11,6 +11,13 @@ # include #endif +#if defined __OpenBSD__ +# include +# include +# include +# include +#endif + namespace fc { namespace detail @@ -186,16 +193,37 @@ namespace fc { if (setsockopt(my->_sock.native_handle(), IPPROTO_TCP, #if defined( __APPLE__ ) TCP_KEEPALIVE, + #elif defined( __OpenBSD__ ) + SO_KEEPALIVE, #else TCP_KEEPIDLE, #endif (char*)&timeout_sec, sizeof(timeout_sec)) < 0) wlog("Error setting TCP keepalive idle time"); -# if !defined(__APPLE__) || defined(TCP_KEEPINTVL) // TCP_KEEPINTVL not defined before 10.9 +# if defined(__OpenBSD__) + int name[4]; + name[0] = CTL_NET; + name[1] = PF_INET; + name[2] = IPPROTO_TCP; + + int value; + size_t sz; + + // get tics per second + name[3] = TCPCTL_SLOWHZ; + if (sysctl(name, 4, &value, &sz, NULL, 0) == -1) + wlog("Error setting TCP keepalive interval"); + + // set interval + value *= timeout_sec; + name[3] = TCPCTL_KEEPINTVL; + if (sysctl(name, 4, NULL, NULL, &value, sizeof(value)) == -1) + wlog("Error setting TCP keepalive interval"); +# elif !defined(__APPLE__) || defined(TCP_KEEPINTVL) // TCP_KEEPINTVL not defined before 10.9 if (setsockopt(my->_sock.native_handle(), IPPROTO_TCP, TCP_KEEPINTVL, (char*)&timeout_sec, sizeof(timeout_sec)) < 0) wlog("Error setting TCP keepalive interval"); -# endif // !__APPLE__ || TCP_KEEPINTVL +# endif // (__OpenBSD__) or (!__APPLE__ || TCP_KEEPINTVL) #endif // !WIN32 } else From 3f1096d23e132ee748724481c8737e9a7aa4f010 Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 16 Aug 2019 13:24:28 -0500 Subject: [PATCH 060/110] Remove custom FindBoost.cmake --- CMakeLists.txt | 4 +- CMakeModules/Boost/BoostConfig.cmake | 18 - CMakeModules/Legacy/Boost/FindBoost.cmake | 1180 --------------------- CMakeModules/Legacy/CMakeLists.txt | 27 - 4 files changed, 1 insertion(+), 1228 deletions(-) delete mode 100644 CMakeModules/Boost/BoostConfig.cmake delete mode 100644 CMakeModules/Legacy/Boost/FindBoost.cmake delete mode 100644 CMakeModules/Legacy/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index bad2407..4394887 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,8 +26,6 @@ INCLUDE( SetupTargetMacros ) INCLUDE(GetGitRevisionDescription) INCLUDE(CheckLibraryExists) -add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/Legacy) - get_git_head_revision(GIT_REFSPEC FC_GIT_REVISION_SHA) get_git_unix_timestamp(FC_GIT_REVISION_UNIX_TIMESTAMP) @@ -138,7 +136,7 @@ IF( WIN32 ) # iphlpapi.lib ENDIF(WIN32) -FIND_PACKAGE(Boost CONFIG COMPONENTS ${BOOST_COMPONENTS}) +FIND_PACKAGE(Boost COMPONENTS ${BOOST_COMPONENTS} REQUIRED) IF(NOT WIN32) MESSAGE(STATUS "Configuring fc to build on Unix/Apple") diff --git a/CMakeModules/Boost/BoostConfig.cmake b/CMakeModules/Boost/BoostConfig.cmake deleted file mode 100644 index a5e01f2..0000000 --- a/CMakeModules/Boost/BoostConfig.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# This overrides `find_package(Boost ... CONFIG ... )` calls -# - calls the CMake's built-in `FindBoost.cmake` and adds `pthread` library dependency - -MESSAGE(STATUS "Using custom FindBoost config") - -find_package(Boost 1.58 REQUIRED COMPONENTS ${Boost_FIND_COMPONENTS}) - -# Inject `pthread` dependency to Boost if needed -if (UNIX AND NOT CYGWIN) - list(FIND Boost_FIND_COMPONENTS thread _using_boost_thread) - if (_using_boost_thread GREATER -1) - find_library(BOOST_THREAD_LIBRARY NAMES pthread DOC "The threading library used by boost-thread") - if (BOOST_THREAD_LIBRARY) - MESSAGE(STATUS "Adding Boost thread lib dependency: ${BOOST_THREAD_LIBRARY}") - list(APPEND Boost_LIBRARIES ${BOOST_THREAD_LIBRARY}) - endif () - endif () -endif () diff --git a/CMakeModules/Legacy/Boost/FindBoost.cmake b/CMakeModules/Legacy/Boost/FindBoost.cmake deleted file mode 100644 index b8276af..0000000 --- a/CMakeModules/Legacy/Boost/FindBoost.cmake +++ /dev/null @@ -1,1180 +0,0 @@ -# - Find Boost include dirs and libraries -# Use this module by invoking find_package with the form: -# find_package(Boost -# [version] [EXACT] # Minimum or EXACT version e.g. 1.36.0 -# [REQUIRED] # Fail with error if Boost is not found -# [COMPONENTS ...] # Boost libraries by their canonical name -# ) # e.g. "date_time" for "libboost_date_time" -# This module finds headers and requested component libraries OR a CMake -# package configuration file provided by a "Boost CMake" build. For the -# latter case skip to the "Boost CMake" section below. For the former -# case results are reported in variables: -# Boost_FOUND - True if headers and requested libraries were found -# Boost_INCLUDE_DIRS - Boost include directories -# Boost_LIBRARY_DIRS - Link directories for Boost libraries -# Boost_LIBRARIES - Boost component libraries to be linked -# Boost__FOUND - True if component was found ( is upper-case) -# Boost__LIBRARY - Libraries to link for component (may include -# target_link_libraries debug/optimized keywords) -# Boost_VERSION - BOOST_VERSION value from boost/version.hpp -# Boost_LIB_VERSION - Version string appended to library filenames -# Boost_MAJOR_VERSION - Boost major version number (X in X.y.z) -# Boost_MINOR_VERSION - Boost minor version number (Y in x.Y.z) -# Boost_SUBMINOR_VERSION - Boost subminor version number (Z in x.y.Z) -# Boost_LIB_DIAGNOSTIC_DEFINITIONS (Windows) -# - Pass to add_definitions() to have diagnostic -# information about Boost's automatic linking -# displayed during compilation -# -# This module reads hints about search locations from variables: -# BOOST_ROOT - Preferred installation prefix -# (or BOOSTROOT) -# BOOST_INCLUDEDIR - Preferred include directory e.g. /include -# BOOST_LIBRARYDIR - Preferred library directory e.g. /lib -# Boost_NO_SYSTEM_PATHS - Set to ON to disable searching in locations not -# specified by these hint variables. Default is OFF. -# Boost_ADDITIONAL_VERSIONS -# - List of Boost versions not known to this module -# (Boost install locations may contain the version) -# and saves search results persistently in CMake cache entries: -# Boost_INCLUDE_DIR - Directory containing Boost headers -# Boost_LIBRARY_DIR - Directory containing Boost libraries -# Boost__LIBRARY_DEBUG - Component library debug variant -# Boost__LIBRARY_RELEASE - Component library release variant -# Users may set the these hints or results as cache entries. Projects should -# not read these entries directly but instead use the above result variables. -# Note that some hint names start in upper-case "BOOST". One may specify -# these as environment variables if they are not specified as CMake variables -# or cache entries. -# -# This module first searches for the Boost header files using the above hint -# variables (excluding BOOST_LIBRARYDIR) and saves the result in -# Boost_INCLUDE_DIR. Then it searches for requested component libraries using -# the above hints (excluding BOOST_INCLUDEDIR and Boost_ADDITIONAL_VERSIONS), -# "lib" directories near Boost_INCLUDE_DIR, and the library name configuration -# settings below. It saves the library directory in Boost_LIBRARY_DIR and -# individual library locations in Boost__LIBRARY_DEBUG and -# Boost__LIBRARY_RELEASE. When one changes settings used by previous -# searches in the same build tree (excluding environment variables) this -# module discards previous search results affected by the changes and searches -# again. -# -# Boost libraries come in many variants encoded in their file name. Users or -# projects may tell this module which variant to find by setting variables: -# Boost_USE_MULTITHREADED - Set to OFF to use the non-multithreaded -# libraries ('mt' tag). Default is ON. -# Boost_USE_STATIC_LIBS - Set to ON to force the use of the static -# libraries. Default is OFF. -# Boost_USE_STATIC_RUNTIME - Set to ON or OFF to specify whether to use -# libraries linked statically to the C++ runtime -# ('s' tag). Default is platform dependent. -# Boost_USE_DEBUG_PYTHON - Set to ON to use libraries compiled with a -# debug Python build ('y' tag). Default is OFF. -# Boost_USE_STLPORT - Set to ON to use libraries compiled with -# STLPort ('p' tag). Default is OFF. -# Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS -# - Set to ON to use libraries compiled with -# STLPort deprecated "native iostreams" -# ('n' tag). Default is OFF. -# Boost_COMPILER - Set to the compiler-specific library suffix -# (e.g. "-gcc43"). Default is auto-computed -# for the C++ compiler in use. -# Boost_THREADAPI - Suffix for "thread" component library name, -# such as "pthread" or "win32". Names with -# and without this suffix will both be tried. -# Other variables one may set to control this module are: -# Boost_DEBUG - Set to ON to enable debug output from FindBoost. -# Please enable this before filing any bug report. -# Boost_DETAILED_FAILURE_MSG -# - Set to ON to add detailed information to the -# failure message even when the REQUIRED option -# is not given to the find_package call. -# Boost_REALPATH - Set to ON to resolve symlinks for discovered -# libraries to assist with packaging. For example, -# the "system" component library may be resolved to -# "/usr/lib/libboost_system.so.1.42.0" instead of -# "/usr/lib/libboost_system.so". This does not -# affect linking and should not be enabled unless -# the user needs this information. -# On Visual Studio and Borland compilers Boost headers request automatic -# linking to corresponding libraries. This requires matching libraries to be -# linked explicitly or available in the link library search path. In this -# case setting Boost_USE_STATIC_LIBS to OFF may not achieve dynamic linking. -# Boost automatic linking typically requests static libraries with a few -# exceptions (such as Boost.Python). Use -# add_definitions(${Boost_LIB_DIAGNOSTIC_DEFINITIONS}) -# to ask Boost to report information about automatic linking requests. -# -# Example to find Boost headers only: -# find_package(Boost 1.36.0) -# if(Boost_FOUND) -# include_directories(${Boost_INCLUDE_DIRS}) -# add_executable(foo foo.cc) -# endif() -# Example to find Boost headers and some libraries: -# set(Boost_USE_STATIC_LIBS ON) -# set(Boost_USE_MULTITHREADED ON) -# set(Boost_USE_STATIC_RUNTIME OFF) -# find_package(Boost 1.36.0 COMPONENTS date_time filesystem system ...) -# if(Boost_FOUND) -# include_directories(${Boost_INCLUDE_DIRS}) -# add_executable(foo foo.cc) -# target_link_libraries(foo ${Boost_LIBRARIES}) -# endif() -# -# Boost CMake ---------------------------------------------------------- -# -# If Boost was built using the boost-cmake project it provides a package -# configuration file for use with find_package's Config mode. This module -# looks for the package configuration file called BoostConfig.cmake or -# boost-config.cmake and stores the result in cache entry "Boost_DIR". If -# found, the package configuration file is loaded and this module returns with -# no further action. See documentation of the Boost CMake package -# configuration for details on what it provides. -# -# Set Boost_NO_BOOST_CMAKE to ON to disable the search for boost-cmake. - -#============================================================================= -# Copyright 2006-2012 Kitware, Inc. -# Copyright 2006-2008 Andreas Schneider -# Copyright 2007 Wengo -# Copyright 2007 Mike Jackson -# Copyright 2008 Andreas Pakulat -# Copyright 2008-2012 Philip Lowman -# -# Distributed under the OSI-approved BSD License (the "License"); -# see accompanying file Copyright.txt for details. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= -# (To distribute this file outside of CMake, substitute the full -# License text for the above reference.) - - -#------------------------------------------------------------------------------- -# Before we go searching, check whether boost-cmake is avaialble, unless the -# user specifically asked NOT to search for boost-cmake. -# -# If Boost_DIR is set, this behaves as any find_package call would. If not, -# it looks at BOOST_ROOT and BOOSTROOT to find Boost. -# - -message(STATUS "Using custom FindBoost.cmake") - -if (NOT Boost_NO_BOOST_CMAKE) - # If Boost_DIR is not set, look for BOOSTROOT and BOOST_ROOT as alternatives, - # since these are more conventional for Boost. - if ("$ENV{Boost_DIR}" STREQUAL "") - if (NOT "$ENV{BOOST_ROOT}" STREQUAL "") - set(ENV{Boost_DIR} $ENV{BOOST_ROOT}) - elseif (NOT "$ENV{BOOSTROOT}" STREQUAL "") - set(ENV{Boost_DIR} $ENV{BOOSTROOT}) - endif() - endif() - - # Do the same find_package call but look specifically for the CMake version. - # Note that args are passed in the Boost_FIND_xxxxx variables, so there is no - # need to delegate them to this find_package call. - find_package(Boost QUIET NO_MODULE) - mark_as_advanced(Boost_DIR) - - # If we found boost-cmake, then we're done. Print out what we found. - # Otherwise let the rest of the module try to find it. - if (Boost_FOUND) - message("Boost ${Boost_FIND_VERSION} found.") - if (Boost_FIND_COMPONENTS) - message("Found Boost components:") - message(" ${Boost_FIND_COMPONENTS}") - endif() - return() - endif() -endif() - - -#------------------------------------------------------------------------------- -# FindBoost functions & macros -# - -############################################ -# -# Check the existence of the libraries. -# -############################################ -# This macro was taken directly from the FindQt4.cmake file that is included -# with the CMake distribution. This is NOT my work. All work was done by the -# original authors of the FindQt4.cmake file. Only minor modifications were -# made to remove references to Qt and make this file more generally applicable -# And ELSE/ENDIF pairs were removed for readability. -######################################################################### - -macro(_Boost_ADJUST_LIB_VARS basename) - if(Boost_INCLUDE_DIR ) - if(Boost_${basename}_LIBRARY_DEBUG AND Boost_${basename}_LIBRARY_RELEASE) - # if the generator supports configuration types then set - # optimized and debug libraries, or if the CMAKE_BUILD_TYPE has a value - if(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) - set(Boost_${basename}_LIBRARY optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG}) - else() - # if there are no configuration types and CMAKE_BUILD_TYPE has no value - # then just use the release libraries - set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE} ) - endif() - # FIXME: This probably should be set for both cases - set(Boost_${basename}_LIBRARIES optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG}) - endif() - - # if only the release version was found, set the debug variable also to the release version - if(Boost_${basename}_LIBRARY_RELEASE AND NOT Boost_${basename}_LIBRARY_DEBUG) - set(Boost_${basename}_LIBRARY_DEBUG ${Boost_${basename}_LIBRARY_RELEASE}) - set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE}) - set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_RELEASE}) - endif() - - # if only the debug version was found, set the release variable also to the debug version - if(Boost_${basename}_LIBRARY_DEBUG AND NOT Boost_${basename}_LIBRARY_RELEASE) - set(Boost_${basename}_LIBRARY_RELEASE ${Boost_${basename}_LIBRARY_DEBUG}) - set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_DEBUG}) - set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_DEBUG}) - endif() - - # If the debug & release library ends up being the same, omit the keywords - if(${Boost_${basename}_LIBRARY_RELEASE} STREQUAL ${Boost_${basename}_LIBRARY_DEBUG}) - set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE} ) - set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_RELEASE} ) - endif() - - if(Boost_${basename}_LIBRARY) - set(Boost_${basename}_FOUND ON) - endif() - - endif() - # Make variables changeble to the advanced user - mark_as_advanced( - Boost_${basename}_LIBRARY_RELEASE - Boost_${basename}_LIBRARY_DEBUG - ) -endmacro() - -macro(_Boost_CHANGE_DETECT changed_var) - set(${changed_var} 0) - foreach(v ${ARGN}) - if(DEFINED _Boost_COMPONENTS_SEARCHED) - if(${v}) - if(_${v}_LAST) - string(COMPARE NOTEQUAL "${${v}}" "${_${v}_LAST}" _${v}_CHANGED) - else() - set(_${v}_CHANGED 1) - endif() - elseif(_${v}_LAST) - set(_${v}_CHANGED 1) - endif() - if(_${v}_CHANGED) - set(${changed_var} 1) - endif() - else() - set(_${v}_CHANGED 0) - endif() - endforeach() -endmacro() - -macro(_Boost_FIND_LIBRARY var) - find_library(${var} ${ARGN}) - - # If we found the first library save Boost_LIBRARY_DIR. - if(${var} AND NOT Boost_LIBRARY_DIR) - get_filename_component(_dir "${${var}}" PATH) - set(Boost_LIBRARY_DIR "${_dir}" CACHE PATH "Boost library directory" FORCE) - endif() - - # If Boost_LIBRARY_DIR is known then search only there. - if(Boost_LIBRARY_DIR) - set(_boost_LIBRARY_SEARCH_DIRS ${Boost_LIBRARY_DIR} NO_DEFAULT_PATH) - endif() -endmacro() - -#------------------------------------------------------------------------------- - -# -# Runs compiler with "-dumpversion" and parses major/minor -# version with a regex. -# -function(_Boost_COMPILER_DUMPVERSION _OUTPUT_VERSION) - - exec_program(${CMAKE_CXX_COMPILER} - ARGS ${CMAKE_CXX_COMPILER_ARG1} -dumpversion - OUTPUT_VARIABLE _boost_COMPILER_VERSION - ) - string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2" - _boost_COMPILER_VERSION ${_boost_COMPILER_VERSION}) - - set(${_OUTPUT_VERSION} ${_boost_COMPILER_VERSION} PARENT_SCOPE) -endfunction() - -# -# Take a list of libraries with "thread" in it -# and prepend duplicates with "thread_${Boost_THREADAPI}" -# at the front of the list -# -function(_Boost_PREPEND_LIST_WITH_THREADAPI _output) - set(_orig_libnames ${ARGN}) - string(REPLACE "thread" "thread_${Boost_THREADAPI}" _threadapi_libnames "${_orig_libnames}") - set(${_output} ${_threadapi_libnames} ${_orig_libnames} PARENT_SCOPE) -endfunction() - -# -# If a library is found, replace its cache entry with its REALPATH -# -function(_Boost_SWAP_WITH_REALPATH _library _docstring) - if(${_library}) - get_filename_component(_boost_filepathreal ${${_library}} REALPATH) - unset(${_library} CACHE) - set(${_library} ${_boost_filepathreal} CACHE FILEPATH "${_docstring}") - endif() -endfunction() - -function(_Boost_CHECK_SPELLING _var) - if(${_var}) - string(TOUPPER ${_var} _var_UC) - message(FATAL_ERROR "ERROR: ${_var} is not the correct spelling. The proper spelling is ${_var_UC}.") - endif() -endfunction() - -# Guesses Boost's compiler prefix used in built library names -# Returns the guess by setting the variable pointed to by _ret -function(_Boost_GUESS_COMPILER_PREFIX _ret) - if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel" - OR "${CMAKE_CXX_COMPILER}" MATCHES "icl" - OR "${CMAKE_CXX_COMPILER}" MATCHES "icpc") - if(WIN32) - set (_boost_COMPILER "-iw") - else() - set (_boost_COMPILER "-il") - endif() - elseif (MSVC12) - set(_boost_COMPILER "-vc120") - elseif (MSVC11) - set(_boost_COMPILER "-vc110") - elseif (MSVC10) - set(_boost_COMPILER "-vc100") - elseif (MSVC90) - set(_boost_COMPILER "-vc90") - elseif (MSVC80) - set(_boost_COMPILER "-vc80") - elseif (MSVC71) - set(_boost_COMPILER "-vc71") - elseif (MSVC70) # Good luck! - set(_boost_COMPILER "-vc7") # yes, this is correct - elseif (MSVC60) # Good luck! - set(_boost_COMPILER "-vc6") # yes, this is correct - elseif (BORLAND) - set(_boost_COMPILER "-bcb") - elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "SunPro") - set(_boost_COMPILER "-sw") - elseif (MINGW) - if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34) - set(_boost_COMPILER "-mgw") # no GCC version encoding prior to 1.34 - else() - _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION) - set(_boost_COMPILER "-mgw${_boost_COMPILER_VERSION}") - endif() - elseif (UNIX) - if (CMAKE_COMPILER_IS_GNUCXX) - if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34) - set(_boost_COMPILER "-gcc") # no GCC version encoding prior to 1.34 - else() - _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION) - # Determine which version of GCC we have. - if(APPLE) - if(Boost_MINOR_VERSION) - if(${Boost_MINOR_VERSION} GREATER 35) - # In Boost 1.36.0 and newer, the mangled compiler name used - # on Mac OS X/Darwin is "xgcc". - set(_boost_COMPILER "-xgcc${_boost_COMPILER_VERSION}") - else() - # In Boost <= 1.35.0, there is no mangled compiler name for - # the Mac OS X/Darwin version of GCC. - set(_boost_COMPILER "") - endif() - else() - # We don't know the Boost version, so assume it's - # pre-1.36.0. - set(_boost_COMPILER "") - endif() - else() - set(_boost_COMPILER "-gcc${_boost_COMPILER_VERSION}") - endif() - endif() - endif () - else() - # TODO at least Boost_DEBUG here? - set(_boost_COMPILER "") - endif() - set(${_ret} ${_boost_COMPILER} PARENT_SCOPE) -endfunction() - -function(_Boost_consider_adding_pthreads _outvar) - # On Unix platforms (excluding cygwin) add pthreads to Boost_LIBRARIES - # if the user is searching for the boost-thread component. - if(UNIX AND NOT CYGWIN) - list(FIND Boost_FIND_COMPONENTS thread _using_boost_thread) - if(_using_boost_thread GREATER -1) - find_library(BOOST_THREAD_LIBRARY NAMES pthread - DOC "The threading library used by boost-thread" - ) - if(BOOST_THREAD_LIBRARY) - set(${_outvar} ${ARGN} ${BOOST_THREAD_LIBRARY} PARENT_SCOPE) - endif() - endif() - endif() -endfunction() - -# -# End functions/macros -# -#------------------------------------------------------------------------------- - -#------------------------------------------------------------------------------- -# main. -#------------------------------------------------------------------------------- - -if(NOT DEFINED Boost_USE_MULTITHREADED) - set(Boost_USE_MULTITHREADED TRUE) -endif() - -# Check the version of Boost against the requested version. -if(Boost_FIND_VERSION AND NOT Boost_FIND_VERSION_MINOR) - message(SEND_ERROR "When requesting a specific version of Boost, you must provide at least the major and minor version numbers, e.g., 1.34") -endif() - -if(Boost_FIND_VERSION_EXACT) - # The version may appear in a directory with or without the patch - # level, even when the patch level is non-zero. - set(_boost_TEST_VERSIONS - "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}.${Boost_FIND_VERSION_PATCH}" - "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") -else() - # The user has not requested an exact version. Among known - # versions, find those that are acceptable to the user request. - set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS} - "1.56.0" "1.56" "1.55.0" "1.55" "1.54.0" "1.54" - "1.53.0" "1.53" "1.52.0" "1.52" "1.51.0" "1.51" - "1.50.0" "1.50" "1.49.0" "1.49" "1.48.0" "1.48" "1.47.0" "1.47" "1.46.1" - "1.46.0" "1.46" "1.45.0" "1.45" "1.44.0" "1.44" "1.43.0" "1.43" "1.42.0" "1.42" - "1.41.0" "1.41" "1.40.0" "1.40" "1.39.0" "1.39" "1.38.0" "1.38" "1.37.0" "1.37" - "1.36.1" "1.36.0" "1.36" "1.35.1" "1.35.0" "1.35" "1.34.1" "1.34.0" - "1.34" "1.33.1" "1.33.0" "1.33") - set(_boost_TEST_VERSIONS) - if(Boost_FIND_VERSION) - set(_Boost_FIND_VERSION_SHORT "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") - # Select acceptable versions. - foreach(version ${_Boost_KNOWN_VERSIONS}) - if(NOT "${version}" VERSION_LESS "${Boost_FIND_VERSION}") - # This version is high enough. - list(APPEND _boost_TEST_VERSIONS "${version}") - elseif("${version}.99" VERSION_EQUAL "${_Boost_FIND_VERSION_SHORT}.99") - # This version is a short-form for the requested version with - # the patch level dropped. - list(APPEND _boost_TEST_VERSIONS "${version}") - endif() - endforeach() - else() - # Any version is acceptable. - set(_boost_TEST_VERSIONS "${_Boost_KNOWN_VERSIONS}") - endif() -endif() - -# The reason that we failed to find Boost. This will be set to a -# user-friendly message when we fail to find some necessary piece of -# Boost. -set(Boost_ERROR_REASON) - -if(Boost_DEBUG) - # Output some of their choices - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_TEST_VERSIONS = ${_boost_TEST_VERSIONS}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_USE_MULTITHREADED = ${Boost_USE_MULTITHREADED}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_USE_STATIC_LIBS = ${Boost_USE_STATIC_LIBS}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_USE_STATIC_RUNTIME = ${Boost_USE_STATIC_RUNTIME}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_ADDITIONAL_VERSIONS = ${Boost_ADDITIONAL_VERSIONS}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_NO_SYSTEM_PATHS = ${Boost_NO_SYSTEM_PATHS}") -endif() - -if(WIN32) - # In windows, automatic linking is performed, so you do not have - # to specify the libraries. If you are linking to a dynamic - # runtime, then you can choose to link to either a static or a - # dynamic Boost library, the default is to do a static link. You - # can alter this for a specific library "whatever" by defining - # BOOST_WHATEVER_DYN_LINK to force Boost library "whatever" to be - # linked dynamically. Alternatively you can force all Boost - # libraries to dynamic link by defining BOOST_ALL_DYN_LINK. - - # This feature can be disabled for Boost library "whatever" by - # defining BOOST_WHATEVER_NO_LIB, or for all of Boost by defining - # BOOST_ALL_NO_LIB. - - # If you want to observe which libraries are being linked against - # then defining BOOST_LIB_DIAGNOSTIC will cause the auto-linking - # code to emit a #pragma message each time a library is selected - # for linking. - set(Boost_LIB_DIAGNOSTIC_DEFINITIONS "-DBOOST_LIB_DIAGNOSTIC") -endif() - -_Boost_CHECK_SPELLING(Boost_ROOT) -_Boost_CHECK_SPELLING(Boost_LIBRARYDIR) -_Boost_CHECK_SPELLING(Boost_INCLUDEDIR) - -# Collect environment variable inputs as hints. Do not consider changes. -foreach(v BOOSTROOT BOOST_ROOT BOOST_INCLUDEDIR BOOST_LIBRARYDIR) - set(_env $ENV{${v}}) - if(_env) - file(TO_CMAKE_PATH "${_env}" _ENV_${v}) - else() - set(_ENV_${v} "") - endif() -endforeach() -if(NOT _ENV_BOOST_ROOT AND _ENV_BOOSTROOT) - set(_ENV_BOOST_ROOT "${_ENV_BOOSTROOT}") -endif() - -# Collect inputs and cached results. Detect changes since the last run. -if(NOT BOOST_ROOT AND BOOSTROOT) - set(BOOST_ROOT "${BOOSTROOT}") -endif() -set(_Boost_VARS_DIR - BOOST_ROOT - Boost_NO_SYSTEM_PATHS - ) - -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Declared as CMake or Environmental Variables:") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " BOOST_ROOT = ${BOOST_ROOT}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " BOOST_INCLUDEDIR = ${BOOST_INCLUDEDIR}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " BOOST_LIBRARYDIR = ${BOOST_LIBRARYDIR}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_TEST_VERSIONS = ${_boost_TEST_VERSIONS}") -endif() - -# ------------------------------------------------------------------------ -# Search for Boost include DIR -# ------------------------------------------------------------------------ - -set(_Boost_VARS_INC BOOST_INCLUDEDIR Boost_INCLUDE_DIR Boost_ADDITIONAL_VERSIONS) -_Boost_CHANGE_DETECT(_Boost_CHANGE_INCDIR ${_Boost_VARS_DIR} ${_Boost_VARS_INC}) -# Clear Boost_INCLUDE_DIR if it did not change but other input affecting the -# location did. We will find a new one based on the new inputs. -if(_Boost_CHANGE_INCDIR AND NOT _Boost_INCLUDE_DIR_CHANGED) - unset(Boost_INCLUDE_DIR CACHE) -endif() - -if(NOT Boost_INCLUDE_DIR) - set(_boost_INCLUDE_SEARCH_DIRS "") - if(BOOST_INCLUDEDIR) - list(APPEND _boost_INCLUDE_SEARCH_DIRS ${BOOST_INCLUDEDIR}) - elseif(_ENV_BOOST_INCLUDEDIR) - list(APPEND _boost_INCLUDE_SEARCH_DIRS ${_ENV_BOOST_INCLUDEDIR}) - endif() - - if( BOOST_ROOT ) - list(APPEND _boost_INCLUDE_SEARCH_DIRS ${BOOST_ROOT}/include ${BOOST_ROOT}) - elseif( _ENV_BOOST_ROOT ) - list(APPEND _boost_INCLUDE_SEARCH_DIRS ${_ENV_BOOST_ROOT}/include ${_ENV_BOOST_ROOT}) - endif() - - if( Boost_NO_SYSTEM_PATHS) - list(APPEND _boost_INCLUDE_SEARCH_DIRS NO_CMAKE_SYSTEM_PATH) - else() - list(APPEND _boost_INCLUDE_SEARCH_DIRS PATHS - C:/boost/include - C:/boost - /sw/local/include - ) - endif() - - # Try to find Boost by stepping backwards through the Boost versions - # we know about. - # Build a list of path suffixes for each version. - set(_boost_PATH_SUFFIXES) - foreach(_boost_VER ${_boost_TEST_VERSIONS}) - # Add in a path suffix, based on the required version, ideally - # we could read this from version.hpp, but for that to work we'd - # need to know the include dir already - set(_boost_BOOSTIFIED_VERSION) - - # Transform 1.35 => 1_35 and 1.36.0 => 1_36_0 - if(_boost_VER MATCHES "[0-9]+\\.[0-9]+\\.[0-9]+") - string(REGEX REPLACE "([0-9]+)\\.([0-9]+)\\.([0-9]+)" "\\1_\\2_\\3" - _boost_BOOSTIFIED_VERSION ${_boost_VER}) - elseif(_boost_VER MATCHES "[0-9]+\\.[0-9]+") - string(REGEX REPLACE "([0-9]+)\\.([0-9]+)" "\\1_\\2" - _boost_BOOSTIFIED_VERSION ${_boost_VER}) - endif() - - list(APPEND _boost_PATH_SUFFIXES - "boost-${_boost_BOOSTIFIED_VERSION}" - "boost_${_boost_BOOSTIFIED_VERSION}" - "boost/boost-${_boost_BOOSTIFIED_VERSION}" - "boost/boost_${_boost_BOOSTIFIED_VERSION}" - ) - - endforeach() - - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Include debugging info:") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " _boost_INCLUDE_SEARCH_DIRS = ${_boost_INCLUDE_SEARCH_DIRS}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " _boost_PATH_SUFFIXES = ${_boost_PATH_SUFFIXES}") - endif() - - # Look for a standard boost header file. - find_path(Boost_INCLUDE_DIR - NAMES boost/config.hpp - HINTS ${_boost_INCLUDE_SEARCH_DIRS} - PATH_SUFFIXES ${_boost_PATH_SUFFIXES} - ) -endif() - -# ------------------------------------------------------------------------ -# Extract version information from version.hpp -# ------------------------------------------------------------------------ - -# Set Boost_FOUND based only on header location and version. -# It will be updated below for component libraries. -if(Boost_INCLUDE_DIR) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "location of version.hpp: ${Boost_INCLUDE_DIR}/boost/version.hpp") - endif() - - # Extract Boost_VERSION and Boost_LIB_VERSION from version.hpp - set(Boost_VERSION 0) - set(Boost_LIB_VERSION "") - file(STRINGS "${Boost_INCLUDE_DIR}/boost/version.hpp" _boost_VERSION_HPP_CONTENTS REGEX "#define BOOST_(LIB_)?VERSION ") - set(_Boost_VERSION_REGEX "([0-9]+)") - set(_Boost_LIB_VERSION_REGEX "\"([0-9_]+)\"") - foreach(v VERSION LIB_VERSION) - if("${_boost_VERSION_HPP_CONTENTS}" MATCHES ".*#define BOOST_${v} ${_Boost_${v}_REGEX}.*") - set(Boost_${v} "${CMAKE_MATCH_1}") - endif() - endforeach() - unset(_boost_VERSION_HPP_CONTENTS) - - math(EXPR Boost_MAJOR_VERSION "${Boost_VERSION} / 100000") - math(EXPR Boost_MINOR_VERSION "${Boost_VERSION} / 100 % 1000") - math(EXPR Boost_SUBMINOR_VERSION "${Boost_VERSION} % 100") - - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}\nBoost include path: ${Boost_INCLUDE_DIR}") - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "version.hpp reveals boost " - "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") - endif() - - if(Boost_FIND_VERSION) - # Set Boost_FOUND based on requested version. - set(_Boost_VERSION "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") - if("${_Boost_VERSION}" VERSION_LESS "${Boost_FIND_VERSION}") - set(Boost_FOUND 0) - set(_Boost_VERSION_AGE "old") - elseif(Boost_FIND_VERSION_EXACT AND - NOT "${_Boost_VERSION}" VERSION_EQUAL "${Boost_FIND_VERSION}") - set(Boost_FOUND 0) - set(_Boost_VERSION_AGE "new") - else() - set(Boost_FOUND 1) - endif() - if(NOT Boost_FOUND) - # State that we found a version of Boost that is too new or too old. - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}\nDetected version of Boost is too ${_Boost_VERSION_AGE}. Requested version was ${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") - if (Boost_FIND_VERSION_PATCH) - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}.${Boost_FIND_VERSION_PATCH}") - endif () - if (NOT Boost_FIND_VERSION_EXACT) - set(Boost_ERROR_REASON "${Boost_ERROR_REASON} (or newer)") - endif () - set(Boost_ERROR_REASON "${Boost_ERROR_REASON}.") - endif () - else() - # Caller will accept any Boost version. - set(Boost_FOUND 1) - endif() -else() - set(Boost_FOUND 0) - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}Unable to find the Boost header files. Please set BOOST_ROOT to the root directory containing Boost or BOOST_INCLUDEDIR to the directory containing Boost's headers.") -endif() - -# ------------------------------------------------------------------------ -# Suffix initialization and compiler suffix detection. -# ------------------------------------------------------------------------ - -set(_Boost_VARS_NAME - Boost_COMPILER - Boost_THREADAPI - Boost_USE_DEBUG_PYTHON - Boost_USE_MULTITHREADED - Boost_USE_STATIC_LIBS - Boost_USE_STATIC_RUNTIME - Boost_USE_STLPORT - Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS - ) -_Boost_CHANGE_DETECT(_Boost_CHANGE_LIBNAME ${_Boost_VARS_NAME}) - -# Setting some more suffixes for the library -set(Boost_LIB_PREFIX "") -if ( WIN32 AND Boost_USE_STATIC_LIBS AND NOT CYGWIN) - set(Boost_LIB_PREFIX "lib") -endif() - -if (Boost_COMPILER) - set(_boost_COMPILER ${Boost_COMPILER}) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "using user-specified Boost_COMPILER = ${_boost_COMPILER}") - endif() -else() - # Attempt to guess the compiler suffix - # NOTE: this is not perfect yet, if you experience any issues - # please report them and use the Boost_COMPILER variable - # to work around the problems. - _Boost_GUESS_COMPILER_PREFIX(_boost_COMPILER) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "guessed _boost_COMPILER = ${_boost_COMPILER}") - endif() -endif() - -set (_boost_MULTITHREADED "-mt") -if( NOT Boost_USE_MULTITHREADED ) - set (_boost_MULTITHREADED "") -endif() -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_MULTITHREADED = ${_boost_MULTITHREADED}") -endif() - -#====================== -# Systematically build up the Boost ABI tag -# http://boost.org/doc/libs/1_41_0/more/getting_started/windows.html#library-naming -set( _boost_RELEASE_ABI_TAG "-") -set( _boost_DEBUG_ABI_TAG "-") -# Key Use this library when: -# s linking statically to the C++ standard library and -# compiler runtime support libraries. -if(Boost_USE_STATIC_RUNTIME) - set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}s") - set( _boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}s") -endif() -# g using debug versions of the standard and runtime -# support libraries -if(WIN32) - if(MSVC OR "${CMAKE_CXX_COMPILER}" MATCHES "icl" - OR "${CMAKE_CXX_COMPILER}" MATCHES "icpc") - set(_boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}g") - endif() -endif() -# y using special debug build of python -if(Boost_USE_DEBUG_PYTHON) - set(_boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}y") -endif() -# d using a debug version of your code -set(_boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}d") -# p using the STLport standard library rather than the -# default one supplied with your compiler -if(Boost_USE_STLPORT) - set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}p") - set( _boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}p") -endif() -# n using the STLport deprecated "native iostreams" feature -if(Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS) - set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}n") - set( _boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}n") -endif() - -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_RELEASE_ABI_TAG = ${_boost_RELEASE_ABI_TAG}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_DEBUG_ABI_TAG = ${_boost_DEBUG_ABI_TAG}") -endif() - -# ------------------------------------------------------------------------ -# Begin finding boost libraries -# ------------------------------------------------------------------------ -set(_Boost_VARS_LIB BOOST_LIBRARYDIR Boost_LIBRARY_DIR) -_Boost_CHANGE_DETECT(_Boost_CHANGE_LIBDIR ${_Boost_VARS_DIR} ${_Boost_VARS_LIB} Boost_INCLUDE_DIR) -# Clear Boost_LIBRARY_DIR if it did not change but other input affecting the -# location did. We will find a new one based on the new inputs. -if(_Boost_CHANGE_LIBDIR AND NOT _Boost_LIBRARY_DIR_CHANGED) - unset(Boost_LIBRARY_DIR CACHE) -endif() - -if(Boost_LIBRARY_DIR) - set(_boost_LIBRARY_SEARCH_DIRS ${Boost_LIBRARY_DIR} NO_DEFAULT_PATH) -else() - set(_boost_LIBRARY_SEARCH_DIRS "") - if(BOOST_LIBRARYDIR) - list(APPEND _boost_LIBRARY_SEARCH_DIRS ${BOOST_LIBRARYDIR}) - elseif(_ENV_BOOST_LIBRARYDIR) - list(APPEND _boost_LIBRARY_SEARCH_DIRS ${_ENV_BOOST_LIBRARYDIR}) - endif() - - if(BOOST_ROOT) - list(APPEND _boost_LIBRARY_SEARCH_DIRS ${BOOST_ROOT}/lib ${BOOST_ROOT}/stage/lib) - elseif(_ENV_BOOST_ROOT) - list(APPEND _boost_LIBRARY_SEARCH_DIRS ${_ENV_BOOST_ROOT}/lib ${_ENV_BOOST_ROOT}/stage/lib) - endif() - - list(APPEND _boost_LIBRARY_SEARCH_DIRS - ${Boost_INCLUDE_DIR}/lib - ${Boost_INCLUDE_DIR}/../lib - ${Boost_INCLUDE_DIR}/../lib/${CMAKE_LIBRARY_ARCHITECTURE} - ${Boost_INCLUDE_DIR}/stage/lib - ) - if( Boost_NO_SYSTEM_PATHS ) - list(APPEND _boost_LIBRARY_SEARCH_DIRS NO_CMAKE_SYSTEM_PATH) - else() - list(APPEND _boost_LIBRARY_SEARCH_DIRS PATHS - C:/boost/lib - C:/boost - /sw/local/lib - ) - endif() -endif() - -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_LIBRARY_SEARCH_DIRS = ${_boost_LIBRARY_SEARCH_DIRS}") -endif() - -# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES -if( Boost_USE_STATIC_LIBS ) - set( _boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) - if(WIN32) - set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) - else() - set(CMAKE_FIND_LIBRARY_SUFFIXES .a ) - endif() -endif() - -# We want to use the tag inline below without risking double dashes -if(_boost_RELEASE_ABI_TAG) - if(${_boost_RELEASE_ABI_TAG} STREQUAL "-") - set(_boost_RELEASE_ABI_TAG "") - endif() -endif() -if(_boost_DEBUG_ABI_TAG) - if(${_boost_DEBUG_ABI_TAG} STREQUAL "-") - set(_boost_DEBUG_ABI_TAG "") - endif() -endif() - -# The previous behavior of FindBoost when Boost_USE_STATIC_LIBS was enabled -# on WIN32 was to: -# 1. Search for static libs compiled against a SHARED C++ standard runtime library (use if found) -# 2. Search for static libs compiled against a STATIC C++ standard runtime library (use if found) -# We maintain this behavior since changing it could break people's builds. -# To disable the ambiguous behavior, the user need only -# set Boost_USE_STATIC_RUNTIME either ON or OFF. -set(_boost_STATIC_RUNTIME_WORKAROUND false) -if(WIN32 AND Boost_USE_STATIC_LIBS) - if(NOT DEFINED Boost_USE_STATIC_RUNTIME) - set(_boost_STATIC_RUNTIME_WORKAROUND true) - endif() -endif() - -# On versions < 1.35, remove the System library from the considered list -# since it wasn't added until 1.35. -if(Boost_VERSION AND Boost_FIND_COMPONENTS) - if(Boost_VERSION LESS 103500) - list(REMOVE_ITEM Boost_FIND_COMPONENTS system) - endif() -endif() - -# If the user changed any of our control inputs flush previous results. -if(_Boost_CHANGE_LIBDIR OR _Boost_CHANGE_LIBNAME) - foreach(COMPONENT ${_Boost_COMPONENTS_SEARCHED}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - foreach(c DEBUG RELEASE) - set(_var Boost_${UPPERCOMPONENT}_LIBRARY_${c}) - unset(${_var} CACHE) - set(${_var} "${_var}-NOTFOUND") - endforeach() - endforeach() - set(_Boost_COMPONENTS_SEARCHED "") -endif() - -foreach(COMPONENT ${Boost_FIND_COMPONENTS}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - - set( _boost_docstring_release "Boost ${COMPONENT} library (release)") - set( _boost_docstring_debug "Boost ${COMPONENT} library (debug)") - - # - # Find RELEASE libraries - # - set(_boost_RELEASE_NAMES - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} - ${Boost_LIB_PREFIX}boost_${COMPONENT} ) - if(_boost_STATIC_RUNTIME_WORKAROUND) - set(_boost_RELEASE_STATIC_ABI_TAG "-s${_boost_RELEASE_ABI_TAG}") - list(APPEND _boost_RELEASE_NAMES - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} ) - endif() - if(Boost_THREADAPI AND ${COMPONENT} STREQUAL "thread") - _Boost_PREPEND_LIST_WITH_THREADAPI(_boost_RELEASE_NAMES ${_boost_RELEASE_NAMES}) - endif() - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Searching for ${UPPERCOMPONENT}_LIBRARY_RELEASE: ${_boost_RELEASE_NAMES}") - endif() - - # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing. - string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS}") - - _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE - NAMES ${_boost_RELEASE_NAMES} - HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp} - NAMES_PER_DIR - DOC "${_boost_docstring_release}" - ) - - # - # Find DEBUG libraries - # - set(_boost_DEBUG_NAMES - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED} - ${Boost_LIB_PREFIX}boost_${COMPONENT} ) - if(_boost_STATIC_RUNTIME_WORKAROUND) - set(_boost_DEBUG_STATIC_ABI_TAG "-s${_boost_DEBUG_ABI_TAG}") - list(APPEND _boost_DEBUG_NAMES - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} ) - endif() - if(Boost_THREADAPI AND ${COMPONENT} STREQUAL "thread") - _Boost_PREPEND_LIST_WITH_THREADAPI(_boost_DEBUG_NAMES ${_boost_DEBUG_NAMES}) - endif() - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Searching for ${UPPERCOMPONENT}_LIBRARY_DEBUG: ${_boost_DEBUG_NAMES}") - endif() - - # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing. - string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS}") - - _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG - NAMES ${_boost_DEBUG_NAMES} - HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp} - NAMES_PER_DIR - DOC "${_boost_docstring_debug}" - ) - - if(Boost_REALPATH) - _Boost_SWAP_WITH_REALPATH(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE "${_boost_docstring_release}") - _Boost_SWAP_WITH_REALPATH(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG "${_boost_docstring_debug}" ) - endif() - - _Boost_ADJUST_LIB_VARS(${UPPERCOMPONENT}) - -endforeach() - -# Restore the original find library ordering -if( Boost_USE_STATIC_LIBS ) - set(CMAKE_FIND_LIBRARY_SUFFIXES ${_boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) -endif() - -# ------------------------------------------------------------------------ -# End finding boost libraries -# ------------------------------------------------------------------------ - -set(Boost_INCLUDE_DIRS ${Boost_INCLUDE_DIR}) -set(Boost_LIBRARY_DIRS ${Boost_LIBRARY_DIR}) - -# The above setting of Boost_FOUND was based only on the header files. -# Update it for the requested component libraries. -if(Boost_FOUND) - # The headers were found. Check for requested component libs. - set(_boost_CHECKED_COMPONENT FALSE) - set(_Boost_MISSING_COMPONENTS "") - foreach(COMPONENT ${Boost_FIND_COMPONENTS}) - string(TOUPPER ${COMPONENT} COMPONENT) - set(_boost_CHECKED_COMPONENT TRUE) - if(NOT Boost_${COMPONENT}_FOUND) - string(TOLOWER ${COMPONENT} COMPONENT) - list(APPEND _Boost_MISSING_COMPONENTS ${COMPONENT}) - endif() - endforeach() - - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] Boost_FOUND = ${Boost_FOUND}") - endif() - - if (_Boost_MISSING_COMPONENTS) - set(Boost_FOUND 0) - # We were unable to find some libraries, so generate a sensible - # error message that lists the libraries we were unable to find. - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}\nThe following Boost libraries could not be found:\n") - foreach(COMPONENT ${_Boost_MISSING_COMPONENTS}) - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON} boost_${COMPONENT}\n") - endforeach() - - list(LENGTH Boost_FIND_COMPONENTS Boost_NUM_COMPONENTS_WANTED) - list(LENGTH _Boost_MISSING_COMPONENTS Boost_NUM_MISSING_COMPONENTS) - if (${Boost_NUM_COMPONENTS_WANTED} EQUAL ${Boost_NUM_MISSING_COMPONENTS}) - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}No Boost libraries were found. You may need to set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") - else () - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}Some (but not all) of the required Boost libraries were found. You may need to install these additional Boost libraries. Alternatively, set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") - endif () - endif () - - if( NOT Boost_LIBRARY_DIRS AND NOT _boost_CHECKED_COMPONENT ) - # Compatibility Code for backwards compatibility with CMake - # 2.4's FindBoost module. - - # Look for the boost library path. - # Note that the user may not have installed any libraries - # so it is quite possible the Boost_LIBRARY_DIRS may not exist. - set(_boost_LIB_DIR ${Boost_INCLUDE_DIR}) - - if("${_boost_LIB_DIR}" MATCHES "boost-[0-9]+") - get_filename_component(_boost_LIB_DIR ${_boost_LIB_DIR} PATH) - endif() - - if("${_boost_LIB_DIR}" MATCHES "/include$") - # Strip off the trailing "/include" in the path. - get_filename_component(_boost_LIB_DIR ${_boost_LIB_DIR} PATH) - endif() - - if(EXISTS "${_boost_LIB_DIR}/lib") - set(_boost_LIB_DIR ${_boost_LIB_DIR}/lib) - else() - if(EXISTS "${_boost_LIB_DIR}/stage/lib") - set(_boost_LIB_DIR ${_boost_LIB_DIR}/stage/lib) - else() - set(_boost_LIB_DIR "") - endif() - endif() - - if(_boost_LIB_DIR AND EXISTS "${_boost_LIB_DIR}") - set(Boost_LIBRARY_DIRS ${_boost_LIB_DIR}) - endif() - - endif() -else() - # Boost headers were not found so no components were found. - foreach(COMPONENT ${Boost_FIND_COMPONENTS}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - set(Boost_${UPPERCOMPONENT}_FOUND 0) - endforeach() -endif() - -# ------------------------------------------------------------------------ -# Notification to end user about what was found -# ------------------------------------------------------------------------ - -set(Boost_LIBRARIES "") -if(Boost_FOUND) - if(NOT Boost_FIND_QUIETLY) - message(STATUS "Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") - if(Boost_FIND_COMPONENTS) - message(STATUS "Found the following Boost libraries:") - endif() - endif() - foreach( COMPONENT ${Boost_FIND_COMPONENTS} ) - string( TOUPPER ${COMPONENT} UPPERCOMPONENT ) - if( Boost_${UPPERCOMPONENT}_FOUND ) - if(NOT Boost_FIND_QUIETLY) - message (STATUS " ${COMPONENT}") - endif() - list(APPEND Boost_LIBRARIES ${Boost_${UPPERCOMPONENT}_LIBRARY}) - endif() - endforeach() - - # Add pthread library on UNIX if thread component was found - _Boost_consider_adding_pthreads(Boost_LIBRARIES ${Boost_LIBRARIES}) -else() - if(Boost_FIND_REQUIRED) - message(SEND_ERROR "Unable to find the requested Boost libraries.\n${Boost_ERROR_REASON}") - else() - if(NOT Boost_FIND_QUIETLY) - # we opt not to automatically output Boost_ERROR_REASON here as - # it could be quite lengthy and somewhat imposing in its requests - # Since Boost is not always a required dependency we'll leave this - # up to the end-user. - if(Boost_DEBUG OR Boost_DETAILED_FAILURE_MSG) - message(STATUS "Could NOT find Boost\n${Boost_ERROR_REASON}") - else() - message(STATUS "Could NOT find Boost") - endif() - endif() - endif() -endif() - -# Configure display of cache entries in GUI. -foreach(v BOOSTROOT BOOST_ROOT ${_Boost_VARS_INC} ${_Boost_VARS_LIB}) - get_property(_type CACHE ${v} PROPERTY TYPE) - if(_type) - set_property(CACHE ${v} PROPERTY ADVANCED 1) - if("x${_type}" STREQUAL "xUNINITIALIZED") - if("x${v}" STREQUAL "xBoost_ADDITIONAL_VERSIONS") - set_property(CACHE ${v} PROPERTY TYPE STRING) - else() - set_property(CACHE ${v} PROPERTY TYPE PATH) - endif() - endif() - endif() -endforeach() - -# Record last used values of input variables so we can -# detect on the next run if the user changed them. -foreach(v - ${_Boost_VARS_INC} ${_Boost_VARS_LIB} - ${_Boost_VARS_DIR} ${_Boost_VARS_NAME} - ) - if(DEFINED ${v}) - set(_${v}_LAST "${${v}}" CACHE INTERNAL "Last used ${v} value.") - else() - unset(_${v}_LAST CACHE) - endif() -endforeach() - -# Maintain a persistent list of components requested anywhere since -# the last flush. -set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}") -list(APPEND _Boost_COMPONENTS_SEARCHED ${Boost_FIND_COMPONENTS}) -list(REMOVE_DUPLICATES _Boost_COMPONENTS_SEARCHED) -list(SORT _Boost_COMPONENTS_SEARCHED) -set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}" - CACHE INTERNAL "Components requested for this build tree.") diff --git a/CMakeModules/Legacy/CMakeLists.txt b/CMakeModules/Legacy/CMakeLists.txt deleted file mode 100644 index 56c115f..0000000 --- a/CMakeModules/Legacy/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# If you are running recent enough version of CMake you shall consider updating/removing these lines ... -MESSAGE(STATUS "Configuring build scripts for older CMake versions") - -# This patches your current boost searching routine so that `pthread` library is included if needed -# - this is here to fix some older CMake + Boost configurations -set(Boost_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Boost" PARENT_SCOPE) - -if (APPLE OR USE_LEGACY_FIND_BOOST) - MESSAGE(STATUS "Configuring for custom FindBoost.cmake") - # Custom FindBoost.cmake - # - overrides `find_package( Boost )` functionality - # - it's a modified https://github.com/Kitware/CMake/blob/363825cd55595b7de62fcf610836f6156a9f1a31/Modules/FindBoost.cmake - # - adds additional Boost search path - # - adds pthread as an dependency if needed - ###### - # This is using an old version of FindBoost.cmake irregardless of your CMake version - # - this will be removed in future release - # - improves Boost library search in some Apple OS configrations - # - this can be fixed with properly setting BOOST_LIBRARYDIR - ##### - - MESSAGE(DEPRECATION "Custom FindBoost.cmake will be deprecated in some future release. If you are using some of the affected configurations try setting the BOOST_LIBRARYDIR variable.") - - list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Boost") - - set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} PARENT_SCOPE) -endif () From 699238f08ffd9ebf1594c5692dc965c67c290817 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sat, 17 Aug 2019 10:23:15 +0200 Subject: [PATCH 061/110] Fix build with older cmake --- CMakeLists.txt | 3 ++- CMakeModules/Boost/BoostConfig.cmake | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 CMakeModules/Boost/BoostConfig.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 4394887..0966c95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -136,7 +136,8 @@ IF( WIN32 ) # iphlpapi.lib ENDIF(WIN32) -FIND_PACKAGE(Boost COMPONENTS ${BOOST_COMPONENTS} REQUIRED) +set(Boost_DIR "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/Boost") +FIND_PACKAGE(Boost CONFIG COMPONENTS ${BOOST_COMPONENTS} ) IF(NOT WIN32) MESSAGE(STATUS "Configuring fc to build on Unix/Apple") diff --git a/CMakeModules/Boost/BoostConfig.cmake b/CMakeModules/Boost/BoostConfig.cmake new file mode 100644 index 0000000..a5e01f2 --- /dev/null +++ b/CMakeModules/Boost/BoostConfig.cmake @@ -0,0 +1,18 @@ +# This overrides `find_package(Boost ... CONFIG ... )` calls +# - calls the CMake's built-in `FindBoost.cmake` and adds `pthread` library dependency + +MESSAGE(STATUS "Using custom FindBoost config") + +find_package(Boost 1.58 REQUIRED COMPONENTS ${Boost_FIND_COMPONENTS}) + +# Inject `pthread` dependency to Boost if needed +if (UNIX AND NOT CYGWIN) + list(FIND Boost_FIND_COMPONENTS thread _using_boost_thread) + if (_using_boost_thread GREATER -1) + find_library(BOOST_THREAD_LIBRARY NAMES pthread DOC "The threading library used by boost-thread") + if (BOOST_THREAD_LIBRARY) + MESSAGE(STATUS "Adding Boost thread lib dependency: ${BOOST_THREAD_LIBRARY}") + list(APPEND Boost_LIBRARIES ${BOOST_THREAD_LIBRARY}) + endif () + endif () +endif () From 7b37cd6effd6d854d4b9af134ba3c82cd2e1daef Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 19 Aug 2019 12:09:53 +0200 Subject: [PATCH 062/110] Fix core #1935 --- include/fc/network/tcp_socket.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fc/network/tcp_socket.hpp b/include/fc/network/tcp_socket.hpp index 160df37..320d45c 100644 --- a/include/fc/network/tcp_socket.hpp +++ b/include/fc/network/tcp_socket.hpp @@ -53,7 +53,7 @@ namespace fc { #ifdef _WIN64 fc::fwd my; #else - fc::fwd my; + fc::fwd my; #endif }; typedef std::shared_ptr tcp_socket_ptr; From 81cc84c1727c1b1c1782e63aba22202cba649af7 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Wed, 21 Aug 2019 11:31:09 +0200 Subject: [PATCH 063/110] Fix core #1948 - editline does not build --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bad2407..292b574 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -250,7 +250,7 @@ install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION include ) # begin editline stuff if(WIN32) target_compile_definitions( fc PRIVATE _CRT_NONSTDC_NO_DEPRECATE ) -elseif(WIN32) +else(WIN32) target_compile_definitions (fc PRIVATE HAVE_EDITLINE) set(editline_libraries editline) endif(WIN32) From ea85954e1735c2cdc7287dbe13568a4290789f6e Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Wed, 21 Aug 2019 11:31:41 +0200 Subject: [PATCH 064/110] Adjust whitespace --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 292b574..02dab61 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -251,8 +251,8 @@ install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION include ) if(WIN32) target_compile_definitions( fc PRIVATE _CRT_NONSTDC_NO_DEPRECATE ) else(WIN32) - target_compile_definitions (fc PRIVATE HAVE_EDITLINE) - set(editline_libraries editline) + target_compile_definitions( fc PRIVATE HAVE_EDITLINE ) + set( editline_libraries editline ) endif(WIN32) # end editline stuff From 78ffb6dbd3c3696f5838d005e3f159b42805172c Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Thu, 22 Aug 2019 11:11:17 +0200 Subject: [PATCH 065/110] Possible fix for core #1952 --- include/fc/variant.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fc/variant.hpp b/include/fc/variant.hpp index f7ef613..b083012 100644 --- a/include/fc/variant.hpp +++ b/include/fc/variant.hpp @@ -27,7 +27,7 @@ namespace fc { void throw_assertion_failure( const std::string& message ); } -#define _FC_ASSERT( cond, msg ) { if( !(cond) ) { fc::throw_assertion_failure( #cond ": " msg ); } } +#define _FC_ASSERT( cond, msg ) { if( !(cond) ) { char t[] = #cond ": " msg; fc::throw_assertion_failure( t ); } } #endif namespace fc From 5bb0254d83ef892186a356f8f54cc4507710b9ba Mon Sep 17 00:00:00 2001 From: crypto-ape <43807588+crypto-ape@users.noreply.github.com> Date: Mon, 26 Aug 2019 14:10:43 +0200 Subject: [PATCH 066/110] fix array declaration for broken msvc static expression evaluation --- src/crypto/elliptic_common.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crypto/elliptic_common.cpp b/src/crypto/elliptic_common.cpp index 8e4f802..407b9d5 100644 --- a/src/crypto/elliptic_common.cpp +++ b/src/crypto/elliptic_common.cpp @@ -229,7 +229,7 @@ namespace fc { namespace ecc { static std::string _to_base58( const extended_key_data& key ) { - char buffer[key.size() + 4]; // it's a small static array => allocate on stack + char buffer[std::tuple_size::value + 4]; // it's a small static array => allocate on stack memcpy( buffer, key.data(), key.size() ); fc::sha256 double_hash = fc::sha256::hash( fc::sha256::hash( (char*)key.data(), key.size() )); memcpy( buffer + key.size(), double_hash.data(), 4 ); From 9f7f1b479067ffe75e293b8e54aa13f7bd052b0a Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Wed, 28 Aug 2019 15:45:47 -0500 Subject: [PATCH 067/110] Replace improper static_variant operator overloads with comparators --- include/fc/reflect/typename.hpp | 2 +- include/fc/static_variant.hpp | 16 ++++++++-------- tests/variant_test.cpp | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/fc/reflect/typename.hpp b/include/fc/reflect/typename.hpp index 3fe9a83..bcd4f2a 100644 --- a/include/fc/reflect/typename.hpp +++ b/include/fc/reflect/typename.hpp @@ -41,7 +41,7 @@ namespace fc { return n.c_str(); } }; - template struct get_typename> + template struct get_typename> { static const char* name() { static std::string n = std::string("flat_set<") + get_typename::name() + ">"; diff --git a/include/fc/static_variant.hpp b/include/fc/static_variant.hpp index 6f1841c..89baa4e 100644 --- a/include/fc/static_variant.hpp +++ b/include/fc/static_variant.hpp @@ -302,6 +302,14 @@ public: static constexpr int value = impl::position::pos; }; + struct type_lt { + bool operator()(const static_variant& a, const static_variant& b) const { return a.which() < b.which(); } + }; + struct type_eq { + bool operator()(const static_variant& a, const static_variant& b) const { return a.which() == b.which(); } + }; + using flat_set_type = flat_set; + static_variant() { init_from_tag(0); @@ -352,14 +360,6 @@ public: v.visit( impl::move_construct(*this) ); return *this; } - friend bool operator == ( const static_variant& a, const static_variant& b ) - { - return a.which() == b.which(); - } - friend bool operator < ( const static_variant& a, const static_variant& b ) - { - return a.which() < b.which(); - } template> X& get() { diff --git a/tests/variant_test.cpp b/tests/variant_test.cpp index 96e62b5..35186d7 100644 --- a/tests/variant_test.cpp +++ b/tests/variant_test.cpp @@ -182,7 +182,7 @@ BOOST_AUTO_TEST_CASE( nested_objects_test ) from_variant( v, sv1, nested_levels + 2 ); - BOOST_CHECK( sv == sv1 ); + BOOST_CHECK( decltype(sv)::type_eq()(sv, sv1) ); // both log and dump should never throw BOOST_TEST_MESSAGE( "========== About to log static_variant. ==========" ); @@ -215,7 +215,7 @@ BOOST_AUTO_TEST_CASE( nested_objects_test ) from_variant( v, vec1, nested_levels + 3 ); - BOOST_CHECK( vec == vec1 ); + BOOST_CHECK( std::equal(vec.begin(), vec.end(), vec1.begin(), decltype(vec)::value_type::type_eq()) ); // both log and dump should never throw BOOST_TEST_MESSAGE( "========== About to log vector. ==========" ); From cce644f686f78491e6823845dd585fcb1e52ef49 Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Thu, 29 Aug 2019 11:26:34 -0500 Subject: [PATCH 068/110] Fix warnings The `appender` class is intended to be inherited and used polymorphically, but does not have a virtual destructor, which causes warnings. This adds a virtual destructor to fix these warnings. --- include/fc/log/appender.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/fc/log/appender.hpp b/include/fc/log/appender.hpp index f8f442f..518c734 100644 --- a/include/fc/log/appender.hpp +++ b/include/fc/log/appender.hpp @@ -34,6 +34,7 @@ namespace fc { return register_appender( type, appender_factory::ptr( new detail::appender_factory_impl() ) ); } + virtual ~appender() = default; static appender::ptr create( const std::string& name, const std::string& type, const variant& args ); static appender::ptr get( const std::string& name ); static bool register_appender( const std::string& type, const appender_factory::ptr& f ); From 45cb433d47086464bed71fb96827fea7b75a0a9d Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Fri, 30 Aug 2019 11:52:05 -0500 Subject: [PATCH 069/110] Fixes from code review --- include/fc/reflect/typename.hpp | 14 ++++++++++++-- tests/variant_test.cpp | 7 +++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/include/fc/reflect/typename.hpp b/include/fc/reflect/typename.hpp index bcd4f2a..41fc348 100644 --- a/include/fc/reflect/typename.hpp +++ b/include/fc/reflect/typename.hpp @@ -12,6 +12,7 @@ #include namespace fc { + template class static_variant; class value; class exception; namespace ip { class address; } @@ -41,10 +42,19 @@ namespace fc { return n.c_str(); } }; - template struct get_typename> + template struct get_typename> + { + static const char* name() { + static std::string n = std::string("flat_set<") + get_typename::name() + ">"; + return n.c_str(); + } + }; + template + struct get_typename, typename static_variant::type_lt>> { static const char* name() { - static std::string n = std::string("flat_set<") + get_typename::name() + ">"; + using TN = get_typename>; + static std::string n = std::string("flat_set<") + TN::name() + ", " + TN::name() + "::type_lt>"; return n.c_str(); } }; diff --git a/tests/variant_test.cpp b/tests/variant_test.cpp index 35186d7..474e5ae 100644 --- a/tests/variant_test.cpp +++ b/tests/variant_test.cpp @@ -182,7 +182,10 @@ BOOST_AUTO_TEST_CASE( nested_objects_test ) from_variant( v, sv1, nested_levels + 2 ); - BOOST_CHECK( decltype(sv)::type_eq()(sv, sv1) ); + auto sv_equal = [](const fc::static_variant& v1, const fc::static_variant& v2) { + return v1.get() == v2.get(); + }; + BOOST_CHECK( sv_equal(sv, sv1) ); // both log and dump should never throw BOOST_TEST_MESSAGE( "========== About to log static_variant. ==========" ); @@ -215,7 +218,7 @@ BOOST_AUTO_TEST_CASE( nested_objects_test ) from_variant( v, vec1, nested_levels + 3 ); - BOOST_CHECK( std::equal(vec.begin(), vec.end(), vec1.begin(), decltype(vec)::value_type::type_eq()) ); + BOOST_CHECK( std::equal(vec.begin(), vec.end(), vec1.begin(), sv_equal) ); // both log and dump should never throw BOOST_TEST_MESSAGE( "========== About to log vector. ==========" ); From c69ea32613f7e4bbc318d3d59a3b18dc834cd4e5 Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Tue, 9 Jul 2019 17:00:03 -0500 Subject: [PATCH 070/110] Improve reflection system and static_variant Previously, fc reflection generated visitor infrastructure capable of visiting each field of a struct; however, this is only useful for run- time operations on structures. No compile-time information was preserved about the fields of a struct, making compile-time introspection of types impossible. Now FC reflection generates rich compile-time information about the members of structs, including types, names, and structure, allowing code to be written to explore types in detail at compile-time and fetch arbitrary fields at runtime without needing to iterate over the unwanted fields. To make this a reality, a new `typelist` type was added to store this compile-time information. This type is also useful within the context of `static_variant`, as SV previously used implementation detail types in a private namespace to provide this functionality. Now `static_variant` uses the reusable functionality of `typelist` to operate, dramatically reducing the amount of code dedicated to `static_variant` and also making `static_variant` types more flexible to work with since their infrastructure is now based on the `typelist` public interface. --- include/fc/reflect/reflect.hpp | 206 ++++++++++++++----- include/fc/reflect/typelist.hpp | 262 ++++++++++++++++++++++++ include/fc/reflect/typename.hpp | 16 ++ include/fc/static_variant.hpp | 340 ++++++++++---------------------- src/network/http/websocket.cpp | 4 + tests/CMakeLists.txt | 1 + tests/reflection_tests.cpp | 126 ++++++++++++ tests/serialization_test.cpp | 1 - 8 files changed, 669 insertions(+), 287 deletions(-) create mode 100644 include/fc/reflect/typelist.hpp create mode 100644 tests/reflection_tests.cpp diff --git a/include/fc/reflect/reflect.hpp b/include/fc/reflect/reflect.hpp index 7578360..348477a 100644 --- a/include/fc/reflect/reflect.hpp +++ b/include/fc/reflect/reflect.hpp @@ -1,6 +1,6 @@ #pragma once /** - * @file fc/reflect.hpp + * @file fc/reflect/reflect.hpp * * @brief Defines types and macros used to provide reflection. * @@ -18,9 +18,114 @@ #include #include +#include namespace fc { +template struct reflector; +namespace member_names { +/// A template which stores the name of the native member at a given index in a given class +template struct member_name { + constexpr static const char* value = "Unknown member"; +}; +} + +/** + * @brief A template to store compile-time information about a field in a reflected struct + * + * @tparam Container The type of the struct or class containing the field + * @tparam Member The type of the field + * @tparam field A pointer-to-member for the reflected field + */ +template +struct field_reflection { + using container = Container; + using type = Member; + using reflector = fc::reflector; + constexpr static std::size_t index = Index; + constexpr static bool is_derived = false; + constexpr static type container::*pointer = field; + + /// @brief Given a reference to the container type, get a reference to the field + static type& get(container& c) { return c.*field; } + static const type& get(const container& c) { return c.*field; } + /// @brief Get the name of the field + static const char* get_name() { return fc::member_names::member_name::value; } +}; +/// Basically the same as @ref field_reflection, but for inherited fields +/// Note that inherited field reflections do not have an index field; indexes are for native fields only +template +struct inherited_field_reflection { + using container = Derived; + using field_container = Base; + using type = Member; + using reflector = fc::reflector; + constexpr static std::size_t index_in_base = IndexInBase; + constexpr static bool is_derived = true; + constexpr static type field_container::*pointer = field; + + static type& get(container& c) { + // And we need a distinct inherited_field_reflection type because this conversion can't be done statically + type container::* derived_field = field; + return c.*derived_field; + } + static const type& get(const container& c) { + type container::* derived_field = field; + return c.*derived_field; + } + static const char* get_name() { + using Reflector = typename fc::reflector::native_members::template at; + return Reflector::get_name(); + } +}; + +namespace impl { +/// Helper template to create a @ref field_reflection without any commas (makes it macro-friendly) +template +struct Reflect_type { + template + struct with_field_type { + template + struct at_index { + template + struct with_field_pointer { + using type = field_reflection; + }; + }; + }; +}; +/// Template to make a transformer of a @ref field_reflection from a base class to a derived class +template +struct Derivation_reflection_transformer { + template struct transform; + template + struct transform> { + using type = inherited_field_reflection; + }; + template + struct transform> { + using type = inherited_field_reflection; + }; +}; +} // namespace impl + +/// Macro to transform reflected fields of a base class to a derived class and concatenate them to a type list +#define FC_CONCAT_BASE_MEMBER_REFLECTIONS(r, derived, base) \ + ::add_list::members, impl::Derivation_reflection_transformer>> +/// Macro to concatenate a new @ref field_reflection to a typelist +#define FC_CONCAT_MEMBER_REFLECTION(r, container, idx, member) \ + ::add::template with_field_type \ + ::template at_index \ + ::template with_field_pointer<&container::member>::type> +#define FC_REFLECT_MEMBER_NAME(r, container, idx, member) \ + template<> struct member_name { constexpr static const char* value = BOOST_PP_STRINGIZE(member); }; +#define FC_REFLECT_TEMPLATE_MEMBER_NAME(r, data, idx, member) \ + template struct member_name { \ + constexpr static const char* value = BOOST_PP_STRINGIZE(member); }; +/// Macro to concatenate a new type to a typelist +#define FC_CONCAT_TYPE(r, x, TYPE) ::add + /** * @brief defines visit functions for T * Unless this is specialized, visit() will not be defined for T. @@ -34,6 +139,14 @@ template struct reflector{ typedef T type; typedef std::false_type is_defined; + /// A typelist with a @ref field_reflection for each native member (non-inherited) of the struct + using native_members = typelist::list<>; + /// A typelist with a @ref field_reflection for each inherited member of the struct + using inherited_members = typelist::list<>; + /// A typelist with a @ref field_reflection for each member of the struct, starting with inherited members + using members = typelist::list<>; + /// A typelist of base classes for this type + using base_classes = typelist::list<>; /** * @tparam Visitor a function object of the form: @@ -91,31 +204,11 @@ void throw_bad_enum_cast( const char* k, const char* e ); 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 - -#define FC_REFLECT_MEMBER_COUNT( r, OP, elem ) \ - OP 1 - #define FC_REFLECT_DERIVED_IMPL_INLINE( TYPE, INHERITS, MEMBERS ) \ 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 ) \ -template\ -void fc::reflector::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 ) \ } #endif // DOXYGEN @@ -214,26 +307,50 @@ namespace fc { \ template<> struct reflector {\ typedef TYPE type; \ typedef std::true_type is_defined; \ + using native_members = \ + typename typelist::builder<>::type \ + BOOST_PP_SEQ_FOR_EACH_I( FC_CONCAT_MEMBER_REFLECTION, TYPE, MEMBERS ) ::finalize; \ + using inherited_members = \ + typename typelist::builder<>::type \ + BOOST_PP_SEQ_FOR_EACH( FC_CONCAT_BASE_MEMBER_REFLECTIONS, TYPE, INHERITS ) ::finalize; \ + using members = typename typelist::concat::type; \ + using base_classes = typename typelist::builder<>::type \ + BOOST_PP_SEQ_FOR_EACH( FC_CONCAT_TYPE, x, INHERITS ) ::finalize; \ enum member_count_enum { \ - local_member_count = 0 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_MEMBER_COUNT, +, MEMBERS ),\ - total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\ + local_member_count = typelist::length(), \ + total_member_count = typelist::length() \ }; \ FC_REFLECT_DERIVED_IMPL_INLINE( TYPE, INHERITS, MEMBERS ) \ -}; } +}; \ +namespace member_names { \ +BOOST_PP_SEQ_FOR_EACH_I( FC_REFLECT_MEMBER_NAME, TYPE, MEMBERS ) \ +} } #define FC_REFLECT_DERIVED_TEMPLATE( TEMPLATE_ARGS, TYPE, INHERITS, MEMBERS ) \ namespace fc { \ - template struct get_typename { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \ + template struct get_typename { \ + static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } \ + }; \ template struct reflector {\ typedef TYPE type; \ typedef std::true_type is_defined; \ + using native_members = \ + typename typelist::builder<>::type \ + BOOST_PP_SEQ_FOR_EACH_I( FC_CONCAT_MEMBER_REFLECTION, TYPE, MEMBERS ) ::finalize; \ + using inherited_members = \ + typename typelist::builder<>::type \ + BOOST_PP_SEQ_FOR_EACH( FC_CONCAT_BASE_MEMBER_REFLECTIONS, TYPE, INHERITS ) ::finalize; \ + using members = typename typelist::concat::type; \ + using base_classes = typename typelist::builder<>::type \ + BOOST_PP_SEQ_FOR_EACH( FC_CONCAT_TYPE, x, INHERITS ) ::finalize; \ enum member_count_enum { \ - local_member_count = 0 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_MEMBER_COUNT, +, MEMBERS ),\ - total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\ + local_member_count = typelist::length(), \ + total_member_count = typelist::length() \ }; \ FC_REFLECT_DERIVED_IMPL_INLINE( TYPE, INHERITS, MEMBERS ) \ -}; } - -//BOOST_PP_SEQ_SIZE(MEMBERS), +}; \ +namespace member_names { \ +BOOST_PP_SEQ_FOR_EACH_I( FC_REFLECT_TEMPLATE_MEMBER_NAME, (TEMPLATE_ARGS)(TYPE), MEMBERS ) \ +} } /** * @def FC_REFLECT(TYPE,MEMBERS) @@ -244,7 +361,8 @@ template struct reflector {\ * @see FC_REFLECT_DERIVED */ #define FC_REFLECT( TYPE, MEMBERS ) \ - FC_REFLECT_DERIVED( TYPE, BOOST_PP_SEQ_NIL, MEMBERS ) + FC_REFLECT_DERIVED( TYPE, BOOST_PP_SEQ_NIL, MEMBERS ) + #define FC_REFLECT_TEMPLATE( TEMPLATE_ARGS, TYPE, MEMBERS ) \ FC_REFLECT_DERIVED_TEMPLATE( TEMPLATE_ARGS, TYPE, BOOST_PP_SEQ_NIL, MEMBERS ) @@ -257,25 +375,11 @@ namespace fc { \ template<> struct get_typename { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \ } -#define FC_REFLECT_FWD( TYPE ) \ -namespace fc { \ - template<> struct get_typename { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \ -template<> struct reflector {\ - typedef TYPE type; \ - typedef std::true_type is_defined; \ - enum member_count_enum { \ - local_member_count = BOOST_PP_SEQ_SIZE(MEMBERS), \ - total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\ - }; \ - template static void visit( const Visitor& v ); \ -}; } - - -#define FC_REFLECT_DERIVED_IMPL( TYPE, MEMBERS ) \ - FC_REFLECT_IMPL_DERIVED_EXT( TYPE, BOOST_PP_SEQ_NIL, MEMBERS ) - -#define FC_REFLECT_IMPL( TYPE, MEMBERS ) \ - FC_REFLECT_DERIVED_IMPL_EXT( TYPE, BOOST_PP_SEQ_NIL, MEMBERS ) - +// vvv These are preserved to merge more smoothly vvv +#define FC_REFLECT_BASE_MEMBER_COUNT( r, OP, elem ) \ + OP fc::reflector::total_member_count +#define FC_REFLECT_MEMBER_COUNT( r, OP, elem ) \ + OP 1 +// ^^^ These can be removed after updating graphene/protocol/types.hpp ^^^ diff --git a/include/fc/reflect/typelist.hpp b/include/fc/reflect/typelist.hpp new file mode 100644 index 0000000..d1d3e0d --- /dev/null +++ b/include/fc/reflect/typelist.hpp @@ -0,0 +1,262 @@ +#pragma once +/** + * @file fc/reflect/typelist.hpp + * + * @brief Defines a template for manipulating and storing compile-time lists of types + */ + +#include +#include + +namespace fc { + +/// This namespace contains the list type, and all of the operations and queries which can be performed upon it +namespace typelist { + +// Forward declare the list so impl can see it +template struct list; + +namespace impl { +using typelist::list; + +template class> struct apply; +template class Delegate> +struct apply, Delegate> { using type = Delegate; }; + +template +struct length; +template<> struct length<> { constexpr static std::size_t value = 0; }; +template +struct length { constexpr static std::size_t value = length::value+1; }; + +template struct concat; +template +struct concat, list> { + using type = list; +}; +template +struct concat, list, NextList, Lists...> { + using type = typename concat, NextList, Lists...>::type; +}; + +template struct make_sequence; +template<> struct make_sequence<0> { using type = list<>; }; +template<> struct make_sequence<1> { using type = list>; }; +template +struct make_sequence { + using type = typename concat::type, + list>>::type; +}; + +template struct transform; +template +struct transform, Transformer> { + using type = list::type...>; +}; + +template struct index_of; +template struct index_of> { constexpr static int value = -1; }; +template +struct index_of> { + constexpr static int deeper = index_of>::value; + constexpr static int value = std::is_same::value? 0 : (deeper == -1? -1 : deeper + 1); +}; + +template struct concat_unique; +template +struct concat_unique, list<>> { + using type = list; +}; +template +struct concat_unique, list> { + using type = std::conditional_t>::value >= 0, + list, list>; +}; +template +struct concat_unique, list> { + using type = typename concat_unique< + typename concat_unique, list>::type, list>::type; +}; +template +struct concat_unique, list<>, Lists...> { + using type = typename concat_unique, Lists...>::type; +}; +template +struct concat_unique, L2, Lists...> { + using type = typename concat_unique>::type, L2, Lists...>::type; +}; + +template struct at; +template +struct at, 0> { using type = T; }; +template +struct at, index> : at, index-1> {}; + +template struct remove_at; +template +struct remove_at, list, 0> { using type = list; }; +template +struct remove_at, list, index> { + using type = typename remove_at, list, index-1>::type; +}; + +template class Filter, typename Filtered, typename List> struct filter; +template class Filter, typename... Filtered> +struct filter, list<>> { using type = list; }; +template class Filter, typename... Filtered, typename T1, typename... Types> +struct filter, list> { + using type = typename std::conditional_t::value, + filter, list>, + filter, list>>::type; +}; + +template struct slice; +template +struct slice, list, index, index, void> { using type = list; }; +template +struct slice, list, 0, end, std::enable_if_t> + : slice, list, 0, end-1> {}; +template +struct slice, list, start, end, std::enable_if_t> + : slice, list, start-1, end-1> {}; + +template struct zip; +template<> +struct zip, list<>> { using type = list<>; }; +template +struct zip, list> { + using type = typename concat>, typename zip, list>::type>::type; +}; + +template +Ret dispatch_helper(Callable& c) { return c(T()); } + +} // namespace impl + +/// The actual list type +template +struct list { using type = list; }; + +/// Apply a list of types as arguments to another template +template class Delegate> +using apply = typename impl::apply::type; + +/// Get the number of types in a list +template +constexpr static std::size_t length() { return apply::value; } + +/// Concatenate two or more typelists together +template +using concat = typename impl::concat::type; + +/// Create a list of sequential integers ranging from [0, count) +template +using make_sequence = typename impl::make_sequence::type; + +/// Template to build typelists using the following syntax: +/// builder<>::type::add::add::add[...]::finalize +/// Or: +/// builder<>::type::add_list>::add_list>[...]::finalize +template> +struct builder { + template using add = typename builder>::type>::type; + template using add_list = typename builder::type>::type; + using type = builder; + using finalize = List; +}; + +/// Transform elements of a typelist +template +using transform = typename impl::transform::type; + +/// Get the index of the given type within a list, or -1 if type is not found +template +constexpr static int index_of() { return impl::index_of::value; } + +/// Check if a given type is in a list +template +constexpr static bool contains() { return impl::index_of::value != -1; } + +/// Remove duplicate items from one or more typelists and concatenate them all together +template +using concat_unique = typename impl::concat_unique, TypeLists...>::type; + +/// Get the type at the specified list index +template +using at = typename impl::at::type; + +/// Get the type at the beginning of the list +template +using first = at; +/// Get the type at the end of the list +template +using last = at()-1>; + +/// Get the list with the element at the given index removed +template +using remove_at = typename impl::remove_at, List, index>::type; + +/// Get the list with the given type removed +template +using remove_element = remove_at()>; + +/// Get a list with all elements that do not pass a filter removed +template class Filter> +using filter = typename impl::filter, List>::type; + +/// Template to invert a filter, i.e. filter::type> +template class Filter> +struct invert_filter { + template + struct type { constexpr static bool value = !Filter::value; }; +}; + +/// Take the sublist at indexes [start, end) +template()> +using slice = typename impl::slice, List, start, end>::type; + +/// Zip two equal-length typelists together, i.e. zip, list> == list, list> +template +using zip = typename impl::zip::type; + +/// Add indexes to types in the list, i.e. index> == list, list<1, B>, list<2, C>> where +/// 0, 1, and 2 are std::integral_constants of type std::size_t +template +using index = typename impl::zip()>::type, List>::type; + +/// This namespace contains some utilities that provide runtime operations on typelists +namespace runtime { +/// Type wrapper object allowing arbitrary types to be passed to functions as information rather than data +template struct wrapper { using type = T; }; + +/** + * @brief Index into the typelist for a type T, and invoke the callable with an argument wrapper() + * @param index Index of the type in the typelist to invoke the callable with + * @param c The callable to invoke + * @return The value returned by the callable + * @note The callable return type must be the same for all list elements + * + * If index is out of bounds, throws std::out_of_range exception + */ +template::value != 0>, + typename Return = decltype(std::declval()(wrapper, 0>>()))> +Return dispatch(list, std::size_t index, Callable c) { + static std::function call_table[] = + { impl::dispatch_helper>... }; + if (index < impl::length::value) return call_table[index](c); + throw std::out_of_range("Invalid index to fc::typelist::runtime::dispatch()"); +} +template +auto dispatch(List l, int64_t index, Callable c) { + if (index < 0) throw std::out_of_range("Negative index to fc::typelist::runtime::dispatch()"); + return dispatch(l, std::size_t(index), std::move(c)); +} + +/// @brief Invoke the provided callable with an argument wrapper() for each type in the list +template +void for_each(list, Callable c) { + bool trues[] = { [](Callable& c, auto t) { c(t); return true; }(c, wrapper())... }; + (void)(trues); +} + +} } } // namespace fc::typelist::runtime diff --git a/include/fc/reflect/typename.hpp b/include/fc/reflect/typename.hpp index 41fc348..15b8523 100644 --- a/include/fc/reflect/typename.hpp +++ b/include/fc/reflect/typename.hpp @@ -112,6 +112,22 @@ namespace fc { return _name.c_str(); } }; + template struct get_typename< const T* > + { + static const char* name() + { + static std::string n = std::string("const ") + get_typename::name() + "*"; + return n.c_str(); + } + }; + template struct get_typename< T* > + { + static const char* name() + { + static std::string n = std::string(get_typename::name()) + "*"; + return n.c_str(); + } + }; struct unsigned_int; class variant_object; diff --git a/include/fc/static_variant.hpp b/include/fc/static_variant.hpp index 89baa4e..d284963 100644 --- a/include/fc/static_variant.hpp +++ b/include/fc/static_variant.hpp @@ -23,174 +23,6 @@ namespace fc { // Implementation details, the user should not import this: namespace impl { -template -struct storage_ops; - -template -struct position; - -template -struct type_info; - -template -struct copy_construct -{ - typedef void result_type; - StaticVariant& sv; - copy_construct( StaticVariant& s ):sv(s){} - template - void operator()( const T& v )const - { - sv.init(v); - } -}; - -template -struct move_construct -{ - typedef void result_type; - StaticVariant& sv; - move_construct( StaticVariant& s ):sv(s){} - template - void operator()( T& v )const - { - sv.init( std::move(v) ); - } -}; - -template -struct storage_ops { - static void del(int n, void *data) {} - static void con(int n, void *data) {} - - template - static typename visitor::result_type apply(int n, void *data, visitor& v) {} - - template - static typename visitor::result_type apply(int n, void *data, const visitor& v) {} - - template - static typename visitor::result_type apply(int n, const void *data, visitor& v) {} - - template - static typename visitor::result_type apply(int n, const void *data, const visitor& v) {} -}; - -template -struct storage_ops { - static void del(int n, void *data) { - if(n == N) reinterpret_cast(data)->~T(); - else storage_ops::del(n, data); - } - static void con(int n, void *data) { - if(n == N) new(reinterpret_cast(data)) T(); - else storage_ops::con(n, data); - } - - template - static typename visitor::result_type apply(int n, void *data, visitor& v) { - if(n == N) return v(*reinterpret_cast(data)); - else return storage_ops::apply(n, data, v); - } - - template - static typename visitor::result_type apply(int n, void *data, const visitor& v) { - if(n == N) return v(*reinterpret_cast(data)); - else return storage_ops::apply(n, data, v); - } - - template - static typename visitor::result_type apply(int n, const void *data, visitor& v) { - if(n == N) return v(*reinterpret_cast(data)); - else return storage_ops::apply(n, data, v); - } - - template - static typename visitor::result_type apply(int n, const void *data, const visitor& v) { - if(n == N) return v(*reinterpret_cast(data)); - else return storage_ops::apply(n, data, v); - } -}; - -template -struct storage_ops { - static void del(int n, void *data) { - FC_THROW_EXCEPTION( fc::assert_exception, "Internal error: static_variant tag is invalid."); - } - static void con(int n, void *data) { - FC_THROW_EXCEPTION( fc::assert_exception, "Internal error: static_variant tag is invalid." ); - } - - template - static typename visitor::result_type apply(int n, void *data, visitor& v) { - FC_THROW_EXCEPTION( fc::assert_exception, "Internal error: static_variant tag is invalid." ); - } - template - static typename visitor::result_type apply(int n, void *data, const visitor& v) { - FC_THROW_EXCEPTION( fc::assert_exception, "Internal error: static_variant tag is invalid." ); - } - template - static typename visitor::result_type apply(int n, const void *data, visitor& v) { - FC_THROW_EXCEPTION( fc::assert_exception, "Internal error: static_variant tag is invalid." ); - } - template - static typename visitor::result_type apply(int n, const void *data, const visitor& v) { - FC_THROW_EXCEPTION( fc::assert_exception, "Internal error: static_variant tag is invalid." ); - } -}; - -template -struct position { - static constexpr int pos = -1; -}; - -template -struct position { - static constexpr int pos = 0; -}; - -template -struct position { - static constexpr int pos = position::pos != -1 ? position::pos + 1 : -1; -}; - -template -struct type_info { - static constexpr bool no_reference_types = false; - static constexpr bool no_duplicates = position::pos == -1 && type_info::no_duplicates; - static constexpr size_t size = type_info::size > sizeof(T&) ? type_info::size : sizeof(T&); - static constexpr size_t count = 1 + type_info::count; -}; - -template -struct type_info { - static constexpr bool no_reference_types = type_info::no_reference_types; - static constexpr bool no_duplicates = position::pos == -1 && type_info::no_duplicates; - static constexpr size_t size = type_info::size > sizeof(T) ? type_info::size : sizeof(T&); - static constexpr size_t count = 1 + type_info::count; -}; - -template<> -struct type_info<> { - static constexpr bool no_reference_types = true; - static constexpr bool no_duplicates = true; - static constexpr size_t count = 0; - static constexpr size_t size = 0; -}; - -template -constexpr size_t size( TTag ) -{ - return 0; -} - -template -constexpr size_t size( TTag tag ) -{ - return tag <= 0 ? sizeof(A) : size( --tag ); -} - - class dynamic_storage { char* storage; @@ -206,71 +38,36 @@ public: void release(); }; - - } // namespace impl -template -static const std::array - init_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0) -{ - return std::array(); -} - -template -static const std::array - init_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0 ) -{ - std::array result{}; - if( !funcs ) funcs = result.data(); - *funcs++ = [] ( Visitor& v, Data d ) { return v( *reinterpret_cast( d ) ); }; - init_wrappers( v, d, funcs ); - return result; -} - -template -static const std::array - init_const_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0 ) -{ - return std::array(); -} - -template -static const std::array - init_const_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0 ) -{ - std::array result{}; - if( !funcs ) funcs = result.data(); - *funcs++ = [] ( Visitor& v, Data d ) { return v( *reinterpret_cast( d ) ); }; - init_const_wrappers( v, d, funcs ); - return result; -} - template class static_variant { public: using tag_type = int64_t; + using list = typelist::list; protected: - static_assert(impl::type_info::no_reference_types, "Reference types are not permitted in static_variant."); - static_assert(impl::type_info::no_duplicates, "static_variant type arguments contain duplicate types."); + static_assert(typelist::length>() == 0, + "Reference types are not permitted in static_variant."); + static_assert(typelist::length>() == typelist::length(), + "static_variant type arguments contain duplicate types."); template - using type_in_typelist = typename std::enable_if::pos != -1, X>::type; // type is in typelist of static_variant. + using type_in_typelist = std::enable_if_t() != -1>; tag_type _tag; impl::dynamic_storage storage; template> void init(const X& x) { - _tag = impl::position::pos; + _tag = typelist::index_of(); storage.alloc( sizeof(X) ); new(storage.data()) X(x); } template> void init(X&& x) { - _tag = impl::position::pos; + _tag = typelist::index_of(); storage.alloc( sizeof(X) ); new(storage.data()) X( std::move(x) ); } @@ -280,26 +77,48 @@ protected: FC_ASSERT( tag >= 0 ); FC_ASSERT( tag < count() ); _tag = tag; - storage.alloc( impl::size( tag ) ); - impl::storage_ops<0, Types...>::con(_tag, storage.data()); + typelist::runtime::dispatch(list(), tag, [this](auto t) { + using T = typename decltype(t)::type; + storage.alloc(sizeof(T)); + new(reinterpret_cast(storage.data())) T(); + }); } void clean() { - impl::storage_ops<0, Types...>::del(_tag, storage.data() ); + typelist::runtime::dispatch(list(), _tag, [data=storage.data()](auto t) { + using T = typename decltype(t)::type; + reinterpret_cast(data)->~T(); + }); storage.release(); } + template + struct import_helper { + static static_variant construct(const T&) { + FC_THROW_EXCEPTION(assert_exception, "Cannot import unsupported type ${T} into static_variant", + ("T", get_typename::name())); + } + static static_variant construct(T&&) { + FC_THROW_EXCEPTION(assert_exception, "Cannot import unsupported type ${T} into static_variant", + ("T", get_typename::name())); + } + }; + template + struct import_helper> { + static static_variant construct(const T& t) { + return static_variant(t); + } + static static_variant construct(T&& t) { + return static_variant(std::move(t)); + } + }; - template - friend struct impl::copy_construct; - template - friend struct impl::move_construct; public: template> struct tag { - static constexpr int value = impl::position::pos; + static const int value = typelist::index_of(); }; struct type_lt { @@ -310,6 +129,25 @@ public: }; using flat_set_type = flat_set; + /// Import the value from a foreign static_variant with types not in this one, and throw if the value is an + /// incompatible type + template + static static_variant import_from(const static_variant& other) { + return typelist::runtime::dispatch(typelist::list(), other.which(), [&other](auto t) { + using other_type = typename decltype(t)::type; + return import_helper::construct(other.template get()); + }); + } + /// Import the value from a foreign static_variant with types not in this one, and throw if the value is an + /// incompatible type + template + static static_variant import_from(static_variant&& other) { + return typelist::runtime::dispatch(typelist::list(), other.which(), [&other](auto t) { + using other_type = typename decltype(t)::type; + return import_helper::construct(std::move(other.template get())); + }); + } + static_variant() { init_from_tag(0); @@ -318,23 +156,41 @@ public: template static_variant( const static_variant& cpy ) { - cpy.visit( impl::copy_construct(*this) ); + typelist::runtime::dispatch(typelist::list(), cpy.which(), [this, &cpy](auto t) mutable { + this->init(cpy.template get()); + }); } static_variant( const static_variant& cpy ) { - cpy.visit( impl::copy_construct(*this) ); + typelist::runtime::dispatch(list(), cpy.which(), [this, &cpy](auto t) mutable { + this->init(cpy.template get()); + }); } static_variant( static_variant&& mv ) { - mv.visit( impl::move_construct(*this) ); + typelist::runtime::dispatch(list(), mv.which(), [this, &mv](auto t) mutable { + this->init(std::move(mv.template get())); + }); + } + + template + static_variant( static_variant&& mv ) + { + typelist::runtime::dispatch(typelist::list(), mv.which(), [this, &mv](auto t) mutable { + this->init(std::move(mv.template get())); + }); } template> static_variant(const X& v) { init(v); } + template> + static_variant(X&& v) { + init(std::move(v)); + } ~static_variant() { clean(); @@ -350,20 +206,24 @@ public: { if( this == &v ) return *this; clean(); - v.visit( impl::copy_construct(*this) ); + typelist::runtime::dispatch(list(), v.which(), [this, &v](auto t)mutable { + this->init(v.template get()); + }); return *this; } static_variant& operator=( static_variant&& v ) { if( this == &v ) return *this; clean(); - v.visit( impl::move_construct(*this) ); + typelist::runtime::dispatch(list(), v.which(), [this, &v](auto t)mutable { + this->init(std::move(v.template get())); + }); return *this; } template> X& get() { - if(_tag == impl::position::pos) { + if(_tag == typelist::index_of()) { return *reinterpret_cast(storage.data()); } else { FC_THROW_EXCEPTION( fc::assert_exception, "static_variant does not contain a value of type ${t}", ("t",fc::get_typename::name()) ); @@ -371,7 +231,7 @@ public: } template> const X& get() const { - if(_tag == impl::position::pos) { + if(_tag == typelist::index_of()) { return *reinterpret_cast(storage.data()); } else { FC_THROW_EXCEPTION( fc::assert_exception, "static_variant does not contain a value of type ${t}", ("t",fc::get_typename::name()) ); @@ -400,36 +260,40 @@ public: template static typename visitor::result_type visit( tag_type tag, visitor& v, void* data ) { - static const auto wrappers = init_wrappers::count,visitor,void*,Types...>( v, data ); FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); - return wrappers[tag]( v, data ); + return typelist::runtime::dispatch(list(), tag, [&v, data](auto t) { + return v(*reinterpret_cast(data)); + }); } template static typename visitor::result_type visit( tag_type tag, const visitor& v, void* data ) { - static const auto wrappers = init_wrappers::count,const visitor,void*,Types...>( v, data ); FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); - return wrappers[tag]( v, data ); + return typelist::runtime::dispatch(list(), tag, [&v, data](auto t) { + return v(*reinterpret_cast(data)); + }); } template static typename visitor::result_type visit( tag_type tag, visitor& v, const void* data ) { - static const auto wrappers = init_const_wrappers::count,visitor,const void*,Types...>( v, data ); FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); - return wrappers[tag]( v, data ); + return typelist::runtime::dispatch(list(), tag, [&v, data](auto t) { + return v(*reinterpret_cast(data)); + }); } template static typename visitor::result_type visit( tag_type tag, const visitor& v, const void* data ) { - static const auto wrappers = init_const_wrappers::count,const visitor,const void*,Types...>( v, data ); FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); - return wrappers[tag]( v, data ); + return typelist::runtime::dispatch(list(), tag, [&v, data](auto t) { + return v(*reinterpret_cast(data)); + }); } - static constexpr int count() { return impl::type_info::count; } + static int count() { return typelist::length(); } void set_which( tag_type w ) { FC_ASSERT( w >= 0 ); FC_ASSERT( w < count() ); @@ -442,6 +306,12 @@ public: template bool is_type() const { return _tag == tag::value; } }; +template<> class static_variant<> { +public: + using tag_type = int64_t; + static_variant() { FC_THROW_EXCEPTION(assert_exception, "Cannot create static_variant with no types"); } +}; +template class static_variant> : public static_variant {}; struct from_static_variant { diff --git a/src/network/http/websocket.cpp b/src/network/http/websocket.cpp index 5138fb0..45332f5 100644 --- a/src/network/http/websocket.cpp +++ b/src/network/http/websocket.cpp @@ -300,6 +300,10 @@ namespace fc { namespace http { _server.close( item.first, 0, "server exit" ); if( _closed ) _closed->wait(); +#ifdef TRAVIS_BUILD +#warning Adding 100ms sleep to ~websocket_server_impl() to stabilize Travis tests + fc::usleep(fc::milliseconds(100)); +#endif } typedef std::map > con_map; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 01cf205..5c17ca7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -41,6 +41,7 @@ add_executable( all_tests all_tests.cpp thread/thread_tests.cpp thread/parallel_tests.cpp bloom_test.cpp + reflection_tests.cpp serialization_test.cpp stacktrace_test.cpp time_test.cpp diff --git a/tests/reflection_tests.cpp b/tests/reflection_tests.cpp new file mode 100644 index 0000000..c4e3491 --- /dev/null +++ b/tests/reflection_tests.cpp @@ -0,0 +1,126 @@ +#include + +#include + +#include + +struct reflect_test_base { + int x = 1; + char y = 'a'; +}; +struct reflect_test_derived : reflect_test_base { + double z = 3.14; +}; +struct reflect_layer_1 { reflect_test_base b; int32_t n; }; +struct reflect_layer_2 { reflect_layer_1 l1; reflect_test_derived d; }; +struct reflect_layer_3 { reflect_layer_2 l2; int32_t i; }; + +FC_REFLECT( reflect_test_base, (x)(y) ); +FC_REFLECT_DERIVED( reflect_test_derived, (reflect_test_base), (z) ); +FC_REFLECT( reflect_layer_1, (b)(n) ); +FC_REFLECT( reflect_layer_2, (l1)(d) ); +FC_REFLECT( reflect_layer_3, (l2)(i) ); + +BOOST_AUTO_TEST_SUITE( fc_reflection ) + +BOOST_AUTO_TEST_CASE( reflection_static_tests ) +{ + // These are all compile-time tests, nothing actually happens here at runtime + using base_reflection = fc::reflector; + using derived_reflection = fc::reflector; + static_assert(fc::typelist::length() == 2, ""); + static_assert(fc::typelist::length() == 3, ""); + static_assert(fc::typelist::at::is_derived, ""); + static_assert(std::is_same::field_container, + reflect_test_base>::value, ""); + static_assert(fc::typelist::at::is_derived, ""); + static_assert(std::is_same::field_container, + reflect_test_base>::value, ""); + static_assert(fc::typelist::at::is_derived == false, ""); + static_assert(std::is_same, 0, 1>, + fc::typelist::list>::value, ""); + static_assert(std::is_same, 0, 2>, + fc::typelist::list>::value, ""); + static_assert(std::is_same, 0, 3>, + fc::typelist::list>::value, ""); + static_assert(std::is_same, 1, 3>, + fc::typelist::list>::value, ""); + static_assert(std::is_same, 2, 3>, + fc::typelist::list>::value, ""); + static_assert(std::is_same, 1, 2>, + fc::typelist::list>::value, ""); + static_assert(std::is_same, 1>, + fc::typelist::list>::value, ""); + static_assert(std::is_same, fc::typelist::list<>>::value, ""); + static_assert(std::is_same, + fc::typelist::list>>::value, ""); + static_assert(std::is_same, + fc::typelist::list, + std::integral_constant>>::value, ""); + static_assert(std::is_same, + fc::typelist::list, + std::integral_constant, + std::integral_constant>>::value, ""); + static_assert(std::is_same, fc::typelist::list<>>, + fc::typelist::list<>>::value, ""); + static_assert(std::is_same, fc::typelist::list>, + fc::typelist::list>>::value, ""); + static_assert(std::is_same, fc::typelist::list>, + fc::typelist::list, + fc::typelist::list>>::value, ""); + static_assert(std::is_same>, fc::typelist::list<>>::value, ""); + static_assert(std::is_same>, + fc::typelist::list, int>, + fc::typelist::list, bool>, + fc::typelist::list, char>, + fc::typelist::list, double>> + >::value, ""); +} + +BOOST_AUTO_TEST_CASE( typelist_dispatch_test ) +{ + using list = fc::typelist::list; + auto get_name = [](auto t) -> std::string { return fc::get_typename::name(); }; + BOOST_CHECK_EQUAL(fc::typelist::runtime::dispatch(list(), 0ul, get_name), "float"); + BOOST_CHECK_EQUAL(fc::typelist::runtime::dispatch(list(), 1ul, get_name), "bool"); + BOOST_CHECK_EQUAL(fc::typelist::runtime::dispatch(list(), 2ul, get_name), "char"); +} + +// Helper template to use fc::typelist::at without a comma, for macro friendliness +template struct index_from { template using at = fc::typelist::at; }; +BOOST_AUTO_TEST_CASE( reflection_get_test ) +{ try { + reflect_test_derived derived; + reflect_test_base& base = derived; + + using base_reflector = fc::reflector; + using derived_reflector = fc::reflector; + + BOOST_CHECK(index_from::at<0>::get(base) == 1); + BOOST_CHECK(index_from::at<1>::get(base) == 'a'); + + fc::typelist::at::get(base) = 5; + fc::typelist::at::get(base) = 'q'; + + BOOST_CHECK(index_from::at<0>::get(base) == 5); + BOOST_CHECK(index_from::at<1>::get(base) == 'q'); + + BOOST_CHECK(index_from::at<0>::get(derived) == 5); + BOOST_CHECK(index_from::at<1>::get(derived) == 'q'); + BOOST_CHECK(index_from::at<2>::get(derived) == 3.14); + + fc::typelist::at::get(derived) = 'X'; + + BOOST_CHECK(index_from::at<1>::get(base) == 'X'); + + reflect_layer_3 l3; + BOOST_CHECK(index_from::members>::at<0> + ::reflector::members>::at<0>::reflector::members>::at<0>::reflector::members>::at<1>::get(l3.l2.l1.b) + == 'a'); + BOOST_CHECK(index_from::members>::at<0>::reflector::members> + ::at<1>::reflector::members>::at<1>::get(l3.l2.d) == 'a'); + BOOST_CHECK(index_from::members>::at<0>::reflector::members> + ::at<1>::reflector::members>::at<2>::get(l3.l2.d) == 3.14); +} FC_CAPTURE_LOG_AND_RETHROW( (0) ) } + +BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/serialization_test.cpp b/tests/serialization_test.cpp index 1e0165c..ccfe8d2 100644 --- a/tests/serialization_test.cpp +++ b/tests/serialization_test.cpp @@ -35,7 +35,6 @@ namespace fc { namespace test { inline bool operator < ( const item& a, const item& b ) { return ( std::tie( a.level, a.w ) < std::tie( b.level, b.w ) ); } - } } // namespace fc::test FC_REFLECT( fc::test::item_wrapper, (v) ); From 94cb1858b8dec8b85d3045d04d8a34c8e0ea6b34 Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Thu, 29 Aug 2019 13:49:49 -0500 Subject: [PATCH 071/110] Fix constexprs, unused code --- include/fc/reflect/reflect.hpp | 8 -------- include/fc/static_variant.hpp | 4 ++-- src/network/http/websocket.cpp | 4 ---- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/include/fc/reflect/reflect.hpp b/include/fc/reflect/reflect.hpp index 348477a..1801471 100644 --- a/include/fc/reflect/reflect.hpp +++ b/include/fc/reflect/reflect.hpp @@ -375,11 +375,3 @@ namespace fc { \ template<> struct get_typename { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \ } -// vvv These are preserved to merge more smoothly vvv -#define FC_REFLECT_BASE_MEMBER_COUNT( r, OP, elem ) \ - OP fc::reflector::total_member_count - -#define FC_REFLECT_MEMBER_COUNT( r, OP, elem ) \ - OP 1 -// ^^^ These can be removed after updating graphene/protocol/types.hpp ^^^ - diff --git a/include/fc/static_variant.hpp b/include/fc/static_variant.hpp index d284963..757ebb3 100644 --- a/include/fc/static_variant.hpp +++ b/include/fc/static_variant.hpp @@ -118,7 +118,7 @@ public: template> struct tag { - static const int value = typelist::index_of(); + static constexpr int value = typelist::index_of(); }; struct type_lt { @@ -293,7 +293,7 @@ public: }); } - static int count() { return typelist::length(); } + static constexpr int count() { return typelist::length(); } void set_which( tag_type w ) { FC_ASSERT( w >= 0 ); FC_ASSERT( w < count() ); diff --git a/src/network/http/websocket.cpp b/src/network/http/websocket.cpp index 45332f5..5138fb0 100644 --- a/src/network/http/websocket.cpp +++ b/src/network/http/websocket.cpp @@ -300,10 +300,6 @@ namespace fc { namespace http { _server.close( item.first, 0, "server exit" ); if( _closed ) _closed->wait(); -#ifdef TRAVIS_BUILD -#warning Adding 100ms sleep to ~websocket_server_impl() to stabilize Travis tests - fc::usleep(fc::milliseconds(100)); -#endif } typedef std::map > con_map; From 292584ca59dded65edf7b679b3aaa498ed028849 Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Fri, 30 Aug 2019 14:34:43 -0500 Subject: [PATCH 072/110] Add static_variant::operator== For real this time :) --- include/fc/static_variant.hpp | 8 ++++++++ tests/variant_test.cpp | 7 ++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/include/fc/static_variant.hpp b/include/fc/static_variant.hpp index 757ebb3..5c3695f 100644 --- a/include/fc/static_variant.hpp +++ b/include/fc/static_variant.hpp @@ -221,6 +221,14 @@ public: return *this; } + friend bool operator==( const static_variant& a, const static_variant& b ) { + if (a.which() != b.which()) + return false; + return typelist::runtime::dispatch(list(), a.which(), [&a, &b](auto t) { + return a.get() == b.get(); + }); + } + template> X& get() { if(_tag == typelist::index_of()) { diff --git a/tests/variant_test.cpp b/tests/variant_test.cpp index 474e5ae..96e62b5 100644 --- a/tests/variant_test.cpp +++ b/tests/variant_test.cpp @@ -182,10 +182,7 @@ BOOST_AUTO_TEST_CASE( nested_objects_test ) from_variant( v, sv1, nested_levels + 2 ); - auto sv_equal = [](const fc::static_variant& v1, const fc::static_variant& v2) { - return v1.get() == v2.get(); - }; - BOOST_CHECK( sv_equal(sv, sv1) ); + BOOST_CHECK( sv == sv1 ); // both log and dump should never throw BOOST_TEST_MESSAGE( "========== About to log static_variant. ==========" ); @@ -218,7 +215,7 @@ BOOST_AUTO_TEST_CASE( nested_objects_test ) from_variant( v, vec1, nested_levels + 3 ); - BOOST_CHECK( std::equal(vec.begin(), vec.end(), vec1.begin(), sv_equal) ); + BOOST_CHECK( vec == vec1 ); // both log and dump should never throw BOOST_TEST_MESSAGE( "========== About to log vector. ==========" ); From 77a82903fcf98f5b3b2d99932fc1db995bce937a Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sun, 1 Sep 2019 15:17:59 +0200 Subject: [PATCH 073/110] Fix core #314 - Use windows default CAs for tls client connections --- src/network/http/websocket.cpp | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/network/http/websocket.cpp b/src/network/http/websocket.cpp index 5138fb0..77ff233 100644 --- a/src/network/http/websocket.cpp +++ b/src/network/http/websocket.cpp @@ -20,6 +20,10 @@ #include #include +#if WIN32 +#include +#endif + #ifdef DEFAULT_LOGGER # undef DEFAULT_LOGGER #endif @@ -28,7 +32,33 @@ namespace fc { namespace http { namespace detail { +#if WIN32 + // taken from https://stackoverflow.com/questions/39772878/reliable-way-to-get-root-ca-certificates-on-windows/40710806 + static void add_windows_root_certs(boost::asio::ssl::context &ctx) + { + HCERTSTORE hStore = CertOpenSystemStore( 0, "ROOT" ); + if( hStore == NULL ) + return; + X509_STORE *store = X509_STORE_new(); + PCCERT_CONTEXT pContext = NULL; + while( (pContext = CertEnumCertificatesInStore( hStore, pContext )) != NULL ) + { + X509 *x509 = d2i_X509( NULL, (const unsigned char **)&pContext->pbCertEncoded, + pContext->cbCertEncoded); + if( x509 != NULL ) + { + X509_STORE_add_cert( store, x509 ); + X509_free( x509 ); + } + } + + CertFreeCertificateContext( pContext ); + CertCloseStore( hStore, 0 ); + + SSL_CTX_set_cert_store( ctx.native_handle(), store ); + } +#endif struct asio_with_stub_log : public websocketpp::config::asio { typedef asio_with_stub_log type; @@ -550,7 +580,13 @@ namespace fc { namespace http { return; ctx->set_verify_mode( boost::asio::ssl::verify_peer ); if( ca_filename == "_default" ) + { +#if WIN32 + add_windows_root_certs( *ctx ); +#else ctx->set_default_verify_paths(); +#endif + } else ctx->load_verify_file( ca_filename ); ctx->set_verify_depth(10); From 1699b0ac36bf8fa1ae98f416b0158946fa28e1ee Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Sun, 1 Sep 2019 12:53:01 -0500 Subject: [PATCH 074/110] Fix build on updated G++ --- include/fc/static_variant.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/fc/static_variant.hpp b/include/fc/static_variant.hpp index 5c3695f..88069d0 100644 --- a/include/fc/static_variant.hpp +++ b/include/fc/static_variant.hpp @@ -225,7 +225,8 @@ public: if (a.which() != b.which()) return false; return typelist::runtime::dispatch(list(), a.which(), [&a, &b](auto t) { - return a.get() == b.get(); + using Value = typename decltype(t)::type; + return a.template get() == b.template get(); }); } From dadfe189d41e70957c658d2eeda15286118bf61f Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Mon, 2 Sep 2019 10:02:51 -0500 Subject: [PATCH 075/110] Add FC_REFLECT_DERIVED_NO_TYPENAME This is moved to FC from graphene/protocol/types.hpp --- include/fc/reflect/reflect.hpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/include/fc/reflect/reflect.hpp b/include/fc/reflect/reflect.hpp index 1801471..bf68d17 100644 --- a/include/fc/reflect/reflect.hpp +++ b/include/fc/reflect/reflect.hpp @@ -325,6 +325,7 @@ template<> struct reflector {\ namespace member_names { \ BOOST_PP_SEQ_FOR_EACH_I( FC_REFLECT_MEMBER_NAME, TYPE, MEMBERS ) \ } } + #define FC_REFLECT_DERIVED_TEMPLATE( TEMPLATE_ARGS, TYPE, INHERITS, MEMBERS ) \ namespace fc { \ template struct get_typename { \ @@ -352,6 +353,28 @@ namespace member_names { \ BOOST_PP_SEQ_FOR_EACH_I( FC_REFLECT_TEMPLATE_MEMBER_NAME, (TEMPLATE_ARGS)(TYPE), MEMBERS ) \ } } +#define FC_REFLECT_DERIVED_NO_TYPENAME( TYPE, INHERITS, MEMBERS ) \ +namespace fc { \ +template<> struct reflector {\ + typedef TYPE type; \ + typedef std::true_type is_defined; \ + using native_members = \ + typename typelist::builder<>::type \ + BOOST_PP_SEQ_FOR_EACH_I( FC_CONCAT_MEMBER_REFLECTION, TYPE, MEMBERS ) ::finalize; \ + using inherited_members = \ + typename typelist::builder<>::type \ + BOOST_PP_SEQ_FOR_EACH( FC_CONCAT_BASE_MEMBER_REFLECTIONS, TYPE, INHERITS ) ::finalize; \ + using members = typename typelist::concat::type; \ + using base_classes = typename typelist::builder<>::type \ + BOOST_PP_SEQ_FOR_EACH( FC_CONCAT_TYPE, x, INHERITS ) ::finalize; \ + enum member_count_enum { \ + local_member_count = typelist::length(), \ + total_member_count = typelist::length() \ + }; \ + FC_REFLECT_DERIVED_IMPL_INLINE( TYPE, INHERITS, MEMBERS ) \ +}; \ +} // fc + /** * @def FC_REFLECT(TYPE,MEMBERS) * @brief Specializes fc::reflector for TYPE From 2e50624b2827e147b93307e41cb242ac5e395f54 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Thu, 12 Sep 2019 16:01:09 +0200 Subject: [PATCH 076/110] Check + rotate logs while logging not by scheduled task --- src/log/file_appender.cpp | 52 ++++++++++++--------------------------- 1 file changed, 16 insertions(+), 36 deletions(-) diff --git a/src/log/file_appender.cpp b/src/log/file_appender.cpp index c2efebf..4f5ab14 100644 --- a/src/log/file_appender.cpp +++ b/src/log/file_appender.cpp @@ -21,15 +21,7 @@ namespace fc { boost::mutex slock; private: - future _rotation_task; - time_point_sec _current_file_start_time; - - time_point_sec get_file_start_time( const time_point_sec& timestamp, const microseconds& interval ) - { - int64_t interval_seconds = interval.to_seconds(); - int64_t file_number = timestamp.sec_since_epoch() / interval_seconds; - return time_point_sec( (uint32_t)(file_number * interval_seconds) ); - } + boost::atomic _current_file_number; public: impl( const config& c) : cfg( c ) @@ -54,22 +46,22 @@ namespace fc { } } - ~impl() - { - try - { - _rotation_task.cancel_and_wait("file_appender is destructing"); - } - catch( ... ) - { - } - } - void rotate_files( bool initializing = false ) { - FC_ASSERT( cfg.rotate ); + if( !cfg.rotate ) return; + + int64_t interval_seconds = cfg.rotation_interval.to_seconds(); fc::time_point now = time_point::now(); - fc::time_point_sec start_time = get_file_start_time( now, cfg.rotation_interval ); + int64_t new_file_number = now.sec_since_epoch() / interval_seconds; + if( initializing ) + _current_file_number.store( new_file_number ); + else + { + int64_t prev_file_number = _current_file_number.load(); + if( prev_file_number >= new_file_number ) return; + if( !_current_file_number.compare_exchange_weak( prev_file_number, new_file_number ) ) return; + } + fc::time_point_sec start_time = time_point_sec( (uint32_t)(new_file_number * interval_seconds) ); string timestamp_string = start_time.to_non_delimited_iso_string(); fc::path link_filename = cfg.filename; fc::path log_filename = link_filename.parent_path() / (link_filename.filename().string() + "." + timestamp_string); @@ -79,14 +71,6 @@ namespace fc { if( !initializing ) { - if( start_time <= _current_file_start_time ) - { - _rotation_task = schedule( [this]() { rotate_files(); }, - _current_file_start_time + cfg.rotation_interval.to_seconds(), - "rotate_files(2)" ); - return; - } - out.flush(); out.close(); } @@ -127,11 +111,6 @@ namespace fc { { } } - - _current_file_start_time = start_time; - _rotation_task = schedule( [this]() { rotate_files(); }, - _current_file_start_time + cfg.rotation_interval.to_seconds(), - "rotate_files(3)" ); } }; @@ -151,8 +130,9 @@ namespace fc { // MS THREAD METHOD MESSAGE \t\t\t File:Line void file_appender::log( const log_message& m ) { + my->rotate_files(); + std::stringstream line; - //line << (m.get_context().get_timestamp().time_since_epoch().count() % (1000ll*1000ll*60ll*60))/1000 <<"ms "; line << string(m.get_context().get_timestamp()) << " "; line << std::setw( 21 ) << (m.get_context().get_thread_name().substr(0,9) + string(":") + m.get_context().get_task_name()).c_str() << " "; From 5cd9f7d6311f2e3ea9cf37eb4bf30ec8509e798d Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sun, 15 Sep 2019 14:09:44 +0200 Subject: [PATCH 077/110] Move log file deletion into separate task --- src/log/file_appender.cpp | 42 +++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/log/file_appender.cpp b/src/log/file_appender.cpp index 4f5ab14..3d8c26d 100644 --- a/src/log/file_appender.cpp +++ b/src/log/file_appender.cpp @@ -21,6 +21,7 @@ namespace fc { boost::mutex slock; private: + future _deletion_task; boost::atomic _current_file_number; public: @@ -36,6 +37,7 @@ namespace fc { FC_ASSERT( cfg.rotation_limit >= cfg.rotation_interval ); rotate_files( true ); + delete_files(); } else { out.open( cfg.filename, std::ios_base::out | std::ios_base::app); } @@ -46,6 +48,17 @@ namespace fc { } } + ~impl() + { + try + { + _deletion_task.cancel_and_wait("file_appender is destructing"); + } + catch( ... ) + { + } + } + void rotate_files( bool initializing = false ) { if( !cfg.rotate ) return; @@ -78,29 +91,35 @@ namespace fc { out.open( log_filename, std::ios_base::out | std::ios_base::app ); create_hard_link(log_filename, link_filename); } + } + void delete_files() + { /* Delete old log files */ - fc::time_point limit_time = now - cfg.rotation_limit; + auto current_file = _current_file_number.load(); + int64_t interval_seconds = cfg.rotation_interval.to_seconds(); + fc::time_point_sec start_time = time_point_sec( (uint32_t)(current_file * interval_seconds) ); + fc::time_point limit_time = time_point::now() - cfg.rotation_limit; + fc::path link_filename = cfg.filename; string link_filename_string = link_filename.filename().string(); directory_iterator itr(link_filename.parent_path()); + string timestamp_string = start_time.to_non_delimited_iso_string(); for( ; itr != directory_iterator(); itr++ ) { try { string current_filename = itr->filename().string(); - if (current_filename.compare(0, link_filename_string.size(), link_filename_string) != 0 || - current_filename.size() <= link_filename_string.size() + 1) - continue; + if( current_filename.compare(0, link_filename_string.size(), link_filename_string) != 0 + || current_filename.size() <= link_filename_string.size() + 1 ) + continue; string current_timestamp_str = current_filename.substr(link_filename_string.size() + 1, timestamp_string.size()); fc::time_point_sec current_timestamp = fc::time_point_sec::from_iso_string( current_timestamp_str ); - if( current_timestamp < start_time ) + if( current_timestamp < start_time + && ( current_timestamp < limit_time || file_size( current_filename ) <= 0 ) ) { - if( current_timestamp < limit_time || file_size( current_filename ) <= 0 ) - { - remove_all( *itr ); - continue; - } + remove_all( *itr ); + continue; } } catch (const fc::canceled_exception&) @@ -111,6 +130,9 @@ namespace fc { { } } + _deletion_task = schedule( [this]() { delete_files(); }, + start_time + cfg.rotation_interval.to_seconds(), + "delete_files(3)" ); } }; From f6fd6a7cf73882788549f39927de6d091228876f Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sun, 15 Sep 2019 14:18:57 +0200 Subject: [PATCH 078/110] Avoid re-computing seconds --- src/log/file_appender.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/log/file_appender.cpp b/src/log/file_appender.cpp index 3d8c26d..633f097 100644 --- a/src/log/file_appender.cpp +++ b/src/log/file_appender.cpp @@ -23,9 +23,10 @@ namespace fc { private: future _deletion_task; boost::atomic _current_file_number; + const int64_t _interval_seconds; public: - impl( const config& c) : cfg( c ) + impl( const config& c) : cfg( c ), _interval_seconds( cfg.rotation_interval.to_seconds() ) { try { @@ -63,9 +64,8 @@ namespace fc { { if( !cfg.rotate ) return; - int64_t interval_seconds = cfg.rotation_interval.to_seconds(); fc::time_point now = time_point::now(); - int64_t new_file_number = now.sec_since_epoch() / interval_seconds; + int64_t new_file_number = now.sec_since_epoch() / _interval_seconds; if( initializing ) _current_file_number.store( new_file_number ); else @@ -74,7 +74,7 @@ namespace fc { if( prev_file_number >= new_file_number ) return; if( !_current_file_number.compare_exchange_weak( prev_file_number, new_file_number ) ) return; } - fc::time_point_sec start_time = time_point_sec( (uint32_t)(new_file_number * interval_seconds) ); + fc::time_point_sec start_time = time_point_sec( (uint32_t)(new_file_number * _interval_seconds) ); string timestamp_string = start_time.to_non_delimited_iso_string(); fc::path link_filename = cfg.filename; fc::path log_filename = link_filename.parent_path() / (link_filename.filename().string() + "." + timestamp_string); @@ -97,8 +97,7 @@ namespace fc { { /* Delete old log files */ auto current_file = _current_file_number.load(); - int64_t interval_seconds = cfg.rotation_interval.to_seconds(); - fc::time_point_sec start_time = time_point_sec( (uint32_t)(current_file * interval_seconds) ); + fc::time_point_sec start_time = time_point_sec( (uint32_t)(current_file * _interval_seconds) ); fc::time_point limit_time = time_point::now() - cfg.rotation_limit; fc::path link_filename = cfg.filename; string link_filename_string = link_filename.filename().string(); @@ -130,8 +129,7 @@ namespace fc { { } } - _deletion_task = schedule( [this]() { delete_files(); }, - start_time + cfg.rotation_interval.to_seconds(), + _deletion_task = schedule( [this]() { delete_files(); }, start_time + _interval_seconds, "delete_files(3)" ); } }; From f4866b777ef20dd13216a5d60480e070ebba9dc2 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 16 Sep 2019 11:59:58 +0200 Subject: [PATCH 079/110] Move helper classes into fc::detail --- src/crypto/base58.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/crypto/base58.cpp b/src/crypto/base58.cpp index 929f387..cbe67a5 100644 --- a/src/crypto/base58.cpp +++ b/src/crypto/base58.cpp @@ -28,6 +28,8 @@ #include #include +namespace fc { namespace detail { + /** Errors thrown by the bignum class */ class bignum_error : public std::runtime_error { @@ -605,11 +607,10 @@ inline bool DecodeBase58(const std::string& str, std::vector& vch return DecodeBase58(str.c_str(), vchRet); } - -namespace fc { +} // detail std::string to_base58( const char* d, size_t s ) { - return EncodeBase58( (const unsigned char*)d, (const unsigned char*)d+s ).c_str(); + return fc::detail::EncodeBase58( (const unsigned char*)d, (const unsigned char*)d+s ).c_str(); } std::string to_base58( const std::vector& d ) @@ -620,8 +621,9 @@ std::string to_base58( const std::vector& d ) } std::vector from_base58( const std::string& base58_str ) { std::vector out; - if( !DecodeBase58( base58_str.c_str(), out ) ) { - FC_THROW_EXCEPTION( parse_error_exception, "Unable to decode base58 string ${base58_str}", ("base58_str",base58_str) ); + if( !fc::detail::DecodeBase58( base58_str.c_str(), out ) ) { + FC_THROW_EXCEPTION( parse_error_exception, "Unable to decode base58 string ${base58_str}", + ("base58_str",base58_str) ); } return std::vector((const char*)out.data(), ((const char*)out.data())+out.size() ); } @@ -629,10 +631,10 @@ std::vector from_base58( const std::string& base58_str ) { * @return the number of bytes decoded */ size_t from_base58( const std::string& base58_str, char* out_data, size_t out_data_len ) { - //slog( "%s", base58_str.c_str() ); std::vector out; - if( !DecodeBase58( base58_str.c_str(), out ) ) { - FC_THROW_EXCEPTION( parse_error_exception, "Unable to decode base58 string ${base58_str}", ("base58_str",base58_str) ); + if( !fc::detail::DecodeBase58( base58_str.c_str(), out ) ) { + FC_THROW_EXCEPTION( parse_error_exception, "Unable to decode base58 string ${base58_str}", + ("base58_str",base58_str) ); } FC_ASSERT( out.size() <= out_data_len ); if (!out.empty()) { @@ -640,6 +642,7 @@ size_t from_base58( const std::string& base58_str, char* out_data, size_t out_da } return out.size(); } -} + +} // fc #endif From 8c9f7151e1cefb02abb478dd759983a50455b16f Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 16 Sep 2019 12:03:59 +0200 Subject: [PATCH 080/110] Moved stuff into fc::test namespace --- tests/api_tests.cpp | 36 +++++++-------- tests/io/tcp_test.cpp | 24 +++++----- tests/thread/parallel_tests.cpp | 79 ++++++++++++++++++--------------- 3 files changed, 74 insertions(+), 65 deletions(-) diff --git a/tests/api_tests.cpp b/tests/api_tests.cpp index ef42b8d..50421a0 100644 --- a/tests/api_tests.cpp +++ b/tests/api_tests.cpp @@ -6,6 +6,8 @@ #include #include +namespace fc { namespace test { + class calculator { public: @@ -15,9 +17,6 @@ class calculator void on_result2( const std::function& cb, int test ); }; -FC_API( calculator, (add)(sub)(on_result)(on_result2) ) - - class login_api { public: @@ -29,8 +28,6 @@ class login_api fc::optional> calc; std::set test( const std::string&, const std::string& ) { return std::set(); } }; -FC_API( login_api, (get_calc)(test) ); - class optionals_api { @@ -44,9 +41,6 @@ public: return fc::json::to_string(fc::variants{{first,2}, {second, 2}, {third, 2}}); } }; -FC_API( optionals_api, (foo)(bar) ); - -using namespace fc; class some_calculator { @@ -58,6 +52,12 @@ class some_calculator std::function _cb; }; +}} // fc::test + +FC_API( fc::test::calculator, (add)(sub)(on_result)(on_result2) ) +FC_API( fc::test::login_api, (get_calc)(test) ); +FC_API( fc::test::optionals_api, (foo)(bar) ); + using namespace fc::http; using namespace fc::rpc; @@ -67,14 +67,14 @@ BOOST_AUTO_TEST_SUITE(api_tests) BOOST_AUTO_TEST_CASE(login_test) { try { - fc::api calc_api( std::make_shared() ); + fc::api calc_api( std::make_shared() ); auto server = std::make_shared(); server->on_connection([&]( const websocket_connection_ptr& c ){ auto wsc = std::make_shared(c, MAX_DEPTH); - auto login = std::make_shared(); + auto login = std::make_shared(); login->calc = calc_api; - wsc->register_api(fc::api(login)); + wsc->register_api(fc::api(login)); c->set_session_data( wsc ); }); @@ -86,7 +86,7 @@ BOOST_AUTO_TEST_CASE(login_test) { auto con = client->connect( "ws://localhost:" + std::to_string(listen_port) ); server->stop_listening(); auto apic = std::make_shared(con, MAX_DEPTH); - auto remote_login_api = apic->get_remote_api(); + auto remote_login_api = apic->get_remote_api(); auto remote_calc = remote_login_api->get_calc(); bool remote_triggered = false; remote_calc->on_result( [&remote_triggered]( uint32_t r ) { remote_triggered = true; } ); @@ -103,8 +103,8 @@ BOOST_AUTO_TEST_CASE(login_test) { BOOST_AUTO_TEST_CASE(optionals_test) { try { - auto optionals = std::make_shared(); - fc::api oapi(optionals); + auto optionals = std::make_shared(); + fc::api oapi(optionals); BOOST_CHECK_EQUAL(oapi->foo("a"), "[\"a\",null,null]"); BOOST_CHECK_EQUAL(oapi->foo("a", "b"), "[\"a\",\"b\",null]"); BOOST_CHECK_EQUAL(oapi->foo("a", "b", "c"), "[\"a\",\"b\",\"c\"]"); @@ -119,7 +119,7 @@ BOOST_AUTO_TEST_CASE(optionals_test) { auto server = std::make_shared(); server->on_connection([&]( const websocket_connection_ptr& c ){ auto wsc = std::make_shared(c, MAX_DEPTH); - wsc->register_api(fc::api(optionals)); + wsc->register_api(fc::api(optionals)); c->set_session_data( wsc ); }); @@ -130,7 +130,7 @@ BOOST_AUTO_TEST_CASE(optionals_test) { auto client = std::make_shared(); auto con = client->connect( "ws://localhost:" + std::to_string(listen_port) ); auto apic = std::make_shared(con, MAX_DEPTH); - auto remote_optionals = apic->get_remote_api(); + auto remote_optionals = apic->get_remote_api(); BOOST_CHECK_EQUAL(remote_optionals->foo("a"), "[\"a\",null,null]"); BOOST_CHECK_EQUAL(remote_optionals->foo("a", "b"), "[\"a\",\"b\",null]"); @@ -145,8 +145,8 @@ BOOST_AUTO_TEST_CASE(optionals_test) { auto client2 = std::make_shared(); auto con2 = client2->connect( "ws://localhost:" + std::to_string(listen_port) ); - string response; - con2->on_message_handler([&](const std::string& s){ + std::string response; + con2->on_message_handler([&response](const std::string& s){ response = s; }); diff --git a/tests/io/tcp_test.cpp b/tests/io/tcp_test.cpp index 0a43975..9d25bfd 100644 --- a/tests/io/tcp_test.cpp +++ b/tests/io/tcp_test.cpp @@ -3,6 +3,16 @@ #include #include +namespace fc { namespace test { + +class my_io_class : public fc::asio::default_io_service_scope +{ +public: + static void reset_num_threads() { fc::asio::default_io_service_scope::num_io_threads = 0; } +}; + +}} // fc::test + BOOST_AUTO_TEST_SUITE(tcp_tests) /*** @@ -15,23 +25,17 @@ BOOST_AUTO_TEST_CASE(tcpconstructor_test) fc::tcp_socket socket; } -class my_io_class : public fc::asio::default_io_service_scope -{ -public: - static void reset_num_threads() { fc::asio::default_io_service_scope::num_io_threads = 0; } -}; - /*** * Test the control of number of threads from outside */ BOOST_AUTO_TEST_CASE( number_threads_test ) { // to erase leftovers from previous tests - my_io_class::reset_num_threads(); + fc::test::my_io_class::reset_num_threads(); fc::asio::default_io_service_scope::set_num_threads(12); - my_io_class my_class; + fc::test::my_io_class my_class; BOOST_CHECK_EQUAL( 12, my_class.get_num_threads() ); } @@ -42,9 +46,9 @@ BOOST_AUTO_TEST_CASE( number_threads_test ) BOOST_AUTO_TEST_CASE( default_number_threads_test ) { // to erase leftovers from previous tests - my_io_class::reset_num_threads(); + fc::test::my_io_class::reset_num_threads(); - my_io_class my_class; + fc::test::my_io_class my_class; fc::asio::default_io_service(); diff --git a/tests/thread/parallel_tests.cpp b/tests/thread/parallel_tests.cpp index 14dcb4d..730027d 100644 --- a/tests/thread/parallel_tests.cpp +++ b/tests/thread/parallel_tests.cpp @@ -35,6 +35,8 @@ #include +namespace fc { namespace test { + struct thread_config { thread_config() { for( int i = 0; i < boost::unit_test::framework::master_test_suite().argc - 1; ++i ) @@ -42,13 +44,51 @@ struct thread_config { { uint16_t threads = atoi(boost::unit_test::framework::master_test_suite().argv[++i]); std::cout << "Using " << threads << " pool threads\n"; - fc::asio::default_io_service_scope::set_num_threads(threads); + asio::default_io_service_scope::set_num_threads(threads); } } }; -BOOST_GLOBAL_FIXTURE( thread_config ); +const std::string TEXT = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"$%&/()=?,.-#+´{[]}`*'_:;<>|"; +template +class hash_test { + public: + std::string _hashname = get_typename::name(); + + void run_single_threaded() { + const std::string first = Hash::hash(TEXT).str(); + time_point start = time_point::now(); + for( int i = 0; i < 1000; i++ ) + BOOST_CHECK_EQUAL( first, Hash::hash(TEXT).str() ); + time_point end = time_point::now(); + ilog( "${c} single-threaded ${h}'s in ${t}µs", ("c",1000)("h",_hashname)("t",end-start) ); + } + + void run_multi_threaded() { + const std::string first = Hash::hash(TEXT).str(); + std::vector> results; + results.reserve( 10000 ); + time_point start = time_point::now(); + for( int i = 0; i < 10000; i++ ) + results.push_back( do_parallel( [] () { return Hash::hash(TEXT).str(); } ) ); + for( auto& result: results ) + BOOST_CHECK_EQUAL( first, result.wait() ); + time_point end = time_point::now(); + ilog( "${c} multi-threaded ${h}'s in ${t}µs", ("c",10000)("h",_hashname)("t",end-start) ); + } + + void run() { + run_single_threaded(); + run_multi_threaded(); + } +}; + +}} // fc::test + +using namespace fc::test; + +BOOST_GLOBAL_FIXTURE( thread_config ); BOOST_AUTO_TEST_SUITE(parallel_tests) @@ -96,41 +136,6 @@ BOOST_AUTO_TEST_CASE( do_something_parallel ) } } -const std::string TEXT = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"$%&/()=?,.-#+´{[]}`*'_:;<>|"; - -template -class hash_test { - public: - std::string _hashname = fc::get_typename::name(); - - void run_single_threaded() { - const std::string first = Hash::hash(TEXT).str(); - fc::time_point start = fc::time_point::now(); - for( int i = 0; i < 1000; i++ ) - BOOST_CHECK_EQUAL( first, Hash::hash(TEXT).str() ); - fc::time_point end = fc::time_point::now(); - ilog( "${c} single-threaded ${h}'s in ${t}µs", ("c",1000)("h",_hashname)("t",end-start) ); - } - - void run_multi_threaded() { - const std::string first = Hash::hash(TEXT).str(); - std::vector> results; - results.reserve( 10000 ); - fc::time_point start = fc::time_point::now(); - for( int i = 0; i < 10000; i++ ) - results.push_back( fc::do_parallel( [] () { return Hash::hash(TEXT).str(); } ) ); - for( auto& result: results ) - BOOST_CHECK_EQUAL( first, result.wait() ); - fc::time_point end = fc::time_point::now(); - ilog( "${c} multi-threaded ${h}'s in ${t}µs", ("c",10000)("h",_hashname)("t",end-start) ); - } - - void run() { - run_single_threaded(); - run_multi_threaded(); - } -}; - BOOST_AUTO_TEST_CASE( hash_parallel ) { hash_test().run(); From 7b98c69c3bb24a5ad75689b519f96e7e0334755f Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 16 Sep 2019 14:38:45 +0200 Subject: [PATCH 081/110] Delete copy constructor + copy assignment in openssl type wrappers --- include/fc/crypto/openssl.hpp | 27 ++++++++++++++------------- src/crypto/dh.cpp | 9 +++------ src/crypto/openssl.cpp | 30 ++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 19 deletions(-) diff --git a/include/fc/crypto/openssl.hpp b/include/fc/crypto/openssl.hpp index af883d6..70b7e7b 100644 --- a/include/fc/crypto/openssl.hpp +++ b/include/fc/crypto/openssl.hpp @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include #include #include @@ -21,6 +22,8 @@ namespace fc struct ssl_wrapper { ssl_wrapper(ssl_type* obj):obj(obj) {} + ssl_wrapper( ssl_wrapper& copy ) = delete; + ssl_wrapper& operator=( ssl_wrapper& copy ) = delete; operator ssl_type*() { return obj; } operator const ssl_type*() const { return obj; } @@ -30,23 +33,21 @@ namespace fc ssl_type* obj; }; - #define SSL_TYPE(name, ssl_type, free_func) \ + #define SSL_TYPE_DECL(name, ssl_type) \ struct name : public ssl_wrapper \ { \ - name(ssl_type* obj=nullptr) \ - : ssl_wrapper(obj) {} \ - ~name() \ - { \ - if( obj != nullptr ) \ - free_func(obj); \ - } \ + name( ssl_type* obj=nullptr ); \ + name( name&& move ); \ + ~name(); \ + name& operator=( name&& move ); \ }; - SSL_TYPE(ec_group, EC_GROUP, EC_GROUP_free) - SSL_TYPE(ec_point, EC_POINT, EC_POINT_free) - SSL_TYPE(ecdsa_sig, ECDSA_SIG, ECDSA_SIG_free) - SSL_TYPE(bn_ctx, BN_CTX, BN_CTX_free) - SSL_TYPE(evp_cipher_ctx, EVP_CIPHER_CTX, EVP_CIPHER_CTX_free ) + SSL_TYPE_DECL(ec_group, EC_GROUP) + SSL_TYPE_DECL(ec_point, EC_POINT) + SSL_TYPE_DECL(ecdsa_sig, ECDSA_SIG) + SSL_TYPE_DECL(bn_ctx, BN_CTX) + SSL_TYPE_DECL(evp_cipher_ctx, EVP_CIPHER_CTX) + SSL_TYPE_DECL(ssl_dh, DH) /** allocates a bignum by default.. */ struct ssl_bignum : public ssl_wrapper diff --git a/src/crypto/dh.cpp b/src/crypto/dh.cpp index c95c774..fbb3077 100644 --- a/src/crypto/dh.cpp +++ b/src/crypto/dh.cpp @@ -1,12 +1,9 @@ #include -#include #if OPENSSL_VERSION_NUMBER >= 0x10100000L #endif namespace fc { - SSL_TYPE(ssl_dh, DH, DH_free) - static bool validate( const ssl_dh& dh, bool& valid ) { int check; DH_check(dh,&check); @@ -36,7 +33,7 @@ namespace fc { { if( !p.size() ) return valid = false; - ssl_dh dh = DH_new(); + ssl_dh dh(DH_new()); #if OPENSSL_VERSION_NUMBER >= 0x10100000L const auto bn_p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL ); const auto bn_g = BN_bin2bn( (unsigned char*)&g, 1, NULL ); @@ -52,7 +49,7 @@ namespace fc { { if( !p.size() ) return valid = false; - ssl_dh dh = DH_new(); + ssl_dh dh(DH_new()); #if OPENSSL_VERSION_NUMBER >= 0x10100000L const auto bn_p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL ); const auto bn_g = BN_bin2bn( (unsigned char*)&g, 1, NULL ); @@ -90,7 +87,7 @@ namespace fc { return true; } bool diffie_hellman::compute_shared_key( const char* buf, uint32_t s ) { - ssl_dh dh = DH_new(); + ssl_dh dh(DH_new()); #if OPENSSL_VERSION_NUMBER >= 0x10100000L auto bn_p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL ); auto bn_pub_key = BN_bin2bn( (unsigned char*)&pub_key.front(), pub_key.size(), NULL ); diff --git a/src/crypto/openssl.cpp b/src/crypto/openssl.cpp index e4c0e88..92b35d9 100644 --- a/src/crypto/openssl.cpp +++ b/src/crypto/openssl.cpp @@ -63,4 +63,34 @@ namespace fc static openssl_scope ossl; return 0; } + + #define SSL_TYPE_IMPL(name, ssl_type, free_func) \ + name::name( ssl_type* obj ) : ssl_wrapper(obj) {} \ + name::name( name&& move ) : ssl_wrapper( move.obj ) \ + { \ + move.obj = nullptr; \ + } \ + name::~name() \ + { \ + if( obj != nullptr ) \ + free_func(obj); \ + } \ + name& name::operator=( name&& move ) \ + { \ + if( this != &move ) \ + { \ + if( obj != nullptr ) \ + free_func(obj); \ + obj = move.obj; \ + move.obj = nullptr; \ + } \ + return *this; \ + } + + SSL_TYPE_IMPL(ec_group, EC_GROUP, EC_GROUP_free) + SSL_TYPE_IMPL(ec_point, EC_POINT, EC_POINT_free) + SSL_TYPE_IMPL(ecdsa_sig, ECDSA_SIG, ECDSA_SIG_free) + SSL_TYPE_IMPL(bn_ctx, BN_CTX, BN_CTX_free) + SSL_TYPE_IMPL(evp_cipher_ctx, EVP_CIPHER_CTX, EVP_CIPHER_CTX_free ) + SSL_TYPE_IMPL(ssl_dh, DH, DH_free) } From 2b3611fa9559950fcf8c33a18e7a0849fdb0793e Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 16 Sep 2019 14:44:55 +0200 Subject: [PATCH 082/110] Delete copy constructor + copy assignment in tcp_socket --- include/fc/network/tcp_socket.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/fc/network/tcp_socket.hpp b/include/fc/network/tcp_socket.hpp index 320d45c..6e69f80 100644 --- a/include/fc/network/tcp_socket.hpp +++ b/include/fc/network/tcp_socket.hpp @@ -12,7 +12,9 @@ namespace fc { { public: tcp_socket(); + tcp_socket( tcp_socket& copy ) = delete; ~tcp_socket(); + tcp_socket& operator=( tcp_socket& copy ) = delete; void connect_to( const fc::ip::endpoint& remote_endpoint ); void bind( const fc::ip::endpoint& local_endpoint ); From e168b6400b461f2953aa062b9eb6fe2bb4495125 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Tue, 17 Sep 2019 13:46:02 +0200 Subject: [PATCH 083/110] Avoid time calculation when not rotating --- src/log/file_appender.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/log/file_appender.cpp b/src/log/file_appender.cpp index 633f097..aec6bec 100644 --- a/src/log/file_appender.cpp +++ b/src/log/file_appender.cpp @@ -24,6 +24,7 @@ namespace fc { future _deletion_task; boost::atomic _current_file_number; const int64_t _interval_seconds; + time_point _next_file_time; public: impl( const config& c) : cfg( c ), _interval_seconds( cfg.rotation_interval.to_seconds() ) @@ -65,6 +66,8 @@ namespace fc { if( !cfg.rotate ) return; fc::time_point now = time_point::now(); + if( now < _next_file_time ) return; + int64_t new_file_number = now.sec_since_epoch() / _interval_seconds; if( initializing ) _current_file_number.store( new_file_number ); @@ -75,6 +78,7 @@ namespace fc { if( !_current_file_number.compare_exchange_weak( prev_file_number, new_file_number ) ) return; } fc::time_point_sec start_time = time_point_sec( (uint32_t)(new_file_number * _interval_seconds) ); + _next_file_time = start_time + _interval_seconds; string timestamp_string = start_time.to_non_delimited_iso_string(); fc::path link_filename = cfg.filename; fc::path log_filename = link_filename.parent_path() / (link_filename.filename().string() + "." + timestamp_string); From d729816b06651ccde50940c92db729cf9fb4c61e Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Wed, 18 Sep 2019 12:51:17 +0200 Subject: [PATCH 084/110] Changes to avoid conflict in following cherry-pick --- src/exception.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/exception.cpp b/src/exception.cpp index d3fadbb..cc93009 100644 --- a/src/exception.cpp +++ b/src/exception.cpp @@ -182,11 +182,11 @@ namespace fc */ string exception::to_detail_string( log_level ll )const { - fc::stringstream ss; + std::stringstream ss; ss << variant(my->_code).as_string() <<" " << my->_name << ": " <_what<<"\n"; for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ) { - ss << itr->get_message() <<"\n"; + ss << itr->get_message() <<"\n"; //fc::format_string( itr->get_format(), itr->get_data() ) <<"\n"; try { ss << " " << json::to_string( itr->get_data() )<<"\n"; @@ -207,12 +207,12 @@ namespace fc */ string exception::to_string( log_level ll )const { - fc::stringstream ss; - ss << what() << ":"; + std::stringstream ss; + ss << what() << " (" << variant(my->_code).as_string() <<")\n"; for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ++itr ) { - if( itr->get_format().size() ) - ss << " " << fc::format_string( itr->get_format(), itr->get_data() ); + ss << fc::format_string( itr->get_format(), itr->get_data() ) << "\n"; + // ss << " " << itr->get_context().to_string() <<"\n"; } return ss.str(); } From 2eb047a6f4d61704478376a88f12205fe12dde69 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Tue, 22 May 2018 10:59:42 -0400 Subject: [PATCH 085/110] Add exception handling to to_string and to_detail_string --- src/exception.cpp | 48 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/src/exception.cpp b/src/exception.cpp index cc93009..bc72783 100644 --- a/src/exception.cpp +++ b/src/exception.cpp @@ -183,9 +183,17 @@ namespace fc string exception::to_detail_string( log_level ll )const { std::stringstream ss; - ss << variant(my->_code).as_string() <<" " << my->_name << ": " <_what<<"\n"; - for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ) - { + try { + try { + ss << variant( my->_code ).as_string(); + } catch( std::bad_alloc& ) { + throw; + } catch( ... ) { + ss << "<- exception in to_detail_string."; + } + ss << " " << my->_name << ": " << my->_what << "\n"; + for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ) { + try { ss << itr->get_message() <<"\n"; //fc::format_string( itr->get_format(), itr->get_data() ) <<"\n"; try { @@ -197,8 +205,18 @@ namespace fc } ss << " " << itr->get_context().to_string(); ++itr; + } catch( std::bad_alloc& ) { + throw; + } catch( ... ) { + ss << "<- exception in to_detail_string."; + } if( itr != my->_elog.end() ) ss<<"\n"; } + } catch( std::bad_alloc& ) { + throw; + } catch( ... ) { + ss << "<- exception in to_detail_string.\n"; + } return ss.str(); } @@ -208,13 +226,31 @@ namespace fc string exception::to_string( log_level ll )const { std::stringstream ss; - ss << what() << " (" << variant(my->_code).as_string() <<")\n"; - for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ++itr ) - { + try { + ss << my->_what; + try { + ss << " (" << variant( my->_code ).as_string() << ")\n"; + } catch( std::bad_alloc& ) { + throw; + } catch( ... ) { + ss << "<- exception in to_string.\n"; + } + for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ++itr ) { + try { ss << fc::format_string( itr->get_format(), itr->get_data() ) << "\n"; // ss << " " << itr->get_context().to_string() <<"\n"; + } catch( std::bad_alloc& ) { + throw; + } catch( ... ) { + ss << "<- exception in to_string.\n"; + } } return ss.str(); + } catch( std::bad_alloc& ) { + throw; + } catch( ... ) { + ss << "<- exception in to_string.\n"; + } } [[noreturn]] void exception_factory::rethrow( const exception& e )const From 3583ee613887698d695e1159d6e6a839bdb25cf7 Mon Sep 17 00:00:00 2001 From: Spartucus Date: Wed, 30 May 2018 17:56:20 +0800 Subject: [PATCH 086/110] Fix non-void function return value Since last catch insert exception string to `ss`, it should returns. --- src/exception.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/exception.cpp b/src/exception.cpp index bc72783..8814f53 100644 --- a/src/exception.cpp +++ b/src/exception.cpp @@ -251,6 +251,7 @@ namespace fc } catch( ... ) { ss << "<- exception in to_string.\n"; } + return ss.str(); } [[noreturn]] void exception_factory::rethrow( const exception& e )const From 5b8a7c281c35ec57bd080d55dad120ddc901fee9 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Wed, 18 Sep 2019 13:04:24 +0200 Subject: [PATCH 087/110] Partial revert "Changes to avoid conflict in following cherry-pick" This reverts commit d729816b06651ccde50940c92db729cf9fb4c61e. --- src/exception.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/exception.cpp b/src/exception.cpp index 8814f53..81cc585 100644 --- a/src/exception.cpp +++ b/src/exception.cpp @@ -194,7 +194,7 @@ namespace fc ss << " " << my->_name << ": " << my->_what << "\n"; for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ) { try { - ss << itr->get_message() <<"\n"; //fc::format_string( itr->get_format(), itr->get_data() ) <<"\n"; + ss << itr->get_message() <<"\n"; try { ss << " " << json::to_string( itr->get_data() )<<"\n"; @@ -227,18 +227,11 @@ namespace fc { std::stringstream ss; try { - ss << my->_what; - try { - ss << " (" << variant( my->_code ).as_string() << ")\n"; - } catch( std::bad_alloc& ) { - throw; - } catch( ... ) { - ss << "<- exception in to_string.\n"; - } + ss << what() << ":"; for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ++itr ) { + if( itr->get_format().size() ) try { - ss << fc::format_string( itr->get_format(), itr->get_data() ) << "\n"; - // ss << " " << itr->get_context().to_string() <<"\n"; + ss << " " << fc::format_string( itr->get_format(), itr->get_data() ); } catch( std::bad_alloc& ) { throw; } catch( ... ) { From 164f1f68e62432b32b1838a6e662cdf8a57f1536 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Wed, 18 Sep 2019 13:06:46 +0200 Subject: [PATCH 088/110] Whitespace fixes --- src/exception.cpp | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/exception.cpp b/src/exception.cpp index 81cc585..bd04f8e 100644 --- a/src/exception.cpp +++ b/src/exception.cpp @@ -192,26 +192,27 @@ namespace fc ss << "<- exception in to_detail_string."; } ss << " " << my->_name << ": " << my->_what << "\n"; - for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ) { + for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ) + { try { - ss << itr->get_message() <<"\n"; - try - { - ss << " " << json::to_string( itr->get_data() )<<"\n"; - } - catch( const fc::assert_exception& e ) - { - ss << "ERROR: Failed to convert log data to string!\n"; - } - ss << " " << itr->get_context().to_string(); - ++itr; + ss << itr->get_message() <<"\n"; + try + { + ss << " " << json::to_string( itr->get_data() )<<"\n"; + } + catch( const fc::assert_exception& e ) + { + ss << "ERROR: Failed to convert log data to string!\n"; + } + ss << " " << itr->get_context().to_string(); + ++itr; } catch( std::bad_alloc& ) { throw; } catch( ... ) { ss << "<- exception in to_detail_string."; } - if( itr != my->_elog.end() ) ss<<"\n"; - } + if( itr != my->_elog.end() ) ss<<"\n"; + } } catch( std::bad_alloc& ) { throw; } catch( ... ) { @@ -230,14 +231,14 @@ namespace fc ss << what() << ":"; for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ++itr ) { if( itr->get_format().size() ) - try { - ss << " " << fc::format_string( itr->get_format(), itr->get_data() ); - } catch( std::bad_alloc& ) { - throw; - } catch( ... ) { - ss << "<- exception in to_string.\n"; - } - } + try { + ss << " " << fc::format_string( itr->get_format(), itr->get_data() ); + } catch( std::bad_alloc& ) { + throw; + } catch( ... ) { + ss << "<- exception in to_string.\n"; + } + } return ss.str(); } catch( std::bad_alloc& ) { throw; From 20c16882235de2d5f6a366252fea6a889d417e76 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Wed, 18 Sep 2019 13:07:01 +0200 Subject: [PATCH 089/110] Removed superfluous return --- src/exception.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/exception.cpp b/src/exception.cpp index bd04f8e..01d2615 100644 --- a/src/exception.cpp +++ b/src/exception.cpp @@ -239,7 +239,6 @@ namespace fc ss << "<- exception in to_string.\n"; } } - return ss.str(); } catch( std::bad_alloc& ) { throw; } catch( ... ) { From cd69d13348da2c4d8f4caf8a275b25141bbec2e6 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 16 Sep 2019 21:02:25 +0200 Subject: [PATCH 090/110] Replaced spin_yield_lock with atomics --- include/fc/thread/future.hpp | 19 ++++---- include/fc/thread/task.hpp | 2 + src/thread/future.cpp | 88 ++++++++++++++---------------------- 3 files changed, 46 insertions(+), 63 deletions(-) diff --git a/include/fc/thread/future.hpp b/include/fc/thread/future.hpp index 4e98c3d..c0db411 100644 --- a/include/fc/thread/future.hpp +++ b/include/fc/thread/future.hpp @@ -3,9 +3,9 @@ #include #include #include -#include -#include +#include +#include //#define FC_TASK_NAMES_ARE_MANDATORY 1 #ifdef FC_TASK_NAMES_ARE_MANDATORY @@ -77,23 +77,22 @@ namespace fc { void _wait( const microseconds& timeout_us ); void _wait_until( const time_point& timeout_us ); - void _enqueue_thread(); - void _dequeue_thread(); void _notify(); - void _set_timeout(); void _set_value(const void* v); void _on_complete( detail::completion_handler* c ); private: + void _enqueue_thread(); + void _dequeue_thread(); + friend class thread; friend struct context; friend class thread_d; - bool _ready; - mutable spin_yield_lock _spin_yield; - thread* _blocked_thread; - unsigned _blocked_fiber_count; + std::atomic _ready; + std::atomic _blocked_thread; + std::atomic _blocked_fiber_count; time_point _timeout; fc::exception_ptr _exceptp; bool _canceled; @@ -103,7 +102,7 @@ namespace fc { private: #endif const char* _desc; - detail::completion_handler* _compl; + std::atomic _compl; }; template diff --git a/include/fc/thread/task.hpp b/include/fc/thread/task.hpp index f7c2ec5..92e1b48 100644 --- a/include/fc/thread/task.hpp +++ b/include/fc/thread/task.hpp @@ -4,6 +4,8 @@ #include #include +#include + namespace fc { struct context; class spin_lock; diff --git a/src/thread/future.cpp b/src/thread/future.cpp index c9dbffa..811378c 100644 --- a/src/thread/future.cpp +++ b/src/thread/future.cpp @@ -6,7 +6,6 @@ #include - namespace fc { promise_base::promise_base( const char* desc ) @@ -22,6 +21,8 @@ namespace fc { _compl(nullptr) { } + promise_base::~promise_base() { } + const char* promise_base::get_desc()const{ return _desc; } @@ -34,16 +35,14 @@ namespace fc { #endif } bool promise_base::ready()const { - return _ready; + return _ready.load(); } bool promise_base::error()const { - { synchronized(_spin_yield) - return _exceptp != nullptr; - } + return std::atomic_load( &_exceptp ) != nullptr; } void promise_base::set_exception( const fc::exception_ptr& e ){ - _exceptp = e; + std::atomic_store( &_exceptp, e ); _set_value(nullptr); } @@ -54,16 +53,17 @@ namespace fc { _wait_until( time_point::now() + timeout_us ); } void promise_base::_wait_until( const time_point& timeout_us ){ - { synchronized(_spin_yield) - if( _ready ) { - if( _exceptp ) - _exceptp->dynamic_rethrow_exception(); - return; - } - _enqueue_thread(); + if( _ready.load() ) { + fc::exception_ptr ex = std::atomic_load( &_exceptp ); + if( ex ) + ex->dynamic_rethrow_exception(); + return; } - std::exception_ptr e; + _enqueue_thread(); + // Need to check _ready again to avoid a race condition. + if( _ready.load() ) return _wait_until( timeout_us ); // this will simply return or throw _exceptp + std::exception_ptr e; // // Create shared_ptr to take ownership of this; i.e. this will // be deleted when p_this goes out of scope. Consequently, @@ -71,9 +71,7 @@ namespace fc { // before we're done reading/writing instance variables! // See https://github.com/cryptonomex/graphene/issues/597 // - ptr p_this = shared_from_this(); - try { // @@ -94,61 +92,45 @@ namespace fc { if( e ) std::rethrow_exception(e); - if( _ready ) - { - if( _exceptp ) - _exceptp->dynamic_rethrow_exception(); - return; - } + if( _ready.load() ) return _wait_until( timeout_us ); // this will simply return or throw _exceptp + FC_THROW_EXCEPTION( timeout_exception, "" ); } void promise_base::_enqueue_thread(){ - ++_blocked_fiber_count; + _blocked_fiber_count.fetch_add( 1 ); + thread* blocked_thread = _blocked_thread.load(); // only one thread can wait on a promise at any given time - assert(!_blocked_thread || - _blocked_thread == &thread::current()); - _blocked_thread = &thread::current(); + do + assert( !blocked_thread || blocked_thread == &thread::current() ); + while( !_blocked_thread.compare_exchange_weak( blocked_thread, &thread::current() ) ); } void promise_base::_dequeue_thread(){ - synchronized(_spin_yield) - if (!--_blocked_fiber_count) - _blocked_thread = nullptr; + if( _blocked_fiber_count.fetch_add( -1 ) == 1 ) + _blocked_thread.store( nullptr ); } void promise_base::_notify(){ // copy _blocked_thread into a local so that if the thread unblocks (e.g., // because of a timeout) before we get a chance to notify it, we won't be // calling notify on a null pointer - thread* blocked_thread; - { synchronized(_spin_yield) - blocked_thread = _blocked_thread; - } + thread* blocked_thread = _blocked_thread.load(); if( blocked_thread ) blocked_thread->notify( shared_from_this() ); } - promise_base::~promise_base() { } - void promise_base::_set_timeout(){ - if( _ready ) - return; - set_exception( std::make_shared() ); - } + void promise_base::_set_value(const void* s){ - // slog( "%p == %d", &_ready, int(_ready)); -// BOOST_ASSERT( !_ready ); - { synchronized(_spin_yield) - if (_ready) //don't allow promise to be set more than once + bool ready = false; + if( !_ready.compare_exchange_strong( ready, true ) ) //don't allow promise to be set more than once return; - _ready = true; - } - _notify(); - if( nullptr != _compl ) { - _compl->on_complete(s,_exceptp); - } + _notify(); + auto* hdl = _compl.load(); + if( nullptr != hdl ) + hdl->on_complete( s, std::atomic_load( &_exceptp ) ); } + void promise_base::_on_complete( detail::completion_handler* c ) { - { synchronized(_spin_yield) - delete _compl; - _compl = c; - } + auto* hdl = _compl.load(); + while( !_compl.compare_exchange_weak( hdl, c ) ); + delete hdl; } } From 201b4b33f02dd2930f70635f050600f0b7502243 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 16 Sep 2019 21:02:50 +0200 Subject: [PATCH 091/110] Print stacktrace when yielding within an exception handler --- src/thread/thread_d.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/thread/thread_d.hpp b/src/thread/thread_d.hpp index 77e8fb7..c81ba1c 100644 --- a/src/thread/thread_d.hpp +++ b/src/thread/thread_d.hpp @@ -1,12 +1,14 @@ #include +#include #include #include #include "context.hpp" #include #include #include + +#include #include -//#include namespace fc { struct sleep_priority_less { @@ -390,7 +392,8 @@ namespace fc { /* NB: At least on Win64, this only catches a yield while in the body of * a catch block; it fails to catch a yield while unwinding the stack, which * is probably just as likely to cause crashes */ - assert(std::current_exception() == std::exception_ptr()); + if( std::current_exception() != std::exception_ptr() ) + print_stacktrace( std::cerr ); check_for_timeouts(); if( !current ) From ef52b3903679c2e67fdc09e82c9f4fa33aa26cb3 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Tue, 17 Sep 2019 08:04:23 +0200 Subject: [PATCH 092/110] Preserve crash in debug mode --- src/thread/thread_d.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/thread/thread_d.hpp b/src/thread/thread_d.hpp index c81ba1c..214c2f0 100644 --- a/src/thread/thread_d.hpp +++ b/src/thread/thread_d.hpp @@ -393,7 +393,10 @@ namespace fc { * a catch block; it fails to catch a yield while unwinding the stack, which * is probably just as likely to cause crashes */ if( std::current_exception() != std::exception_ptr() ) + { print_stacktrace( std::cerr ); + assert( std::current_exception() != std::exception_ptr() ); + } check_for_timeouts(); if( !current ) From eb42ebb528770b992b41d9c9ef04ba7e22ff459d Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Tue, 17 Sep 2019 08:04:50 +0200 Subject: [PATCH 093/110] Add log message --- src/thread/thread_d.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/thread/thread_d.hpp b/src/thread/thread_d.hpp index 214c2f0..88c8d45 100644 --- a/src/thread/thread_d.hpp +++ b/src/thread/thread_d.hpp @@ -394,6 +394,7 @@ namespace fc { * is probably just as likely to cause crashes */ if( std::current_exception() != std::exception_ptr() ) { + elog( "Thread ${name} yielded in exception handler!", ("name",thread::current().name()) ); print_stacktrace( std::cerr ); assert( std::current_exception() != std::exception_ptr() ); } From 4ce37756306c84263f8097f6d8881beaa7c9629d Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Tue, 17 Sep 2019 08:06:58 +0200 Subject: [PATCH 094/110] Clean up before returning --- src/thread/future.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/thread/future.cpp b/src/thread/future.cpp index 811378c..b4779dd 100644 --- a/src/thread/future.cpp +++ b/src/thread/future.cpp @@ -61,7 +61,11 @@ namespace fc { } _enqueue_thread(); // Need to check _ready again to avoid a race condition. - if( _ready.load() ) return _wait_until( timeout_us ); // this will simply return or throw _exceptp + if( _ready.load() ) + { + _dequeue_thread(); + return _wait_until( timeout_us ); // this will simply return or throw _exceptp + } std::exception_ptr e; // From 9077892d873868f2e4a7c8493d903ade82911f59 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Tue, 17 Sep 2019 16:11:09 +0200 Subject: [PATCH 095/110] Log stacktrace instead of writing to stderr --- src/thread/thread_d.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/thread/thread_d.hpp b/src/thread/thread_d.hpp index 88c8d45..2f06d00 100644 --- a/src/thread/thread_d.hpp +++ b/src/thread/thread_d.hpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include namespace fc { @@ -394,8 +394,10 @@ namespace fc { * is probably just as likely to cause crashes */ if( std::current_exception() != std::exception_ptr() ) { - elog( "Thread ${name} yielded in exception handler!", ("name",thread::current().name()) ); - print_stacktrace( std::cerr ); + std::stringstream stacktrace; + print_stacktrace( stacktrace ); + elog( "Thread ${name} yielded in exception handler!\n${trace}", + ("name",thread::current().name())("trace",stacktrace.str()) ); assert( std::current_exception() != std::exception_ptr() ); } From 2cc32d79ba9422e1eed93c6ef540ca9db14dd9a9 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Tue, 17 Sep 2019 18:13:12 +0200 Subject: [PATCH 096/110] Fixed assert --- src/thread/thread_d.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/thread/thread_d.hpp b/src/thread/thread_d.hpp index 2f06d00..7209485 100644 --- a/src/thread/thread_d.hpp +++ b/src/thread/thread_d.hpp @@ -398,7 +398,7 @@ namespace fc { print_stacktrace( stacktrace ); elog( "Thread ${name} yielded in exception handler!\n${trace}", ("name",thread::current().name())("trace",stacktrace.str()) ); - assert( std::current_exception() != std::exception_ptr() ); + assert( std::current_exception() == std::exception_ptr() ); } check_for_timeouts(); From 253c1d56b9dd4049e080f5112144a471e04461dc Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Fri, 20 Sep 2019 09:27:44 +0200 Subject: [PATCH 097/110] Added test for zero-initialized arrays --- tests/CMakeLists.txt | 1 + tests/crypto/array_initialization_test.cpp | 67 ++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 tests/crypto/array_initialization_test.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 01cf205..6a3e474 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -26,6 +26,7 @@ target_link_libraries( ecc_test fc ) add_executable( all_tests all_tests.cpp compress/compress.cpp crypto/aes_test.cpp + crypto/array_initialization_test.cpp crypto/base_n_tests.cpp crypto/bigint_test.cpp crypto/blind.cpp diff --git a/tests/crypto/array_initialization_test.cpp b/tests/crypto/array_initialization_test.cpp new file mode 100644 index 0000000..a8d2724 --- /dev/null +++ b/tests/crypto/array_initialization_test.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2019 BitShares Blockchain Foundation, and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include + +#include +#include + +#include + +static void check_null_key() +{ + fc::ecc::public_key_data key1; + fc::ecc::public_key_data key2; + unsigned char zeroes[33]; + static_assert( key1.size() == sizeof(zeroes), "Wrong array size!" ); + memset( zeroes, 0, sizeof(zeroes) ); + BOOST_CHECK( !memcmp( key1.data(), zeroes, sizeof(zeroes) ) ); + BOOST_CHECK( !memcmp( key2.data(), zeroes, sizeof(zeroes) ) ); + + // now "pollute" the keys for the next invocation + key1 = fc::ecc::private_key::generate().get_public_key(); + for( unsigned char c = 0; c < key2.size(); c++ ) + { + key2[c] = c ^ 17; + zeroes[c] = c ^ 47; + } + + // ...and use them to prevent the compiler from optimizing the pollution away. + wlog( "Key1: ${k}", ("k",fc::ecc::public_key::to_base58(key1)) ); + wlog( "Key2: ${k}", ("k",fc::ecc::public_key::to_base58(key2)) ); +} + +BOOST_AUTO_TEST_SUITE(fc_crypto) + +BOOST_AUTO_TEST_CASE(array_init_test) +{ + check_null_key(); + check_null_key(); + { + char junk[128]; + fc::rand_bytes( junk, sizeof(junk) ); + } + check_null_key(); +} + +BOOST_AUTO_TEST_SUITE_END() From afc0e0070001ca230778c7eea6b0085fd4979645 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Thu, 19 Sep 2019 16:08:19 +0200 Subject: [PATCH 098/110] Added zero_initialized_array template to restore functionality of fc::array --- include/fc/container/zeroed_array.hpp | 72 +++++++++++++++++++++++++++ include/fc/crypto/elliptic.hpp | 19 +++---- src/crypto/elliptic_common.cpp | 2 +- src/crypto/elliptic_secp256k1.cpp | 2 +- 4 files changed, 84 insertions(+), 11 deletions(-) create mode 100644 include/fc/container/zeroed_array.hpp diff --git a/include/fc/container/zeroed_array.hpp b/include/fc/container/zeroed_array.hpp new file mode 100644 index 0000000..a51abec --- /dev/null +++ b/include/fc/container/zeroed_array.hpp @@ -0,0 +1,72 @@ +#pragma once +/* + * Copyright (c) 2019 BitShares Blockchain Foundation, and contributors + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include + +namespace fc { + + template< typename T, size_t N > + class zero_initialized_array; + + template< size_t N > + class zero_initialized_array< unsigned char, N > : public std::array< unsigned char, N > { + public: + zero_initialized_array() : std::array< unsigned char, N >() { } + }; + + template + struct get_typename< zero_initialized_array > + { + static const char* name() + { + static std::string _name = std::string("zero_initialized_array<") + + std::string(fc::get_typename::name()) + + "," + fc::to_string(N) + ">"; + return _name.c_str(); + } + }; + + class variant; + template + void to_variant( const zero_initialized_array& bi, variant& v, uint32_t max_depth = 1 ) + { + to_variant( static_cast&>( bi ), v, max_depth ); + } + template + void from_variant( const variant& v, zero_initialized_array& bi, uint32_t max_depth = 1 ) + { + from_variant( v, static_cast&>( bi ), max_depth ); + } + + namespace raw { + template + inline void pack( Stream& s, const zero_initialized_array& v, uint32_t _max_depth ) { + pack( s, static_cast&>( v ), _max_depth ); + } + template + inline void unpack( Stream& s, zero_initialized_array& v, uint32_t _max_depth ) { try { + unpack( s, static_cast&>( v ), _max_depth ); + } FC_RETHROW_EXCEPTIONS( warn, "zero_initialized_array", ("length",N) ) } + } +} diff --git a/include/fc/crypto/elliptic.hpp b/include/fc/crypto/elliptic.hpp index 3784299..e47dee6 100644 --- a/include/fc/crypto/elliptic.hpp +++ b/include/fc/crypto/elliptic.hpp @@ -1,4 +1,5 @@ #pragma once +#include #include #include #include @@ -17,15 +18,15 @@ namespace fc { class private_key_impl; } - typedef fc::sha256 blind_factor_type; - typedef std::array commitment_type; - typedef std::array public_key_data; - typedef fc::sha256 private_key_secret; - typedef std::array public_key_point_data; ///< the full non-compressed version of the ECC point - typedef std::array signature; - typedef std::array compact_signature; - typedef std::vector range_proof_type; - typedef std::array extended_key_data; + typedef fc::sha256 blind_factor_type; + typedef zero_initialized_array commitment_type; + typedef zero_initialized_array public_key_data; + typedef fc::sha256 private_key_secret; + typedef zero_initialized_array public_key_point_data; ///< the full non-compressed version of the ECC point + typedef zero_initialized_array signature; + typedef zero_initialized_array compact_signature; + typedef std::vector range_proof_type; + typedef zero_initialized_array extended_key_data; /** * @class public_key diff --git a/src/crypto/elliptic_common.cpp b/src/crypto/elliptic_common.cpp index dd89c3a..2ed84a8 100644 --- a/src/crypto/elliptic_common.cpp +++ b/src/crypto/elliptic_common.cpp @@ -19,7 +19,7 @@ namespace fc { namespace ecc { namespace detail { - typedef std::array chr37; + typedef zero_initialized_array chr37; fc::sha256 _left( const fc::sha512& v ) { diff --git a/src/crypto/elliptic_secp256k1.cpp b/src/crypto/elliptic_secp256k1.cpp index b180d44..477077e 100644 --- a/src/crypto/elliptic_secp256k1.cpp +++ b/src/crypto/elliptic_secp256k1.cpp @@ -53,7 +53,7 @@ namespace fc { namespace ecc { public_key_data _key; }; - typedef std::array chr37; + typedef zero_initialized_array chr37; chr37 _derive_message( const public_key_data& key, int i ); fc::sha256 _left( const fc::sha512& v ); fc::sha256 _right( const fc::sha512& v ); From ed479c8c3eb4907958e908cf11f997d839e4e02f Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Fri, 20 Sep 2019 08:42:39 +0200 Subject: [PATCH 099/110] Reformatting --- include/fc/container/zeroed_array.hpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/include/fc/container/zeroed_array.hpp b/include/fc/container/zeroed_array.hpp index a51abec..0f91a0f 100644 --- a/include/fc/container/zeroed_array.hpp +++ b/include/fc/container/zeroed_array.hpp @@ -1,4 +1,3 @@ -#pragma once /* * Copyright (c) 2019 BitShares Blockchain Foundation, and contributors * @@ -22,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#pragma once #include namespace fc { @@ -65,8 +65,10 @@ namespace fc { pack( s, static_cast&>( v ), _max_depth ); } template - inline void unpack( Stream& s, zero_initialized_array& v, uint32_t _max_depth ) { try { - unpack( s, static_cast&>( v ), _max_depth ); - } FC_RETHROW_EXCEPTIONS( warn, "zero_initialized_array", ("length",N) ) } + inline void unpack( Stream& s, zero_initialized_array& v, uint32_t _max_depth ) { + try { + unpack( s, static_cast&>( v ), _max_depth ); + } FC_RETHROW_EXCEPTIONS( warn, "zero_initialized_array", ("length",N) ) + } } } From ec77b4943c2cfb9fca052f56d610454b7ad2bcd4 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sun, 22 Sep 2019 10:03:29 +0200 Subject: [PATCH 100/110] Added std::tuple_size for master compatibility --- include/fc/container/zeroed_array.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/fc/container/zeroed_array.hpp b/include/fc/container/zeroed_array.hpp index 0f91a0f..df1d530 100644 --- a/include/fc/container/zeroed_array.hpp +++ b/include/fc/container/zeroed_array.hpp @@ -72,3 +72,9 @@ namespace fc { } } } + +namespace std { + template<> + template< typename T, size_t N > + class tuple_size< fc::zero_initialized_array< T, N > > : public tuple_size< array< T, N > > {}; +} From 4bdab0bb0a474483984ea7d5b98feeaefef7a5bc Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Tue, 24 Sep 2019 17:24:38 +0200 Subject: [PATCH 101/110] Removed checks for obsolete boost version numbers --- src/thread/context.hpp | 58 +++-------------------------------------- src/thread/thread_d.hpp | 12 ++------- 2 files changed, 5 insertions(+), 65 deletions(-) diff --git a/src/thread/context.hpp b/src/thread/context.hpp index 51450cc..0c85103 100644 --- a/src/thread/context.hpp +++ b/src/thread/context.hpp @@ -19,11 +19,11 @@ namespace bc = boost::context::detail; namespace bco = boost::coroutines; typedef bco::stack_allocator stack_allocator; -#elif BOOST_VERSION >= 105400 +#else # include namespace bc = boost::context; namespace bco = boost::coroutines; -# if BOOST_VERSION >= 105600 && !defined(NDEBUG) +# if !defined(NDEBUG) # include # include typedef bco::protected_stack_allocator stack_allocator; @@ -32,16 +32,7 @@ typedef bco::stack_allocator stack_allocator; # endif -#elif BOOST_VERSION >= 105300 - #include - namespace bc = boost::context; - namespace bco = boost::coroutines; -#elif BOOST_VERSION >= 105200 - namespace bc = boost::context; -#else - namespace bc = boost::ctx; - namespace bco = boost::coroutine; -#endif +#endif // BOOST_VERSION >= 106100 namespace fc { class thread; @@ -55,10 +46,7 @@ namespace fc { */ struct context { typedef fc::context* ptr; - -#if BOOST_VERSION >= 105400 bco::stack_context stack_ctx; -#endif #if BOOST_VERSION >= 106100 using context_fn = void (*)(bc::transfer_t); @@ -81,32 +69,13 @@ namespace fc { cur_task(0), context_posted_num(0) { -#if BOOST_VERSION >= 105600 size_t stack_size = FC_CONTEXT_STACK_SIZE; alloc.allocate(stack_ctx, stack_size); my_context = bc::make_fcontext( stack_ctx.sp, stack_ctx.size, sf); -#elif BOOST_VERSION >= 105400 - size_t stack_size = FC_CONTEXT_STACK_SIZE; - alloc.allocate(stack_ctx, stack_size); - my_context = bc::make_fcontext( stack_ctx.sp, stack_ctx.size, sf); -#elif BOOST_VERSION >= 105300 - size_t stack_size = FC_CONTEXT_STACK_SIZE; - void* stackptr = alloc.allocate(stack_size); - my_context = bc::make_fcontext( stackptr, stack_size, sf); -#else - size_t stack_size = FC_CONTEXT_STACK_SIZE; - my_context.fc_stack.base = alloc.allocate( stack_size ); - my_context.fc_stack.limit = static_cast( my_context.fc_stack.base) - stack_size; - make_fcontext( &my_context, sf ); -#endif } context( fc::thread* t) : -#if BOOST_VERSION >= 105600 my_context(nullptr), -#elif BOOST_VERSION >= 105300 - my_context(new bc::fcontext_t), -#endif caller_context(0), stack_alloc(0), next_blocked(0), @@ -123,23 +92,8 @@ namespace fc { {} ~context() { -#if BOOST_VERSION >= 105600 if(stack_alloc) stack_alloc->deallocate( stack_ctx ); -#elif BOOST_VERSION >= 105400 - if(stack_alloc) - stack_alloc->deallocate( stack_ctx ); - else - delete my_context; -#elif BOOST_VERSION >= 105300 - if(stack_alloc) - stack_alloc->deallocate( my_context->fc_stack.sp, FC_CONTEXT_STACK_SIZE); - else - delete my_context; -#else - if(stack_alloc) - stack_alloc->deallocate( my_context.fc_stack.base, FC_CONTEXT_STACK_SIZE ); -#endif } void reinitialize() @@ -225,13 +179,7 @@ namespace fc { bool is_complete()const { return complete; } - - -#if BOOST_VERSION >= 105300 && BOOST_VERSION < 105600 - bc::fcontext_t* my_context; -#else bc::fcontext_t my_context; -#endif fc::context* caller_context; stack_allocator* stack_alloc; priority prio; diff --git a/src/thread/thread_d.hpp b/src/thread/thread_d.hpp index 7209485..a28aa30 100644 --- a/src/thread/thread_d.hpp +++ b/src/thread/thread_d.hpp @@ -433,12 +433,8 @@ namespace fc { auto p = context_pair{nullptr, prev}; auto t = bc::jump_fcontext( next->my_context, &p ); static_cast(t.data)->second->my_context = t.fctx; -#elif BOOST_VERSION >= 105600 - bc::jump_fcontext( &prev->my_context, next->my_context, 0 ); -#elif BOOST_VERSION >= 105300 - bc::jump_fcontext( prev->my_context, next->my_context, 0 ); #else - bc::jump_fcontext( &prev->my_context, &next->my_context, 0 ); + bc::jump_fcontext( &prev->my_context, next->my_context, 0 ); #endif BOOST_ASSERT( current ); BOOST_ASSERT( current == prev ); @@ -479,12 +475,8 @@ namespace fc { auto p = context_pair{this, prev}; auto t = bc::jump_fcontext( next->my_context, &p ); static_cast(t.data)->second->my_context = t.fctx; -#elif BOOST_VERSION >= 105600 - bc::jump_fcontext( &prev->my_context, next->my_context, (intptr_t)this ); -#elif BOOST_VERSION >= 105300 - bc::jump_fcontext( prev->my_context, next->my_context, (intptr_t)this ); #else - bc::jump_fcontext( &prev->my_context, &next->my_context, (intptr_t)this ); + bc::jump_fcontext( &prev->my_context, next->my_context, (intptr_t)this ); #endif BOOST_ASSERT( current ); BOOST_ASSERT( current == prev ); From 6e22341d9f44665b81248bd0fcc2d50394c6a59a Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Fri, 1 Nov 2019 15:14:46 -0500 Subject: [PATCH 102/110] Fix warning in zeroed_array.hpp Only one template declaration is needed here, I think. Clang gives many, many warnings over it. --- include/fc/container/zeroed_array.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/fc/container/zeroed_array.hpp b/include/fc/container/zeroed_array.hpp index df1d530..14bd116 100644 --- a/include/fc/container/zeroed_array.hpp +++ b/include/fc/container/zeroed_array.hpp @@ -74,7 +74,6 @@ namespace fc { } namespace std { - template<> template< typename T, size_t N > class tuple_size< fc::zero_initialized_array< T, N > > : public tuple_size< array< T, N > > {}; } From 56d9e4d968930554b7e1c55044678d2862398ea6 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Tue, 26 Nov 2019 08:26:16 +0100 Subject: [PATCH 103/110] Fix for OSX build --- include/fc/reflect/typename.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/fc/reflect/typename.hpp b/include/fc/reflect/typename.hpp index 15b8523..23a116b 100644 --- a/include/fc/reflect/typename.hpp +++ b/include/fc/reflect/typename.hpp @@ -18,6 +18,9 @@ namespace fc { namespace ip { class address; } template struct get_typename; +#if defined(__APPLE__) or defined(__OpenBSD__) + template<> struct get_typename { static const char* name() { return "size_t"; } }; +#endif template<> struct get_typename { static const char* name() { return "int32_t"; } }; template<> struct get_typename { static const char* name() { return "int64_t"; } }; template<> struct get_typename { static const char* name() { return "int16_t"; } }; From 3b7e67a3dcb8693b017e866eeb36a40008a66713 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Tue, 10 Dec 2019 15:41:08 +0100 Subject: [PATCH 104/110] Fixed busy-wait in delete_files --- src/log/file_appender.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/log/file_appender.cpp b/src/log/file_appender.cpp index aec6bec..46b804b 100644 --- a/src/log/file_appender.cpp +++ b/src/log/file_appender.cpp @@ -133,7 +133,9 @@ namespace fc { { } } - _deletion_task = schedule( [this]() { delete_files(); }, start_time + _interval_seconds, + uint64_t next_file = time_point::now().sec_since_epoch() / _interval_seconds + 1; + _deletion_task = schedule( [this]() { delete_files(); }, + fc::time_point_sec( next_file * _interval_seconds), "delete_files(3)" ); } }; From 142b7eb4c6dc4fb1e00cd88183c5ea654ae5849e Mon Sep 17 00:00:00 2001 From: Abit Date: Fri, 21 Feb 2020 12:52:25 +0100 Subject: [PATCH 105/110] Return a user-friendly msg on RPC execution error --- src/rpc/websocket_api.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rpc/websocket_api.cpp b/src/rpc/websocket_api.cpp index da97a9e..10fe081 100644 --- a/src/rpc/websocket_api.cpp +++ b/src/rpc/websocket_api.cpp @@ -221,7 +221,8 @@ response websocket_api_connection::on_request( const variant& var ) catch ( const fc::exception& e ) { if( has_id ) - return response( call.id, error_object{ e.code(), "Execution error", variant( e, _max_conversion_depth ) }, + return response( call.id, error_object{ e.code(), "Execution error: " + e.to_string(), + variant( e, _max_conversion_depth ) }, call.jsonrpc ); } catch ( const std::exception& e ) From 9763d1c1945b1c246d947cae69094e91e5b14e9c Mon Sep 17 00:00:00 2001 From: abitmore Date: Thu, 26 Mar 2020 16:27:59 +0000 Subject: [PATCH 106/110] Update bool serialization Make the logic clearer, to avoid issues on some compilers. Thanks to @pureland and team. --- include/fc/io/raw.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index 6b0371b..ffd1ad5 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -307,7 +307,7 @@ namespace fc { 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 ); + fc::raw::pack( s, v ? uint8_t(1) : uint8_t(0), _max_depth - 1 ); } template inline void unpack( Stream& s, bool& v, uint32_t _max_depth ) { From cc1103fe454b4aedc161d08869381cc77e397615 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 28 Mar 2020 16:05:03 +0000 Subject: [PATCH 107/110] Fix potential infinity loop Fix exception::to_detail_string(...) --- src/exception.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/exception.cpp b/src/exception.cpp index 01d2615..aff58c9 100644 --- a/src/exception.cpp +++ b/src/exception.cpp @@ -205,12 +205,12 @@ namespace fc ss << "ERROR: Failed to convert log data to string!\n"; } ss << " " << itr->get_context().to_string(); - ++itr; } catch( std::bad_alloc& ) { throw; } catch( ... ) { ss << "<- exception in to_detail_string."; } + ++itr; if( itr != my->_elog.end() ) ss<<"\n"; } } catch( std::bad_alloc& ) { From 34ddc2b859a7f40367d9928c09d1fedbaa95f13c Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 28 Mar 2020 17:12:43 +0000 Subject: [PATCH 108/110] Update to_variant(size_t) for macOS and OpenBSD Fix to_variant(size_t) for OpenBSD, move implementation for macOS to cpp file --- include/fc/variant.hpp | 4 +--- src/variant.cpp | 5 ++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/include/fc/variant.hpp b/include/fc/variant.hpp index 79d0a04..f0c8f25 100644 --- a/include/fc/variant.hpp +++ b/include/fc/variant.hpp @@ -581,9 +581,7 @@ namespace fc memset( this, 0, sizeof(*this) ); to_variant( val, *this, max_depth ); } - #ifdef __APPLE__ - inline void to_variant( size_t s, variant& v, uint32_t max_depth ) { v = variant(uint64_t(s)); } - #endif + template void to_variant( const std::shared_ptr& var, variant& vo, uint32_t max_depth ) { diff --git a/src/variant.cpp b/src/variant.cpp index eaa12d3..a4d09b1 100644 --- a/src/variant.cpp +++ b/src/variant.cpp @@ -701,9 +701,8 @@ void from_variant( const variant& var, uint128_t& vo, uint32_t max_depth ) #endif } -#if defined(__APPLE__) -#elif defined(__OpenBSD__) - void to_variant( size_t s, variant& v, uint32_t max_depth ) { v = variant( int64_t(s) ); } +#if defined(__APPLE__) or defined(__OpenBSD__) + void to_variant( size_t s, variant& v, uint32_t max_depth ) { v = variant( uint64_t(s) ); } #elif !defined(_WIN32) void to_variant( long long int s, variant& v, uint32_t max_depth ) { v = variant( int64_t(s) ); } void to_variant( unsigned long long int s, variant& v, uint32_t max_depth ) { v = variant( uint64_t(s)); } From 98a16ce397a97a5ff0f950fb2cca29fabb2371f8 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sun, 29 Mar 2020 20:40:16 +0000 Subject: [PATCH 109/110] Replace int with 64-bit types in static_variant --- include/fc/static_variant.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/fc/static_variant.hpp b/include/fc/static_variant.hpp index 88069d0..768231a 100644 --- a/include/fc/static_variant.hpp +++ b/include/fc/static_variant.hpp @@ -118,7 +118,7 @@ public: template> struct tag { - static constexpr int value = typelist::index_of(); + static constexpr tag_type value = typelist::index_of(); }; struct type_lt { @@ -302,7 +302,7 @@ public: }); } - static constexpr int count() { return typelist::length(); } + static constexpr size_t count() { return typelist::length(); } void set_which( tag_type w ) { FC_ASSERT( w >= 0 ); FC_ASSERT( w < count() ); From ca3e76d226a8d51369d503bb195e72ec42d314a7 Mon Sep 17 00:00:00 2001 From: abitmore Date: Mon, 6 Apr 2020 15:16:12 +0000 Subject: [PATCH 110/110] Fix compiler warnings about static_variant --- include/fc/static_variant.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/fc/static_variant.hpp b/include/fc/static_variant.hpp index 768231a..452b090 100644 --- a/include/fc/static_variant.hpp +++ b/include/fc/static_variant.hpp @@ -75,7 +75,7 @@ protected: void init_from_tag(tag_type tag) { FC_ASSERT( tag >= 0 ); - FC_ASSERT( tag < count() ); + FC_ASSERT( static_cast(tag) < count() ); _tag = tag; typelist::runtime::dispatch(list(), tag, [this](auto t) { using T = typename decltype(t)::type; @@ -269,7 +269,7 @@ public: template static typename visitor::result_type visit( tag_type tag, visitor& v, void* data ) { - FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); + FC_ASSERT( tag >= 0 && static_cast(tag) < count(), "Unsupported type ${tag}!", ("tag",tag) ); return typelist::runtime::dispatch(list(), tag, [&v, data](auto t) { return v(*reinterpret_cast(data)); }); @@ -278,7 +278,7 @@ public: template static typename visitor::result_type visit( tag_type tag, const visitor& v, void* data ) { - FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); + FC_ASSERT( tag >= 0 && static_cast(tag) < count(), "Unsupported type ${tag}!", ("tag",tag) ); return typelist::runtime::dispatch(list(), tag, [&v, data](auto t) { return v(*reinterpret_cast(data)); }); @@ -287,7 +287,7 @@ public: template static typename visitor::result_type visit( tag_type tag, visitor& v, const void* data ) { - FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); + FC_ASSERT( tag >= 0 && static_cast(tag) < count(), "Unsupported type ${tag}!", ("tag",tag) ); return typelist::runtime::dispatch(list(), tag, [&v, data](auto t) { return v(*reinterpret_cast(data)); }); @@ -296,18 +296,18 @@ public: template static typename visitor::result_type visit( tag_type tag, const visitor& v, const void* data ) { - FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); + FC_ASSERT( tag >= 0 && static_cast(tag) < count(), "Unsupported type ${tag}!", ("tag",tag) ); return typelist::runtime::dispatch(list(), tag, [&v, data](auto t) { return v(*reinterpret_cast(data)); }); } static constexpr size_t count() { return typelist::length(); } - void set_which( tag_type w ) { - FC_ASSERT( w >= 0 ); - FC_ASSERT( w < count() ); + void set_which( tag_type tag ) { + FC_ASSERT( tag >= 0 ); + FC_ASSERT( static_cast(tag) < count() ); clean(); - init_from_tag(w); + init_from_tag(tag); } tag_type which() const {return _tag;}