Line data Source code
1 : // Support for interoperability between Boost.System and <system_error> 2 : // 3 : // Copyright 2018 Peter Dimov 4 : // 5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 : // 8 : // See library home page at http://www.boost.org/libs/system 9 : 10 : #include <system_error> 11 : #include <map> 12 : #include <memory> 13 : #include <mutex> 14 : 15 : // 16 : 17 : namespace boost 18 : { 19 : 20 : namespace system 21 : { 22 : 23 : namespace detail 24 : { 25 : 26 : class BOOST_SYMBOL_VISIBLE std_category: public std::error_category 27 : { 28 : private: 29 : 30 : boost::system::error_category const * pc_; 31 : 32 : public: 33 : 34 0 : explicit std_category( boost::system::error_category const * pc, unsigned id ): pc_( pc ) 35 : { 36 0 : if( id != 0 ) 37 : { 38 : #if defined(_MSC_VER) && defined(_CPPLIB_VER) && _MSC_VER >= 1900 && _MSC_VER < 2000 39 : 40 : // Poking into the protected _Addr member of std::error_category 41 : // is not a particularly good programming practice, but what can 42 : // you do 43 : 44 : _Addr = id; 45 : 46 : #endif 47 : } 48 : } 49 : 50 0 : virtual const char * name() const BOOST_NOEXCEPT 51 : { 52 0 : return pc_->name(); 53 : } 54 : 55 0 : virtual std::string message( int ev ) const 56 : { 57 0 : return pc_->message( ev ); 58 : } 59 : 60 0 : virtual std::error_condition default_error_condition( int ev ) const BOOST_NOEXCEPT 61 : { 62 0 : return pc_->default_error_condition( ev ); 63 : } 64 : 65 : virtual bool equivalent( int code, const std::error_condition & condition ) const BOOST_NOEXCEPT; 66 : virtual bool equivalent( const std::error_code & code, int condition ) const BOOST_NOEXCEPT; 67 : }; 68 : 69 : inline std::error_category const & to_std_category( boost::system::error_category const & cat ) BOOST_SYMBOL_VISIBLE; 70 : 71 : struct cat_ptr_less 72 : { 73 0 : bool operator()( boost::system::error_category const * p1, boost::system::error_category const * p2 ) const BOOST_NOEXCEPT 74 : { 75 0 : return *p1 < *p2; 76 : } 77 : }; 78 : 79 0 : inline std::error_category const & to_std_category( boost::system::error_category const & cat ) 80 : { 81 0 : if( cat == boost::system::system_category() ) 82 : { 83 0 : static const std_category system_instance( &cat, 0x1F4D7 ); 84 0 : return system_instance; 85 : } 86 0 : else if( cat == boost::system::generic_category() ) 87 : { 88 0 : static const std_category generic_instance( &cat, 0x1F4D3 ); 89 0 : return generic_instance; 90 : } 91 : else 92 : { 93 0 : typedef std::map< boost::system::error_category const *, std::unique_ptr<std_category>, cat_ptr_less > map_type; 94 : 95 0 : static map_type map_; 96 0 : static std::mutex map_mx_; 97 : 98 0 : std::lock_guard<std::mutex> guard( map_mx_ ); 99 : 100 0 : map_type::iterator i = map_.find( &cat ); 101 : 102 0 : if( i == map_.end() ) 103 : { 104 0 : std::unique_ptr<std_category> p( new std_category( &cat, 0 ) ); 105 : 106 0 : std::pair<map_type::iterator, bool> r = map_.insert( map_type::value_type( &cat, std::move( p ) ) ); 107 : 108 0 : i = r.first; 109 : } 110 : 111 0 : return *i->second; 112 : } 113 : } 114 : 115 0 : inline bool std_category::equivalent( int code, const std::error_condition & condition ) const BOOST_NOEXCEPT 116 : { 117 0 : if( condition.category() == *this ) 118 : { 119 0 : boost::system::error_condition bn( condition.value(), *pc_ ); 120 0 : return pc_->equivalent( code, bn ); 121 : } 122 0 : else if( condition.category() == std::generic_category() || condition.category() == boost::system::generic_category() ) 123 : { 124 0 : boost::system::error_condition bn( condition.value(), boost::system::generic_category() ); 125 0 : return pc_->equivalent( code, bn ); 126 : } 127 : 128 : #ifndef BOOST_NO_RTTI 129 : 130 0 : else if( std_category const* pc2 = dynamic_cast< std_category const* >( &condition.category() ) ) 131 : { 132 0 : boost::system::error_condition bn( condition.value(), *pc2->pc_ ); 133 0 : return pc_->equivalent( code, bn ); 134 : } 135 : 136 : #endif 137 : 138 : else 139 : { 140 0 : return default_error_condition( code ) == condition; 141 : } 142 : } 143 : 144 0 : inline bool std_category::equivalent( const std::error_code & code, int condition ) const BOOST_NOEXCEPT 145 : { 146 0 : if( code.category() == *this ) 147 : { 148 0 : boost::system::error_code bc( code.value(), *pc_ ); 149 0 : return pc_->equivalent( bc, condition ); 150 : } 151 0 : else if( code.category() == std::generic_category() || code.category() == boost::system::generic_category() ) 152 : { 153 0 : boost::system::error_code bc( code.value(), boost::system::generic_category() ); 154 0 : return pc_->equivalent( bc, condition ); 155 : } 156 : 157 : #ifndef BOOST_NO_RTTI 158 : 159 0 : else if( std_category const* pc2 = dynamic_cast< std_category const* >( &code.category() ) ) 160 : { 161 0 : boost::system::error_code bc( code.value(), *pc2->pc_ ); 162 0 : return pc_->equivalent( bc, condition ); 163 : } 164 : #endif 165 : 166 0 : else if( *pc_ == boost::system::generic_category() ) 167 : { 168 0 : return std::generic_category().equivalent( code, condition ); 169 : } 170 : else 171 : { 172 : return false; 173 : } 174 : } 175 : 176 : } // namespace detail 177 : 178 : } // namespace system 179 : 180 : } // namespace boost