#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 #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