1 //
2 // error_code.hpp
3 // ~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 //
10 
11 #ifndef ASIO_ERROR_CODE_HPP
12 #define ASIO_ERROR_CODE_HPP
13 
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17 
18 #include "asio/detail/config.hpp"
19 
20 #if defined(ASIO_HAS_STD_SYSTEM_ERROR)
21 # include <system_error>
22 #else // defined(ASIO_HAS_STD_SYSTEM_ERROR)
23 # include <string>
24 # include "asio/detail/noncopyable.hpp"
25 # if !defined(ASIO_NO_IOSTREAM)
26 #  include <iosfwd>
27 # endif // !defined(ASIO_NO_IOSTREAM)
28 #endif // defined(ASIO_HAS_STD_SYSTEM_ERROR)
29 
30 #include "asio/detail/push_options.hpp"
31 
32 namespace asio {
33 
34 #if defined(ASIO_HAS_STD_SYSTEM_ERROR)
35 
36 typedef std::error_category error_category;
37 
38 #else // defined(ASIO_HAS_STD_SYSTEM_ERROR)
39 
40 /// Base class for all error categories.
41 class error_category : private noncopyable
42 {
43 public:
44   /// Destructor.
45   virtual ~error_category()
46   {
47   }
48 
49   /// Returns a string naming the error gategory.
50   virtual const char* name() const = 0;
51 
52   /// Returns a string describing the error denoted by @c value.
53   virtual std::string message(int value) const = 0;
54 
55   /// Equality operator to compare two error categories.
56   bool operator==(const error_category& rhs) const
57   {
58     return this == &rhs;
59   }
60 
61   /// Inequality operator to compare two error categories.
62   bool operator!=(const error_category& rhs) const
63   {
64     return !(*this == rhs);
65   }
66 };
67 
68 #endif // defined(ASIO_HAS_STD_SYSTEM_ERROR)
69 
70 /// Returns the error category used for the system errors produced by asio.
71 extern ASIO_DECL const error_category& system_category();
72 
73 #if defined(ASIO_HAS_STD_SYSTEM_ERROR)
74 
75 typedef std::error_code error_code;
76 
77 #else // defined(ASIO_HAS_STD_SYSTEM_ERROR)
78 
79 /// Class to represent an error code value.
80 class error_code
81 {
82 public:
83   /// Default constructor.
error_code()84   error_code()
85     : value_(0),
86       category_(&system_category())
87   {
88   }
89 
90   /// Construct with specific error code and category.
error_code(int v,const error_category & c)91   error_code(int v, const error_category& c)
92     : value_(v),
93       category_(&c)
94   {
95   }
96 
97   /// Construct from an error code enum.
98   template <typename ErrorEnum>
error_code(ErrorEnum e)99   error_code(ErrorEnum e)
100   {
101     *this = make_error_code(e);
102   }
103 
104   /// Clear the error value to the default.
clear()105   void clear()
106   {
107     value_ = 0;
108     category_ = &system_category();
109   }
110 
111   /// Assign a new error value.
assign(int v,const error_category & c)112   void assign(int v, const error_category& c)
113   {
114     value_ = v;
115     category_ = &c;
116   }
117 
118   /// Get the error value.
value() const119   int value() const
120   {
121     return value_;
122   }
123 
124   /// Get the error category.
category() const125   const error_category& category() const
126   {
127     return *category_;
128   }
129 
130   /// Get the message associated with the error.
message() const131   std::string message() const
132   {
133     return category_->message(value_);
134   }
135 
136   struct unspecified_bool_type_t
137   {
138   };
139 
140   typedef void (*unspecified_bool_type)(unspecified_bool_type_t);
141 
unspecified_bool_true(unspecified_bool_type_t)142   static void unspecified_bool_true(unspecified_bool_type_t) {}
143 
144   /// Operator returns non-null if there is a non-success error code.
operator unspecified_bool_type() const145   operator unspecified_bool_type() const
146   {
147     if (value_ == 0)
148       return 0;
149     else
150       return &error_code::unspecified_bool_true;
151   }
152 
153   /// Operator to test if the error represents success.
operator !() const154   bool operator!() const
155   {
156     return value_ == 0;
157   }
158 
159   /// Equality operator to compare two error objects.
operator ==(const error_code & e1,const error_code & e2)160   friend bool operator==(const error_code& e1, const error_code& e2)
161   {
162     return e1.value_ == e2.value_ && e1.category_ == e2.category_;
163   }
164 
165   /// Inequality operator to compare two error objects.
operator !=(const error_code & e1,const error_code & e2)166   friend bool operator!=(const error_code& e1, const error_code& e2)
167   {
168     return e1.value_ != e2.value_ || e1.category_ != e2.category_;
169   }
170 
171 private:
172   // The value associated with the error code.
173   int value_;
174 
175   // The category associated with the error code.
176   const error_category* category_;
177 };
178 
179 # if !defined(ASIO_NO_IOSTREAM)
180 
181 /// Output an error code.
182 template <typename Elem, typename Traits>
operator <<(std::basic_ostream<Elem,Traits> & os,const error_code & ec)183 std::basic_ostream<Elem, Traits>& operator<<(
184     std::basic_ostream<Elem, Traits>& os, const error_code& ec)
185 {
186   os << ec.category().name() << ':' << ec.value();
187   return os;
188 }
189 
190 # endif // !defined(ASIO_NO_IOSTREAM)
191 
192 #endif // defined(ASIO_HAS_STD_SYSTEM_ERROR)
193 
194 } // namespace asio
195 
196 #include "asio/detail/pop_options.hpp"
197 
198 #if defined(ASIO_HEADER_ONLY)
199 # include "asio/impl/error_code.ipp"
200 #endif // defined(ASIO_HEADER_ONLY)
201 
202 #endif // ASIO_ERROR_CODE_HPP
203