error_code.hpp 17 KB

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