Line data Source code
1 : #ifndef BOOST_SYSTEM_ERROR_CODE_HPP_INCLUDED
2 : #define BOOST_SYSTEM_ERROR_CODE_HPP_INCLUDED
3 :
4 : // Copyright Beman Dawes 2006, 2007
5 : // Copyright Christoper Kohlhoff 2007
6 : // Copyright Peter Dimov 2017, 2018
7 : //
8 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
9 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10 : //
11 : // See library home page at http://www.boost.org/libs/system
12 :
13 : #include <boost/system/api_config.hpp>
14 : #include <boost/system/detail/config.hpp>
15 : #include <boost/cstdint.hpp>
16 : #include <boost/config.hpp>
17 : #include <ostream>
18 : #include <string>
19 : #include <functional>
20 : #include <cstring>
21 :
22 : // TODO: undef these macros if not already defined
23 : #include <boost/cerrno.hpp>
24 :
25 : #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
26 : # include <system_error>
27 : #endif
28 :
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 :
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 :
150 : #endif
151 :
152 : template<> struct is_error_condition_enum<errc::errc_t>
153 : {
154 : static const bool value = true;
155 : };
156 :
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"
161 : #endif
162 :
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
172 : {
173 : private:
174 :
175 : friend std::size_t hash_value( error_code const & ec );
176 :
177 : #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
178 : public:
179 :
180 : error_category( error_category const & ) = delete;
181 : error_category& operator=( error_category const & ) = delete;
182 :
183 : #else
184 : private:
185 :
186 : error_category( error_category const & );
187 : error_category& operator=( error_category const & );
188 :
189 : #endif
190 :
191 : private:
192 :
193 : boost::ulong_long_type id_;
194 :
195 : protected:
196 :
197 : #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && !defined(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS)
198 :
199 : ~error_category() = default;
200 :
201 : #else
202 :
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() {}
209 :
210 : #endif
211 :
212 : BOOST_SYSTEM_CONSTEXPR error_category() BOOST_NOEXCEPT: id_( 0 )
213 : {
214 : }
215 :
216 : explicit BOOST_SYSTEM_CONSTEXPR error_category( boost::ulong_long_type id ) BOOST_NOEXCEPT: id_( id )
217 : {
218 : }
219 :
220 : public:
221 :
222 : virtual const char * name() const BOOST_NOEXCEPT = 0;
223 :
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;
227 :
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;
230 :
231 : virtual bool failed( int ev ) const BOOST_NOEXCEPT;
232 :
233 0 : BOOST_SYSTEM_CONSTEXPR bool operator==( const error_category & rhs ) const BOOST_NOEXCEPT
234 : {
235 0 : 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 : }
242 :
243 0 : BOOST_SYSTEM_CONSTEXPR bool operator<( const error_category & rhs ) const BOOST_NOEXCEPT
244 : {
245 0 : if( id_ < rhs.id_ )
246 : {
247 : return true;
248 : }
249 :
250 0 : if( id_ > rhs.id_ )
251 : {
252 : return false;
253 : }
254 :
255 0 : if( rhs.id_ != 0 )
256 : {
257 : return false; // equal
258 : }
259 :
260 0 : return std::less<error_category const *>()( this, &rhs );
261 : }
262 :
263 : #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
264 :
265 : operator std::error_category const & () const;
266 :
267 : #endif
268 : };
269 :
270 : #ifdef BOOST_MSVC
271 : #pragma warning( pop )
272 : #endif
273 :
274 : // predefined error categories
275 :
276 : namespace detail
277 : {
278 :
279 : class BOOST_SYMBOL_VISIBLE generic_error_category: public error_category
280 : {
281 : public:
282 :
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 : }
289 :
290 0 : const char * name() const BOOST_NOEXCEPT
291 : {
292 0 : return "generic";
293 : }
294 :
295 : std::string message( int ev ) const;
296 : char const * message( int ev, char * buffer, std::size_t len ) const BOOST_NOEXCEPT;
297 : };
298 :
299 : class BOOST_SYMBOL_VISIBLE system_error_category: public error_category
300 : {
301 : public:
302 :
303 : BOOST_SYSTEM_CONSTEXPR system_error_category() BOOST_NOEXCEPT:
304 : error_category( ( boost::ulong_long_type( 0x8FAFD21E ) << 32 ) + 0x25C5E09B )
305 : {
306 : }
307 :
308 0 : const char * name() const BOOST_NOEXCEPT
309 : {
310 0 : return "system";
311 : }
312 :
313 : error_condition default_error_condition( int ev ) const BOOST_NOEXCEPT;
314 :
315 : std::string message( int ev ) const;
316 : char const * message( int ev, char * buffer, std::size_t len ) const BOOST_NOEXCEPT;
317 : };
318 :
319 : } // namespace detail
320 :
321 : #if ( defined( BOOST_GCC ) && BOOST_GCC >= 40600 ) || defined( BOOST_CLANG )
322 : #pragma GCC diagnostic pop
323 : #endif
324 :
325 : // generic_category(), system_category()
326 :
327 : #if defined(BOOST_SYSTEM_HAS_CONSTEXPR)
328 :
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 : template<class T> constexpr system_error_category cat_holder<T>::system_category_instance;
339 : template<class T> constexpr generic_error_category cat_holder<T>::generic_category_instance;
340 :
341 : } // namespace detail
342 :
343 : constexpr error_category const & system_category() BOOST_NOEXCEPT
344 : {
345 : return detail::cat_holder<void>::system_category_instance;
346 : }
347 :
348 : constexpr error_category const & generic_category() BOOST_NOEXCEPT
349 : {
350 : return detail::cat_holder<void>::generic_category_instance;
351 : }
352 :
353 : #else // #if defined(BOOST_SYSTEM_HAS_CONSTEXPR)
354 :
355 : inline error_category const & system_category() BOOST_NOEXCEPT BOOST_SYMBOL_VISIBLE;
356 :
357 : inline error_category const & system_category() BOOST_NOEXCEPT
358 : {
359 : static const detail::system_error_category system_category_instance;
360 : return system_category_instance;
361 : }
362 :
363 : inline error_category const & generic_category() BOOST_NOEXCEPT BOOST_SYMBOL_VISIBLE;
364 :
365 : inline error_category const & generic_category() BOOST_NOEXCEPT
366 : {
367 : static const detail::generic_error_category generic_category_instance;
368 : return generic_category_instance;
369 : }
370 :
371 : #endif // #if defined(BOOST_SYSTEM_HAS_CONSTEXPR)
372 :
373 : // deprecated synonyms
374 :
375 : #ifdef BOOST_SYSTEM_ENABLE_DEPRECATED
376 :
377 : inline const error_category & get_system_category() { return system_category(); }
378 : inline const error_category & get_generic_category() { return generic_category(); }
379 : inline const error_category & get_posix_category() { return generic_category(); }
380 : static const error_category & posix_category BOOST_ATTRIBUTE_UNUSED = generic_category();
381 : static const error_category & errno_ecat BOOST_ATTRIBUTE_UNUSED = generic_category();
382 : static const error_category & native_ecat BOOST_ATTRIBUTE_UNUSED = system_category();
383 :
384 : #endif
385 :
386 : // enable_if
387 :
388 : namespace detail
389 : {
390 :
391 : template<bool C, class T = void> struct enable_if
392 : {
393 : typedef T type;
394 : };
395 :
396 : template<class T> struct enable_if<false, T>
397 : {
398 : };
399 :
400 : // failed_impl
401 :
402 : #if !defined(BOOST_SYSTEM_HAS_CONSTEXPR)
403 :
404 : inline bool failed_impl( int ev, error_category const & cat )
405 : {
406 : return cat.failed( ev );
407 : }
408 :
409 : #else
410 :
411 0 : BOOST_SYSTEM_CONSTEXPR inline bool failed_impl( int ev, error_category const & cat )
412 : {
413 0 : if( cat == system_category() || cat == generic_category() )
414 : {
415 0 : return ev != 0;
416 : }
417 : else
418 : {
419 0 : return cat.failed( ev );
420 : }
421 : }
422 :
423 : #endif
424 :
425 : } // namespace detail
426 :
427 : // class error_condition
428 :
429 : // error_conditions are portable, error_codes are system or library specific
430 :
431 : class error_condition
432 : {
433 : private:
434 :
435 : int val_;
436 : bool failed_;
437 : error_category const * cat_;
438 :
439 : public:
440 :
441 : // constructors:
442 :
443 : BOOST_SYSTEM_CONSTEXPR error_condition() BOOST_NOEXCEPT:
444 : val_( 0 ), failed_( false ), cat_( &generic_category() )
445 : {
446 : }
447 :
448 0 : BOOST_SYSTEM_CONSTEXPR error_condition( int val, const error_category & cat ) BOOST_NOEXCEPT:
449 0 : val_( val ), failed_( detail::failed_impl( val, cat ) ), cat_( &cat )
450 : {
451 : }
452 :
453 : template<class ErrorConditionEnum> BOOST_SYSTEM_CONSTEXPR error_condition( ErrorConditionEnum e,
454 : typename detail::enable_if<is_error_condition_enum<ErrorConditionEnum>::value>::type* = 0) BOOST_NOEXCEPT
455 : {
456 : *this = make_error_condition( e );
457 : }
458 :
459 : // modifiers:
460 :
461 : BOOST_SYSTEM_CONSTEXPR void assign( int val, const error_category & cat ) BOOST_NOEXCEPT
462 : {
463 : val_ = val;
464 : failed_ = detail::failed_impl( val, cat );
465 : cat_ = &cat;
466 : }
467 :
468 : template<typename ErrorConditionEnum>
469 : BOOST_SYSTEM_CONSTEXPR typename detail::enable_if<is_error_condition_enum<ErrorConditionEnum>::value, error_condition>::type &
470 : operator=( ErrorConditionEnum val ) BOOST_NOEXCEPT
471 : {
472 : *this = make_error_condition( val );
473 : return *this;
474 : }
475 :
476 : BOOST_SYSTEM_CONSTEXPR void clear() BOOST_NOEXCEPT
477 : {
478 : val_ = 0;
479 : failed_ = false;
480 : cat_ = &generic_category();
481 : }
482 :
483 : // observers:
484 :
485 0 : BOOST_SYSTEM_CONSTEXPR int value() const BOOST_NOEXCEPT
486 : {
487 0 : return val_;
488 : }
489 :
490 0 : BOOST_SYSTEM_CONSTEXPR const error_category & category() const BOOST_NOEXCEPT
491 : {
492 0 : return *cat_;
493 : }
494 :
495 : std::string message() const
496 : {
497 : return cat_->message( value() );
498 : }
499 :
500 : char const * message( char * buffer, std::size_t len ) const BOOST_NOEXCEPT
501 : {
502 : return cat_->message( value(), buffer, len );
503 : }
504 :
505 : BOOST_SYSTEM_CONSTEXPR bool failed() const BOOST_NOEXCEPT
506 : {
507 : return failed_;
508 : }
509 :
510 : #if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
511 :
512 : BOOST_SYSTEM_CONSTEXPR explicit operator bool() const BOOST_NOEXCEPT // true if error
513 : {
514 : return val_ != 0;
515 : }
516 :
517 : #else
518 :
519 : typedef void (*unspecified_bool_type)();
520 : static void unspecified_bool_true() {}
521 :
522 : BOOST_SYSTEM_CONSTEXPR operator unspecified_bool_type() const BOOST_NOEXCEPT // true if error
523 : {
524 : return val_ != 0? unspecified_bool_true: 0;
525 : }
526 :
527 : BOOST_SYSTEM_CONSTEXPR bool operator!() const BOOST_NOEXCEPT // true if no error
528 : {
529 : return val_ == 0;
530 : }
531 :
532 : #endif
533 :
534 : // relationals:
535 : // the more symmetrical non-member syntax allows enum
536 : // conversions work for both rhs and lhs.
537 :
538 0 : BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( const error_condition & lhs, const error_condition & rhs ) BOOST_NOEXCEPT
539 : {
540 0 : return lhs.val_ == rhs.val_ && *lhs.cat_ == *rhs.cat_;
541 : }
542 :
543 : BOOST_SYSTEM_CONSTEXPR inline friend bool operator<( const error_condition & lhs, const error_condition & rhs ) BOOST_NOEXCEPT
544 : {
545 : return *lhs.cat_ < *rhs.cat_ || ( *lhs.cat_ == *rhs.cat_ && lhs.val_ < rhs.val_ );
546 : }
547 :
548 : #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
549 :
550 0 : operator std::error_condition () const
551 : {
552 0 : return std::error_condition( value(), category() );
553 : }
554 :
555 : #endif
556 : };
557 :
558 : // class error_code
559 :
560 : // We want error_code to be a value type that can be copied without slicing
561 : // and without requiring heap allocation, but we also want it to have
562 : // polymorphic behavior based on the error category. This is achieved by
563 : // abstract base class error_category supplying the polymorphic behavior,
564 : // and error_code containing a pointer to an object of a type derived
565 : // from error_category.
566 :
567 : class error_code
568 : {
569 : private:
570 :
571 : int val_;
572 : bool failed_;
573 : const error_category * cat_;
574 :
575 : public:
576 :
577 : // constructors:
578 :
579 : BOOST_SYSTEM_CONSTEXPR error_code() BOOST_NOEXCEPT:
580 : val_( 0 ), failed_( false ), cat_( &system_category() )
581 : {
582 : }
583 :
584 0 : BOOST_SYSTEM_CONSTEXPR error_code( int val, const error_category & cat ) BOOST_NOEXCEPT:
585 0 : val_( val ), failed_( detail::failed_impl( val, cat ) ), cat_( &cat )
586 : {
587 : }
588 :
589 : template<class ErrorCodeEnum> BOOST_SYSTEM_CONSTEXPR error_code( ErrorCodeEnum e,
590 : typename detail::enable_if<is_error_code_enum<ErrorCodeEnum>::value>::type* = 0 ) BOOST_NOEXCEPT
591 : {
592 : *this = make_error_code( e );
593 : }
594 :
595 : // modifiers:
596 :
597 : BOOST_SYSTEM_CONSTEXPR void assign( int val, const error_category & cat ) BOOST_NOEXCEPT
598 : {
599 : val_ = val;
600 : failed_ = detail::failed_impl( val, cat );
601 : cat_ = &cat;
602 : }
603 :
604 : template<typename ErrorCodeEnum>
605 : BOOST_SYSTEM_CONSTEXPR typename detail::enable_if<is_error_code_enum<ErrorCodeEnum>::value, error_code>::type &
606 : operator=( ErrorCodeEnum val ) BOOST_NOEXCEPT
607 : {
608 : *this = make_error_code( val );
609 : return *this;
610 : }
611 :
612 : BOOST_SYSTEM_CONSTEXPR void clear() BOOST_NOEXCEPT
613 : {
614 : val_ = 0;
615 : failed_ = false;
616 : cat_ = &system_category();
617 : }
618 :
619 : // observers:
620 :
621 0 : BOOST_SYSTEM_CONSTEXPR int value() const BOOST_NOEXCEPT
622 : {
623 0 : return val_;
624 : }
625 :
626 0 : BOOST_SYSTEM_CONSTEXPR const error_category & category() const BOOST_NOEXCEPT
627 : {
628 0 : return *cat_;
629 : }
630 :
631 : error_condition default_error_condition() const BOOST_NOEXCEPT
632 : {
633 : return cat_->default_error_condition( value() );
634 : }
635 :
636 0 : std::string message() const
637 : {
638 0 : return cat_->message( value() );
639 : }
640 :
641 : char const * message( char * buffer, std::size_t len ) const BOOST_NOEXCEPT
642 : {
643 : return cat_->message( value(), buffer, len );
644 : }
645 :
646 : BOOST_SYSTEM_CONSTEXPR bool failed() const BOOST_NOEXCEPT
647 : {
648 : return failed_;
649 : }
650 :
651 : #if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
652 :
653 : BOOST_SYSTEM_CONSTEXPR explicit operator bool() const BOOST_NOEXCEPT // true if error
654 : {
655 : return val_ != 0;
656 : }
657 :
658 : #else
659 :
660 : typedef void (*unspecified_bool_type)();
661 : static void unspecified_bool_true() {}
662 :
663 : BOOST_SYSTEM_CONSTEXPR operator unspecified_bool_type() const BOOST_NOEXCEPT // true if error
664 : {
665 : return val_ != 0? unspecified_bool_true: 0;
666 : }
667 :
668 : BOOST_SYSTEM_CONSTEXPR bool operator!() const BOOST_NOEXCEPT // true if no error
669 : {
670 : return val_ == 0;
671 : }
672 :
673 : #endif
674 :
675 : // relationals:
676 :
677 : // the more symmetrical non-member syntax allows enum
678 : // conversions work for both rhs and lhs.
679 :
680 : BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( const error_code & lhs, const error_code & rhs ) BOOST_NOEXCEPT
681 : {
682 : return lhs.val_ == rhs.val_ && *lhs.cat_ == *rhs.cat_;
683 : }
684 :
685 : BOOST_SYSTEM_CONSTEXPR inline friend bool operator<( const error_code & lhs, const error_code & rhs ) BOOST_NOEXCEPT
686 : {
687 : return *lhs.cat_ < *rhs.cat_ || ( *lhs.cat_ == *rhs.cat_ && lhs.val_ < rhs.val_ );
688 : }
689 :
690 : #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
691 :
692 : operator std::error_code () const
693 : {
694 : return std::error_code( value(), category() );
695 : }
696 :
697 : #endif
698 : };
699 :
700 : } // namespace system
701 :
702 : // boost::throws()
703 :
704 : namespace detail
705 : {
706 :
707 : // Misuse of the error_code object is turned into a noisy failure by
708 : // poisoning the reference. This particular implementation doesn't
709 : // produce warnings or errors from popular compilers, is very efficient
710 : // (as determined by inspecting generated code), and does not suffer
711 : // from order of initialization problems. In practice, it also seems
712 : // cause user function error handling implementation errors to be detected
713 : // very early in the development cycle.
714 :
715 : inline system::error_code* throws()
716 : {
717 : // See github.com/boostorg/system/pull/12 by visigoth for why the return
718 : // is poisoned with nonzero rather than (0). A test, test_throws_usage(),
719 : // has been added to error_code_test.cpp, and as visigoth mentioned it
720 : // fails on clang for release builds with a return of 0 but works fine
721 : // with (1).
722 : // Since the undefined behavior sanitizer (-fsanitize=undefined) does not
723 : // allow a reference to be formed to the unaligned address of (1), we use
724 : // (8) instead.
725 :
726 : return reinterpret_cast<system::error_code*>(8);
727 : }
728 :
729 : } // namespace detail
730 :
731 : inline system::error_code& throws()
732 : {
733 : return *detail::throws();
734 : }
735 :
736 : // non-member functions of error_code and error_condition
737 :
738 : namespace system
739 : {
740 :
741 : BOOST_SYSTEM_CONSTEXPR inline bool operator!=( const error_code & lhs, const error_code & rhs ) BOOST_NOEXCEPT
742 : {
743 : return !( lhs == rhs );
744 : }
745 :
746 : BOOST_SYSTEM_CONSTEXPR inline bool operator!=( const error_condition & lhs, const error_condition & rhs ) BOOST_NOEXCEPT
747 : {
748 : return !( lhs == rhs );
749 : }
750 :
751 : inline bool operator==( const error_code & code, const error_condition & condition ) BOOST_NOEXCEPT
752 : {
753 : return code.category().equivalent( code.value(), condition ) || condition.category().equivalent( code, condition.value() );
754 : }
755 :
756 : inline bool operator!=( const error_code & lhs, const error_condition & rhs ) BOOST_NOEXCEPT
757 : {
758 : return !( lhs == rhs );
759 : }
760 :
761 : inline bool operator==( const error_condition & condition, const error_code & code ) BOOST_NOEXCEPT
762 : {
763 : return code.category().equivalent( code.value(), condition ) || condition.category().equivalent( code, condition.value() );
764 : }
765 :
766 : inline bool operator!=( const error_condition & lhs, const error_code & rhs ) BOOST_NOEXCEPT
767 : {
768 : return !( lhs == rhs );
769 : }
770 :
771 : template <class charT, class traits>
772 : inline std::basic_ostream<charT,traits>&
773 : operator<< (std::basic_ostream<charT,traits>& os, error_code ec)
774 : {
775 : os << ec.category().name() << ':' << ec.value();
776 : return os;
777 : }
778 :
779 : inline std::size_t hash_value( error_code const & ec )
780 : {
781 : error_category const & cat = ec.category();
782 :
783 : boost::ulong_long_type id = cat.id_;
784 :
785 : if( id == 0 )
786 : {
787 : id = reinterpret_cast<boost::uintptr_t>( &cat );
788 : }
789 :
790 : boost::ulong_long_type hv = ( boost::ulong_long_type( 0xCBF29CE4 ) << 32 ) + 0x84222325;
791 : boost::ulong_long_type const prime = ( boost::ulong_long_type( 0x00000100 ) << 32 ) + 0x000001B3;
792 :
793 : // id
794 :
795 : hv ^= id;
796 : hv *= prime;
797 :
798 : // value
799 :
800 : hv ^= static_cast<unsigned>( ec.value() );
801 : hv *= prime;
802 :
803 : return static_cast<std::size_t>( hv );
804 : }
805 :
806 : // make_* functions for errc::errc_t
807 :
808 : namespace errc
809 : {
810 :
811 : // explicit conversion:
812 : BOOST_SYSTEM_CONSTEXPR inline error_code make_error_code( errc_t e ) BOOST_NOEXCEPT
813 : {
814 : return error_code( e, generic_category() );
815 : }
816 :
817 : // implicit conversion:
818 : BOOST_SYSTEM_CONSTEXPR inline error_condition make_error_condition( errc_t e ) BOOST_NOEXCEPT
819 : {
820 : return error_condition( e, generic_category() );
821 : }
822 :
823 : } // namespace errc
824 :
825 : // error_category default implementation
826 :
827 0 : inline error_condition error_category::default_error_condition( int ev ) const BOOST_NOEXCEPT
828 : {
829 0 : return error_condition( ev, *this );
830 : }
831 :
832 0 : inline bool error_category::equivalent( int code, const error_condition & condition ) const BOOST_NOEXCEPT
833 : {
834 0 : return default_error_condition( code ) == condition;
835 : }
836 :
837 0 : inline bool error_category::equivalent( const error_code & code, int condition ) const BOOST_NOEXCEPT
838 : {
839 0 : return *this == code.category() && code.value() == condition;
840 : }
841 :
842 0 : inline char const * error_category::message( int ev, char * buffer, std::size_t len ) const BOOST_NOEXCEPT
843 : {
844 0 : if( len == 0 )
845 : {
846 : return buffer;
847 : }
848 :
849 0 : if( len == 1 )
850 : {
851 0 : buffer[0] = 0;
852 0 : return buffer;
853 : }
854 :
855 : #if !defined(BOOST_NO_EXCEPTIONS)
856 0 : try
857 : #endif
858 : {
859 0 : std::string m = this->message( ev );
860 :
861 : # if defined( BOOST_MSVC )
862 : # pragma warning( push )
863 : # pragma warning( disable: 4996 )
864 : # elif defined(__clang__) && defined(__has_warning)
865 : # pragma clang diagnostic push
866 : # if __has_warning("-Wdeprecated-declarations")
867 : # pragma clang diagnostic ignored "-Wdeprecated-declarations"
868 : # endif
869 : # endif
870 :
871 0 : std::strncpy( buffer, m.c_str(), len - 1 );
872 0 : buffer[ len-1 ] = 0;
873 :
874 : # if defined( BOOST_MSVC )
875 : # pragma warning( pop )
876 : # elif defined(__clang__) && defined(__has_warning)
877 : # pragma clang diagnostic pop
878 : # endif
879 :
880 0 : return buffer;
881 : }
882 : #if !defined(BOOST_NO_EXCEPTIONS)
883 0 : catch( ... )
884 : {
885 0 : return "Message text unavailable";
886 : }
887 : #endif
888 : }
889 :
890 0 : inline bool error_category::failed( int ev ) const BOOST_NOEXCEPT
891 : {
892 0 : return ev != 0;
893 : }
894 :
895 : } // namespace system
896 :
897 : } // namespace boost
898 :
899 : // generic_error_category implementation
900 :
901 : #include <boost/system/detail/generic_category.hpp>
902 :
903 0 : inline std::string boost::system::detail::generic_error_category::message( int ev ) const
904 : {
905 0 : return generic_error_category_message( ev );
906 : }
907 :
908 0 : inline char const * boost::system::detail::generic_error_category::message( int ev, char * buffer, std::size_t len ) const BOOST_NOEXCEPT
909 : {
910 0 : return generic_error_category_message( ev, buffer, len );
911 : }
912 :
913 : // system_error_category implementation
914 :
915 : #if defined(BOOST_WINDOWS_API)
916 :
917 : #include <boost/system/detail/system_category_win32.hpp>
918 :
919 : inline boost::system::error_condition boost::system::detail::system_error_category::default_error_condition( int ev ) const BOOST_NOEXCEPT
920 : {
921 : return system_category_default_error_condition_win32( ev );
922 : }
923 :
924 : inline std::string boost::system::detail::system_error_category::message( int ev ) const
925 : {
926 : return system_category_message_win32( ev );
927 : }
928 :
929 : inline char const * boost::system::detail::system_error_category::message( int ev, char * buffer, std::size_t len ) const BOOST_NOEXCEPT
930 : {
931 : return system_category_message_win32( ev, buffer, len );
932 : }
933 :
934 : #else // #if defined(BOOST_WINDOWS_API)
935 :
936 : #include <boost/system/detail/system_category_posix.hpp>
937 :
938 0 : inline boost::system::error_condition boost::system::detail::system_error_category::default_error_condition( int ev ) const BOOST_NOEXCEPT
939 : {
940 0 : return system_category_default_error_condition_posix( ev );
941 : }
942 :
943 0 : inline std::string boost::system::detail::system_error_category::message( int ev ) const
944 : {
945 0 : return generic_error_category_message( ev );
946 : }
947 :
948 0 : inline char const * boost::system::detail::system_error_category::message( int ev, char * buffer, std::size_t len ) const BOOST_NOEXCEPT
949 : {
950 0 : return generic_error_category_message( ev, buffer, len );
951 : }
952 :
953 : #endif // #if defined(BOOST_WINDOWS_API)
954 :
955 : // interoperability with std::error_code, std::error_condition
956 :
957 : #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
958 :
959 : #include <boost/system/detail/std_interoperability.hpp>
960 :
961 0 : inline boost::system::error_category::operator std::error_category const & () const
962 : {
963 0 : return boost::system::detail::to_std_category( *this );
964 : }
965 :
966 : #endif // #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
967 :
968 : #endif // BOOST_SYSTEM_ERROR_CODE_HPP_INCLUDED
|