Imported Upstream version 1.64.0
[platform/upstream/boost.git] / boost / system / error_code.hpp
1 //  boost/system/error_code.hpp  ---------------------------------------------//
2
3 //  Copyright Beman Dawes 2006, 2007
4 //  Copyright Christoper Kohlhoff 2007
5
6 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
7 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8
9 //  See library home page at http://www.boost.org/libs/system
10
11 #ifndef BOOST_SYSTEM_ERROR_CODE_HPP
12 #define BOOST_SYSTEM_ERROR_CODE_HPP
13
14 #include <boost/system/config.hpp>
15 #include <boost/cstdint.hpp>
16 #include <boost/assert.hpp>
17 #include <boost/noncopyable.hpp>
18 #include <boost/utility/enable_if.hpp>
19 #include <ostream>
20 #include <string>
21 #include <stdexcept>
22 #include <functional>
23
24 // TODO: undef these macros if not already defined
25 #include <boost/cerrno.hpp>
26
27 #if !defined(BOOST_POSIX_API) && !defined(BOOST_WINDOWS_API)
28 #  error BOOST_POSIX_API or BOOST_WINDOWS_API must be defined
29 #endif
30
31 #include <boost/config/abi_prefix.hpp> // must be the last #include
32
33 #ifndef BOOST_SYSTEM_NOEXCEPT
34 #define BOOST_SYSTEM_NOEXCEPT BOOST_NOEXCEPT
35 #endif
36
37 namespace boost
38 {
39   namespace system
40   {
41
42     class error_code;         // values defined by the operating system
43     class error_condition;    // portable generic values defined below, but ultimately
44                               // based on the POSIX standard
45
46     //  "Concept" helpers  ---------------------------------------------------//
47
48     template< class T >
49     struct is_error_code_enum { static const bool value = false; };
50
51     template< class T >
52     struct is_error_condition_enum { static const bool value = false; };
53
54     //  generic error_conditions  --------------------------------------------//
55
56     namespace errc
57     {
58       enum errc_t
59       {
60         success = 0,
61         address_family_not_supported = EAFNOSUPPORT,
62         address_in_use = EADDRINUSE,
63         address_not_available = EADDRNOTAVAIL,
64         already_connected = EISCONN,
65         argument_list_too_long = E2BIG,
66         argument_out_of_domain = EDOM,
67         bad_address = EFAULT,
68         bad_file_descriptor = EBADF,
69         bad_message = EBADMSG,
70         broken_pipe = EPIPE,
71         connection_aborted = ECONNABORTED,
72         connection_already_in_progress = EALREADY,
73         connection_refused = ECONNREFUSED,
74         connection_reset = ECONNRESET,
75         cross_device_link = EXDEV,
76         destination_address_required = EDESTADDRREQ,
77         device_or_resource_busy = EBUSY,
78         directory_not_empty = ENOTEMPTY,
79         executable_format_error = ENOEXEC,
80         file_exists = EEXIST,
81         file_too_large = EFBIG,
82         filename_too_long = ENAMETOOLONG,
83         function_not_supported = ENOSYS,
84         host_unreachable = EHOSTUNREACH,
85         identifier_removed = EIDRM,
86         illegal_byte_sequence = EILSEQ,
87         inappropriate_io_control_operation = ENOTTY,
88         interrupted = EINTR,
89         invalid_argument = EINVAL,
90         invalid_seek = ESPIPE,
91         io_error = EIO,
92         is_a_directory = EISDIR,
93         message_size = EMSGSIZE,
94         network_down = ENETDOWN,
95         network_reset = ENETRESET,
96         network_unreachable = ENETUNREACH,
97         no_buffer_space = ENOBUFS,
98         no_child_process = ECHILD,
99         no_link = ENOLINK,
100         no_lock_available = ENOLCK,
101         no_message_available = ENODATA,
102         no_message = ENOMSG,
103         no_protocol_option = ENOPROTOOPT,
104         no_space_on_device = ENOSPC,
105         no_stream_resources = ENOSR,
106         no_such_device_or_address = ENXIO,
107         no_such_device = ENODEV,
108         no_such_file_or_directory = ENOENT,
109         no_such_process = ESRCH,
110         not_a_directory = ENOTDIR,
111         not_a_socket = ENOTSOCK,
112         not_a_stream = ENOSTR,
113         not_connected = ENOTCONN,
114         not_enough_memory = ENOMEM,
115         not_supported = ENOTSUP,
116         operation_canceled = ECANCELED,
117         operation_in_progress = EINPROGRESS,
118         operation_not_permitted = EPERM,
119         operation_not_supported = EOPNOTSUPP,
120         operation_would_block = EWOULDBLOCK,
121         owner_dead = EOWNERDEAD,
122         permission_denied = EACCES,
123         protocol_error = EPROTO,
124         protocol_not_supported = EPROTONOSUPPORT,
125         read_only_file_system = EROFS,
126         resource_deadlock_would_occur = EDEADLK,
127         resource_unavailable_try_again = EAGAIN,
128         result_out_of_range = ERANGE,
129         state_not_recoverable = ENOTRECOVERABLE,
130         stream_timeout = ETIME,
131         text_file_busy = ETXTBSY,
132         timed_out = ETIMEDOUT,
133         too_many_files_open_in_system = ENFILE,
134         too_many_files_open = EMFILE,
135         too_many_links = EMLINK,
136         too_many_symbolic_link_levels = ELOOP,
137         value_too_large = EOVERFLOW,
138         wrong_protocol_type = EPROTOTYPE
139       };
140
141     } // namespace errc
142
143 # ifndef BOOST_SYSTEM_NO_DEPRECATED
144     namespace posix = errc;
145     namespace posix_error = errc;
146 # endif
147
148     template<> struct is_error_condition_enum<errc::errc_t>
149       { static const bool value = true; };
150
151
152     //  ----------------------------------------------------------------------//
153
154     //  Operating system specific interfaces  --------------------------------//
155
156
157     //  The interface is divided into general and system-specific portions to
158     //  meet these requirements:
159     //
160     //  * Code calling an operating system API can create an error_code with
161     //    a single category (system_category), even for POSIX-like operating
162     //    systems that return some POSIX errno values and some native errno
163     //    values. This code should not have to pay the cost of distinguishing
164     //    between categories, since it is not yet known if that is needed.
165     //
166     //  * Users wishing to write system-specific code should be given enums for
167     //    at least the common error cases.
168     //
169     //  * System specific code should fail at compile time if moved to another
170     //    operating system.
171
172     //  The system specific portions of the interface are located in headers
173     //  with names reflecting the operating system. For example,
174     //
175     //       <boost/system/cygwin_error.hpp>
176     //       <boost/system/linux_error.hpp>
177     //       <boost/system/windows_error.hpp>
178     //
179     //  These headers are effectively empty for compiles on operating systems
180     //  where they are not applicable.
181
182     //  ----------------------------------------------------------------------//
183
184     //  class error_category  ------------------------------------------------//
185
186     class error_category : public noncopyable
187     {
188     public:
189       virtual ~error_category(){}
190
191       virtual const char *     name() const BOOST_SYSTEM_NOEXCEPT = 0;
192       virtual std::string      message( int ev ) const = 0;
193       inline virtual error_condition  default_error_condition( int ev ) const  BOOST_SYSTEM_NOEXCEPT;
194       inline virtual bool             equivalent( int code,
195                                            const error_condition & condition ) const  BOOST_SYSTEM_NOEXCEPT;
196       inline virtual bool             equivalent( const error_code & code,
197                                            int condition ) const  BOOST_SYSTEM_NOEXCEPT;
198
199       bool operator==(const error_category & rhs) const BOOST_SYSTEM_NOEXCEPT { return this == &rhs; }
200       bool operator!=(const error_category & rhs) const BOOST_SYSTEM_NOEXCEPT { return this != &rhs; }
201       bool operator<( const error_category & rhs ) const BOOST_SYSTEM_NOEXCEPT
202       {
203         return std::less<const error_category*>()( this, &rhs );
204       }
205     };
206
207     //  predefined error categories  -----------------------------------------//
208
209 # ifdef BOOST_ERROR_CODE_HEADER_ONLY
210     inline const error_category &  system_category() BOOST_SYSTEM_NOEXCEPT;
211     inline const error_category &  generic_category() BOOST_SYSTEM_NOEXCEPT;
212 #else
213     BOOST_SYSTEM_DECL const error_category &  system_category() BOOST_SYSTEM_NOEXCEPT;
214     BOOST_SYSTEM_DECL const error_category &  generic_category() BOOST_SYSTEM_NOEXCEPT;
215 #endif
216     //  deprecated synonyms --------------------------------------------------//
217
218 # ifndef BOOST_SYSTEM_NO_DEPRECATED
219     inline const error_category &  get_system_category() { return system_category(); }
220     inline const error_category &  get_generic_category() { return generic_category(); }
221     inline const error_category &  get_posix_category() { return generic_category(); }
222     static const error_category &  posix_category BOOST_ATTRIBUTE_UNUSED = generic_category();
223     static const error_category &  errno_ecat     BOOST_ATTRIBUTE_UNUSED = generic_category();
224     static const error_category &  native_ecat    BOOST_ATTRIBUTE_UNUSED = system_category();
225 # endif
226
227     //  class error_condition  -----------------------------------------------//
228
229     //  error_conditions are portable, error_codes are system or library specific
230
231     class error_condition
232     {
233     public:
234
235       // constructors:
236       error_condition() BOOST_SYSTEM_NOEXCEPT : m_val(0), m_cat(&generic_category()) {}
237       error_condition( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT : m_val(val), m_cat(&cat) {}
238
239       template <class ErrorConditionEnum>
240         error_condition(ErrorConditionEnum e,
241           typename boost::enable_if<is_error_condition_enum<ErrorConditionEnum> >::type* = 0) BOOST_SYSTEM_NOEXCEPT
242       {
243         *this = make_error_condition(e);
244       }
245
246       // modifiers:
247
248       void assign( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT
249       {
250         m_val = val;
251         m_cat = &cat;
252       }
253
254       template<typename ErrorConditionEnum>
255         typename boost::enable_if<is_error_condition_enum<ErrorConditionEnum>, error_condition>::type &
256           operator=( ErrorConditionEnum val ) BOOST_SYSTEM_NOEXCEPT
257       {
258         *this = make_error_condition(val);
259         return *this;
260       }
261
262       void clear() BOOST_SYSTEM_NOEXCEPT
263       {
264         m_val = 0;
265         m_cat = &generic_category();
266       }
267
268       // observers:
269       int                     value() const BOOST_SYSTEM_NOEXCEPT    { return m_val; }
270       const error_category &  category() const BOOST_SYSTEM_NOEXCEPT { return *m_cat; }
271       std::string             message() const  { return m_cat->message(value()); }
272
273       typedef void (*unspecified_bool_type)();
274       static void unspecified_bool_true() {}
275
276       operator unspecified_bool_type() const BOOST_SYSTEM_NOEXCEPT  // true if error
277       {
278         return m_val == 0 ? 0 : unspecified_bool_true;
279       }
280
281       bool operator!() const BOOST_SYSTEM_NOEXCEPT  // true if no error
282       {
283         return m_val == 0;
284       }
285
286       // relationals:
287       //  the more symmetrical non-member syntax allows enum
288       //  conversions work for both rhs and lhs.
289       inline friend bool operator==( const error_condition & lhs,
290                                      const error_condition & rhs ) BOOST_SYSTEM_NOEXCEPT
291       {
292         return lhs.m_cat == rhs.m_cat && lhs.m_val == rhs.m_val;
293       }
294
295       inline friend bool operator<( const error_condition & lhs,
296                                     const error_condition & rhs ) BOOST_SYSTEM_NOEXCEPT
297         //  the more symmetrical non-member syntax allows enum
298         //  conversions work for both rhs and lhs.
299       {
300         return lhs.m_cat < rhs.m_cat
301           || (lhs.m_cat == rhs.m_cat && lhs.m_val < rhs.m_val);
302       }
303
304     private:
305       int                     m_val;
306       const error_category *  m_cat;
307
308     };
309
310     //  class error_code  ----------------------------------------------------//
311
312     //  We want error_code to be a value type that can be copied without slicing
313     //  and without requiring heap allocation, but we also want it to have
314     //  polymorphic behavior based on the error category. This is achieved by
315     //  abstract base class error_category supplying the polymorphic behavior,
316     //  and error_code containing a pointer to an object of a type derived
317     //  from error_category.
318     class error_code
319     {
320     public:
321
322       // constructors:
323       error_code() BOOST_SYSTEM_NOEXCEPT : m_val(0), m_cat(&system_category()) {}
324       error_code( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT : m_val(val), m_cat(&cat) {}
325
326       template <class ErrorCodeEnum>
327         error_code(ErrorCodeEnum e,
328           typename boost::enable_if<is_error_code_enum<ErrorCodeEnum> >::type* = 0) BOOST_SYSTEM_NOEXCEPT
329       {
330         *this = make_error_code(e);
331       }
332
333       // modifiers:
334       void assign( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT
335       {
336         m_val = val;
337         m_cat = &cat;
338       }
339
340       template<typename ErrorCodeEnum>
341         typename boost::enable_if<is_error_code_enum<ErrorCodeEnum>, error_code>::type &
342           operator=( ErrorCodeEnum val ) BOOST_SYSTEM_NOEXCEPT
343       {
344         *this = make_error_code(val);
345         return *this;
346       }
347
348       void clear() BOOST_SYSTEM_NOEXCEPT
349       {
350         m_val = 0;
351         m_cat = &system_category();
352       }
353
354       // observers:
355       int                     value() const  BOOST_SYSTEM_NOEXCEPT   { return m_val; }
356       const error_category &  category() const BOOST_SYSTEM_NOEXCEPT { return *m_cat; }
357       error_condition         default_error_condition() const BOOST_SYSTEM_NOEXCEPT  { return m_cat->default_error_condition(value()); }
358       std::string             message() const  { return m_cat->message(value()); }
359
360       typedef void (*unspecified_bool_type)();
361       static void unspecified_bool_true() {}
362
363       operator unspecified_bool_type() const  BOOST_SYSTEM_NOEXCEPT // true if error
364       {
365         return m_val == 0 ? 0 : unspecified_bool_true;
366       }
367
368       bool operator!() const  BOOST_SYSTEM_NOEXCEPT // true if no error
369       {
370         return m_val == 0;
371       }
372
373       // relationals:
374       inline friend bool operator==( const error_code & lhs,
375                                      const error_code & rhs ) BOOST_SYSTEM_NOEXCEPT
376         //  the more symmetrical non-member syntax allows enum
377         //  conversions work for both rhs and lhs.
378       {
379         return lhs.m_cat == rhs.m_cat && lhs.m_val == rhs.m_val;
380       }
381
382       inline friend bool operator<( const error_code & lhs,
383                                     const error_code & rhs ) BOOST_SYSTEM_NOEXCEPT
384         //  the more symmetrical non-member syntax allows enum
385         //  conversions work for both rhs and lhs.
386       {
387         return lhs.m_cat < rhs.m_cat
388           || (lhs.m_cat == rhs.m_cat && lhs.m_val < rhs.m_val);
389       }
390
391     private:
392       int                     m_val;
393       const error_category *  m_cat;
394
395     };
396
397     //  predefined error_code object used as "throw on error" tag
398 # ifndef BOOST_SYSTEM_NO_DEPRECATED
399     BOOST_SYSTEM_DECL extern error_code throws;
400 # endif
401
402     //  Moving from a "throws" object to a "throws" function without breaking
403     //  existing code is a bit of a problem. The workaround is to place the
404     //  "throws" function in namespace boost rather than namespace boost::system.
405
406   }  // namespace system
407
408   namespace detail { inline system::error_code * throws() { return 0; } }
409     //  Misuse of the error_code object is turned into a noisy failure by
410     //  poisoning the reference. This particular implementation doesn't
411     //  produce warnings or errors from popular compilers, is very efficient
412     //  (as determined by inspecting generated code), and does not suffer
413     //  from order of initialization problems. In practice, it also seems
414     //  cause user function error handling implementation errors to be detected
415     //  very early in the development cycle.
416
417   inline system::error_code & throws()
418     { return *detail::throws(); }
419
420   namespace system
421   {
422     //  non-member functions  ------------------------------------------------//
423
424     inline bool operator!=( const error_code & lhs,
425                             const error_code & rhs ) BOOST_SYSTEM_NOEXCEPT
426     {
427       return !(lhs == rhs);
428     }
429
430     inline bool operator!=( const error_condition & lhs,
431                             const error_condition & rhs ) BOOST_SYSTEM_NOEXCEPT
432     {
433       return !(lhs == rhs);
434     }
435
436     inline bool operator==( const error_code & code,
437                             const error_condition & condition ) BOOST_SYSTEM_NOEXCEPT
438     {
439       return code.category().equivalent( code.value(), condition )
440         || condition.category().equivalent( code, condition.value() );
441     }
442
443     inline bool operator!=( const error_code & lhs,
444                             const error_condition & rhs ) BOOST_SYSTEM_NOEXCEPT
445     {
446       return !(lhs == rhs);
447     }
448
449     inline bool operator==( const error_condition & condition,
450                             const error_code & code ) BOOST_SYSTEM_NOEXCEPT
451     {
452       return condition.category().equivalent( code, condition.value() )
453         || code.category().equivalent( code.value(), condition );
454     }
455
456     inline bool operator!=( const error_condition & lhs,
457                             const error_code & rhs ) BOOST_SYSTEM_NOEXCEPT
458     {
459       return !(lhs == rhs);
460     }
461
462     // TODO: both of these may move elsewhere, but the LWG hasn't spoken yet.
463
464     template <class charT, class traits>
465     inline std::basic_ostream<charT,traits>&
466       operator<< (std::basic_ostream<charT,traits>& os, error_code ec)
467     {
468       os << ec.category().name() << ':' << ec.value();
469       return os;
470     }
471
472     inline std::size_t hash_value( const error_code & ec )
473     {
474       return static_cast<std::size_t>(ec.value())
475         + reinterpret_cast<std::size_t>(&ec.category());
476     }
477
478     //  make_* functions for errc::errc_t  -----------------------------//
479
480     namespace errc
481     {
482       //  explicit conversion:
483       inline error_code make_error_code( errc_t e ) BOOST_SYSTEM_NOEXCEPT
484         { return error_code( e, generic_category() ); }
485
486       //  implicit conversion:
487       inline error_condition make_error_condition( errc_t e ) BOOST_SYSTEM_NOEXCEPT
488         { return error_condition( e, generic_category() ); }
489     }
490
491     //  error_category default implementation  -------------------------------//
492
493     error_condition error_category::default_error_condition( int ev ) const BOOST_SYSTEM_NOEXCEPT
494     {
495       return error_condition( ev, *this );
496     }
497
498     bool error_category::equivalent( int code,
499       const error_condition & condition ) const BOOST_SYSTEM_NOEXCEPT
500     {
501       return default_error_condition( code ) == condition;
502     }
503
504     bool error_category::equivalent( const error_code & code,
505       int condition ) const BOOST_SYSTEM_NOEXCEPT
506     {
507       return *this == code.category() && code.value() == condition;
508     }
509
510   } // namespace system
511 } // namespace boost
512
513 #include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
514
515 # ifdef BOOST_ERROR_CODE_HEADER_ONLY
516 #   include <boost/system/detail/error_code.ipp>
517 # endif
518
519 #endif // BOOST_SYSTEM_ERROR_CODE_HPP
520
521