From abc94afdb2da951e3d3f43af8e007891c24c3601 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 27 Aug 2020 02:23:50 +0300 Subject: [PATCH] Extract error_code into its own header --- include/boost/system/detail/error_code.hpp | 214 +++++++++++++++++++++ include/boost/system/error_code.hpp | 183 +----------------- 2 files changed, 215 insertions(+), 182 deletions(-) create mode 100644 include/boost/system/detail/error_code.hpp diff --git a/include/boost/system/detail/error_code.hpp b/include/boost/system/detail/error_code.hpp new file mode 100644 index 0000000..832a97c --- /dev/null +++ b/include/boost/system/detail/error_code.hpp @@ -0,0 +1,214 @@ +#ifndef BOOST_SYSTEM_DETAIL_ERROR_CODE_HPP_INCLUDED +#define BOOST_SYSTEM_DETAIL_ERROR_CODE_HPP_INCLUDED + +// Copyright Beman Dawes 2006, 2007 +// Copyright Christoper Kohlhoff 2007 +// Copyright Peter Dimov 2017, 2018 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See library home page at http://www.boost.org/libs/system + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + +namespace system +{ + +// class error_code + +// We want error_code to be a value type that can be copied without slicing +// and without requiring heap allocation, but we also want it to have +// polymorphic behavior based on the error category. This is achieved by +// abstract base class error_category supplying the polymorphic behavior, +// and error_code containing a pointer to an object of a type derived +// from error_category. + +class error_code +{ +private: + + int val_; + bool failed_; + const error_category * cat_; + +public: + + // constructors: + + BOOST_SYSTEM_CONSTEXPR error_code() BOOST_NOEXCEPT: + val_( 0 ), failed_( false ), cat_( &system_category() ) + { + } + + BOOST_SYSTEM_CONSTEXPR error_code( int val, const error_category & cat ) BOOST_NOEXCEPT: + val_( val ), failed_( detail::failed_impl( val, cat ) ), cat_( &cat ) + { + } + + template BOOST_SYSTEM_CONSTEXPR error_code( ErrorCodeEnum e, + typename detail::enable_if::value>::type* = 0 ) BOOST_NOEXCEPT + { + *this = make_error_code( e ); + } + + // modifiers: + + BOOST_SYSTEM_CONSTEXPR void assign( int val, const error_category & cat ) BOOST_NOEXCEPT + { + val_ = val; + failed_ = detail::failed_impl( val, cat ); + cat_ = &cat; + } + + template + BOOST_SYSTEM_CONSTEXPR typename detail::enable_if::value, error_code>::type & + operator=( ErrorCodeEnum val ) BOOST_NOEXCEPT + { + *this = make_error_code( val ); + return *this; + } + + BOOST_SYSTEM_CONSTEXPR void clear() BOOST_NOEXCEPT + { + val_ = 0; + failed_ = false; + cat_ = &system_category(); + } + + // observers: + + BOOST_SYSTEM_CONSTEXPR int value() const BOOST_NOEXCEPT + { + return val_; + } + + BOOST_SYSTEM_CONSTEXPR const error_category & category() const BOOST_NOEXCEPT + { + return *cat_; + } + + error_condition default_error_condition() const BOOST_NOEXCEPT + { + return cat_->default_error_condition( value() ); + } + + std::string message() const + { + return cat_->message( value() ); + } + + char const * message( char * buffer, std::size_t len ) const BOOST_NOEXCEPT + { + return cat_->message( value(), buffer, len ); + } + + BOOST_SYSTEM_CONSTEXPR bool failed() const BOOST_NOEXCEPT + { + return failed_; + } + +#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + + BOOST_SYSTEM_CONSTEXPR explicit operator bool() const BOOST_NOEXCEPT // true if error + { + return failed_; + } + +#else + + typedef void (*unspecified_bool_type)(); + static void unspecified_bool_true() {} + + BOOST_SYSTEM_CONSTEXPR operator unspecified_bool_type() const BOOST_NOEXCEPT // true if error + { + return failed_? unspecified_bool_true: 0; + } + + BOOST_SYSTEM_CONSTEXPR bool operator!() const BOOST_NOEXCEPT // true if no error + { + return !failed_; + } + +#endif + + // relationals: + + // the more symmetrical non-member syntax allows enum + // conversions work for both rhs and lhs. + + BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( const error_code & lhs, const error_code & rhs ) BOOST_NOEXCEPT + { + return lhs.val_ == rhs.val_ && *lhs.cat_ == *rhs.cat_; + } + + BOOST_SYSTEM_CONSTEXPR inline friend bool operator<( const error_code & lhs, const error_code & rhs ) BOOST_NOEXCEPT + { + return *lhs.cat_ < *rhs.cat_ || ( *lhs.cat_ == *rhs.cat_ && lhs.val_ < rhs.val_ ); + } + +#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR) + + operator std::error_code () const + { + return std::error_code( value(), category() ); + } + +#endif +}; + +BOOST_SYSTEM_CONSTEXPR inline bool operator!=( const error_code & lhs, const error_code & rhs ) BOOST_NOEXCEPT +{ + return !( lhs == rhs ); +} + +template + inline std::basic_ostream& + operator<< (std::basic_ostream& os, error_code const & ec) +{ + os << ec.category().name() << ':' << ec.value(); + return os; +} + +inline std::size_t hash_value( error_code const & ec ) +{ + error_category const & cat = ec.category(); + + boost::ulong_long_type id_ = cat.id_; + + if( id_ == 0 ) + { + id_ = reinterpret_cast( &cat ); + } + + boost::ulong_long_type hv = ( boost::ulong_long_type( 0xCBF29CE4 ) << 32 ) + 0x84222325; + boost::ulong_long_type const prime = ( boost::ulong_long_type( 0x00000100 ) << 32 ) + 0x000001B3; + + // id + + hv ^= id_; + hv *= prime; + + // value + + hv ^= static_cast( ec.value() ); + hv *= prime; + + return static_cast( hv ); +} + +} // namespace system + +} // namespace boost + +#endif // #ifndef BOOST_SYSTEM_DETAIL_ERROR_CODE_HPP_INCLUDED diff --git a/include/boost/system/error_code.hpp b/include/boost/system/error_code.hpp index ad4b3cd..9944a6f 100644 --- a/include/boost/system/error_code.hpp +++ b/include/boost/system/error_code.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -45,148 +46,6 @@ class error_code; // values defined by the operating system class error_condition; // portable generic values defined below, but ultimately // based on the POSIX standard -// class error_code - -// We want error_code to be a value type that can be copied without slicing -// and without requiring heap allocation, but we also want it to have -// polymorphic behavior based on the error category. This is achieved by -// abstract base class error_category supplying the polymorphic behavior, -// and error_code containing a pointer to an object of a type derived -// from error_category. - -class error_code -{ -private: - - int val_; - bool failed_; - const error_category * cat_; - -public: - - // constructors: - - BOOST_SYSTEM_CONSTEXPR error_code() BOOST_NOEXCEPT: - val_( 0 ), failed_( false ), cat_( &system_category() ) - { - } - - BOOST_SYSTEM_CONSTEXPR error_code( int val, const error_category & cat ) BOOST_NOEXCEPT: - val_( val ), failed_( detail::failed_impl( val, cat ) ), cat_( &cat ) - { - } - - template BOOST_SYSTEM_CONSTEXPR error_code( ErrorCodeEnum e, - typename detail::enable_if::value>::type* = 0 ) BOOST_NOEXCEPT - { - *this = make_error_code( e ); - } - - // modifiers: - - BOOST_SYSTEM_CONSTEXPR void assign( int val, const error_category & cat ) BOOST_NOEXCEPT - { - val_ = val; - failed_ = detail::failed_impl( val, cat ); - cat_ = &cat; - } - - template - BOOST_SYSTEM_CONSTEXPR typename detail::enable_if::value, error_code>::type & - operator=( ErrorCodeEnum val ) BOOST_NOEXCEPT - { - *this = make_error_code( val ); - return *this; - } - - BOOST_SYSTEM_CONSTEXPR void clear() BOOST_NOEXCEPT - { - val_ = 0; - failed_ = false; - cat_ = &system_category(); - } - - // observers: - - BOOST_SYSTEM_CONSTEXPR int value() const BOOST_NOEXCEPT - { - return val_; - } - - BOOST_SYSTEM_CONSTEXPR const error_category & category() const BOOST_NOEXCEPT - { - return *cat_; - } - - error_condition default_error_condition() const BOOST_NOEXCEPT - { - return cat_->default_error_condition( value() ); - } - - std::string message() const - { - return cat_->message( value() ); - } - - char const * message( char * buffer, std::size_t len ) const BOOST_NOEXCEPT - { - return cat_->message( value(), buffer, len ); - } - - BOOST_SYSTEM_CONSTEXPR bool failed() const BOOST_NOEXCEPT - { - return failed_; - } - -#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) - - BOOST_SYSTEM_CONSTEXPR explicit operator bool() const BOOST_NOEXCEPT // true if error - { - return failed_; - } - -#else - - typedef void (*unspecified_bool_type)(); - static void unspecified_bool_true() {} - - BOOST_SYSTEM_CONSTEXPR operator unspecified_bool_type() const BOOST_NOEXCEPT // true if error - { - return failed_? unspecified_bool_true: 0; - } - - BOOST_SYSTEM_CONSTEXPR bool operator!() const BOOST_NOEXCEPT // true if no error - { - return !failed_; - } - -#endif - - // relationals: - - // the more symmetrical non-member syntax allows enum - // conversions work for both rhs and lhs. - - BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( const error_code & lhs, const error_code & rhs ) BOOST_NOEXCEPT - { - return lhs.val_ == rhs.val_ && *lhs.cat_ == *rhs.cat_; - } - - BOOST_SYSTEM_CONSTEXPR inline friend bool operator<( const error_code & lhs, const error_code & rhs ) BOOST_NOEXCEPT - { - return *lhs.cat_ < *rhs.cat_ || ( *lhs.cat_ == *rhs.cat_ && lhs.val_ < rhs.val_ ); - } - -#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR) - - operator std::error_code () const - { - return std::error_code( value(), category() ); - } - -#endif -}; - } // namespace system // boost::throws() @@ -228,11 +87,6 @@ inline system::error_code& throws() namespace system { -BOOST_SYSTEM_CONSTEXPR inline bool operator!=( const error_code & lhs, const error_code & rhs ) BOOST_NOEXCEPT -{ - return !( lhs == rhs ); -} - BOOST_SYSTEM_CONSTEXPR inline bool operator!=( const error_condition & lhs, const error_condition & rhs ) BOOST_NOEXCEPT { return !( lhs == rhs ); @@ -258,41 +112,6 @@ inline bool operator!=( const error_condition & lhs, const error_code & rhs ) BO return !( lhs == rhs ); } -template - inline std::basic_ostream& - operator<< (std::basic_ostream& os, error_code ec) -{ - os << ec.category().name() << ':' << ec.value(); - return os; -} - -inline std::size_t hash_value( error_code const & ec ) -{ - error_category const & cat = ec.category(); - - boost::ulong_long_type id_ = cat.id_; - - if( id_ == 0 ) - { - id_ = reinterpret_cast( &cat ); - } - - boost::ulong_long_type hv = ( boost::ulong_long_type( 0xCBF29CE4 ) << 32 ) + 0x84222325; - boost::ulong_long_type const prime = ( boost::ulong_long_type( 0x00000100 ) << 32 ) + 0x000001B3; - - // id - - hv ^= id_; - hv *= prime; - - // value - - hv ^= static_cast( ec.value() ); - hv *= prime; - - return static_cast( hv ); -} - // make_* functions for errc::errc_t namespace errc