1 #ifndef BOOST_SYSTEM_DETAIL_ERROR_CATEGORY_HPP_INCLUDED
2 #define BOOST_SYSTEM_DETAIL_ERROR_CATEGORY_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/detail/config.hpp>
14 #include <boost/cstdint.hpp>
15 #include <boost/config.hpp>
16 #include <string>
17 #include <functional>
18 #include <cstddef>
19 
20 #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
21 # include <system_error>
22 #endif
23 
24 namespace boost
25 {
26 
27 namespace system
28 {
29 
30 class error_category;
31 class error_code;
32 class error_condition;
33 
34 std::size_t hash_value( error_code const & ec );
35 
36 namespace detail
37 {
38 
39 BOOST_SYSTEM_CONSTEXPR bool failed_impl( int ev, error_category const & cat );
40 
41 #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
42 
43 std::error_category const & to_std_category( error_category const & cat );
44 
45 #endif
46 
47 } // namespace detail
48 
49 #if ( defined( BOOST_GCC ) && BOOST_GCC >= 40600 ) || defined( BOOST_CLANG )
50 #pragma GCC diagnostic push
51 #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
52 #endif
53 
54 class BOOST_SYMBOL_VISIBLE error_category
55 {
56 private:
57 
58     friend std::size_t hash_value( error_code const & ec );
59     friend BOOST_SYSTEM_CONSTEXPR bool detail::failed_impl( int ev, error_category const & cat );
60 
61 #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
62     friend std::error_category const & detail::to_std_category( error_category const & cat );
63 #endif
64 
65 #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
66 public:
67 
68     error_category( error_category const & ) = delete;
69     error_category& operator=( error_category const & ) = delete;
70 
71 #else
72 private:
73 
74     error_category( error_category const & );
75     error_category& operator=( error_category const & );
76 
77 #endif
78 
79 private:
80 
81     boost::ulong_long_type id_;
82 
83 protected:
84 
85 #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && !defined(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS)
86 
87     ~error_category() = default;
88 
89 #else
90 
91     // We'd like to make the destructor protected, to make code that deletes
92     // an error_category* not compile; unfortunately, doing the below makes
93     // the destructor user-provided and hence breaks use after main, as the
94     // categories may get destroyed before code that uses them
95 
96     // ~error_category() {}
97 
98 #endif
99 
error_category()100     BOOST_SYSTEM_CONSTEXPR error_category() BOOST_NOEXCEPT: id_( 0 )
101     {
102     }
103 
error_category(boost::ulong_long_type id)104     explicit BOOST_SYSTEM_CONSTEXPR error_category( boost::ulong_long_type id ) BOOST_NOEXCEPT: id_( id )
105     {
106     }
107 
108 public:
109 
110     virtual const char * name() const BOOST_NOEXCEPT = 0;
111 
112     virtual error_condition default_error_condition( int ev ) const BOOST_NOEXCEPT;
113     virtual bool equivalent( int code, const error_condition & condition ) const BOOST_NOEXCEPT;
114     virtual bool equivalent( const error_code & code, int condition ) const BOOST_NOEXCEPT;
115 
116     virtual std::string message( int ev ) const = 0;
117     virtual char const * message( int ev, char * buffer, std::size_t len ) const BOOST_NOEXCEPT;
118 
failed(int ev) const119     virtual bool failed( int ev ) const BOOST_NOEXCEPT
120     {
121         return ev != 0;
122     }
123 
operator ==(const error_category & rhs) const124     BOOST_SYSTEM_CONSTEXPR bool operator==( const error_category & rhs ) const BOOST_NOEXCEPT
125     {
126         return rhs.id_ == 0? this == &rhs: id_ == rhs.id_;
127     }
128 
operator !=(const error_category & rhs) const129     BOOST_SYSTEM_CONSTEXPR bool operator!=( const error_category & rhs ) const BOOST_NOEXCEPT
130     {
131         return !( *this == rhs );
132     }
133 
operator <(const error_category & rhs) const134     BOOST_SYSTEM_CONSTEXPR bool operator<( const error_category & rhs ) const BOOST_NOEXCEPT
135     {
136         if( id_ < rhs.id_ )
137         {
138             return true;
139         }
140 
141         if( id_ > rhs.id_ )
142         {
143             return false;
144         }
145 
146         if( rhs.id_ != 0 )
147         {
148             return false; // equal
149         }
150 
151         return std::less<error_category const *>()( this, &rhs );
152     }
153 
154 #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
155 
156     operator std::error_category const & () const;
157 
158 #endif
159 };
160 
161 #if ( defined( BOOST_GCC ) && BOOST_GCC >= 40600 ) || defined( BOOST_CLANG )
162 #pragma GCC diagnostic pop
163 #endif
164 
165 namespace detail
166 {
167 
168 static const boost::ulong_long_type generic_category_id = ( boost::ulong_long_type( 0xB2AB117A ) << 32 ) + 0x257EDF0D;
169 static const boost::ulong_long_type system_category_id = ( boost::ulong_long_type( 0x8FAFD21E ) << 32 ) + 0x25C5E09B;
170 
failed_impl(int ev,error_category const & cat)171 BOOST_SYSTEM_CONSTEXPR inline bool failed_impl( int ev, error_category const & cat )
172 {
173     if( cat.id_ == system_category_id || cat.id_ == generic_category_id )
174     {
175         return ev != 0;
176     }
177     else
178     {
179         return cat.failed( ev );
180     }
181 }
182 
183 } // namespace detail
184 
185 } // namespace system
186 
187 } // namespace boost
188 
189 #endif // #ifndef BOOST_SYSTEM_DETAIL_ERROR_CATEGORY_HPP_INCLUDED
190