1 | // boost/system/error_code.hpp -------------------------------------------------------// |
2 | |
3 | // Copyright Beman Dawes 2006, 2007 |
4 | // Copyright Christoper Kohlhoff 2007 |
5 | // Copyright Peter Dimov 2017, 2018 |
6 | |
7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
9 | |
10 | // See library home page at http://www.boost.org/libs/system |
11 | |
12 | #ifndef BOOST_SYSTEM_ERROR_CODE_HPP |
13 | #define BOOST_SYSTEM_ERROR_CODE_HPP |
14 | |
15 | #include <boost/system/config.hpp> |
16 | #include <boost/cstdint.hpp> |
17 | #include <boost/assert.hpp> |
18 | #include <boost/noncopyable.hpp> |
19 | #include <boost/utility/enable_if.hpp> |
20 | #include <ostream> |
21 | #include <string> |
22 | #include <stdexcept> |
23 | #include <functional> |
24 | |
25 | // TODO: undef these macros if not already defined |
26 | #include <boost/cerrno.hpp> |
27 | |
28 | #if !defined(BOOST_POSIX_API) && !defined(BOOST_WINDOWS_API) |
29 | # error BOOST_POSIX_API or BOOST_WINDOWS_API must be defined |
30 | #endif |
31 | |
32 | #ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR |
33 | #include <system_error> |
34 | #endif |
35 | |
36 | #include <boost/config/abi_prefix.hpp> // must be the last #include |
37 | |
38 | #ifndef BOOST_SYSTEM_NOEXCEPT |
39 | #define BOOST_SYSTEM_NOEXCEPT BOOST_NOEXCEPT |
40 | #endif |
41 | |
42 | namespace boost |
43 | { |
44 | namespace system |
45 | { |
46 | |
47 | class error_code; // values defined by the operating system |
48 | class error_condition; // portable generic values defined below, but ultimately |
49 | // based on the POSIX standard |
50 | |
51 | // "Concept" helpers -------------------------------------------------------------// |
52 | |
53 | template< class T > |
54 | struct is_error_code_enum { static const bool value = false; }; |
55 | |
56 | template< class T > |
57 | struct is_error_condition_enum { static const bool value = false; }; |
58 | |
59 | // generic error_conditions ------------------------------------------------------// |
60 | |
61 | namespace errc |
62 | { |
63 | enum errc_t |
64 | { |
65 | success = 0, |
66 | address_family_not_supported = EAFNOSUPPORT, |
67 | address_in_use = EADDRINUSE, |
68 | address_not_available = EADDRNOTAVAIL, |
69 | already_connected = EISCONN, |
70 | argument_list_too_long = E2BIG, |
71 | argument_out_of_domain = EDOM, |
72 | bad_address = EFAULT, |
73 | bad_file_descriptor = EBADF, |
74 | bad_message = EBADMSG, |
75 | broken_pipe = EPIPE, |
76 | connection_aborted = ECONNABORTED, |
77 | connection_already_in_progress = EALREADY, |
78 | connection_refused = ECONNREFUSED, |
79 | connection_reset = ECONNRESET, |
80 | cross_device_link = EXDEV, |
81 | destination_address_required = EDESTADDRREQ, |
82 | device_or_resource_busy = EBUSY, |
83 | directory_not_empty = ENOTEMPTY, |
84 | executable_format_error = ENOEXEC, |
85 | file_exists = EEXIST, |
86 | file_too_large = EFBIG, |
87 | filename_too_long = ENAMETOOLONG, |
88 | function_not_supported = ENOSYS, |
89 | host_unreachable = EHOSTUNREACH, |
90 | identifier_removed = EIDRM, |
91 | illegal_byte_sequence = EILSEQ, |
92 | inappropriate_io_control_operation = ENOTTY, |
93 | interrupted = EINTR, |
94 | invalid_argument = EINVAL, |
95 | invalid_seek = ESPIPE, |
96 | io_error = EIO, |
97 | is_a_directory = EISDIR, |
98 | message_size = EMSGSIZE, |
99 | network_down = ENETDOWN, |
100 | network_reset = ENETRESET, |
101 | network_unreachable = ENETUNREACH, |
102 | no_buffer_space = ENOBUFS, |
103 | no_child_process = ECHILD, |
104 | no_link = ENOLINK, |
105 | no_lock_available = ENOLCK, |
106 | no_message_available = ENODATA, |
107 | no_message = ENOMSG, |
108 | no_protocol_option = ENOPROTOOPT, |
109 | no_space_on_device = ENOSPC, |
110 | no_stream_resources = ENOSR, |
111 | no_such_device_or_address = ENXIO, |
112 | no_such_device = ENODEV, |
113 | no_such_file_or_directory = ENOENT, |
114 | no_such_process = ESRCH, |
115 | not_a_directory = ENOTDIR, |
116 | not_a_socket = ENOTSOCK, |
117 | not_a_stream = ENOSTR, |
118 | not_connected = ENOTCONN, |
119 | not_enough_memory = ENOMEM, |
120 | not_supported = ENOTSUP, |
121 | operation_canceled = ECANCELED, |
122 | operation_in_progress = EINPROGRESS, |
123 | operation_not_permitted = EPERM, |
124 | operation_not_supported = EOPNOTSUPP, |
125 | operation_would_block = EWOULDBLOCK, |
126 | owner_dead = EOWNERDEAD, |
127 | permission_denied = EACCES, |
128 | protocol_error = EPROTO, |
129 | protocol_not_supported = EPROTONOSUPPORT, |
130 | read_only_file_system = EROFS, |
131 | resource_deadlock_would_occur = EDEADLK, |
132 | resource_unavailable_try_again = EAGAIN, |
133 | result_out_of_range = ERANGE, |
134 | state_not_recoverable = ENOTRECOVERABLE, |
135 | stream_timeout = ETIME, |
136 | text_file_busy = ETXTBSY, |
137 | timed_out = ETIMEDOUT, |
138 | too_many_files_open_in_system = ENFILE, |
139 | too_many_files_open = EMFILE, |
140 | too_many_links = EMLINK, |
141 | too_many_symbolic_link_levels = ELOOP, |
142 | value_too_large = EOVERFLOW, |
143 | wrong_protocol_type = EPROTOTYPE |
144 | }; |
145 | |
146 | } // namespace errc |
147 | |
148 | # ifdef BOOST_SYSTEM_ENABLE_DEPRECATED |
149 | namespace posix = errc; |
150 | namespace posix_error = errc; |
151 | # endif |
152 | |
153 | template<> struct is_error_condition_enum<errc::errc_t> |
154 | { static const bool value = true; }; |
155 | |
156 | |
157 | // --------------------------------------------------------------------------------// |
158 | |
159 | // Operating system specific interfaces ------------------------------------------// |
160 | |
161 | |
162 | // The interface is divided into general and system-specific portions to |
163 | // meet these requirements: |
164 | // |
165 | // * Code calling an operating system API can create an error_code with |
166 | // a single category (system_category), even for POSIX-like operating |
167 | // systems that return some POSIX errno values and some native errno |
168 | // values. This code should not have to pay the cost of distinguishing |
169 | // between categories, since it is not yet known if that is needed. |
170 | // |
171 | // * Users wishing to write system-specific code should be given enums for |
172 | // at least the common error cases. |
173 | // |
174 | // * System specific code should fail at compile time if moved to another |
175 | // operating system. |
176 | |
177 | // The system specific portions of the interface are located in headers |
178 | // with names reflecting the operating system. For example, |
179 | // |
180 | // <boost/system/cygwin_error.hpp> |
181 | // <boost/system/linux_error.hpp> |
182 | // <boost/system/windows_error.hpp> |
183 | // |
184 | // These headers are effectively empty for compiles on operating systems |
185 | // where they are not applicable. |
186 | |
187 | // --------------------------------------------------------------------------------// |
188 | |
189 | class error_category; |
190 | |
191 | // predefined error categories ---------------------------------------------------// |
192 | |
193 | #ifdef BOOST_ERROR_CODE_HEADER_ONLY |
194 | inline const error_category & system_category() BOOST_SYSTEM_NOEXCEPT; |
195 | inline const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT; |
196 | #else |
197 | BOOST_SYSTEM_DECL const error_category & system_category() BOOST_SYSTEM_NOEXCEPT; |
198 | BOOST_SYSTEM_DECL const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT; |
199 | #endif |
200 | // deprecated synonyms ------------------------------------------------------------// |
201 | |
202 | #ifdef BOOST_SYSTEM_ENABLE_DEPRECATED |
203 | inline const error_category & get_system_category() { return system_category(); } |
204 | inline const error_category & get_generic_category() { return generic_category(); } |
205 | inline const error_category & get_posix_category() { return generic_category(); } |
206 | static const error_category & posix_category BOOST_ATTRIBUTE_UNUSED |
207 | = generic_category(); |
208 | static const error_category & errno_ecat BOOST_ATTRIBUTE_UNUSED |
209 | = generic_category(); |
210 | static const error_category & native_ecat BOOST_ATTRIBUTE_UNUSED |
211 | = system_category(); |
212 | #endif |
213 | |
214 | #ifdef BOOST_MSVC |
215 | #pragma warning(push) |
216 | // 'this' : used in base member initializer list |
217 | #pragma warning(disable: 4355) |
218 | #endif |
219 | |
220 | // class error_category ------------------------------------------------// |
221 | |
222 | class error_category : public noncopyable |
223 | { |
224 | #ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR |
225 | |
226 | private: |
227 | |
228 | class std_category: public std::error_category |
229 | { |
230 | private: |
231 | |
232 | boost::system::error_category const * pc_; |
233 | |
234 | public: |
235 | |
236 | explicit std_category( boost::system::error_category const * pc ): pc_( pc ) |
237 | { |
238 | } |
239 | |
240 | virtual const char * name() const BOOST_NOEXCEPT |
241 | { |
242 | return pc_->name(); |
243 | } |
244 | |
245 | virtual std::string message( int ev ) const |
246 | { |
247 | return pc_->message( ev ); |
248 | } |
249 | |
250 | virtual std::error_condition default_error_condition( int ev ) const |
251 | BOOST_NOEXCEPT; |
252 | virtual bool equivalent( int code, const std::error_condition & condition ) const |
253 | BOOST_NOEXCEPT; |
254 | virtual bool equivalent( const std::error_code & code, int condition ) const |
255 | BOOST_NOEXCEPT; |
256 | }; |
257 | |
258 | std_category std_cat_; |
259 | |
260 | public: |
261 | |
262 | error_category() BOOST_SYSTEM_NOEXCEPT: std_cat_( this ) {} |
263 | |
264 | operator std::error_category const & () const BOOST_SYSTEM_NOEXCEPT |
265 | { |
266 | // do not map generic to std::generic on purpose; occasionally, |
267 | // there are two std::generic categories in a program, which leads |
268 | // to error codes/conditions mysteriously not being equal to themselves |
269 | return std_cat_; |
270 | } |
271 | |
272 | #else |
273 | |
274 | // to maintain ABI compatibility between 03 and 11, |
275 | // define a class with the same layout |
276 | |
277 | private: |
278 | |
279 | class std_category |
280 | { |
281 | private: |
282 | |
283 | boost::system::error_category const * pc_; |
284 | |
285 | public: |
286 | |
287 | explicit std_category( boost::system::error_category const * pc ): pc_( pc ) |
288 | { |
289 | } |
290 | |
291 | virtual ~std_category() {} |
292 | |
293 | virtual const char * name() const BOOST_NOEXCEPT |
294 | { |
295 | return pc_->name(); |
296 | } |
297 | |
298 | // we can't define message, because (1) it returns an std::string, |
299 | // which can be different between 03 and 11, and (2) on mingw, there |
300 | // are actually two `message` functions, not one, so it doesn't work |
301 | // even if we do |
302 | |
303 | // neither can we define default_error_condition or equivalent |
304 | |
305 | // if these functions are called, it will crash, but that's still |
306 | // better than the alternative of having the class layout change |
307 | }; |
308 | |
309 | std_category std_cat_; |
310 | |
311 | public: |
312 | |
313 | error_category() BOOST_SYSTEM_NOEXCEPT: std_cat_( this ) {} |
314 | |
315 | #endif |
316 | |
317 | public: |
318 | virtual ~error_category(){} |
319 | |
320 | virtual const char * name() const BOOST_SYSTEM_NOEXCEPT = 0; |
321 | virtual std::string message( int ev ) const = 0; |
322 | inline virtual error_condition default_error_condition( int ev ) const |
323 | BOOST_SYSTEM_NOEXCEPT; |
324 | inline virtual bool equivalent( int code, |
325 | const error_condition & condition ) const |
326 | BOOST_SYSTEM_NOEXCEPT; |
327 | inline virtual bool equivalent( const error_code & code, |
328 | int condition ) const BOOST_SYSTEM_NOEXCEPT; |
329 | |
330 | bool operator==(const error_category & rhs) const BOOST_SYSTEM_NOEXCEPT |
331 | { return this == &rhs; } |
332 | bool operator!=(const error_category & rhs) const BOOST_SYSTEM_NOEXCEPT |
333 | { return this != &rhs; } |
334 | bool operator<( const error_category & rhs ) const BOOST_SYSTEM_NOEXCEPT |
335 | { return std::less<const error_category*>()( this, &rhs ); } |
336 | }; |
337 | |
338 | #ifdef BOOST_MSVC |
339 | #pragma warning(pop) |
340 | #endif |
341 | |
342 | // class error_condition ---------------------------------------------------------// |
343 | |
344 | // error_conditions are portable, error_codes are system or library specific |
345 | |
346 | class error_condition |
347 | { |
348 | public: |
349 | |
350 | // constructors: |
351 | error_condition() BOOST_SYSTEM_NOEXCEPT : m_val(0), m_cat(&generic_category()) {} |
352 | error_condition( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT |
353 | : m_val(val), m_cat(&cat) {} |
354 | |
355 | template <class ErrorConditionEnum> |
356 | error_condition(ErrorConditionEnum e, |
357 | typename boost::enable_if<is_error_condition_enum<ErrorConditionEnum> >::type* |
358 | = 0) BOOST_SYSTEM_NOEXCEPT |
359 | { |
360 | *this = make_error_condition(e); |
361 | } |
362 | |
363 | // modifiers: |
364 | |
365 | void assign( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT |
366 | { |
367 | m_val = val; |
368 | m_cat = &cat; |
369 | } |
370 | |
371 | template<typename ErrorConditionEnum> |
372 | typename boost::enable_if<is_error_condition_enum<ErrorConditionEnum>, |
373 | error_condition>::type & |
374 | operator=( ErrorConditionEnum val ) BOOST_SYSTEM_NOEXCEPT |
375 | { |
376 | *this = make_error_condition(val); |
377 | return *this; |
378 | } |
379 | |
380 | void clear() BOOST_SYSTEM_NOEXCEPT |
381 | { |
382 | m_val = 0; |
383 | m_cat = &generic_category(); |
384 | } |
385 | |
386 | // observers: |
387 | int value() const BOOST_SYSTEM_NOEXCEPT { return m_val; } |
388 | const error_category & category() const BOOST_SYSTEM_NOEXCEPT { return *m_cat; } |
389 | std::string message() const { return m_cat->message(value()); } |
390 | |
391 | #if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) |
392 | |
393 | explicit operator bool() const BOOST_SYSTEM_NOEXCEPT // true if error |
394 | { |
395 | return m_val != 0; |
396 | } |
397 | |
398 | #else |
399 | |
400 | typedef void (*unspecified_bool_type)(); |
401 | static void unspecified_bool_true() {} |
402 | |
403 | operator unspecified_bool_type() const BOOST_SYSTEM_NOEXCEPT // true if error |
404 | { |
405 | return m_val == 0 ? 0 : unspecified_bool_true; |
406 | } |
407 | |
408 | bool operator!() const BOOST_SYSTEM_NOEXCEPT // true if no error |
409 | { |
410 | return m_val == 0; |
411 | } |
412 | |
413 | #endif |
414 | |
415 | // relationals: |
416 | // the more symmetrical non-member syntax allows enum |
417 | // conversions work for both rhs and lhs. |
418 | inline friend bool operator==( const error_condition & lhs, |
419 | const error_condition & rhs ) BOOST_SYSTEM_NOEXCEPT |
420 | { |
421 | return lhs.m_cat == rhs.m_cat && lhs.m_val == rhs.m_val; |
422 | } |
423 | |
424 | inline friend bool operator<( const error_condition & lhs, |
425 | const error_condition & rhs ) BOOST_SYSTEM_NOEXCEPT |
426 | // the more symmetrical non-member syntax allows enum |
427 | // conversions work for both rhs and lhs. |
428 | { |
429 | return lhs.m_cat < rhs.m_cat |
430 | || (lhs.m_cat == rhs.m_cat && lhs.m_val < rhs.m_val); |
431 | } |
432 | |
433 | #ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR |
434 | |
435 | operator std::error_condition () const BOOST_SYSTEM_NOEXCEPT |
436 | { |
437 | return std::error_condition( value(), category() ); |
438 | } |
439 | |
440 | #endif |
441 | |
442 | private: |
443 | int m_val; |
444 | const error_category * m_cat; |
445 | |
446 | }; |
447 | |
448 | // class error_code --------------------------------------------------------------// |
449 | |
450 | // We want error_code to be a value type that can be copied without slicing |
451 | // and without requiring heap allocation, but we also want it to have |
452 | // polymorphic behavior based on the error category. This is achieved by |
453 | // abstract base class error_category supplying the polymorphic behavior, |
454 | // and error_code containing a pointer to an object of a type derived |
455 | // from error_category. |
456 | class error_code |
457 | { |
458 | public: |
459 | |
460 | // constructors: |
461 | error_code() BOOST_SYSTEM_NOEXCEPT : m_val(0), m_cat(&system_category()) {} |
462 | error_code( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT |
463 | : m_val(val), m_cat(&cat) {} |
464 | |
465 | template <class ErrorCodeEnum> |
466 | error_code(ErrorCodeEnum e, |
467 | typename boost::enable_if<is_error_code_enum<ErrorCodeEnum> >::type* = 0) |
468 | BOOST_SYSTEM_NOEXCEPT |
469 | { |
470 | *this = make_error_code(e); |
471 | } |
472 | |
473 | // modifiers: |
474 | void assign( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT |
475 | { |
476 | m_val = val; |
477 | m_cat = &cat; |
478 | } |
479 | |
480 | template<typename ErrorCodeEnum> |
481 | typename boost::enable_if<is_error_code_enum<ErrorCodeEnum>, error_code>::type & |
482 | operator=( ErrorCodeEnum val ) BOOST_SYSTEM_NOEXCEPT |
483 | { |
484 | *this = make_error_code(val); |
485 | return *this; |
486 | } |
487 | |
488 | void clear() BOOST_SYSTEM_NOEXCEPT |
489 | { |
490 | m_val = 0; |
491 | m_cat = &system_category(); |
492 | } |
493 | |
494 | // observers: |
495 | int value() const BOOST_SYSTEM_NOEXCEPT { return m_val; } |
496 | const error_category & category() const BOOST_SYSTEM_NOEXCEPT { return *m_cat; } |
497 | error_condition default_error_condition() const BOOST_SYSTEM_NOEXCEPT |
498 | { return m_cat->default_error_condition(value()); } |
499 | std::string message() const { return m_cat->message(value()); } |
500 | |
501 | #if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) |
502 | |
503 | explicit operator bool() const BOOST_SYSTEM_NOEXCEPT // true if error |
504 | { |
505 | return m_val != 0; |
506 | } |
507 | |
508 | #else |
509 | |
510 | typedef void (*unspecified_bool_type)(); |
511 | static void unspecified_bool_true() {} |
512 | |
513 | operator unspecified_bool_type() const BOOST_SYSTEM_NOEXCEPT // true if error |
514 | { |
515 | return m_val == 0 ? 0 : unspecified_bool_true; |
516 | } |
517 | |
518 | bool operator!() const BOOST_SYSTEM_NOEXCEPT // true if no error |
519 | { |
520 | return m_val == 0; |
521 | } |
522 | |
523 | #endif |
524 | |
525 | // relationals: |
526 | inline friend bool operator==( const error_code & lhs, |
527 | const error_code & rhs ) BOOST_SYSTEM_NOEXCEPT |
528 | // the more symmetrical non-member syntax allows enum |
529 | // conversions work for both rhs and lhs. |
530 | { |
531 | return lhs.m_cat == rhs.m_cat && lhs.m_val == rhs.m_val; |
532 | } |
533 | |
534 | inline friend bool operator<( const error_code & lhs, |
535 | const error_code & rhs ) BOOST_SYSTEM_NOEXCEPT |
536 | // the more symmetrical non-member syntax allows enum |
537 | // conversions work for both rhs and lhs. |
538 | { |
539 | return lhs.m_cat < rhs.m_cat |
540 | || (lhs.m_cat == rhs.m_cat && lhs.m_val < rhs.m_val); |
541 | } |
542 | |
543 | #ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR |
544 | |
545 | operator std::error_code () const BOOST_SYSTEM_NOEXCEPT |
546 | { |
547 | return std::error_code( value(), category() ); |
548 | } |
549 | |
550 | #endif |
551 | |
552 | private: |
553 | int m_val; |
554 | const error_category * m_cat; |
555 | |
556 | }; |
557 | |
558 | // predefined error_code object used as "throw on error" tag |
559 | # ifdef BOOST_SYSTEM_ENABLE_DEPRECATED |
560 | BOOST_SYSTEM_DECL extern error_code throws; |
561 | # endif |
562 | |
563 | // Moving from a "throws" object to a "throws" function without breaking |
564 | // existing code is a bit of a problem. The workaround is to place the |
565 | // "throws" function in namespace boost rather than namespace boost::system. |
566 | |
567 | } // namespace system |
568 | |
569 | namespace detail |
570 | { |
571 | // Misuse of the error_code object is turned into a noisy failure by |
572 | // poisoning the reference. This particular implementation doesn't |
573 | // produce warnings or errors from popular compilers, is very efficient |
574 | // (as determined by inspecting generated code), and does not suffer |
575 | // from order of initialization problems. In practice, it also seems |
576 | // cause user function error handling implementation errors to be detected |
577 | // very early in the development cycle. |
578 | inline system::error_code* throws() |
579 | { |
580 | // See github.com/boostorg/system/pull/12 by visigoth for why the return |
581 | // is poisoned with nonzero rather than (0). A test, test_throws_usage(), |
582 | // has been added to error_code_test.cpp, and as visigoth mentioned it |
583 | // fails on clang for release builds with a return of 0 but works fine |
584 | // with (1). |
585 | // Since the undefined behavior sanitizer (-fsanitize=undefined) does not |
586 | // allow a reference to be formed to the unaligned address of (1), we use |
587 | // (8) instead. |
588 | return reinterpret_cast<system::error_code*>(8); |
589 | } |
590 | } |
591 | |
592 | inline system::error_code& throws() |
593 | { return *detail::throws(); } |
594 | |
595 | namespace system |
596 | { |
597 | // non-member functions ------------------------------------------------// |
598 | |
599 | inline bool operator!=( const error_code & lhs, |
600 | const error_code & rhs ) BOOST_SYSTEM_NOEXCEPT |
601 | { |
602 | return !(lhs == rhs); |
603 | } |
604 | |
605 | inline bool operator!=( const error_condition & lhs, |
606 | const error_condition & rhs ) BOOST_SYSTEM_NOEXCEPT |
607 | { |
608 | return !(lhs == rhs); |
609 | } |
610 | |
611 | inline bool operator==( const error_code & code, |
612 | const error_condition & condition ) BOOST_SYSTEM_NOEXCEPT |
613 | { |
614 | return code.category().equivalent( code.value(), condition ) |
615 | || condition.category().equivalent( code, condition.value() ); |
616 | } |
617 | |
618 | inline bool operator!=( const error_code & lhs, |
619 | const error_condition & rhs ) BOOST_SYSTEM_NOEXCEPT |
620 | { |
621 | return !(lhs == rhs); |
622 | } |
623 | |
624 | inline bool operator==( const error_condition & condition, |
625 | const error_code & code ) BOOST_SYSTEM_NOEXCEPT |
626 | { |
627 | return condition.category().equivalent( code, condition.value() ) |
628 | || code.category().equivalent( code.value(), condition ); |
629 | } |
630 | |
631 | inline bool operator!=( const error_condition & lhs, |
632 | const error_code & rhs ) BOOST_SYSTEM_NOEXCEPT |
633 | { |
634 | return !(lhs == rhs); |
635 | } |
636 | |
637 | // TODO: both of these may move elsewhere, but the LWG hasn't spoken yet. |
638 | |
639 | template <class charT, class traits> |
640 | inline std::basic_ostream<charT,traits>& |
641 | operator<< (std::basic_ostream<charT,traits>& os, error_code ec) |
642 | { |
643 | os << ec.category().name() << ':' << ec.value(); |
644 | return os; |
645 | } |
646 | |
647 | inline std::size_t hash_value( const error_code & ec ) |
648 | { |
649 | return static_cast<std::size_t>(ec.value()) |
650 | + reinterpret_cast<std::size_t>(&ec.category()); |
651 | } |
652 | |
653 | // make_* functions for errc::errc_t ---------------------------------------------// |
654 | |
655 | namespace errc |
656 | { |
657 | // explicit conversion: |
658 | inline error_code make_error_code( errc_t e ) BOOST_SYSTEM_NOEXCEPT |
659 | { return error_code( e, generic_category() ); } |
660 | |
661 | // implicit conversion: |
662 | inline error_condition make_error_condition( errc_t e ) BOOST_SYSTEM_NOEXCEPT |
663 | { return error_condition( e, generic_category() ); } |
664 | } |
665 | |
666 | // error_category default implementation -----------------------------------------// |
667 | |
668 | error_condition error_category::default_error_condition( int ev ) const |
669 | BOOST_SYSTEM_NOEXCEPT |
670 | { |
671 | return error_condition( ev, *this ); |
672 | } |
673 | |
674 | bool error_category::equivalent( int code, |
675 | const error_condition & condition ) const BOOST_SYSTEM_NOEXCEPT |
676 | { |
677 | return default_error_condition( code ) == condition; |
678 | } |
679 | |
680 | bool error_category::equivalent( const error_code & code, |
681 | int condition ) const BOOST_SYSTEM_NOEXCEPT |
682 | { |
683 | return *this == code.category() && code.value() == condition; |
684 | } |
685 | |
686 | #ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR |
687 | |
688 | inline std::error_condition error_category::std_category::default_error_condition( |
689 | int ev ) const BOOST_NOEXCEPT |
690 | { |
691 | return pc_->default_error_condition( ev ); |
692 | } |
693 | |
694 | inline bool error_category::std_category::equivalent( int code, |
695 | const std::error_condition & condition ) const BOOST_NOEXCEPT |
696 | { |
697 | if( condition.category() == *this ) |
698 | { |
699 | boost::system::error_condition bn( condition.value(), *pc_ ); |
700 | return pc_->equivalent( code, bn ); |
701 | } |
702 | else if( condition.category() == std::generic_category() |
703 | || condition.category() == boost::system::generic_category() ) |
704 | { |
705 | boost::system::error_condition bn( condition.value(), |
706 | boost::system::generic_category() ); |
707 | |
708 | return pc_->equivalent( code, bn ); |
709 | } |
710 | #ifndef BOOST_NO_RTTI |
711 | else if( std_category const* pc2 = dynamic_cast< std_category const* >( |
712 | &condition.category() ) ) |
713 | { |
714 | boost::system::error_condition bn( condition.value(), *pc2->pc_ ); |
715 | return pc_->equivalent( code, bn ); |
716 | } |
717 | #endif |
718 | else |
719 | { |
720 | return default_error_condition( code ) == condition; |
721 | } |
722 | } |
723 | |
724 | inline bool error_category::std_category::equivalent( const std::error_code & code, |
725 | int condition ) const BOOST_NOEXCEPT |
726 | { |
727 | if( code.category() == *this ) |
728 | { |
729 | boost::system::error_code bc( code.value(), *pc_ ); |
730 | return pc_->equivalent( bc, condition ); |
731 | } |
732 | else if( code.category() == std::generic_category() |
733 | || code.category() == boost::system::generic_category() ) |
734 | { |
735 | boost::system::error_code bc( code.value(), |
736 | boost::system::generic_category() ); |
737 | |
738 | return pc_->equivalent( bc, condition ); |
739 | } |
740 | #ifndef BOOST_NO_RTTI |
741 | else if( std_category const* pc2 = dynamic_cast< std_category const* >( |
742 | &code.category() ) ) |
743 | { |
744 | boost::system::error_code bc( code.value(), *pc2->pc_ ); |
745 | return pc_->equivalent( bc, condition ); |
746 | } |
747 | #endif |
748 | else if( *pc_ == boost::system::generic_category() ) |
749 | { |
750 | return std::generic_category().equivalent( code, condition ); |
751 | } |
752 | else |
753 | { |
754 | return false; |
755 | } |
756 | } |
757 | |
758 | #endif |
759 | |
760 | } // namespace system |
761 | } // namespace boost |
762 | |
763 | #include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas |
764 | |
765 | # ifdef BOOST_ERROR_CODE_HEADER_ONLY |
766 | # include <boost/system/detail/error_code.ipp> |
767 | # endif |
768 | |
769 | #endif // BOOST_SYSTEM_ERROR_CODE_HPP |
770 | |