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