Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/system/detail/error_code.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 #ifndef BOOST_SYSTEM_DETAIL_ERROR_CODE_HPP_INCLUDED
0002 #define BOOST_SYSTEM_DETAIL_ERROR_CODE_HPP_INCLUDED
0003 
0004 //  Copyright Beman Dawes 2006, 2007
0005 //  Copyright Christoper Kohlhoff 2007
0006 //  Copyright Peter Dimov 2017-2021
0007 //
0008 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
0009 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0010 //
0011 //  See library home page at http://www.boost.org/libs/system
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 #include <boost/system/detail/std_category.hpp>
0025 #include <boost/assert/source_location.hpp>
0026 #include <boost/cstdint.hpp>
0027 #include <boost/config.hpp>
0028 #include <boost/config/workaround.hpp>
0029 #include <ostream>
0030 #include <new>
0031 #include <cstdio>
0032 #include <system_error>
0033 
0034 #if defined(BOOST_GCC) && BOOST_GCC >= 40600 && BOOST_GCC < 70000
0035 # pragma GCC diagnostic push
0036 # pragma GCC diagnostic ignored "-Wstrict-aliasing"
0037 #endif
0038 
0039 namespace boost
0040 {
0041 
0042 namespace system
0043 {
0044 
0045 //  class error_code
0046 
0047 //  We want error_code to be a value type that can be copied without slicing
0048 //  and without requiring heap allocation, but we also want it to have
0049 //  polymorphic behavior based on the error category. This is achieved by
0050 //  abstract base class error_category supplying the polymorphic behavior,
0051 //  and error_code containing a pointer to an object of a type derived
0052 //  from error_category.
0053 
0054 bool operator==( const error_code & code, const error_condition & condition ) noexcept;
0055 std::size_t hash_value( error_code const & ec );
0056 
0057 class error_code
0058 {
0059 private:
0060 
0061     friend bool operator==( const error_code & code, const error_condition & condition ) noexcept;
0062     friend std::size_t hash_value( error_code const & ec );
0063 
0064 private:
0065 
0066     struct data
0067     {
0068         int val_;
0069         const error_category * cat_;
0070     };
0071 
0072     union
0073     {
0074         data d1_;
0075         unsigned char d2_[ sizeof(std::error_code) ];
0076     };
0077 
0078     // 0: default constructed, d1_ value initialized
0079     // 1: holds std::error_code in d2_
0080     // 2: holds error code in d1_, failed == false
0081     // 3: holds error code in d1_, failed == true
0082     // >3: pointer to source_location, failed_ in lsb
0083     boost::uintptr_t lc_flags_;
0084 
0085 private:
0086 
0087     char const* category_name() const noexcept
0088     {
0089         // return category().name();
0090 
0091         if( lc_flags_ == 0 )
0092         {
0093             // must match detail::system_error_category::name()
0094             return "system";
0095         }
0096         else if( lc_flags_ == 1 )
0097         {
0098             // must match detail::interop_error_category::name()
0099             return "std:unknown";
0100         }
0101         else
0102         {
0103             return d1_.cat_->name();
0104         }
0105     }
0106 
0107 public:
0108 
0109     // constructors:
0110 
0111     constexpr error_code() noexcept:
0112         d1_(), lc_flags_( 0 )
0113     {
0114     }
0115 
0116     BOOST_SYSTEM_CONSTEXPR error_code( int val, const error_category & cat ) noexcept:
0117         d1_(), lc_flags_( 2 + detail::failed_impl( val, cat ) )
0118     {
0119         d1_.val_ = val;
0120         d1_.cat_ = &cat;
0121     }
0122 
0123     error_code( int val, const error_category & cat, source_location const * loc ) noexcept:
0124         d1_(), lc_flags_( ( loc? reinterpret_cast<boost::uintptr_t>( loc ): 2 ) | +detail::failed_impl( val, cat ) )
0125     {
0126         d1_.val_ = val;
0127         d1_.cat_ = &cat;
0128     }
0129 
0130     template<class ErrorCodeEnum> BOOST_SYSTEM_CONSTEXPR error_code( ErrorCodeEnum e,
0131         typename detail::enable_if<
0132             is_error_code_enum<ErrorCodeEnum>::value
0133             || std::is_error_code_enum<ErrorCodeEnum>::value
0134         >::type* = 0 ) noexcept: d1_(), lc_flags_( 0 )
0135     {
0136         *this = make_error_code( e );
0137     }
0138 
0139     error_code( error_code const& ec, source_location const * loc ) noexcept:
0140         d1_(), lc_flags_( 0 )
0141     {
0142         *this = ec;
0143 
0144         if( ec.lc_flags_ != 0 && ec.lc_flags_ != 1 )
0145         {
0146             lc_flags_ = ( loc? reinterpret_cast<boost::uintptr_t>( loc ): 2 ) | ( ec.lc_flags_ & 1 );
0147         }
0148     }
0149 
0150     error_code( std::error_code const& ec ) noexcept:
0151         d1_(), lc_flags_( 0 )
0152     {
0153 #ifndef BOOST_NO_RTTI
0154 
0155         if( detail::std_category const* pc2 = dynamic_cast< detail::std_category const* >( &ec.category() ) )
0156         {
0157             *this = boost::system::error_code( ec.value(), pc2->original_category() );
0158         }
0159         else
0160 
0161 #endif
0162         {
0163             ::new( d2_ ) std::error_code( ec );
0164             lc_flags_ = 1;
0165         }
0166     }
0167 
0168     // modifiers:
0169 
0170     BOOST_SYSTEM_CONSTEXPR void assign( int val, const error_category & cat ) noexcept
0171     {
0172         *this = error_code( val, cat );
0173     }
0174 
0175     void assign( int val, const error_category & cat, source_location const * loc ) noexcept
0176     {
0177         *this = error_code( val, cat, loc );
0178     }
0179 
0180     void assign( error_code const& ec, source_location const * loc ) noexcept
0181     {
0182         *this = error_code( ec, loc );
0183     }
0184 
0185     template<typename ErrorCodeEnum>
0186         BOOST_SYSTEM_CONSTEXPR typename detail::enable_if<is_error_code_enum<ErrorCodeEnum>::value, error_code>::type &
0187         operator=( ErrorCodeEnum val ) noexcept
0188     {
0189         *this = make_error_code( val );
0190         return *this;
0191     }
0192 
0193     BOOST_SYSTEM_CONSTEXPR void clear() noexcept
0194     {
0195         *this = error_code();
0196     }
0197 
0198     // observers:
0199 
0200     BOOST_SYSTEM_CONSTEXPR int value() const noexcept
0201     {
0202         if( lc_flags_ != 1 )
0203         {
0204             return d1_.val_;
0205         }
0206         else
0207         {
0208             std::error_code const& ec = *reinterpret_cast<std::error_code const*>( d2_ );
0209 
0210             unsigned cv = static_cast<unsigned>( ec.value() );
0211             unsigned ch = static_cast<unsigned>( reinterpret_cast<boost::uintptr_t>( &ec.category() ) % 2097143 ); // 2^21-9, prime
0212 
0213             return static_cast<int>( cv + 1000 * ch );
0214         }
0215     }
0216 
0217     BOOST_SYSTEM_CONSTEXPR const error_category & category() const noexcept
0218     {
0219         if( lc_flags_ == 0 )
0220         {
0221             return system_category();
0222         }
0223         else if( lc_flags_ == 1 )
0224         {
0225             return detail::interop_category();
0226         }
0227         else
0228         {
0229             return *d1_.cat_;
0230         }
0231     }
0232 
0233     // deprecated?
0234     error_condition default_error_condition() const noexcept
0235     {
0236         return category().default_error_condition( value() );
0237     }
0238 
0239     std::string message() const
0240     {
0241         if( lc_flags_ == 1 )
0242         {
0243             std::error_code const& ec = *reinterpret_cast<std::error_code const*>( d2_ );
0244             return ec.message();
0245         }
0246         else if( lc_flags_ == 0 )
0247         {
0248             return detail::system_error_category_message( value() );
0249         }
0250         else
0251         {
0252             return category().message( value() );
0253         }
0254     }
0255 
0256     char const * message( char * buffer, std::size_t len ) const noexcept
0257     {
0258         if( lc_flags_ == 1 )
0259         {
0260             std::error_code const& ec = *reinterpret_cast<std::error_code const*>( d2_ );
0261 
0262 #if !defined(BOOST_NO_EXCEPTIONS)
0263             try
0264 #endif
0265             {
0266                 detail::snprintf( buffer, len, "%s", ec.message().c_str() );
0267                 return buffer;
0268             }
0269 #if !defined(BOOST_NO_EXCEPTIONS)
0270             catch( ... )
0271             {
0272                 detail::snprintf( buffer, len, "No message text available for error std:%s:%d", ec.category().name(), ec.value() );
0273                 return buffer;
0274             }
0275 #endif
0276         }
0277         else if( lc_flags_ == 0 )
0278         {
0279             return detail::system_error_category_message( value(), buffer, len );
0280         }
0281         else
0282         {
0283             return category().message( value(), buffer, len );
0284         }
0285     }
0286 
0287     BOOST_SYSTEM_CONSTEXPR bool failed() const noexcept
0288     {
0289         if( lc_flags_ & 1 )
0290         {
0291             if( lc_flags_ == 1 )
0292             {
0293                 std::error_code const& ec = *reinterpret_cast<std::error_code const*>( d2_ );
0294                 return ec.value() != 0;
0295             }
0296 
0297             return true;
0298         }
0299         else
0300         {
0301             return false;
0302         }
0303     }
0304 
0305     BOOST_SYSTEM_CONSTEXPR explicit operator bool() const noexcept  // true if error
0306     {
0307         return failed();
0308     }
0309 
0310     bool has_location() const noexcept
0311     {
0312         return lc_flags_ >= 4;
0313     }
0314 
0315     source_location const & location() const noexcept
0316     {
0317         BOOST_STATIC_CONSTEXPR source_location loc;
0318         return lc_flags_ >= 4? *reinterpret_cast<source_location const*>( lc_flags_ &~ static_cast<boost::uintptr_t>( 1 ) ): loc;
0319     }
0320 
0321     // relationals:
0322 
0323 private:
0324 
0325     // private equality for use in error_category::equivalent
0326 
0327     friend class error_category;
0328 
0329     BOOST_SYSTEM_CONSTEXPR bool equals( int val, error_category const& cat ) const noexcept
0330     {
0331         if( lc_flags_ == 0 )
0332         {
0333             return val == 0 && cat.id_ == detail::system_category_id;
0334         }
0335         else if( lc_flags_ == 1 )
0336         {
0337             return cat.id_ == detail::interop_category_id && val == value();
0338         }
0339         else
0340         {
0341             return val == d1_.val_ && cat == *d1_.cat_;
0342         }
0343     }
0344 
0345 public:
0346 
0347     //  the more symmetrical non-member syntax allows enum
0348     //  conversions work for both rhs and lhs.
0349 
0350     BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( const error_code & lhs, const error_code & rhs ) noexcept
0351     {
0352         bool s1 = lhs.lc_flags_ == 1;
0353         bool s2 = rhs.lc_flags_ == 1;
0354 
0355         if( s1 != s2 ) return false;
0356 
0357         if( s1 && s2 )
0358         {
0359             std::error_code const& e1 = *reinterpret_cast<std::error_code const*>( lhs.d2_ );
0360             std::error_code const& e2 = *reinterpret_cast<std::error_code const*>( rhs.d2_ );
0361 
0362             return e1 == e2;
0363         }
0364         else
0365         {
0366             return lhs.value() == rhs.value() && lhs.category() == rhs.category();
0367         }
0368     }
0369 
0370     BOOST_SYSTEM_CONSTEXPR inline friend bool operator<( const error_code & lhs, const error_code & rhs ) noexcept
0371     {
0372         bool s1 = lhs.lc_flags_ == 1;
0373         bool s2 = rhs.lc_flags_ == 1;
0374 
0375         if( s1 < s2 ) return true;
0376         if( s2 < s1 ) return false;
0377 
0378         if( s1 && s2 )
0379         {
0380             std::error_code const& e1 = *reinterpret_cast<std::error_code const*>( lhs.d2_ );
0381             std::error_code const& e2 = *reinterpret_cast<std::error_code const*>( rhs.d2_ );
0382 
0383             return e1 < e2;
0384         }
0385         else
0386         {
0387             return lhs.category() < rhs.category() || (lhs.category() == rhs.category() && lhs.value() < rhs.value());
0388         }
0389     }
0390 
0391     BOOST_SYSTEM_CONSTEXPR inline friend bool operator!=( const error_code & lhs, const error_code & rhs ) noexcept
0392     {
0393         return !( lhs == rhs );
0394     }
0395 
0396     inline friend bool operator==( std::error_code const & lhs, error_code const & rhs ) noexcept
0397     {
0398         return lhs == static_cast< std::error_code >( rhs );
0399     }
0400 
0401     inline friend bool operator==( error_code const & lhs, std::error_code const & rhs ) noexcept
0402     {
0403         return static_cast< std::error_code >( lhs ) == rhs;
0404     }
0405 
0406     inline friend bool operator!=( std::error_code const & lhs, error_code const & rhs ) noexcept
0407     {
0408         return !( lhs == rhs );
0409     }
0410 
0411     inline friend bool operator!=( error_code const & lhs, std::error_code const & rhs ) noexcept
0412     {
0413         return !( lhs == rhs );
0414     }
0415 
0416     //
0417 
0418     template<class E, class N = typename detail::enable_if<std::is_error_condition_enum<E>::value>::type>
0419     inline friend bool operator==( error_code const & lhs, E rhs ) noexcept
0420     {
0421         return lhs == make_error_condition( rhs );
0422     }
0423 
0424     template<class E, class N = typename detail::enable_if<std::is_error_condition_enum<E>::value>::type>
0425     inline friend bool operator==( E lhs, error_code const & rhs ) noexcept
0426     {
0427         return make_error_condition( lhs ) == rhs;
0428     }
0429 
0430     template<class E, class N = typename detail::enable_if<std::is_error_condition_enum<E>::value>::type>
0431     inline friend bool operator!=( error_code const & lhs, E rhs ) noexcept
0432     {
0433         return !( lhs == rhs );
0434     }
0435 
0436     template<class E, class N = typename detail::enable_if<std::is_error_condition_enum<E>::value>::type>
0437     inline friend bool operator!=( E lhs, error_code const & rhs ) noexcept
0438     {
0439         return !( lhs == rhs );
0440     }
0441 
0442     //
0443 
0444     template<class E, class N1 = void, class N2 = typename detail::enable_if<std::is_error_code_enum<E>::value>::type>
0445     BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( error_code const & lhs, E rhs ) noexcept
0446     {
0447         return lhs == make_error_code( rhs );
0448     }
0449 
0450     template<class E, class N1 = void, class N2 = typename detail::enable_if<std::is_error_code_enum<E>::value>::type>
0451     BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( E lhs, error_code const & rhs ) noexcept
0452     {
0453         return make_error_code( lhs ) == rhs;
0454     }
0455 
0456     template<class E, class N1 = void, class N2 = typename detail::enable_if<std::is_error_code_enum<E>::value>::type>
0457     BOOST_SYSTEM_CONSTEXPR inline friend bool operator!=( error_code const & lhs, E rhs ) noexcept
0458     {
0459         return !( lhs == rhs );
0460     }
0461 
0462     template<class E, class N1 = void, class N2 = typename detail::enable_if<std::is_error_code_enum<E>::value>::type>
0463     BOOST_SYSTEM_CONSTEXPR inline friend bool operator!=( E lhs, error_code const & rhs ) noexcept
0464     {
0465         return !( lhs == rhs );
0466     }
0467 
0468 #if defined(BOOST_SYSTEM_CLANG_6)
0469 
0470     inline friend bool operator==( error_code const & lhs, std::error_condition const & rhs ) noexcept
0471     {
0472         return static_cast< std::error_code >( lhs ) == rhs;
0473     }
0474 
0475     inline friend bool operator==( std::error_condition const & lhs, error_code const & rhs ) noexcept
0476     {
0477         return lhs == static_cast< std::error_code >( rhs );
0478     }
0479 
0480     inline friend bool operator!=( error_code const & lhs, std::error_condition const & rhs ) noexcept
0481     {
0482         return !( lhs == rhs );
0483     }
0484 
0485     inline friend bool operator!=( std::error_condition const & lhs, error_code const & rhs ) noexcept
0486     {
0487         return !( lhs == rhs );
0488     }
0489 
0490 #endif
0491 
0492     // conversions
0493 
0494     operator std::error_code () const
0495     {
0496         if( lc_flags_ == 1 )
0497         {
0498             return *reinterpret_cast<std::error_code const*>( d2_ );
0499         }
0500         else if( lc_flags_ == 0 )
0501         {
0502 // This condition must be the same as the one in error_category_impl.hpp
0503 #if defined(BOOST_SYSTEM_AVOID_STD_SYSTEM_CATEGORY)
0504 
0505             return std::error_code( 0, boost::system::system_category() );
0506 
0507 #else
0508 
0509             return std::error_code();
0510 
0511 #endif
0512         }
0513         else
0514         {
0515             return std::error_code( d1_.val_, *d1_.cat_ );
0516         }
0517     }
0518 
0519     operator std::error_code ()
0520     {
0521         return const_cast<error_code const&>( *this );
0522     }
0523 
0524     template<class T,
0525       class E = typename detail::enable_if<detail::is_same<T, std::error_code>::value>::type>
0526       operator T& ()
0527     {
0528         if( lc_flags_ != 1 )
0529         {
0530             std::error_code e2( *this );
0531             ::new( d2_ ) std::error_code( e2 );
0532             lc_flags_ = 1;
0533         }
0534 
0535         return *reinterpret_cast<std::error_code*>( d2_ );
0536     }
0537 
0538 #if defined(BOOST_SYSTEM_CLANG_6)
0539 
0540     template<class T,
0541       class E = typename std::enable_if<std::is_same<T, std::error_code>::value>::type>
0542       operator T const& () = delete;
0543 
0544 #endif
0545 
0546     std::string to_string() const
0547     {
0548         if( lc_flags_ == 1 )
0549         {
0550             std::error_code const& e2 = *reinterpret_cast<std::error_code const*>( d2_ );
0551 
0552             std::string r( "std:" );
0553             r += e2.category().name();
0554             detail::append_int( r, e2.value() );
0555 
0556             return r;
0557         }
0558         else
0559         {
0560             std::string r = category_name();
0561             detail::append_int( r, value() );
0562             return r;
0563         }
0564     }
0565 
0566     template<class Ch, class Tr>
0567         inline friend std::basic_ostream<Ch, Tr>&
0568         operator<< (std::basic_ostream<Ch, Tr>& os, error_code const & ec)
0569     {
0570         return os << ec.to_string().c_str();
0571     }
0572 
0573     std::string what() const
0574     {
0575         std::string r = message();
0576 
0577         r += " [";
0578         r += to_string();
0579 
0580         if( has_location() )
0581         {
0582             r += " at ";
0583             r += location().to_string();
0584         }
0585 
0586         r += "]";
0587         return r;
0588     }
0589 };
0590 
0591 inline bool operator==( const error_code & code, const error_condition & condition ) noexcept
0592 {
0593     if( code.lc_flags_ == 1 )
0594     {
0595         return static_cast<std::error_code>( code ) == static_cast<std::error_condition>( condition );
0596     }
0597     else
0598     {
0599         return code.category().equivalent( code.value(), condition ) || condition.category().equivalent( code, condition.value() );
0600     }
0601 }
0602 
0603 inline bool operator==( const error_condition & condition, const error_code & code ) noexcept
0604 {
0605     return code == condition;
0606 }
0607 
0608 inline bool operator!=( const error_code & lhs, const error_condition & rhs ) noexcept
0609 {
0610     return !( lhs == rhs );
0611 }
0612 
0613 inline bool operator!=( const error_condition & lhs, const error_code & rhs ) noexcept
0614 {
0615     return !( lhs == rhs );
0616 }
0617 
0618 inline std::size_t hash_value( error_code const & ec )
0619 {
0620     if( ec.lc_flags_ == 1 )
0621     {
0622         std::error_code const& e2 = *reinterpret_cast<std::error_code const*>( ec.d2_ );
0623         return std::hash<std::error_code>()( e2 );
0624     }
0625 
0626     error_category const & cat = ec.category();
0627 
0628     boost::ulong_long_type id_ = cat.id_;
0629 
0630     if( id_ == 0 )
0631     {
0632         id_ = reinterpret_cast<boost::uintptr_t>( &cat );
0633     }
0634 
0635     boost::ulong_long_type hv = ( boost::ulong_long_type( 0xCBF29CE4 ) << 32 ) + 0x84222325;
0636     boost::ulong_long_type const prime = ( boost::ulong_long_type( 0x00000100 ) << 32 ) + 0x000001B3;
0637 
0638     // id
0639 
0640     hv ^= id_;
0641     hv *= prime;
0642 
0643     // value
0644 
0645     hv ^= static_cast<unsigned>( ec.value() );
0646     hv *= prime;
0647 
0648     return static_cast<std::size_t>( hv );
0649 }
0650 
0651 } // namespace system
0652 
0653 } // namespace boost
0654 
0655 #if defined(BOOST_GCC) && BOOST_GCC >= 40600 && BOOST_GCC < 70000
0656 # pragma GCC diagnostic pop
0657 #endif
0658 
0659 #endif // #ifndef BOOST_SYSTEM_DETAIL_ERROR_CODE_HPP_INCLUDED