]>
Commit | Line | Data |
---|---|---|
92f5a8d4 TL |
1 | #ifndef BOOST_SYSTEM_ERROR_CODE_HPP_INCLUDED |
2 | #define BOOST_SYSTEM_ERROR_CODE_HPP_INCLUDED | |
7c673cae FG |
3 | |
4 | // Copyright Beman Dawes 2006, 2007 | |
5 | // Copyright Christoper Kohlhoff 2007 | |
11fdf7f2 | 6 | // Copyright Peter Dimov 2017, 2018 |
92f5a8d4 | 7 | // |
7c673cae FG |
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) | |
92f5a8d4 | 10 | // |
7c673cae FG |
11 | // See library home page at http://www.boost.org/libs/system |
12 | ||
92f5a8d4 TL |
13 | #include <boost/system/api_config.hpp> |
14 | #include <boost/system/detail/config.hpp> | |
7c673cae | 15 | #include <boost/cstdint.hpp> |
92f5a8d4 | 16 | #include <boost/config.hpp> |
7c673cae FG |
17 | #include <ostream> |
18 | #include <string> | |
7c673cae | 19 | #include <functional> |
92f5a8d4 | 20 | #include <cstring> |
7c673cae FG |
21 | |
22 | // TODO: undef these macros if not already defined | |
23 | #include <boost/cerrno.hpp> | |
24 | ||
92f5a8d4 TL |
25 | #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR) |
26 | # include <system_error> | |
27 | #endif | |
28 | ||
7c673cae FG |
29 | #if !defined(BOOST_POSIX_API) && !defined(BOOST_WINDOWS_API) |
30 | # error BOOST_POSIX_API or BOOST_WINDOWS_API must be defined | |
31 | #endif | |
32 | ||
92f5a8d4 TL |
33 | namespace boost |
34 | { | |
35 | ||
36 | namespace system | |
37 | { | |
38 | ||
39 | class error_code; // values defined by the operating system | |
40 | class error_condition; // portable generic values defined below, but ultimately | |
41 | // based on the POSIX standard | |
42 | ||
43 | // "Concept" helpers | |
44 | ||
45 | template<class T> struct is_error_code_enum | |
46 | { | |
47 | static const bool value = false; | |
48 | }; | |
49 | ||
50 | template<class T> struct is_error_condition_enum | |
51 | { | |
52 | static const bool value = false; | |
53 | }; | |
54 | ||
55 | // Generic error_conditions | |
56 | ||
57 | namespace errc | |
58 | { | |
59 | ||
60 | enum errc_t | |
61 | { | |
62 | success = 0, | |
63 | address_family_not_supported = EAFNOSUPPORT, | |
64 | address_in_use = EADDRINUSE, | |
65 | address_not_available = EADDRNOTAVAIL, | |
66 | already_connected = EISCONN, | |
67 | argument_list_too_long = E2BIG, | |
68 | argument_out_of_domain = EDOM, | |
69 | bad_address = EFAULT, | |
70 | bad_file_descriptor = EBADF, | |
71 | bad_message = EBADMSG, | |
72 | broken_pipe = EPIPE, | |
73 | connection_aborted = ECONNABORTED, | |
74 | connection_already_in_progress = EALREADY, | |
75 | connection_refused = ECONNREFUSED, | |
76 | connection_reset = ECONNRESET, | |
77 | cross_device_link = EXDEV, | |
78 | destination_address_required = EDESTADDRREQ, | |
79 | device_or_resource_busy = EBUSY, | |
80 | directory_not_empty = ENOTEMPTY, | |
81 | executable_format_error = ENOEXEC, | |
82 | file_exists = EEXIST, | |
83 | file_too_large = EFBIG, | |
84 | filename_too_long = ENAMETOOLONG, | |
85 | function_not_supported = ENOSYS, | |
86 | host_unreachable = EHOSTUNREACH, | |
87 | identifier_removed = EIDRM, | |
88 | illegal_byte_sequence = EILSEQ, | |
89 | inappropriate_io_control_operation = ENOTTY, | |
90 | interrupted = EINTR, | |
91 | invalid_argument = EINVAL, | |
92 | invalid_seek = ESPIPE, | |
93 | io_error = EIO, | |
94 | is_a_directory = EISDIR, | |
95 | message_size = EMSGSIZE, | |
96 | network_down = ENETDOWN, | |
97 | network_reset = ENETRESET, | |
98 | network_unreachable = ENETUNREACH, | |
99 | no_buffer_space = ENOBUFS, | |
100 | no_child_process = ECHILD, | |
101 | no_link = ENOLINK, | |
102 | no_lock_available = ENOLCK, | |
103 | no_message_available = ENODATA, | |
104 | no_message = ENOMSG, | |
105 | no_protocol_option = ENOPROTOOPT, | |
106 | no_space_on_device = ENOSPC, | |
107 | no_stream_resources = ENOSR, | |
108 | no_such_device_or_address = ENXIO, | |
109 | no_such_device = ENODEV, | |
110 | no_such_file_or_directory = ENOENT, | |
111 | no_such_process = ESRCH, | |
112 | not_a_directory = ENOTDIR, | |
113 | not_a_socket = ENOTSOCK, | |
114 | not_a_stream = ENOSTR, | |
115 | not_connected = ENOTCONN, | |
116 | not_enough_memory = ENOMEM, | |
117 | not_supported = ENOTSUP, | |
118 | operation_canceled = ECANCELED, | |
119 | operation_in_progress = EINPROGRESS, | |
120 | operation_not_permitted = EPERM, | |
121 | operation_not_supported = EOPNOTSUPP, | |
122 | operation_would_block = EWOULDBLOCK, | |
123 | owner_dead = EOWNERDEAD, | |
124 | permission_denied = EACCES, | |
125 | protocol_error = EPROTO, | |
126 | protocol_not_supported = EPROTONOSUPPORT, | |
127 | read_only_file_system = EROFS, | |
128 | resource_deadlock_would_occur = EDEADLK, | |
129 | resource_unavailable_try_again = EAGAIN, | |
130 | result_out_of_range = ERANGE, | |
131 | state_not_recoverable = ENOTRECOVERABLE, | |
132 | stream_timeout = ETIME, | |
133 | text_file_busy = ETXTBSY, | |
134 | timed_out = ETIMEDOUT, | |
135 | too_many_files_open_in_system = ENFILE, | |
136 | too_many_files_open = EMFILE, | |
137 | too_many_links = EMLINK, | |
138 | too_many_symbolic_link_levels = ELOOP, | |
139 | value_too_large = EOVERFLOW, | |
140 | wrong_protocol_type = EPROTOTYPE | |
141 | }; | |
142 | ||
143 | } // namespace errc | |
144 | ||
145 | #ifdef BOOST_SYSTEM_ENABLE_DEPRECATED | |
146 | ||
147 | namespace posix = errc; | |
148 | namespace posix_error = errc; | |
149 | ||
b32b8144 FG |
150 | #endif |
151 | ||
92f5a8d4 TL |
152 | template<> struct is_error_condition_enum<errc::errc_t> |
153 | { | |
154 | static const bool value = true; | |
155 | }; | |
7c673cae | 156 | |
92f5a8d4 TL |
157 | // class error_category |
158 | #if ( defined( BOOST_GCC ) && BOOST_GCC >= 40600 ) || defined( BOOST_CLANG ) | |
159 | #pragma GCC diagnostic push | |
160 | #pragma GCC diagnostic ignored "-Wnon-virtual-dtor" | |
7c673cae FG |
161 | #endif |
162 | ||
92f5a8d4 TL |
163 | #ifdef BOOST_MSVC |
164 | #pragma warning( push ) | |
165 | // 'this' : used in base member initializer list | |
166 | #pragma warning( disable: 4355 ) | |
167 | #endif | |
168 | ||
169 | std::size_t hash_value( error_code const & ec ); | |
170 | ||
171 | class BOOST_SYMBOL_VISIBLE error_category | |
7c673cae | 172 | { |
92f5a8d4 | 173 | private: |
7c673cae | 174 | |
92f5a8d4 | 175 | friend std::size_t hash_value( error_code const & ec ); |
7c673cae | 176 | |
92f5a8d4 TL |
177 | #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) |
178 | public: | |
7c673cae | 179 | |
92f5a8d4 TL |
180 | error_category( error_category const & ) = delete; |
181 | error_category& operator=( error_category const & ) = delete; | |
7c673cae | 182 | |
92f5a8d4 TL |
183 | #else |
184 | private: | |
7c673cae | 185 | |
92f5a8d4 TL |
186 | error_category( error_category const & ); |
187 | error_category& operator=( error_category const & ); | |
7c673cae | 188 | |
92f5a8d4 TL |
189 | #endif |
190 | ||
191 | private: | |
7c673cae | 192 | |
92f5a8d4 | 193 | boost::ulong_long_type id_; |
7c673cae | 194 | |
92f5a8d4 | 195 | protected: |
b32b8144 | 196 | |
92f5a8d4 | 197 | #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && !defined(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS) |
b32b8144 | 198 | |
92f5a8d4 | 199 | ~error_category() = default; |
b32b8144 | 200 | |
b32b8144 | 201 | #else |
b32b8144 | 202 | |
92f5a8d4 TL |
203 | // We'd like to make the destructor protected, to make code that deletes |
204 | // an error_category* not compile; unfortunately, doing the below makes | |
205 | // the destructor user-provided and hence breaks use after main, as the | |
206 | // categories may get destroyed before code that uses them | |
207 | ||
208 | // ~error_category() {} | |
b32b8144 | 209 | |
b32b8144 | 210 | #endif |
7c673cae | 211 | |
92f5a8d4 TL |
212 | BOOST_SYSTEM_CONSTEXPR error_category() BOOST_NOEXCEPT: id_( 0 ) |
213 | { | |
214 | } | |
7c673cae | 215 | |
92f5a8d4 | 216 | explicit BOOST_SYSTEM_CONSTEXPR error_category( boost::ulong_long_type id ) BOOST_NOEXCEPT: id_( id ) |
7c673cae | 217 | { |
92f5a8d4 TL |
218 | } |
219 | ||
220 | public: | |
221 | ||
222 | virtual const char * name() const BOOST_NOEXCEPT = 0; | |
b32b8144 | 223 | |
92f5a8d4 TL |
224 | virtual error_condition default_error_condition( int ev ) const BOOST_NOEXCEPT; |
225 | virtual bool equivalent( int code, const error_condition & condition ) const BOOST_NOEXCEPT; | |
226 | virtual bool equivalent( const error_code & code, int condition ) const BOOST_NOEXCEPT; | |
b32b8144 | 227 | |
92f5a8d4 TL |
228 | virtual std::string message( int ev ) const = 0; |
229 | virtual char const * message( int ev, char * buffer, std::size_t len ) const BOOST_NOEXCEPT; | |
b32b8144 | 230 | |
92f5a8d4 | 231 | virtual bool failed( int ev ) const BOOST_NOEXCEPT; |
b32b8144 | 232 | |
92f5a8d4 TL |
233 | BOOST_SYSTEM_CONSTEXPR bool operator==( const error_category & rhs ) const BOOST_NOEXCEPT |
234 | { | |
235 | return rhs.id_ == 0? this == &rhs: id_ == rhs.id_; | |
236 | } | |
237 | ||
238 | BOOST_SYSTEM_CONSTEXPR bool operator!=( const error_category & rhs ) const BOOST_NOEXCEPT | |
239 | { | |
240 | return !( *this == rhs ); | |
241 | } | |
b32b8144 | 242 | |
92f5a8d4 TL |
243 | BOOST_SYSTEM_CONSTEXPR bool operator<( const error_category & rhs ) const BOOST_NOEXCEPT |
244 | { | |
245 | if( id_ < rhs.id_ ) | |
b32b8144 | 246 | { |
92f5a8d4 | 247 | return true; |
b32b8144 FG |
248 | } |
249 | ||
92f5a8d4 | 250 | if( id_ > rhs.id_ ) |
b32b8144 | 251 | { |
92f5a8d4 | 252 | return false; |
b32b8144 FG |
253 | } |
254 | ||
92f5a8d4 | 255 | if( rhs.id_ != 0 ) |
b32b8144 | 256 | { |
92f5a8d4 | 257 | return false; // equal |
b32b8144 FG |
258 | } |
259 | ||
92f5a8d4 TL |
260 | return std::less<error_category const *>()( this, &rhs ); |
261 | } | |
b32b8144 | 262 | |
92f5a8d4 | 263 | #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR) |
b32b8144 | 264 | |
92f5a8d4 | 265 | operator std::error_category const & () const; |
b32b8144 | 266 | |
92f5a8d4 TL |
267 | #endif |
268 | }; | |
b32b8144 | 269 | |
92f5a8d4 TL |
270 | #ifdef BOOST_MSVC |
271 | #pragma warning( pop ) | |
272 | #endif | |
b32b8144 | 273 | |
92f5a8d4 | 274 | // predefined error categories |
b32b8144 | 275 | |
92f5a8d4 TL |
276 | namespace detail |
277 | { | |
b32b8144 | 278 | |
92f5a8d4 TL |
279 | class BOOST_SYMBOL_VISIBLE generic_error_category: public error_category |
280 | { | |
281 | public: | |
b32b8144 | 282 | |
92f5a8d4 TL |
283 | // clang++ 3.8 and below: initialization of const object |
284 | // requires a user-provided default constructor | |
285 | BOOST_SYSTEM_CONSTEXPR generic_error_category() BOOST_NOEXCEPT: | |
286 | error_category( ( boost::ulong_long_type( 0xB2AB117A ) << 32 ) + 0x257EDF0D ) | |
287 | { | |
288 | } | |
b32b8144 | 289 | |
92f5a8d4 TL |
290 | const char * name() const BOOST_NOEXCEPT |
291 | { | |
292 | return "generic"; | |
293 | } | |
b32b8144 | 294 | |
92f5a8d4 TL |
295 | std::string message( int ev ) const; |
296 | char const * message( int ev, char * buffer, std::size_t len ) const BOOST_NOEXCEPT; | |
297 | }; | |
b32b8144 | 298 | |
92f5a8d4 TL |
299 | class BOOST_SYMBOL_VISIBLE system_error_category: public error_category |
300 | { | |
301 | public: | |
b32b8144 | 302 | |
92f5a8d4 TL |
303 | BOOST_SYSTEM_CONSTEXPR system_error_category() BOOST_NOEXCEPT: |
304 | error_category( ( boost::ulong_long_type( 0x8FAFD21E ) << 32 ) + 0x25C5E09B ) | |
305 | { | |
306 | } | |
b32b8144 | 307 | |
92f5a8d4 TL |
308 | const char * name() const BOOST_NOEXCEPT |
309 | { | |
310 | return "system"; | |
311 | } | |
b32b8144 | 312 | |
92f5a8d4 | 313 | error_condition default_error_condition( int ev ) const BOOST_NOEXCEPT; |
b32b8144 | 314 | |
92f5a8d4 TL |
315 | std::string message( int ev ) const; |
316 | char const * message( int ev, char * buffer, std::size_t len ) const BOOST_NOEXCEPT; | |
317 | }; | |
b32b8144 | 318 | |
92f5a8d4 | 319 | } // namespace detail |
b32b8144 | 320 | |
92f5a8d4 TL |
321 | #if ( defined( BOOST_GCC ) && BOOST_GCC >= 40600 ) || defined( BOOST_CLANG ) |
322 | #pragma GCC diagnostic pop | |
323 | #endif | |
b32b8144 | 324 | |
92f5a8d4 | 325 | // generic_category(), system_category() |
b32b8144 | 326 | |
92f5a8d4 | 327 | #if defined(BOOST_SYSTEM_HAS_CONSTEXPR) |
b32b8144 | 328 | |
92f5a8d4 TL |
329 | namespace detail |
330 | { | |
331 | ||
332 | template<class T> struct BOOST_SYMBOL_VISIBLE cat_holder | |
333 | { | |
334 | static constexpr system_error_category system_category_instance{}; | |
335 | static constexpr generic_error_category generic_category_instance{}; | |
336 | }; | |
337 | ||
338 | // Before C++17 it was mandatory to redeclare all static constexpr | |
339 | #if defined(BOOST_NO_CXX17_INLINE_VARIABLES) | |
340 | template<class T> constexpr system_error_category cat_holder<T>::system_category_instance; | |
341 | template<class T> constexpr generic_error_category cat_holder<T>::generic_category_instance; | |
b32b8144 FG |
342 | #endif |
343 | ||
92f5a8d4 | 344 | } // namespace detail |
7c673cae | 345 | |
92f5a8d4 TL |
346 | constexpr error_category const & system_category() BOOST_NOEXCEPT |
347 | { | |
348 | return detail::cat_holder<void>::system_category_instance; | |
349 | } | |
350 | ||
351 | constexpr error_category const & generic_category() BOOST_NOEXCEPT | |
352 | { | |
353 | return detail::cat_holder<void>::generic_category_instance; | |
354 | } | |
7c673cae | 355 | |
92f5a8d4 | 356 | #else // #if defined(BOOST_SYSTEM_HAS_CONSTEXPR) |
7c673cae | 357 | |
92f5a8d4 | 358 | inline error_category const & system_category() BOOST_NOEXCEPT BOOST_SYMBOL_VISIBLE; |
7c673cae | 359 | |
92f5a8d4 TL |
360 | inline error_category const & system_category() BOOST_NOEXCEPT |
361 | { | |
362 | static const detail::system_error_category system_category_instance; | |
363 | return system_category_instance; | |
364 | } | |
7c673cae | 365 | |
92f5a8d4 | 366 | inline error_category const & generic_category() BOOST_NOEXCEPT BOOST_SYMBOL_VISIBLE; |
7c673cae | 367 | |
92f5a8d4 TL |
368 | inline error_category const & generic_category() BOOST_NOEXCEPT |
369 | { | |
370 | static const detail::generic_error_category generic_category_instance; | |
371 | return generic_category_instance; | |
372 | } | |
7c673cae | 373 | |
92f5a8d4 | 374 | #endif // #if defined(BOOST_SYSTEM_HAS_CONSTEXPR) |
7c673cae | 375 | |
92f5a8d4 | 376 | // deprecated synonyms |
7c673cae | 377 | |
92f5a8d4 | 378 | #ifdef BOOST_SYSTEM_ENABLE_DEPRECATED |
7c673cae | 379 | |
92f5a8d4 TL |
380 | inline const error_category & get_system_category() { return system_category(); } |
381 | inline const error_category & get_generic_category() { return generic_category(); } | |
382 | inline const error_category & get_posix_category() { return generic_category(); } | |
383 | static const error_category & posix_category BOOST_ATTRIBUTE_UNUSED = generic_category(); | |
384 | static const error_category & errno_ecat BOOST_ATTRIBUTE_UNUSED = generic_category(); | |
385 | static const error_category & native_ecat BOOST_ATTRIBUTE_UNUSED = system_category(); | |
7c673cae | 386 | |
92f5a8d4 | 387 | #endif |
7c673cae | 388 | |
92f5a8d4 | 389 | // enable_if |
11fdf7f2 | 390 | |
92f5a8d4 TL |
391 | namespace detail |
392 | { | |
11fdf7f2 | 393 | |
92f5a8d4 TL |
394 | template<bool C, class T = void> struct enable_if |
395 | { | |
396 | typedef T type; | |
397 | }; | |
11fdf7f2 | 398 | |
92f5a8d4 TL |
399 | template<class T> struct enable_if<false, T> |
400 | { | |
401 | }; | |
7c673cae | 402 | |
92f5a8d4 | 403 | // failed_impl |
7c673cae | 404 | |
92f5a8d4 | 405 | #if !defined(BOOST_SYSTEM_HAS_CONSTEXPR) |
7c673cae | 406 | |
92f5a8d4 TL |
407 | inline bool failed_impl( int ev, error_category const & cat ) |
408 | { | |
409 | return cat.failed( ev ); | |
410 | } | |
11fdf7f2 | 411 | |
92f5a8d4 TL |
412 | #else |
413 | ||
414 | BOOST_SYSTEM_CONSTEXPR inline bool failed_impl( int ev, error_category const & cat ) | |
415 | { | |
416 | if( cat == system_category() || cat == generic_category() ) | |
417 | { | |
418 | return ev != 0; | |
419 | } | |
420 | else | |
421 | { | |
422 | return cat.failed( ev ); | |
423 | } | |
424 | } | |
b32b8144 FG |
425 | |
426 | #endif | |
427 | ||
92f5a8d4 TL |
428 | } // namespace detail |
429 | ||
430 | // class error_condition | |
431 | ||
432 | // error_conditions are portable, error_codes are system or library specific | |
433 | ||
434 | class error_condition | |
435 | { | |
436 | private: | |
437 | ||
438 | int val_; | |
439 | bool failed_; | |
440 | error_category const * cat_; | |
441 | ||
442 | public: | |
443 | ||
444 | // constructors: | |
445 | ||
446 | BOOST_SYSTEM_CONSTEXPR error_condition() BOOST_NOEXCEPT: | |
447 | val_( 0 ), failed_( false ), cat_( &generic_category() ) | |
448 | { | |
449 | } | |
450 | ||
451 | BOOST_SYSTEM_CONSTEXPR error_condition( int val, const error_category & cat ) BOOST_NOEXCEPT: | |
452 | val_( val ), failed_( detail::failed_impl( val, cat ) ), cat_( &cat ) | |
453 | { | |
454 | } | |
455 | ||
456 | template<class ErrorConditionEnum> BOOST_SYSTEM_CONSTEXPR error_condition( ErrorConditionEnum e, | |
457 | typename detail::enable_if<is_error_condition_enum<ErrorConditionEnum>::value>::type* = 0) BOOST_NOEXCEPT | |
458 | { | |
459 | *this = make_error_condition( e ); | |
460 | } | |
461 | ||
462 | // modifiers: | |
463 | ||
464 | BOOST_SYSTEM_CONSTEXPR void assign( int val, const error_category & cat ) BOOST_NOEXCEPT | |
465 | { | |
466 | val_ = val; | |
467 | failed_ = detail::failed_impl( val, cat ); | |
468 | cat_ = &cat; | |
469 | } | |
470 | ||
471 | template<typename ErrorConditionEnum> | |
472 | BOOST_SYSTEM_CONSTEXPR typename detail::enable_if<is_error_condition_enum<ErrorConditionEnum>::value, error_condition>::type & | |
473 | operator=( ErrorConditionEnum val ) BOOST_NOEXCEPT | |
474 | { | |
475 | *this = make_error_condition( val ); | |
7c673cae | 476 | return *this; |
92f5a8d4 TL |
477 | } |
478 | ||
479 | BOOST_SYSTEM_CONSTEXPR void clear() BOOST_NOEXCEPT | |
480 | { | |
481 | val_ = 0; | |
482 | failed_ = false; | |
483 | cat_ = &generic_category(); | |
484 | } | |
485 | ||
486 | // observers: | |
487 | ||
488 | BOOST_SYSTEM_CONSTEXPR int value() const BOOST_NOEXCEPT | |
489 | { | |
490 | return val_; | |
491 | } | |
492 | ||
493 | BOOST_SYSTEM_CONSTEXPR const error_category & category() const BOOST_NOEXCEPT | |
494 | { | |
495 | return *cat_; | |
496 | } | |
497 | ||
498 | std::string message() const | |
499 | { | |
500 | return cat_->message( value() ); | |
501 | } | |
7c673cae | 502 | |
92f5a8d4 TL |
503 | char const * message( char * buffer, std::size_t len ) const BOOST_NOEXCEPT |
504 | { | |
505 | return cat_->message( value(), buffer, len ); | |
506 | } | |
7c673cae | 507 | |
92f5a8d4 TL |
508 | BOOST_SYSTEM_CONSTEXPR bool failed() const BOOST_NOEXCEPT |
509 | { | |
510 | return failed_; | |
511 | } | |
7c673cae | 512 | |
11fdf7f2 TL |
513 | #if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) |
514 | ||
92f5a8d4 TL |
515 | BOOST_SYSTEM_CONSTEXPR explicit operator bool() const BOOST_NOEXCEPT // true if error |
516 | { | |
517 | return val_ != 0; | |
518 | } | |
11fdf7f2 TL |
519 | |
520 | #else | |
521 | ||
92f5a8d4 TL |
522 | typedef void (*unspecified_bool_type)(); |
523 | static void unspecified_bool_true() {} | |
7c673cae | 524 | |
92f5a8d4 TL |
525 | BOOST_SYSTEM_CONSTEXPR operator unspecified_bool_type() const BOOST_NOEXCEPT // true if error |
526 | { | |
527 | return val_ != 0? unspecified_bool_true: 0; | |
528 | } | |
7c673cae | 529 | |
92f5a8d4 TL |
530 | BOOST_SYSTEM_CONSTEXPR bool operator!() const BOOST_NOEXCEPT // true if no error |
531 | { | |
532 | return val_ == 0; | |
533 | } | |
7c673cae | 534 | |
11fdf7f2 TL |
535 | #endif |
536 | ||
92f5a8d4 TL |
537 | // relationals: |
538 | // the more symmetrical non-member syntax allows enum | |
539 | // conversions work for both rhs and lhs. | |
540 | ||
541 | BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( const error_condition & lhs, const error_condition & rhs ) BOOST_NOEXCEPT | |
542 | { | |
543 | return lhs.val_ == rhs.val_ && *lhs.cat_ == *rhs.cat_; | |
544 | } | |
545 | ||
546 | BOOST_SYSTEM_CONSTEXPR inline friend bool operator<( const error_condition & lhs, const error_condition & rhs ) BOOST_NOEXCEPT | |
547 | { | |
548 | return *lhs.cat_ < *rhs.cat_ || ( *lhs.cat_ == *rhs.cat_ && lhs.val_ < rhs.val_ ); | |
549 | } | |
550 | ||
551 | #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR) | |
552 | ||
553 | operator std::error_condition () const | |
554 | { | |
555 | return std::error_condition( value(), category() ); | |
556 | } | |
b32b8144 FG |
557 | |
558 | #endif | |
92f5a8d4 | 559 | }; |
b32b8144 | 560 | |
92f5a8d4 | 561 | // class error_code |
7c673cae | 562 | |
92f5a8d4 TL |
563 | // We want error_code to be a value type that can be copied without slicing |
564 | // and without requiring heap allocation, but we also want it to have | |
565 | // polymorphic behavior based on the error category. This is achieved by | |
566 | // abstract base class error_category supplying the polymorphic behavior, | |
567 | // and error_code containing a pointer to an object of a type derived | |
568 | // from error_category. | |
7c673cae | 569 | |
92f5a8d4 TL |
570 | class error_code |
571 | { | |
572 | private: | |
573 | ||
574 | int val_; | |
575 | bool failed_; | |
576 | const error_category * cat_; | |
7c673cae | 577 | |
92f5a8d4 | 578 | public: |
7c673cae | 579 | |
92f5a8d4 TL |
580 | // constructors: |
581 | ||
582 | BOOST_SYSTEM_CONSTEXPR error_code() BOOST_NOEXCEPT: | |
583 | val_( 0 ), failed_( false ), cat_( &system_category() ) | |
b32b8144 | 584 | { |
b32b8144 | 585 | } |
7c673cae | 586 | |
92f5a8d4 TL |
587 | BOOST_SYSTEM_CONSTEXPR error_code( int val, const error_category & cat ) BOOST_NOEXCEPT: |
588 | val_( val ), failed_( detail::failed_impl( val, cat ) ), cat_( &cat ) | |
589 | { | |
590 | } | |
7c673cae | 591 | |
92f5a8d4 TL |
592 | template<class ErrorCodeEnum> BOOST_SYSTEM_CONSTEXPR error_code( ErrorCodeEnum e, |
593 | typename detail::enable_if<is_error_code_enum<ErrorCodeEnum>::value>::type* = 0 ) BOOST_NOEXCEPT | |
594 | { | |
595 | *this = make_error_code( e ); | |
596 | } | |
597 | ||
598 | // modifiers: | |
599 | ||
600 | BOOST_SYSTEM_CONSTEXPR void assign( int val, const error_category & cat ) BOOST_NOEXCEPT | |
601 | { | |
602 | val_ = val; | |
603 | failed_ = detail::failed_impl( val, cat ); | |
604 | cat_ = &cat; | |
605 | } | |
7c673cae | 606 | |
92f5a8d4 TL |
607 | template<typename ErrorCodeEnum> |
608 | BOOST_SYSTEM_CONSTEXPR typename detail::enable_if<is_error_code_enum<ErrorCodeEnum>::value, error_code>::type & | |
609 | operator=( ErrorCodeEnum val ) BOOST_NOEXCEPT | |
7c673cae | 610 | { |
92f5a8d4 TL |
611 | *this = make_error_code( val ); |
612 | return *this; | |
7c673cae FG |
613 | } |
614 | ||
92f5a8d4 | 615 | BOOST_SYSTEM_CONSTEXPR void clear() BOOST_NOEXCEPT |
7c673cae | 616 | { |
92f5a8d4 TL |
617 | val_ = 0; |
618 | failed_ = false; | |
619 | cat_ = &system_category(); | |
7c673cae FG |
620 | } |
621 | ||
92f5a8d4 TL |
622 | // observers: |
623 | ||
624 | BOOST_SYSTEM_CONSTEXPR int value() const BOOST_NOEXCEPT | |
7c673cae | 625 | { |
92f5a8d4 | 626 | return val_; |
7c673cae FG |
627 | } |
628 | ||
92f5a8d4 | 629 | BOOST_SYSTEM_CONSTEXPR const error_category & category() const BOOST_NOEXCEPT |
7c673cae | 630 | { |
92f5a8d4 | 631 | return *cat_; |
7c673cae FG |
632 | } |
633 | ||
92f5a8d4 | 634 | error_condition default_error_condition() const BOOST_NOEXCEPT |
7c673cae | 635 | { |
92f5a8d4 | 636 | return cat_->default_error_condition( value() ); |
7c673cae FG |
637 | } |
638 | ||
92f5a8d4 | 639 | std::string message() const |
7c673cae | 640 | { |
92f5a8d4 | 641 | return cat_->message( value() ); |
7c673cae FG |
642 | } |
643 | ||
92f5a8d4 TL |
644 | char const * message( char * buffer, std::size_t len ) const BOOST_NOEXCEPT |
645 | { | |
646 | return cat_->message( value(), buffer, len ); | |
647 | } | |
7c673cae | 648 | |
92f5a8d4 | 649 | BOOST_SYSTEM_CONSTEXPR bool failed() const BOOST_NOEXCEPT |
7c673cae | 650 | { |
92f5a8d4 | 651 | return failed_; |
7c673cae FG |
652 | } |
653 | ||
92f5a8d4 TL |
654 | #if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) |
655 | ||
656 | BOOST_SYSTEM_CONSTEXPR explicit operator bool() const BOOST_NOEXCEPT // true if error | |
7c673cae | 657 | { |
92f5a8d4 | 658 | return val_ != 0; |
7c673cae FG |
659 | } |
660 | ||
92f5a8d4 TL |
661 | #else |
662 | ||
663 | typedef void (*unspecified_bool_type)(); | |
664 | static void unspecified_bool_true() {} | |
7c673cae | 665 | |
92f5a8d4 | 666 | BOOST_SYSTEM_CONSTEXPR operator unspecified_bool_type() const BOOST_NOEXCEPT // true if error |
7c673cae | 667 | { |
92f5a8d4 TL |
668 | return val_ != 0? unspecified_bool_true: 0; |
669 | } | |
7c673cae | 670 | |
92f5a8d4 TL |
671 | BOOST_SYSTEM_CONSTEXPR bool operator!() const BOOST_NOEXCEPT // true if no error |
672 | { | |
673 | return val_ == 0; | |
7c673cae FG |
674 | } |
675 | ||
92f5a8d4 TL |
676 | #endif |
677 | ||
678 | // relationals: | |
679 | ||
680 | // the more symmetrical non-member syntax allows enum | |
681 | // conversions work for both rhs and lhs. | |
7c673cae | 682 | |
92f5a8d4 | 683 | BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( const error_code & lhs, const error_code & rhs ) BOOST_NOEXCEPT |
7c673cae | 684 | { |
92f5a8d4 | 685 | return lhs.val_ == rhs.val_ && *lhs.cat_ == *rhs.cat_; |
7c673cae FG |
686 | } |
687 | ||
92f5a8d4 TL |
688 | BOOST_SYSTEM_CONSTEXPR inline friend bool operator<( const error_code & lhs, const error_code & rhs ) BOOST_NOEXCEPT |
689 | { | |
690 | return *lhs.cat_ < *rhs.cat_ || ( *lhs.cat_ == *rhs.cat_ && lhs.val_ < rhs.val_ ); | |
691 | } | |
692 | ||
693 | #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR) | |
694 | ||
695 | operator std::error_code () const | |
7c673cae | 696 | { |
92f5a8d4 | 697 | return std::error_code( value(), category() ); |
7c673cae FG |
698 | } |
699 | ||
92f5a8d4 TL |
700 | #endif |
701 | }; | |
702 | ||
703 | } // namespace system | |
704 | ||
705 | // boost::throws() | |
706 | ||
707 | namespace detail | |
708 | { | |
709 | ||
710 | // Misuse of the error_code object is turned into a noisy failure by | |
711 | // poisoning the reference. This particular implementation doesn't | |
712 | // produce warnings or errors from popular compilers, is very efficient | |
713 | // (as determined by inspecting generated code), and does not suffer | |
714 | // from order of initialization problems. In practice, it also seems | |
715 | // cause user function error handling implementation errors to be detected | |
716 | // very early in the development cycle. | |
717 | ||
718 | inline system::error_code* throws() | |
719 | { | |
720 | // See github.com/boostorg/system/pull/12 by visigoth for why the return | |
721 | // is poisoned with nonzero rather than (0). A test, test_throws_usage(), | |
722 | // has been added to error_code_test.cpp, and as visigoth mentioned it | |
723 | // fails on clang for release builds with a return of 0 but works fine | |
724 | // with (1). | |
725 | // Since the undefined behavior sanitizer (-fsanitize=undefined) does not | |
726 | // allow a reference to be formed to the unaligned address of (1), we use | |
727 | // (8) instead. | |
728 | ||
729 | return reinterpret_cast<system::error_code*>(8); | |
730 | } | |
731 | ||
732 | } // namespace detail | |
733 | ||
734 | inline system::error_code& throws() | |
735 | { | |
736 | return *detail::throws(); | |
737 | } | |
738 | ||
739 | // non-member functions of error_code and error_condition | |
740 | ||
741 | namespace system | |
742 | { | |
743 | ||
744 | BOOST_SYSTEM_CONSTEXPR inline bool operator!=( const error_code & lhs, const error_code & rhs ) BOOST_NOEXCEPT | |
745 | { | |
746 | return !( lhs == rhs ); | |
747 | } | |
748 | ||
749 | BOOST_SYSTEM_CONSTEXPR inline bool operator!=( const error_condition & lhs, const error_condition & rhs ) BOOST_NOEXCEPT | |
750 | { | |
751 | return !( lhs == rhs ); | |
752 | } | |
753 | ||
754 | inline bool operator==( const error_code & code, const error_condition & condition ) BOOST_NOEXCEPT | |
755 | { | |
756 | return code.category().equivalent( code.value(), condition ) || condition.category().equivalent( code, condition.value() ); | |
757 | } | |
758 | ||
759 | inline bool operator!=( const error_code & lhs, const error_condition & rhs ) BOOST_NOEXCEPT | |
760 | { | |
761 | return !( lhs == rhs ); | |
762 | } | |
763 | ||
764 | inline bool operator==( const error_condition & condition, const error_code & code ) BOOST_NOEXCEPT | |
765 | { | |
766 | return code.category().equivalent( code.value(), condition ) || condition.category().equivalent( code, condition.value() ); | |
767 | } | |
768 | ||
769 | inline bool operator!=( const error_condition & lhs, const error_code & rhs ) BOOST_NOEXCEPT | |
770 | { | |
771 | return !( lhs == rhs ); | |
772 | } | |
773 | ||
774 | template <class charT, class traits> | |
775 | inline std::basic_ostream<charT,traits>& | |
776 | operator<< (std::basic_ostream<charT,traits>& os, error_code ec) | |
777 | { | |
778 | os << ec.category().name() << ':' << ec.value(); | |
779 | return os; | |
780 | } | |
781 | ||
782 | inline std::size_t hash_value( error_code const & ec ) | |
783 | { | |
784 | error_category const & cat = ec.category(); | |
785 | ||
786 | boost::ulong_long_type id = cat.id_; | |
787 | ||
788 | if( id == 0 ) | |
7c673cae | 789 | { |
92f5a8d4 | 790 | id = reinterpret_cast<boost::uintptr_t>( &cat ); |
7c673cae FG |
791 | } |
792 | ||
92f5a8d4 TL |
793 | boost::ulong_long_type hv = ( boost::ulong_long_type( 0xCBF29CE4 ) << 32 ) + 0x84222325; |
794 | boost::ulong_long_type const prime = ( boost::ulong_long_type( 0x00000100 ) << 32 ) + 0x000001B3; | |
795 | ||
796 | // id | |
797 | ||
798 | hv ^= id; | |
799 | hv *= prime; | |
800 | ||
801 | // value | |
802 | ||
803 | hv ^= static_cast<unsigned>( ec.value() ); | |
804 | hv *= prime; | |
805 | ||
806 | return static_cast<std::size_t>( hv ); | |
807 | } | |
808 | ||
809 | // make_* functions for errc::errc_t | |
810 | ||
811 | namespace errc | |
812 | { | |
813 | ||
814 | // explicit conversion: | |
815 | BOOST_SYSTEM_CONSTEXPR inline error_code make_error_code( errc_t e ) BOOST_NOEXCEPT | |
816 | { | |
817 | return error_code( e, generic_category() ); | |
818 | } | |
819 | ||
820 | // implicit conversion: | |
821 | BOOST_SYSTEM_CONSTEXPR inline error_condition make_error_condition( errc_t e ) BOOST_NOEXCEPT | |
822 | { | |
823 | return error_condition( e, generic_category() ); | |
824 | } | |
825 | ||
826 | } // namespace errc | |
827 | ||
828 | // error_category default implementation | |
829 | ||
830 | inline error_condition error_category::default_error_condition( int ev ) const BOOST_NOEXCEPT | |
831 | { | |
832 | return error_condition( ev, *this ); | |
833 | } | |
834 | ||
835 | inline bool error_category::equivalent( int code, const error_condition & condition ) const BOOST_NOEXCEPT | |
836 | { | |
837 | return default_error_condition( code ) == condition; | |
838 | } | |
839 | ||
840 | inline bool error_category::equivalent( const error_code & code, int condition ) const BOOST_NOEXCEPT | |
841 | { | |
842 | return *this == code.category() && code.value() == condition; | |
843 | } | |
b32b8144 | 844 | |
92f5a8d4 TL |
845 | inline char const * error_category::message( int ev, char * buffer, std::size_t len ) const BOOST_NOEXCEPT |
846 | { | |
847 | if( len == 0 ) | |
b32b8144 | 848 | { |
92f5a8d4 | 849 | return buffer; |
b32b8144 FG |
850 | } |
851 | ||
92f5a8d4 | 852 | if( len == 1 ) |
b32b8144 | 853 | { |
92f5a8d4 TL |
854 | buffer[0] = 0; |
855 | return buffer; | |
856 | } | |
b32b8144 | 857 | |
92f5a8d4 TL |
858 | #if !defined(BOOST_NO_EXCEPTIONS) |
859 | try | |
b32b8144 | 860 | #endif |
92f5a8d4 TL |
861 | { |
862 | std::string m = this->message( ev ); | |
863 | ||
864 | # if defined( BOOST_MSVC ) | |
865 | # pragma warning( push ) | |
866 | # pragma warning( disable: 4996 ) | |
867 | # elif defined(__clang__) && defined(__has_warning) | |
868 | # pragma clang diagnostic push | |
869 | # if __has_warning("-Wdeprecated-declarations") | |
870 | # pragma clang diagnostic ignored "-Wdeprecated-declarations" | |
871 | # endif | |
872 | # endif | |
873 | ||
874 | std::strncpy( buffer, m.c_str(), len - 1 ); | |
875 | buffer[ len-1 ] = 0; | |
876 | ||
877 | # if defined( BOOST_MSVC ) | |
878 | # pragma warning( pop ) | |
879 | # elif defined(__clang__) && defined(__has_warning) | |
880 | # pragma clang diagnostic pop | |
881 | # endif | |
b32b8144 | 882 | |
92f5a8d4 TL |
883 | return buffer; |
884 | } | |
885 | #if !defined(BOOST_NO_EXCEPTIONS) | |
886 | catch( ... ) | |
887 | { | |
888 | return "Message text unavailable"; | |
889 | } | |
b32b8144 | 890 | #endif |
92f5a8d4 TL |
891 | } |
892 | ||
893 | inline bool error_category::failed( int ev ) const BOOST_NOEXCEPT | |
894 | { | |
895 | return ev != 0; | |
896 | } | |
897 | ||
898 | } // namespace system | |
b32b8144 | 899 | |
7c673cae FG |
900 | } // namespace boost |
901 | ||
92f5a8d4 | 902 | // generic_error_category implementation |
7c673cae | 903 | |
92f5a8d4 TL |
904 | #include <boost/system/detail/generic_category.hpp> |
905 | ||
906 | inline std::string boost::system::detail::generic_error_category::message( int ev ) const | |
907 | { | |
908 | return generic_error_category_message( ev ); | |
909 | } | |
910 | ||
911 | inline char const * boost::system::detail::generic_error_category::message( int ev, char * buffer, std::size_t len ) const BOOST_NOEXCEPT | |
912 | { | |
913 | return generic_error_category_message( ev, buffer, len ); | |
914 | } | |
915 | ||
916 | // system_error_category implementation | |
917 | ||
918 | #if defined(BOOST_WINDOWS_API) | |
919 | ||
920 | #include <boost/system/detail/system_category_win32.hpp> | |
921 | ||
922 | inline boost::system::error_condition boost::system::detail::system_error_category::default_error_condition( int ev ) const BOOST_NOEXCEPT | |
923 | { | |
924 | return system_category_default_error_condition_win32( ev ); | |
925 | } | |
926 | ||
927 | inline std::string boost::system::detail::system_error_category::message( int ev ) const | |
928 | { | |
929 | return system_category_message_win32( ev ); | |
930 | } | |
931 | ||
932 | inline char const * boost::system::detail::system_error_category::message( int ev, char * buffer, std::size_t len ) const BOOST_NOEXCEPT | |
933 | { | |
934 | return system_category_message_win32( ev, buffer, len ); | |
935 | } | |
936 | ||
937 | #else // #if defined(BOOST_WINDOWS_API) | |
938 | ||
939 | #include <boost/system/detail/system_category_posix.hpp> | |
940 | ||
941 | inline boost::system::error_condition boost::system::detail::system_error_category::default_error_condition( int ev ) const BOOST_NOEXCEPT | |
942 | { | |
943 | return system_category_default_error_condition_posix( ev ); | |
944 | } | |
945 | ||
946 | inline std::string boost::system::detail::system_error_category::message( int ev ) const | |
947 | { | |
948 | return generic_error_category_message( ev ); | |
949 | } | |
950 | ||
951 | inline char const * boost::system::detail::system_error_category::message( int ev, char * buffer, std::size_t len ) const BOOST_NOEXCEPT | |
952 | { | |
953 | return generic_error_category_message( ev, buffer, len ); | |
954 | } | |
955 | ||
956 | #endif // #if defined(BOOST_WINDOWS_API) | |
957 | ||
958 | // interoperability with std::error_code, std::error_condition | |
959 | ||
960 | #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR) | |
961 | ||
962 | #include <boost/system/detail/std_interoperability.hpp> | |
963 | ||
964 | inline boost::system::error_category::operator std::error_category const & () const | |
965 | { | |
966 | return boost::system::detail::to_std_category( *this ); | |
967 | } | |
968 | ||
969 | #endif // #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR) | |
7c673cae | 970 | |
92f5a8d4 | 971 | #endif // BOOST_SYSTEM_ERROR_CODE_HPP_INCLUDED |