error_code.hpp 18 KB

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