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