File indexing completed on 2025-01-18 09:52:35
0001 #ifndef BOOST_SYSTEM_DETAIL_ERROR_CODE_HPP_INCLUDED
0002 #define BOOST_SYSTEM_DETAIL_ERROR_CODE_HPP_INCLUDED
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <boost/system/is_error_code_enum.hpp>
0014 #include <boost/system/detail/error_category.hpp>
0015 #include <boost/system/detail/error_condition.hpp>
0016 #include <boost/system/detail/system_category.hpp>
0017 #include <boost/system/detail/system_category_impl.hpp>
0018 #include <boost/system/detail/interop_category.hpp>
0019 #include <boost/system/detail/enable_if.hpp>
0020 #include <boost/system/detail/is_same.hpp>
0021 #include <boost/system/detail/append_int.hpp>
0022 #include <boost/system/detail/snprintf.hpp>
0023 #include <boost/system/detail/config.hpp>
0024
0025 #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
0026 # include <boost/system/detail/std_category.hpp>
0027 #endif
0028
0029 #include <boost/assert/source_location.hpp>
0030 #include <boost/cstdint.hpp>
0031 #include <boost/config.hpp>
0032 #include <boost/config/workaround.hpp>
0033 #include <ostream>
0034 #include <new>
0035 #include <cstdio>
0036
0037 #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
0038 # include <system_error>
0039 #endif
0040
0041 #if defined(BOOST_GCC) && BOOST_GCC >= 40600 && BOOST_GCC < 70000
0042 # pragma GCC diagnostic push
0043 # pragma GCC diagnostic ignored "-Wstrict-aliasing"
0044 #endif
0045
0046 namespace boost
0047 {
0048
0049 namespace system
0050 {
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061 bool operator==( const error_code & code, const error_condition & condition ) BOOST_NOEXCEPT;
0062 std::size_t hash_value( error_code const & ec );
0063
0064 class error_code
0065 {
0066 private:
0067
0068 friend bool operator==( const error_code & code, const error_condition & condition ) BOOST_NOEXCEPT;
0069 friend std::size_t hash_value( error_code const & ec );
0070
0071 private:
0072
0073 struct data
0074 {
0075 int val_;
0076 const error_category * cat_;
0077 };
0078
0079 union
0080 {
0081 data d1_;
0082 #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
0083 unsigned char d2_[ sizeof(std::error_code) ];
0084 #endif
0085 };
0086
0087
0088
0089
0090
0091
0092 boost::uintptr_t lc_flags_;
0093
0094 private:
0095
0096 char const* category_name() const BOOST_NOEXCEPT
0097 {
0098
0099
0100 if( lc_flags_ == 0 )
0101 {
0102
0103 return "system";
0104 }
0105 else if( lc_flags_ == 1 )
0106 {
0107
0108 return "std:unknown";
0109 }
0110 else
0111 {
0112 return d1_.cat_->name();
0113 }
0114 }
0115
0116 public:
0117
0118
0119
0120 #if !BOOST_WORKAROUND(BOOST_GCC, < 40800)
0121 BOOST_CONSTEXPR
0122 #endif
0123 error_code() BOOST_NOEXCEPT:
0124 d1_(), lc_flags_( 0 )
0125 {
0126 }
0127
0128 BOOST_SYSTEM_CONSTEXPR error_code( int val, const error_category & cat ) BOOST_NOEXCEPT:
0129 d1_(), lc_flags_( 2 + detail::failed_impl( val, cat ) )
0130 {
0131 d1_.val_ = val;
0132 d1_.cat_ = &cat;
0133 }
0134
0135 error_code( int val, const error_category & cat, source_location const * loc ) BOOST_NOEXCEPT:
0136 d1_(), lc_flags_( ( loc? reinterpret_cast<boost::uintptr_t>( loc ): 2 ) | +detail::failed_impl( val, cat ) )
0137 {
0138 d1_.val_ = val;
0139 d1_.cat_ = &cat;
0140 }
0141
0142 template<class ErrorCodeEnum> BOOST_SYSTEM_CONSTEXPR error_code( ErrorCodeEnum e,
0143 typename detail::enable_if<
0144 is_error_code_enum<ErrorCodeEnum>::value
0145 #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
0146 || std::is_error_code_enum<ErrorCodeEnum>::value
0147 #endif
0148 >::type* = 0 ) BOOST_NOEXCEPT: d1_(), lc_flags_( 0 )
0149 {
0150 *this = make_error_code( e );
0151 }
0152
0153 error_code( error_code const& ec, source_location const * loc ) BOOST_NOEXCEPT:
0154 d1_(), lc_flags_( 0 )
0155 {
0156 *this = ec;
0157
0158 if( ec.lc_flags_ != 0 && ec.lc_flags_ != 1 )
0159 {
0160 lc_flags_ = ( loc? reinterpret_cast<boost::uintptr_t>( loc ): 2 ) | ( ec.lc_flags_ & 1 );
0161 }
0162 }
0163
0164 #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
0165
0166 error_code( std::error_code const& ec ) BOOST_NOEXCEPT:
0167 d1_(), lc_flags_( 0 )
0168 {
0169 #ifndef BOOST_NO_RTTI
0170
0171 if( detail::std_category const* pc2 = dynamic_cast< detail::std_category const* >( &ec.category() ) )
0172 {
0173 *this = boost::system::error_code( ec.value(), pc2->original_category() );
0174 }
0175 else
0176
0177 #endif
0178 {
0179 ::new( d2_ ) std::error_code( ec );
0180 lc_flags_ = 1;
0181 }
0182 }
0183
0184 #endif
0185
0186
0187
0188 BOOST_SYSTEM_CONSTEXPR void assign( int val, const error_category & cat ) BOOST_NOEXCEPT
0189 {
0190 *this = error_code( val, cat );
0191 }
0192
0193 void assign( int val, const error_category & cat, source_location const * loc ) BOOST_NOEXCEPT
0194 {
0195 *this = error_code( val, cat, loc );
0196 }
0197
0198 void assign( error_code const& ec, source_location const * loc ) BOOST_NOEXCEPT
0199 {
0200 *this = error_code( ec, loc );
0201 }
0202
0203 template<typename ErrorCodeEnum>
0204 BOOST_SYSTEM_CONSTEXPR typename detail::enable_if<is_error_code_enum<ErrorCodeEnum>::value, error_code>::type &
0205 operator=( ErrorCodeEnum val ) BOOST_NOEXCEPT
0206 {
0207 *this = make_error_code( val );
0208 return *this;
0209 }
0210
0211 BOOST_SYSTEM_CONSTEXPR void clear() BOOST_NOEXCEPT
0212 {
0213 *this = error_code();
0214 }
0215
0216
0217
0218 BOOST_SYSTEM_CONSTEXPR int value() const BOOST_NOEXCEPT
0219 {
0220 if( lc_flags_ != 1 )
0221 {
0222 return d1_.val_;
0223 }
0224 else
0225 {
0226 #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
0227
0228 std::error_code const& ec = *reinterpret_cast<std::error_code const*>( d2_ );
0229
0230 unsigned cv = static_cast<unsigned>( ec.value() );
0231 unsigned ch = static_cast<unsigned>( reinterpret_cast<boost::uintptr_t>( &ec.category() ) % 2097143 );
0232
0233 return static_cast<int>( cv + 1000 * ch );
0234 #else
0235
0236 return -1;
0237 #endif
0238 }
0239 }
0240
0241 BOOST_SYSTEM_CONSTEXPR const error_category & category() const BOOST_NOEXCEPT
0242 {
0243 if( lc_flags_ == 0 )
0244 {
0245 return system_category();
0246 }
0247 else if( lc_flags_ == 1 )
0248 {
0249 return detail::interop_category();
0250 }
0251 else
0252 {
0253 return *d1_.cat_;
0254 }
0255 }
0256
0257
0258 error_condition default_error_condition() const BOOST_NOEXCEPT
0259 {
0260 return category().default_error_condition( value() );
0261 }
0262
0263 std::string message() const
0264 {
0265 #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
0266
0267 if( lc_flags_ == 1 )
0268 {
0269 std::error_code const& ec = *reinterpret_cast<std::error_code const*>( d2_ );
0270 return ec.message();
0271 }
0272
0273 #endif
0274
0275 if( lc_flags_ == 0 )
0276 {
0277 return detail::system_error_category_message( value() );
0278 }
0279 else
0280 {
0281 return category().message( value() );
0282 }
0283 }
0284
0285 char const * message( char * buffer, std::size_t len ) const BOOST_NOEXCEPT
0286 {
0287 #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
0288 if( lc_flags_ == 1 )
0289 {
0290 std::error_code const& ec = *reinterpret_cast<std::error_code const*>( d2_ );
0291
0292 #if !defined(BOOST_NO_EXCEPTIONS)
0293 try
0294 #endif
0295 {
0296 detail::snprintf( buffer, len, "%s", ec.message().c_str() );
0297 return buffer;
0298 }
0299 #if !defined(BOOST_NO_EXCEPTIONS)
0300 catch( ... )
0301 {
0302 detail::snprintf( buffer, len, "No message text available for error std:%s:%d", ec.category().name(), ec.value() );
0303 return buffer;
0304 }
0305 #endif
0306 }
0307 #endif
0308
0309 if( lc_flags_ == 0 )
0310 {
0311 return detail::system_error_category_message( value(), buffer, len );
0312 }
0313 else
0314 {
0315 return category().message( value(), buffer, len );
0316 }
0317 }
0318
0319 BOOST_SYSTEM_CONSTEXPR bool failed() const BOOST_NOEXCEPT
0320 {
0321 if( lc_flags_ & 1 )
0322 {
0323 #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
0324 if( lc_flags_ == 1 )
0325 {
0326 std::error_code const& ec = *reinterpret_cast<std::error_code const*>( d2_ );
0327 return ec.value() != 0;
0328 }
0329 #endif
0330 return true;
0331 }
0332 else
0333 {
0334 return false;
0335 }
0336 }
0337
0338 #if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
0339
0340 BOOST_SYSTEM_CONSTEXPR explicit operator bool() const BOOST_NOEXCEPT
0341 {
0342 return failed();
0343 }
0344
0345 #else
0346
0347 typedef void (*unspecified_bool_type)();
0348 static void unspecified_bool_true() {}
0349
0350 BOOST_SYSTEM_CONSTEXPR operator unspecified_bool_type() const BOOST_NOEXCEPT
0351 {
0352 return failed()? unspecified_bool_true: 0;
0353 }
0354
0355 BOOST_SYSTEM_CONSTEXPR bool operator!() const BOOST_NOEXCEPT
0356 {
0357 return !failed();
0358 }
0359
0360 #endif
0361
0362 bool has_location() const BOOST_NOEXCEPT
0363 {
0364 return lc_flags_ >= 4;
0365 }
0366
0367 source_location const & location() const BOOST_NOEXCEPT
0368 {
0369 BOOST_STATIC_CONSTEXPR source_location loc;
0370 return lc_flags_ >= 4? *reinterpret_cast<source_location const*>( lc_flags_ &~ static_cast<boost::uintptr_t>( 1 ) ): loc;
0371 }
0372
0373
0374
0375 private:
0376
0377
0378
0379 friend class error_category;
0380
0381 BOOST_SYSTEM_CONSTEXPR bool equals( int val, error_category const& cat ) const BOOST_NOEXCEPT
0382 {
0383 if( lc_flags_ == 0 )
0384 {
0385 return val == 0 && cat.id_ == detail::system_category_id;
0386 }
0387 else if( lc_flags_ == 1 )
0388 {
0389 return cat.id_ == detail::interop_category_id && val == value();
0390 }
0391 else
0392 {
0393 return val == d1_.val_ && cat == *d1_.cat_;
0394 }
0395 }
0396
0397 public:
0398
0399
0400
0401
0402 BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( const error_code & lhs, const error_code & rhs ) BOOST_NOEXCEPT
0403 {
0404 #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
0405
0406 bool s1 = lhs.lc_flags_ == 1;
0407 bool s2 = rhs.lc_flags_ == 1;
0408
0409 if( s1 != s2 ) return false;
0410
0411 if( s1 && s2 )
0412 {
0413 std::error_code const& e1 = *reinterpret_cast<std::error_code const*>( lhs.d2_ );
0414 std::error_code const& e2 = *reinterpret_cast<std::error_code const*>( rhs.d2_ );
0415
0416 return e1 == e2;
0417 }
0418 else
0419 #endif
0420 {
0421 return lhs.value() == rhs.value() && lhs.category() == rhs.category();
0422 }
0423 }
0424
0425 BOOST_SYSTEM_CONSTEXPR inline friend bool operator<( const error_code & lhs, const error_code & rhs ) BOOST_NOEXCEPT
0426 {
0427 #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
0428
0429 bool s1 = lhs.lc_flags_ == 1;
0430 bool s2 = rhs.lc_flags_ == 1;
0431
0432 if( s1 < s2 ) return true;
0433 if( s2 < s1 ) return false;
0434
0435 if( s1 && s2 )
0436 {
0437 std::error_code const& e1 = *reinterpret_cast<std::error_code const*>( lhs.d2_ );
0438 std::error_code const& e2 = *reinterpret_cast<std::error_code const*>( rhs.d2_ );
0439
0440 return e1 < e2;
0441 }
0442 else
0443 #endif
0444 {
0445 return lhs.category() < rhs.category() || (lhs.category() == rhs.category() && lhs.value() < rhs.value());
0446 }
0447 }
0448
0449 BOOST_SYSTEM_CONSTEXPR inline friend bool operator!=( const error_code & lhs, const error_code & rhs ) BOOST_NOEXCEPT
0450 {
0451 return !( lhs == rhs );
0452 }
0453
0454 #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
0455
0456 inline friend bool operator==( std::error_code const & lhs, error_code const & rhs ) BOOST_NOEXCEPT
0457 {
0458 return lhs == static_cast< std::error_code >( rhs );
0459 }
0460
0461 inline friend bool operator==( error_code const & lhs, std::error_code const & rhs ) BOOST_NOEXCEPT
0462 {
0463 return static_cast< std::error_code >( lhs ) == rhs;
0464 }
0465
0466 inline friend bool operator!=( std::error_code const & lhs, error_code const & rhs ) BOOST_NOEXCEPT
0467 {
0468 return !( lhs == rhs );
0469 }
0470
0471 inline friend bool operator!=( error_code const & lhs, std::error_code const & rhs ) BOOST_NOEXCEPT
0472 {
0473 return !( lhs == rhs );
0474 }
0475
0476
0477
0478 template<class E, class N = typename detail::enable_if<std::is_error_condition_enum<E>::value>::type>
0479 inline friend bool operator==( error_code const & lhs, E rhs ) BOOST_NOEXCEPT
0480 {
0481 return lhs == make_error_condition( rhs );
0482 }
0483
0484 template<class E, class N = typename detail::enable_if<std::is_error_condition_enum<E>::value>::type>
0485 inline friend bool operator==( E lhs, error_code const & rhs ) BOOST_NOEXCEPT
0486 {
0487 return make_error_condition( lhs ) == rhs;
0488 }
0489
0490 template<class E, class N = typename detail::enable_if<std::is_error_condition_enum<E>::value>::type>
0491 inline friend bool operator!=( error_code const & lhs, E rhs ) BOOST_NOEXCEPT
0492 {
0493 return !( lhs == rhs );
0494 }
0495
0496 template<class E, class N = typename detail::enable_if<std::is_error_condition_enum<E>::value>::type>
0497 inline friend bool operator!=( E lhs, error_code const & rhs ) BOOST_NOEXCEPT
0498 {
0499 return !( lhs == rhs );
0500 }
0501
0502
0503
0504 template<class E, class N1 = void, class N2 = typename detail::enable_if<std::is_error_code_enum<E>::value>::type>
0505 BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( error_code const & lhs, E rhs ) BOOST_NOEXCEPT
0506 {
0507 return lhs == make_error_code( rhs );
0508 }
0509
0510 template<class E, class N1 = void, class N2 = typename detail::enable_if<std::is_error_code_enum<E>::value>::type>
0511 BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( E lhs, error_code const & rhs ) BOOST_NOEXCEPT
0512 {
0513 return make_error_code( lhs ) == rhs;
0514 }
0515
0516 template<class E, class N1 = void, class N2 = typename detail::enable_if<std::is_error_code_enum<E>::value>::type>
0517 BOOST_SYSTEM_CONSTEXPR inline friend bool operator!=( error_code const & lhs, E rhs ) BOOST_NOEXCEPT
0518 {
0519 return !( lhs == rhs );
0520 }
0521
0522 template<class E, class N1 = void, class N2 = typename detail::enable_if<std::is_error_code_enum<E>::value>::type>
0523 BOOST_SYSTEM_CONSTEXPR inline friend bool operator!=( E lhs, error_code const & rhs ) BOOST_NOEXCEPT
0524 {
0525 return !( lhs == rhs );
0526 }
0527
0528 #if defined(BOOST_SYSTEM_CLANG_6)
0529
0530 inline friend bool operator==( error_code const & lhs, std::error_condition const & rhs ) BOOST_NOEXCEPT
0531 {
0532 return static_cast< std::error_code >( lhs ) == rhs;
0533 }
0534
0535 inline friend bool operator==( std::error_condition const & lhs, error_code const & rhs ) BOOST_NOEXCEPT
0536 {
0537 return lhs == static_cast< std::error_code >( rhs );
0538 }
0539
0540 inline friend bool operator!=( error_code const & lhs, std::error_condition const & rhs ) BOOST_NOEXCEPT
0541 {
0542 return !( lhs == rhs );
0543 }
0544
0545 inline friend bool operator!=( std::error_condition const & lhs, error_code const & rhs ) BOOST_NOEXCEPT
0546 {
0547 return !( lhs == rhs );
0548 }
0549
0550 #endif
0551
0552
0553
0554 operator std::error_code () const
0555 {
0556 if( lc_flags_ == 1 )
0557 {
0558 return *reinterpret_cast<std::error_code const*>( d2_ );
0559 }
0560 else if( lc_flags_ == 0 )
0561 {
0562
0563 #if defined(BOOST_SYSTEM_AVOID_STD_SYSTEM_CATEGORY)
0564
0565 return std::error_code( 0, boost::system::system_category() );
0566
0567 #else
0568
0569 return std::error_code();
0570
0571 #endif
0572 }
0573 else
0574 {
0575 return std::error_code( d1_.val_, *d1_.cat_ );
0576 }
0577 }
0578
0579 operator std::error_code ()
0580 {
0581 return const_cast<error_code const&>( *this );
0582 }
0583
0584 template<class T,
0585 class E = typename detail::enable_if<detail::is_same<T, std::error_code>::value>::type>
0586 operator T& ()
0587 {
0588 if( lc_flags_ != 1 )
0589 {
0590 std::error_code e2( *this );
0591 ::new( d2_ ) std::error_code( e2 );
0592 lc_flags_ = 1;
0593 }
0594
0595 return *reinterpret_cast<std::error_code*>( d2_ );
0596 }
0597
0598 #if defined(BOOST_SYSTEM_CLANG_6)
0599
0600 template<class T,
0601 class E = typename std::enable_if<std::is_same<T, std::error_code>::value>::type>
0602 operator T const& () = delete;
0603
0604 #endif
0605
0606 #endif
0607
0608 std::string to_string() const
0609 {
0610 #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
0611
0612 if( lc_flags_ == 1 )
0613 {
0614 std::error_code const& e2 = *reinterpret_cast<std::error_code const*>( d2_ );
0615
0616 std::string r( "std:" );
0617 r += e2.category().name();
0618 detail::append_int( r, e2.value() );
0619
0620 return r;
0621 }
0622 else
0623 #endif
0624 {
0625 std::string r = category_name();
0626 detail::append_int( r, value() );
0627 return r;
0628 }
0629 }
0630
0631 template<class Ch, class Tr>
0632 inline friend std::basic_ostream<Ch, Tr>&
0633 operator<< (std::basic_ostream<Ch, Tr>& os, error_code const & ec)
0634 {
0635 return os << ec.to_string().c_str();
0636 }
0637
0638 std::string what() const
0639 {
0640 std::string r = message();
0641
0642 r += " [";
0643 r += to_string();
0644
0645 if( has_location() )
0646 {
0647 r += " at ";
0648 r += location().to_string();
0649 }
0650
0651 r += "]";
0652 return r;
0653 }
0654 };
0655
0656 inline bool operator==( const error_code & code, const error_condition & condition ) BOOST_NOEXCEPT
0657 {
0658 #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
0659
0660 if( code.lc_flags_ == 1 )
0661 {
0662 return static_cast<std::error_code>( code ) == static_cast<std::error_condition>( condition );
0663 }
0664 else
0665
0666 #endif
0667 {
0668 return code.category().equivalent( code.value(), condition ) || condition.category().equivalent( code, condition.value() );
0669 }
0670 }
0671
0672 inline bool operator==( const error_condition & condition, const error_code & code ) BOOST_NOEXCEPT
0673 {
0674 return code == condition;
0675 }
0676
0677 inline bool operator!=( const error_code & lhs, const error_condition & rhs ) BOOST_NOEXCEPT
0678 {
0679 return !( lhs == rhs );
0680 }
0681
0682 inline bool operator!=( const error_condition & lhs, const error_code & rhs ) BOOST_NOEXCEPT
0683 {
0684 return !( lhs == rhs );
0685 }
0686
0687 inline std::size_t hash_value( error_code const & ec )
0688 {
0689 #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
0690
0691 if( ec.lc_flags_ == 1 )
0692 {
0693 std::error_code const& e2 = *reinterpret_cast<std::error_code const*>( ec.d2_ );
0694 return std::hash<std::error_code>()( e2 );
0695 }
0696
0697 #endif
0698
0699 error_category const & cat = ec.category();
0700
0701 boost::ulong_long_type id_ = cat.id_;
0702
0703 if( id_ == 0 )
0704 {
0705 id_ = reinterpret_cast<boost::uintptr_t>( &cat );
0706 }
0707
0708 boost::ulong_long_type hv = ( boost::ulong_long_type( 0xCBF29CE4 ) << 32 ) + 0x84222325;
0709 boost::ulong_long_type const prime = ( boost::ulong_long_type( 0x00000100 ) << 32 ) + 0x000001B3;
0710
0711
0712
0713 hv ^= id_;
0714 hv *= prime;
0715
0716
0717
0718 hv ^= static_cast<unsigned>( ec.value() );
0719 hv *= prime;
0720
0721 return static_cast<std::size_t>( hv );
0722 }
0723
0724 }
0725
0726 }
0727
0728 #if defined(BOOST_GCC) && BOOST_GCC >= 40600 && BOOST_GCC < 70000
0729 # pragma GCC diagnostic pop
0730 #endif
0731
0732 #endif