| 1 | #ifndef BOOST_SYSTEM_DETAIL_ERROR_CATEGORY_HPP_INCLUDED |
| 2 | #define BOOST_SYSTEM_DETAIL_ERROR_CATEGORY_HPP_INCLUDED |
| 3 | |
| 4 | // Copyright Beman Dawes 2006, 2007 |
| 5 | // Copyright Christoper Kohlhoff 2007 |
| 6 | // Copyright Peter Dimov 2017, 2018 |
| 7 | // |
| 8 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
| 9 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| 10 | // |
| 11 | // See library home page at http://www.boost.org/libs/system |
| 12 | |
| 13 | #include <boost/system/detail/config.hpp> |
| 14 | #include <boost/cstdint.hpp> |
| 15 | #include <boost/config.hpp> |
| 16 | #include <boost/config/workaround.hpp> |
| 17 | #include <string> |
| 18 | #include <functional> |
| 19 | #include <cstddef> |
| 20 | #include <system_error> |
| 21 | #include <atomic> |
| 22 | |
| 23 | namespace boost |
| 24 | { |
| 25 | |
| 26 | namespace system |
| 27 | { |
| 28 | |
| 29 | class error_category; |
| 30 | class error_code; |
| 31 | class error_condition; |
| 32 | |
| 33 | std::size_t hash_value( error_code const & ec ); |
| 34 | |
| 35 | namespace detail |
| 36 | { |
| 37 | |
| 38 | BOOST_SYSTEM_CONSTEXPR bool failed_impl( int ev, error_category const & cat ); |
| 39 | |
| 40 | class std_category; |
| 41 | |
| 42 | } // namespace detail |
| 43 | |
| 44 | #if ( defined( BOOST_GCC ) && BOOST_GCC >= 40600 ) || defined( BOOST_CLANG ) |
| 45 | #pragma GCC diagnostic push |
| 46 | #pragma GCC diagnostic ignored "-Wnon-virtual-dtor" |
| 47 | #endif |
| 48 | |
| 49 | #if defined(BOOST_MSVC) && BOOST_MSVC < 1900 |
| 50 | #pragma warning(push) |
| 51 | #pragma warning(disable: 4351) // new behavior: elements of array will be default initialized |
| 52 | #endif |
| 53 | |
| 54 | class BOOST_SYMBOL_VISIBLE error_category |
| 55 | { |
| 56 | private: |
| 57 | |
| 58 | friend std::size_t hash_value( error_code const & ec ); |
| 59 | friend BOOST_SYSTEM_CONSTEXPR bool detail::failed_impl( int ev, error_category const & cat ); |
| 60 | |
| 61 | friend class error_code; |
| 62 | friend class error_condition; |
| 63 | |
| 64 | public: |
| 65 | |
| 66 | error_category( error_category const & ) = delete; |
| 67 | error_category& operator=( error_category const & ) = delete; |
| 68 | |
| 69 | private: |
| 70 | |
| 71 | boost::ulong_long_type id_; |
| 72 | |
| 73 | static std::size_t const stdcat_size_ = 4 * sizeof( void const* ); |
| 74 | |
| 75 | union |
| 76 | { |
| 77 | mutable unsigned char stdcat_[ stdcat_size_ ]; |
| 78 | void const* stdcat_align_; |
| 79 | }; |
| 80 | |
| 81 | mutable std::atomic< unsigned > sc_init_; |
| 82 | |
| 83 | protected: |
| 84 | |
| 85 | ~error_category() = default; |
| 86 | |
| 87 | constexpr error_category() noexcept: id_( 0 ), stdcat_(), sc_init_() |
| 88 | { |
| 89 | } |
| 90 | |
| 91 | explicit constexpr error_category( boost::ulong_long_type id ) noexcept: id_( id ), stdcat_(), sc_init_() |
| 92 | { |
| 93 | } |
| 94 | |
| 95 | public: |
| 96 | |
| 97 | virtual const char * name() const noexcept = 0; |
| 98 | |
| 99 | virtual error_condition default_error_condition( int ev ) const noexcept; |
| 100 | virtual bool equivalent( int code, const error_condition & condition ) const noexcept; |
| 101 | virtual bool equivalent( const error_code & code, int condition ) const noexcept; |
| 102 | |
| 103 | virtual std::string message( int ev ) const = 0; |
| 104 | virtual char const * message( int ev, char * buffer, std::size_t len ) const noexcept; |
| 105 | |
| 106 | virtual bool failed( int ev ) const noexcept |
| 107 | { |
| 108 | return ev != 0; |
| 109 | } |
| 110 | |
| 111 | friend BOOST_SYSTEM_CONSTEXPR bool operator==( error_category const & lhs, error_category const & rhs ) noexcept |
| 112 | { |
| 113 | return rhs.id_ == 0? &lhs == &rhs: lhs.id_ == rhs.id_; |
| 114 | } |
| 115 | |
| 116 | friend BOOST_SYSTEM_CONSTEXPR bool operator!=( error_category const & lhs, error_category const & rhs ) noexcept |
| 117 | { |
| 118 | return !( lhs == rhs ); |
| 119 | } |
| 120 | |
| 121 | friend BOOST_SYSTEM_CONSTEXPR bool operator<( error_category const & lhs, error_category const & rhs ) noexcept |
| 122 | { |
| 123 | if( lhs.id_ < rhs.id_ ) |
| 124 | { |
| 125 | return true; |
| 126 | } |
| 127 | |
| 128 | if( lhs.id_ > rhs.id_ ) |
| 129 | { |
| 130 | return false; |
| 131 | } |
| 132 | |
| 133 | if( rhs.id_ != 0 ) |
| 134 | { |
| 135 | return false; // equal |
| 136 | } |
| 137 | |
| 138 | return std::less<error_category const *>()( &lhs, &rhs ); |
| 139 | } |
| 140 | |
| 141 | void init_stdcat() const; |
| 142 | |
| 143 | # if defined(__SUNPRO_CC) // trailing __global is not supported |
| 144 | operator std::error_category const & () const; |
| 145 | # else |
| 146 | operator std::error_category const & () const BOOST_SYMBOL_VISIBLE; |
| 147 | # endif |
| 148 | }; |
| 149 | |
| 150 | #if defined(BOOST_MSVC) && BOOST_MSVC < 1900 |
| 151 | #pragma warning(pop) |
| 152 | #endif |
| 153 | |
| 154 | #if ( defined( BOOST_GCC ) && BOOST_GCC >= 40600 ) || defined( BOOST_CLANG ) |
| 155 | #pragma GCC diagnostic pop |
| 156 | #endif |
| 157 | |
| 158 | namespace detail |
| 159 | { |
| 160 | |
| 161 | static const boost::ulong_long_type generic_category_id = ( boost::ulong_long_type( 0xB2AB117A ) << 32 ) + 0x257EDFD0; |
| 162 | static const boost::ulong_long_type system_category_id = generic_category_id + 1; |
| 163 | static const boost::ulong_long_type interop_category_id = generic_category_id + 2; |
| 164 | |
| 165 | BOOST_SYSTEM_CONSTEXPR inline bool failed_impl( int ev, error_category const & cat ) |
| 166 | { |
| 167 | if( cat.id_ == system_category_id || cat.id_ == generic_category_id ) |
| 168 | { |
| 169 | return ev != 0; |
| 170 | } |
| 171 | else |
| 172 | { |
| 173 | return cat.failed( ev ); |
| 174 | } |
| 175 | } |
| 176 | |
| 177 | } // namespace detail |
| 178 | |
| 179 | } // namespace system |
| 180 | |
| 181 | } // namespace boost |
| 182 | |
| 183 | #endif // #ifndef BOOST_SYSTEM_DETAIL_ERROR_CATEGORY_HPP_INCLUDED |
| 184 | |