1 | #ifndef BOOST_SYSTEM_DETAIL_ERROR_CONDITION_HPP_INCLUDED |
2 | #define BOOST_SYSTEM_DETAIL_ERROR_CONDITION_HPP_INCLUDED |
3 | |
4 | // Copyright Beman Dawes 2006, 2007 |
5 | // Copyright Christoper Kohlhoff 2007 |
6 | // Copyright Peter Dimov 2017-2021 |
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/error_category.hpp> |
14 | #include <boost/system/detail/generic_category.hpp> |
15 | #include <boost/system/detail/enable_if.hpp> |
16 | #include <boost/system/detail/is_same.hpp> |
17 | #include <boost/system/detail/errc.hpp> |
18 | #include <boost/system/detail/append_int.hpp> |
19 | #include <boost/system/is_error_condition_enum.hpp> |
20 | #include <boost/system/detail/config.hpp> |
21 | #include <boost/config.hpp> |
22 | |
23 | namespace boost |
24 | { |
25 | |
26 | namespace system |
27 | { |
28 | |
29 | // class error_condition |
30 | |
31 | // error_conditions are portable, error_codes are system or library specific |
32 | |
33 | namespace detail |
34 | { |
35 | |
36 | struct generic_value_tag |
37 | { |
38 | int value; |
39 | BOOST_SYSTEM_CONSTEXPR explicit generic_value_tag( int v ): value( v ) {} |
40 | }; |
41 | |
42 | } // namespace detail |
43 | |
44 | class error_condition |
45 | { |
46 | private: |
47 | |
48 | int val_; |
49 | error_category const * cat_; |
50 | |
51 | private: |
52 | |
53 | boost::ulong_long_type cat_id() const noexcept |
54 | { |
55 | return cat_? cat_->id_: detail::generic_category_id; |
56 | } |
57 | |
58 | public: |
59 | |
60 | // constructors: |
61 | |
62 | BOOST_SYSTEM_CONSTEXPR error_condition() noexcept: |
63 | val_( 0 ), cat_( 0 ) |
64 | { |
65 | } |
66 | |
67 | BOOST_SYSTEM_CONSTEXPR error_condition( int val, const error_category & cat ) noexcept: |
68 | val_( val ), cat_( &cat ) |
69 | { |
70 | } |
71 | |
72 | BOOST_SYSTEM_CONSTEXPR explicit error_condition( boost::system::detail::generic_value_tag vt ) noexcept: |
73 | val_( vt.value ), cat_( 0 ) |
74 | { |
75 | } |
76 | |
77 | template<class ErrorConditionEnum> BOOST_SYSTEM_CONSTEXPR error_condition( ErrorConditionEnum e, |
78 | typename detail::enable_if< |
79 | is_error_condition_enum<ErrorConditionEnum>::value && !boost::system::detail::is_same<ErrorConditionEnum, errc::errc_t>::value |
80 | >::type* = 0) noexcept |
81 | { |
82 | *this = make_error_condition( e ); |
83 | } |
84 | |
85 | template<class ErrorConditionEnum> BOOST_SYSTEM_CONSTEXPR error_condition( ErrorConditionEnum e, |
86 | typename detail::enable_if<boost::system::detail::is_same<ErrorConditionEnum, errc::errc_t>::value>::type* = 0) noexcept: |
87 | val_( e ), cat_( 0 ) |
88 | { |
89 | } |
90 | |
91 | // modifiers: |
92 | |
93 | BOOST_SYSTEM_CONSTEXPR void assign( int val, const error_category & cat ) noexcept |
94 | { |
95 | val_ = val; |
96 | cat_ = &cat; |
97 | } |
98 | |
99 | template<typename ErrorConditionEnum> |
100 | BOOST_SYSTEM_CONSTEXPR typename detail::enable_if<is_error_condition_enum<ErrorConditionEnum>::value, error_condition>::type & |
101 | operator=( ErrorConditionEnum val ) noexcept |
102 | { |
103 | *this = error_condition( val ); |
104 | return *this; |
105 | } |
106 | |
107 | BOOST_SYSTEM_CONSTEXPR void clear() noexcept |
108 | { |
109 | val_ = 0; |
110 | cat_ = 0; |
111 | } |
112 | |
113 | // observers: |
114 | |
115 | BOOST_SYSTEM_CONSTEXPR int value() const noexcept |
116 | { |
117 | return val_; |
118 | } |
119 | |
120 | BOOST_SYSTEM_CONSTEXPR const error_category & category() const noexcept |
121 | { |
122 | return cat_? *cat_: generic_category(); |
123 | } |
124 | |
125 | std::string message() const |
126 | { |
127 | if( cat_ ) |
128 | { |
129 | return cat_->message( ev: value() ); |
130 | } |
131 | else |
132 | { |
133 | return detail::generic_error_category_message( ev: value() ); |
134 | } |
135 | } |
136 | |
137 | char const * message( char * buffer, std::size_t len ) const noexcept |
138 | { |
139 | if( cat_ ) |
140 | { |
141 | return cat_->message( ev: value(), buffer, len ); |
142 | } |
143 | else |
144 | { |
145 | return detail::generic_error_category_message( ev: value(), buffer, len ); |
146 | } |
147 | } |
148 | |
149 | BOOST_SYSTEM_CONSTEXPR bool failed() const noexcept |
150 | { |
151 | if( cat_ ) |
152 | { |
153 | return detail::failed_impl( ev: val_, cat: *cat_ ); |
154 | } |
155 | else |
156 | { |
157 | return val_ != 0; |
158 | } |
159 | } |
160 | |
161 | BOOST_SYSTEM_CONSTEXPR explicit operator bool() const noexcept // true if error |
162 | { |
163 | return failed(); |
164 | } |
165 | |
166 | // relationals: |
167 | // the more symmetrical non-member syntax allows enum |
168 | // conversions work for both rhs and lhs. |
169 | |
170 | BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( const error_condition & lhs, const error_condition & rhs ) noexcept |
171 | { |
172 | if( lhs.val_ != rhs.val_ ) |
173 | { |
174 | return false; |
175 | } |
176 | else if( lhs.cat_ == 0 ) |
177 | { |
178 | return rhs.cat_id() == detail::generic_category_id; |
179 | } |
180 | else if( rhs.cat_ == 0 ) |
181 | { |
182 | return lhs.cat_id() == detail::generic_category_id; |
183 | } |
184 | else |
185 | { |
186 | return *lhs.cat_ == *rhs.cat_; |
187 | } |
188 | } |
189 | |
190 | BOOST_SYSTEM_CONSTEXPR inline friend bool operator<( const error_condition & lhs, const error_condition & rhs ) noexcept |
191 | { |
192 | error_category const& lcat = lhs.category(); |
193 | error_category const& rcat = rhs.category(); |
194 | return lcat < rcat || ( lcat == rcat && lhs.val_ < rhs.val_ ); |
195 | } |
196 | |
197 | BOOST_SYSTEM_CONSTEXPR inline friend bool operator!=( const error_condition & lhs, const error_condition & rhs ) noexcept |
198 | { |
199 | return !( lhs == rhs ); |
200 | } |
201 | |
202 | operator std::error_condition () const |
203 | { |
204 | // This condition must be the same as the one in error_category_impl.hpp |
205 | #if defined(BOOST_SYSTEM_AVOID_STD_GENERIC_CATEGORY) |
206 | |
207 | return std::error_condition( value(), category() ); |
208 | |
209 | #else |
210 | |
211 | if( cat_ ) |
212 | { |
213 | return std::error_condition( val_, *cat_ ); |
214 | } |
215 | else |
216 | { |
217 | return std::error_condition( val_, std::generic_category() ); |
218 | } |
219 | |
220 | #endif |
221 | } |
222 | |
223 | inline friend bool operator==( std::error_code const & lhs, error_condition const & rhs ) noexcept |
224 | { |
225 | return lhs == static_cast< std::error_condition >( rhs ); |
226 | } |
227 | |
228 | inline friend bool operator==( error_condition const & lhs, std::error_code const & rhs ) noexcept |
229 | { |
230 | return static_cast< std::error_condition >( lhs ) == rhs; |
231 | } |
232 | |
233 | inline friend bool operator!=( std::error_code const & lhs, error_condition const & rhs ) noexcept |
234 | { |
235 | return !( lhs == rhs ); |
236 | } |
237 | |
238 | inline friend bool operator!=( error_condition const & lhs, std::error_code const & rhs ) noexcept |
239 | { |
240 | return !( lhs == rhs ); |
241 | } |
242 | |
243 | // |
244 | |
245 | template<class E, class N = typename detail::enable_if<std::is_error_condition_enum<E>::value>::type> |
246 | BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( error_condition const & lhs, E rhs ) noexcept |
247 | { |
248 | return lhs == make_error_condition( rhs ); |
249 | } |
250 | |
251 | template<class E, class N = typename detail::enable_if<std::is_error_condition_enum<E>::value>::type> |
252 | BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( E lhs, error_condition const & rhs ) noexcept |
253 | { |
254 | return make_error_condition( lhs ) == rhs; |
255 | } |
256 | |
257 | template<class E, class N = typename detail::enable_if<std::is_error_condition_enum<E>::value>::type> |
258 | BOOST_SYSTEM_CONSTEXPR inline friend bool operator!=( error_condition const & lhs, E rhs ) noexcept |
259 | { |
260 | return !( lhs == rhs ); |
261 | } |
262 | |
263 | template<class E, class N = typename detail::enable_if<std::is_error_condition_enum<E>::value>::type> |
264 | BOOST_SYSTEM_CONSTEXPR inline friend bool operator!=( E lhs, error_condition const & rhs ) noexcept |
265 | { |
266 | return !( lhs == rhs ); |
267 | } |
268 | |
269 | // |
270 | |
271 | template<class E, class N1 = void, class N2 = typename detail::enable_if<std::is_error_code_enum<E>::value>::type> |
272 | inline friend bool operator==( error_condition const & lhs, E rhs ) noexcept |
273 | { |
274 | return lhs == make_error_code( rhs ); |
275 | } |
276 | |
277 | template<class E, class N1 = void, class N2 = typename detail::enable_if<std::is_error_code_enum<E>::value>::type> |
278 | inline friend bool operator==( E lhs, error_condition const & rhs ) noexcept |
279 | { |
280 | return make_error_code( lhs ) == rhs; |
281 | } |
282 | |
283 | template<class E, class N1 = void, class N2 = typename detail::enable_if<std::is_error_code_enum<E>::value>::type> |
284 | inline friend bool operator!=( error_condition const & lhs, E rhs ) noexcept |
285 | { |
286 | return !( lhs == rhs ); |
287 | } |
288 | |
289 | template<class E, class N1 = void, class N2 = typename detail::enable_if<std::is_error_code_enum<E>::value>::type> |
290 | inline friend bool operator!=( E lhs, error_condition const & rhs ) noexcept |
291 | { |
292 | return !( lhs == rhs ); |
293 | } |
294 | |
295 | std::string to_string() const |
296 | { |
297 | std::string r( "cond:" ); |
298 | |
299 | if( cat_ ) |
300 | { |
301 | r += cat_->name(); |
302 | } |
303 | else |
304 | { |
305 | r += "generic" ; |
306 | } |
307 | |
308 | detail::append_int( s&: r, v: value() ); |
309 | |
310 | return r; |
311 | } |
312 | |
313 | template<class Ch, class Tr> |
314 | inline friend std::basic_ostream<Ch, Tr>& |
315 | operator<< (std::basic_ostream<Ch, Tr>& os, error_condition const & en) |
316 | { |
317 | os << en.to_string(); |
318 | return os; |
319 | } |
320 | }; |
321 | |
322 | } // namespace system |
323 | |
324 | } // namespace boost |
325 | |
326 | #endif // #ifndef BOOST_SYSTEM_DETAIL_ERROR_CONDITION_HPP_INCLUDED |
327 | |