/Src/Dependencies/Boost/boost/system/error_code.hpp

http://hadesmem.googlecode.com/ · C++ Header · 513 lines · 340 code · 93 blank · 80 comment · 29 complexity · cbd83d263fea6db2034904684f172d47 MD5 · raw file

  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_symbolic_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 const char * name() const = 0;
  160. virtual std::string message( int ev ) const = 0;
  161. virtual error_condition default_error_condition( int ev ) const;
  162. virtual bool equivalent( int code,
  163. const error_condition & condition ) const;
  164. virtual bool equivalent( const error_code & code,
  165. int condition ) const;
  166. bool operator==(const error_category & rhs) const { return this == &rhs; }
  167. bool operator!=(const error_category & rhs) const { return this != &rhs; }
  168. bool operator<( const error_category & rhs ) const
  169. {
  170. return std::less<const error_category*>()( this, &rhs );
  171. }
  172. };
  173. // predefined error categories -----------------------------------------//
  174. BOOST_SYSTEM_DECL const error_category & system_category();
  175. BOOST_SYSTEM_DECL const error_category & generic_category();
  176. // deprecated synonyms --------------------------------------------------//
  177. # ifndef BOOST_SYSTEM_NO_DEPRECATED
  178. inline const error_category & get_system_category() { return system_category(); }
  179. inline const error_category & get_generic_category() { return generic_category(); }
  180. inline const error_category & get_posix_category() { return generic_category(); }
  181. static const error_category & posix_category = generic_category();
  182. static const error_category & errno_ecat = generic_category();
  183. static const error_category & native_ecat = system_category();
  184. # endif
  185. // class error_condition -----------------------------------------------//
  186. // error_conditions are portable, error_codes are system or library specific
  187. class error_condition
  188. {
  189. public:
  190. // constructors:
  191. error_condition() : m_val(0), m_cat(&generic_category()) {}
  192. error_condition( int val, const error_category & cat ) : m_val(val), m_cat(&cat) {}
  193. template <class ErrorConditionEnum>
  194. error_condition(ErrorConditionEnum e,
  195. typename boost::enable_if<is_error_condition_enum<ErrorConditionEnum> >::type* = 0)
  196. {
  197. *this = make_error_condition(e);
  198. }
  199. // modifiers:
  200. void assign( int val, const error_category & cat )
  201. {
  202. m_val = val;
  203. m_cat = &cat;
  204. }
  205. template<typename ErrorConditionEnum>
  206. typename boost::enable_if<is_error_condition_enum<ErrorConditionEnum>, error_condition>::type &
  207. operator=( ErrorConditionEnum val )
  208. {
  209. *this = make_error_condition(val);
  210. return *this;
  211. }
  212. void clear()
  213. {
  214. m_val = 0;
  215. m_cat = &generic_category();
  216. }
  217. // observers:
  218. int value() const { return m_val; }
  219. const error_category & category() const { return *m_cat; }
  220. std::string message() const { return m_cat->message(value()); }
  221. typedef void (*unspecified_bool_type)();
  222. static void unspecified_bool_true() {}
  223. operator unspecified_bool_type() const // true if error
  224. {
  225. return m_val == 0 ? 0 : unspecified_bool_true;
  226. }
  227. bool operator!() const // true if no error
  228. {
  229. return m_val == 0;
  230. }
  231. // relationals:
  232. // the more symmetrical non-member syntax allows enum
  233. // conversions work for both rhs and lhs.
  234. inline friend bool operator==( const error_condition & lhs,
  235. const error_condition & rhs )
  236. {
  237. return lhs.m_cat == rhs.m_cat && lhs.m_val == rhs.m_val;
  238. }
  239. inline friend bool operator<( const error_condition & lhs,
  240. const error_condition & rhs )
  241. // the more symmetrical non-member syntax allows enum
  242. // conversions work for both rhs and lhs.
  243. {
  244. return lhs.m_cat < rhs.m_cat
  245. || (lhs.m_cat == rhs.m_cat && lhs.m_val < rhs.m_val);
  246. }
  247. private:
  248. int m_val;
  249. const error_category * m_cat;
  250. };
  251. // class error_code ----------------------------------------------------//
  252. // We want error_code to be a value type that can be copied without slicing
  253. // and without requiring heap allocation, but we also want it to have
  254. // polymorphic behavior based on the error category. This is achieved by
  255. // abstract base class error_category supplying the polymorphic behavior,
  256. // and error_code containing a pointer to an object of a type derived
  257. // from error_category.
  258. class error_code
  259. {
  260. public:
  261. // constructors:
  262. error_code() : m_val(0), m_cat(&system_category()) {}
  263. error_code( int val, const error_category & cat ) : m_val(val), m_cat(&cat) {}
  264. template <class ErrorCodeEnum>
  265. error_code(ErrorCodeEnum e,
  266. typename boost::enable_if<is_error_code_enum<ErrorCodeEnum> >::type* = 0)
  267. {
  268. *this = make_error_code(e);
  269. }
  270. // modifiers:
  271. void assign( int val, const error_category & cat )
  272. {
  273. m_val = val;
  274. m_cat = &cat;
  275. }
  276. template<typename ErrorCodeEnum>
  277. typename boost::enable_if<is_error_code_enum<ErrorCodeEnum>, error_code>::type &
  278. operator=( ErrorCodeEnum val )
  279. {
  280. *this = make_error_code(val);
  281. return *this;
  282. }
  283. void clear()
  284. {
  285. m_val = 0;
  286. m_cat = &system_category();
  287. }
  288. // observers:
  289. int value() const { return m_val; }
  290. const error_category & category() const { return *m_cat; }
  291. error_condition default_error_condition() const { return m_cat->default_error_condition(value()); }
  292. std::string message() const { return m_cat->message(value()); }
  293. typedef void (*unspecified_bool_type)();
  294. static void unspecified_bool_true() {}
  295. operator unspecified_bool_type() const // true if error
  296. {
  297. return m_val == 0 ? 0 : unspecified_bool_true;
  298. }
  299. bool operator!() const // true if no error
  300. {
  301. return m_val == 0;
  302. }
  303. // relationals:
  304. inline friend bool operator==( const error_code & lhs,
  305. const error_code & rhs )
  306. // the more symmetrical non-member syntax allows enum
  307. // conversions work for both rhs and lhs.
  308. {
  309. return lhs.m_cat == rhs.m_cat && lhs.m_val == rhs.m_val;
  310. }
  311. inline friend bool operator<( const error_code & lhs,
  312. const error_code & rhs )
  313. // the more symmetrical non-member syntax allows enum
  314. // conversions work for both rhs and lhs.
  315. {
  316. return lhs.m_cat < rhs.m_cat
  317. || (lhs.m_cat == rhs.m_cat && lhs.m_val < rhs.m_val);
  318. }
  319. private:
  320. int m_val;
  321. const error_category * m_cat;
  322. };
  323. // predefined error_code object used as "throw on error" tag
  324. # ifndef BOOST_SYSTEM_NO_DEPRECATED
  325. BOOST_SYSTEM_DECL extern error_code throws;
  326. # endif
  327. // Moving from a "throws" object to a "throws" function without breaking
  328. // existing code is a bit of a problem. The workaround is to place the
  329. // "throws" function in namespace boost rather than namespace boost::system.
  330. } // namespace system
  331. namespace detail { inline system::error_code * throws() { return 0; } }
  332. // Misuse of the error_code object is turned into a noisy failure by
  333. // poisoning the reference. This particular implementation doesn't
  334. // produce warnings or errors from popular compilers, is very efficient
  335. // (as determined by inspecting generated code), and does not suffer
  336. // from order of initialization problems. In practice, it also seems
  337. // cause user function error handling implementation errors to be detected
  338. // very early in the development cycle.
  339. inline system::error_code & throws()
  340. { return *detail::throws(); }
  341. namespace system
  342. {
  343. // non-member functions ------------------------------------------------//
  344. inline bool operator!=( const error_code & lhs,
  345. const error_code & rhs )
  346. {
  347. return !(lhs == rhs);
  348. }
  349. inline bool operator!=( const error_condition & lhs,
  350. const error_condition & rhs )
  351. {
  352. return !(lhs == rhs);
  353. }
  354. inline bool operator==( const error_code & code,
  355. const error_condition & condition )
  356. {
  357. return code.category().equivalent( code.value(), condition )
  358. || condition.category().equivalent( code, condition.value() );
  359. }
  360. inline bool operator!=( const error_code & lhs,
  361. const error_condition & rhs )
  362. {
  363. return !(lhs == rhs);
  364. }
  365. inline bool operator==( const error_condition & condition,
  366. const error_code & code )
  367. {
  368. return condition.category().equivalent( code, condition.value() )
  369. || code.category().equivalent( code.value(), condition );
  370. }
  371. inline bool operator!=( const error_condition & lhs,
  372. const error_code & rhs )
  373. {
  374. return !(lhs == rhs);
  375. }
  376. // TODO: both of these may move elsewhere, but the LWG hasn't spoken yet.
  377. template <class charT, class traits>
  378. inline std::basic_ostream<charT,traits>&
  379. operator<< (std::basic_ostream<charT,traits>& os, error_code ec)
  380. {
  381. os << ec.category().name() << ':' << ec.value();
  382. return os;
  383. }
  384. inline std::size_t hash_value( const error_code & ec )
  385. {
  386. return static_cast<std::size_t>(ec.value())
  387. + reinterpret_cast<std::size_t>(&ec.category());
  388. }
  389. // make_* functions for errc::errc_t -----------------------------//
  390. namespace errc
  391. {
  392. // explicit conversion:
  393. inline error_code make_error_code( errc_t e )
  394. { return error_code( e, generic_category() ); }
  395. // implicit conversion:
  396. inline error_condition make_error_condition( errc_t e )
  397. { return error_condition( e, generic_category() ); }
  398. }
  399. // error_category default implementation -------------------------------//
  400. inline error_condition error_category::default_error_condition( int ev ) const
  401. {
  402. return error_condition( ev, *this );
  403. }
  404. inline bool error_category::equivalent( int code,
  405. const error_condition & condition ) const
  406. {
  407. return default_error_condition( code ) == condition;
  408. }
  409. inline bool error_category::equivalent( const error_code & code,
  410. int condition ) const
  411. {
  412. return *this == code.category() && code.value() == condition;
  413. }
  414. } // namespace system
  415. } // namespace boost
  416. #include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
  417. # ifdef BOOST_ERROR_CODE_HEADER_ONLY
  418. # include <boost/../libs/system/src/error_code.cpp>
  419. # endif
  420. #endif // BOOST_ERROR_CODE_HPP