You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

system_error 15KB

3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. // <system_error> -*- C++ -*-
  2. // Copyright (C) 2007-2020 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file include/system_error
  21. * This is a Standard C++ Library header.
  22. */
  23. #ifndef _GLIBCXX_SYSTEM_ERROR
  24. #define _GLIBCXX_SYSTEM_ERROR 1
  25. #pragma GCC system_header
  26. #if __cplusplus < 201103L
  27. # include <bits/c++0x_warning.h>
  28. #else
  29. #include <bits/c++config.h>
  30. #include <bits/error_constants.h>
  31. #include <iosfwd>
  32. #include <stdexcept>
  33. #if __cplusplus > 201703L
  34. # include <compare>
  35. #endif
  36. namespace std _GLIBCXX_VISIBILITY(default)
  37. {
  38. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  39. /** @addtogroup diagnostics
  40. * @{
  41. */
  42. class error_code;
  43. class error_condition;
  44. class system_error;
  45. /// is_error_code_enum
  46. template<typename _Tp>
  47. struct is_error_code_enum : public false_type { };
  48. /// is_error_condition_enum
  49. template<typename _Tp>
  50. struct is_error_condition_enum : public false_type { };
  51. template<>
  52. struct is_error_condition_enum<errc>
  53. : public true_type { };
  54. #if __cplusplus > 201402L
  55. template <typename _Tp>
  56. inline constexpr bool is_error_code_enum_v =
  57. is_error_code_enum<_Tp>::value;
  58. template <typename _Tp>
  59. inline constexpr bool is_error_condition_enum_v =
  60. is_error_condition_enum<_Tp>::value;
  61. #endif // C++17
  62. inline namespace _V2 {
  63. /** Abstract base class for types defining a category of error codes.
  64. *
  65. * An error category defines a context that give meaning to the integer
  66. * stored in an `error_code` or `error_condition` object. For example,
  67. * the standard `errno` constants such a `EINVAL` and `ENOMEM` are
  68. * associated with the "generic" category and other OS-specific error
  69. * numbers are associated with the "system" category, but a user-defined
  70. * category might give different meanings to the same numerical values.
  71. */
  72. class error_category
  73. {
  74. public:
  75. constexpr error_category() noexcept = default;
  76. virtual ~error_category();
  77. error_category(const error_category&) = delete;
  78. error_category& operator=(const error_category&) = delete;
  79. virtual const char*
  80. name() const noexcept = 0;
  81. // We need two different virtual functions here, one returning a
  82. // COW string and one returning an SSO string. Their positions in the
  83. // vtable must be consistent for dynamic dispatch to work, but which one
  84. // the name "message()" finds depends on which ABI the caller is using.
  85. #if _GLIBCXX_USE_CXX11_ABI
  86. private:
  87. _GLIBCXX_DEFAULT_ABI_TAG
  88. virtual __cow_string
  89. _M_message(int) const;
  90. public:
  91. _GLIBCXX_DEFAULT_ABI_TAG
  92. virtual string
  93. message(int) const = 0;
  94. #else
  95. virtual string
  96. message(int) const = 0;
  97. private:
  98. virtual __sso_string
  99. _M_message(int) const;
  100. #endif
  101. public:
  102. virtual error_condition
  103. default_error_condition(int __i) const noexcept;
  104. virtual bool
  105. equivalent(int __i, const error_condition& __cond) const noexcept;
  106. virtual bool
  107. equivalent(const error_code& __code, int __i) const noexcept;
  108. bool
  109. operator==(const error_category& __other) const noexcept
  110. { return this == &__other; }
  111. #if __cpp_lib_three_way_comparison
  112. strong_ordering
  113. operator<=>(const error_category& __rhs) const noexcept
  114. { return std::compare_three_way()(this, &__rhs); }
  115. #else
  116. bool
  117. operator!=(const error_category& __other) const noexcept
  118. { return this != &__other; }
  119. bool
  120. operator<(const error_category& __other) const noexcept
  121. { return less<const error_category*>()(this, &__other); }
  122. #endif
  123. };
  124. // DR 890.
  125. /// Error category for `errno` error codes.
  126. _GLIBCXX_CONST const error_category& generic_category() noexcept;
  127. /// Error category for other error codes defined by the OS.
  128. _GLIBCXX_CONST const error_category& system_category() noexcept;
  129. } // end inline namespace
  130. error_code make_error_code(errc) noexcept;
  131. /** Class error_code
  132. *
  133. * This class is a value type storing an integer error number and a
  134. * category that gives meaning to the error number. Typically this is done
  135. * close the the point where the error happens, to capture the original
  136. * error value.
  137. *
  138. * An `error_code` object can be used to store the original error value
  139. * emitted by some subsystem, with a category relevant to the subsystem.
  140. * For example, errors from POSIX library functions can be represented by
  141. * an `errno` value and the "generic" category, but errors from an HTTP
  142. * library might be represented by an HTTP response status code (e.g. 404)
  143. * and a custom category defined by the library.
  144. */
  145. struct error_code
  146. {
  147. error_code() noexcept
  148. : _M_value(0), _M_cat(&system_category()) { }
  149. error_code(int __v, const error_category& __cat) noexcept
  150. : _M_value(__v), _M_cat(&__cat) { }
  151. template<typename _ErrorCodeEnum, typename = typename
  152. enable_if<is_error_code_enum<_ErrorCodeEnum>::value>::type>
  153. error_code(_ErrorCodeEnum __e) noexcept
  154. { *this = make_error_code(__e); }
  155. void
  156. assign(int __v, const error_category& __cat) noexcept
  157. {
  158. _M_value = __v;
  159. _M_cat = &__cat;
  160. }
  161. void
  162. clear() noexcept
  163. { assign(0, system_category()); }
  164. // DR 804.
  165. template<typename _ErrorCodeEnum>
  166. typename enable_if<is_error_code_enum<_ErrorCodeEnum>::value,
  167. error_code&>::type
  168. operator=(_ErrorCodeEnum __e) noexcept
  169. { return *this = make_error_code(__e); }
  170. int
  171. value() const noexcept { return _M_value; }
  172. const error_category&
  173. category() const noexcept { return *_M_cat; }
  174. error_condition
  175. default_error_condition() const noexcept;
  176. _GLIBCXX_DEFAULT_ABI_TAG
  177. string
  178. message() const
  179. { return category().message(value()); }
  180. explicit operator bool() const noexcept
  181. { return _M_value != 0; }
  182. // DR 804.
  183. private:
  184. int _M_value;
  185. const error_category* _M_cat;
  186. };
  187. // 19.4.2.6 non-member functions
  188. /// @relates error_code @{
  189. inline error_code
  190. make_error_code(errc __e) noexcept
  191. { return error_code(static_cast<int>(__e), generic_category()); }
  192. #if __cpp_lib_three_way_comparison
  193. inline strong_ordering
  194. operator<=>(const error_code& __lhs, const error_code& __rhs) noexcept
  195. {
  196. if (auto __c = __lhs.category() <=> __rhs.category(); __c != 0)
  197. return __c;
  198. return __lhs.value() <=> __rhs.value();
  199. }
  200. #else
  201. inline bool
  202. operator<(const error_code& __lhs, const error_code& __rhs) noexcept
  203. {
  204. return (__lhs.category() < __rhs.category()
  205. || (__lhs.category() == __rhs.category()
  206. && __lhs.value() < __rhs.value()));
  207. }
  208. #endif
  209. template<typename _CharT, typename _Traits>
  210. basic_ostream<_CharT, _Traits>&
  211. operator<<(basic_ostream<_CharT, _Traits>& __os, const error_code& __e)
  212. { return (__os << __e.category().name() << ':' << __e.value()); }
  213. // @}
  214. error_condition make_error_condition(errc) noexcept;
  215. /** Class error_condition
  216. *
  217. * This class represents error conditions that may be visible at an API
  218. * boundary. Different `error_code` values that can occur within a library
  219. * or module might map to the same `error_condition`.
  220. *
  221. * An `error_condition` represents something that the program can test for,
  222. * and subsequently take appropriate action.
  223. */
  224. struct error_condition
  225. {
  226. error_condition() noexcept
  227. : _M_value(0), _M_cat(&generic_category()) { }
  228. error_condition(int __v, const error_category& __cat) noexcept
  229. : _M_value(__v), _M_cat(&__cat) { }
  230. template<typename _ErrorConditionEnum, typename = typename
  231. enable_if<is_error_condition_enum<_ErrorConditionEnum>::value>::type>
  232. error_condition(_ErrorConditionEnum __e) noexcept
  233. { *this = make_error_condition(__e); }
  234. void
  235. assign(int __v, const error_category& __cat) noexcept
  236. {
  237. _M_value = __v;
  238. _M_cat = &__cat;
  239. }
  240. // DR 804.
  241. template<typename _ErrorConditionEnum>
  242. typename enable_if<is_error_condition_enum
  243. <_ErrorConditionEnum>::value, error_condition&>::type
  244. operator=(_ErrorConditionEnum __e) noexcept
  245. { return *this = make_error_condition(__e); }
  246. void
  247. clear() noexcept
  248. { assign(0, generic_category()); }
  249. // 19.4.3.4 observers
  250. int
  251. value() const noexcept { return _M_value; }
  252. const error_category&
  253. category() const noexcept { return *_M_cat; }
  254. _GLIBCXX_DEFAULT_ABI_TAG
  255. string
  256. message() const
  257. { return category().message(value()); }
  258. explicit operator bool() const noexcept
  259. { return _M_value != 0; }
  260. // DR 804.
  261. private:
  262. int _M_value;
  263. const error_category* _M_cat;
  264. };
  265. // 19.4.3.6 non-member functions
  266. /// Create an `error_condition` representing a standard `errc` condition.
  267. /// @relates error_condition
  268. inline error_condition
  269. make_error_condition(errc __e) noexcept
  270. { return error_condition(static_cast<int>(__e), generic_category()); }
  271. // 19.4.4 Comparison operators
  272. /// @relates error_code
  273. inline bool
  274. operator==(const error_code& __lhs, const error_code& __rhs) noexcept
  275. { return (__lhs.category() == __rhs.category()
  276. && __lhs.value() == __rhs.value()); }
  277. /// @relates error_code
  278. /// @relates error_condition
  279. inline bool
  280. operator==(const error_code& __lhs, const error_condition& __rhs) noexcept
  281. {
  282. return (__lhs.category().equivalent(__lhs.value(), __rhs)
  283. || __rhs.category().equivalent(__lhs, __rhs.value()));
  284. }
  285. /// @relates error_condition
  286. inline bool
  287. operator==(const error_condition& __lhs,
  288. const error_condition& __rhs) noexcept
  289. {
  290. return (__lhs.category() == __rhs.category()
  291. && __lhs.value() == __rhs.value());
  292. }
  293. #if __cpp_lib_three_way_comparison
  294. /// Define an ordering for error_condition objects.
  295. /// @relates error_condition
  296. inline strong_ordering
  297. operator<=>(const error_condition& __lhs,
  298. const error_condition& __rhs) noexcept
  299. {
  300. if (auto __c = __lhs.category() <=> __rhs.category(); __c != 0)
  301. return __c;
  302. return __lhs.value() <=> __rhs.value();
  303. }
  304. #else
  305. /// Define an ordering for error_condition objects.
  306. /// @relates error_condition
  307. inline bool
  308. operator<(const error_condition& __lhs,
  309. const error_condition& __rhs) noexcept
  310. {
  311. return (__lhs.category() < __rhs.category()
  312. || (__lhs.category() == __rhs.category()
  313. && __lhs.value() < __rhs.value()));
  314. }
  315. /// @relates error_code
  316. /// @relates error_condition
  317. inline bool
  318. operator==(const error_condition& __lhs, const error_code& __rhs) noexcept
  319. {
  320. return (__rhs.category().equivalent(__rhs.value(), __lhs)
  321. || __lhs.category().equivalent(__rhs, __lhs.value()));
  322. }
  323. /// @relates error_code
  324. inline bool
  325. operator!=(const error_code& __lhs, const error_code& __rhs) noexcept
  326. { return !(__lhs == __rhs); }
  327. /// @relates error_code
  328. /// @relates error_condition
  329. inline bool
  330. operator!=(const error_code& __lhs, const error_condition& __rhs) noexcept
  331. { return !(__lhs == __rhs); }
  332. /// @relates error_code
  333. /// @relates error_condition
  334. inline bool
  335. operator!=(const error_condition& __lhs, const error_code& __rhs) noexcept
  336. { return !(__lhs == __rhs); }
  337. /// @relates error_condition
  338. inline bool
  339. operator!=(const error_condition& __lhs,
  340. const error_condition& __rhs) noexcept
  341. { return !(__lhs == __rhs); }
  342. #endif // three_way_comparison
  343. /**
  344. * @brief An exception type that includes an `error_code` value.
  345. *
  346. * Typically used to report errors from the operating system and other
  347. * low-level APIs.
  348. *
  349. * @ingroup exceptions
  350. */
  351. class system_error : public std::runtime_error
  352. {
  353. private:
  354. error_code _M_code;
  355. public:
  356. system_error(error_code __ec = error_code())
  357. : runtime_error(__ec.message()), _M_code(__ec) { }
  358. system_error(error_code __ec, const string& __what)
  359. : runtime_error(__what + ": " + __ec.message()), _M_code(__ec) { }
  360. system_error(error_code __ec, const char* __what)
  361. : runtime_error(__what + (": " + __ec.message())), _M_code(__ec) { }
  362. system_error(int __v, const error_category& __ecat, const char* __what)
  363. : system_error(error_code(__v, __ecat), __what) { }
  364. system_error(int __v, const error_category& __ecat)
  365. : runtime_error(error_code(__v, __ecat).message()),
  366. _M_code(__v, __ecat) { }
  367. system_error(int __v, const error_category& __ecat, const string& __what)
  368. : runtime_error(__what + ": " + error_code(__v, __ecat).message()),
  369. _M_code(__v, __ecat) { }
  370. #if __cplusplus >= 201103L
  371. system_error (const system_error &) = default;
  372. system_error &operator= (const system_error &) = default;
  373. #endif
  374. virtual ~system_error() noexcept;
  375. const error_code&
  376. code() const noexcept { return _M_code; }
  377. };
  378. _GLIBCXX_END_NAMESPACE_VERSION
  379. } // namespace
  380. #include <bits/functional_hash.h>
  381. namespace std _GLIBCXX_VISIBILITY(default)
  382. {
  383. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  384. #ifndef _GLIBCXX_COMPATIBILITY_CXX0X
  385. // DR 1182.
  386. /// std::hash specialization for error_code.
  387. /// @relates error_code
  388. template<>
  389. struct hash<error_code>
  390. : public __hash_base<size_t, error_code>
  391. {
  392. size_t
  393. operator()(const error_code& __e) const noexcept
  394. {
  395. const size_t __tmp = std::_Hash_impl::hash(__e.value());
  396. return std::_Hash_impl::__hash_combine(&__e.category(), __tmp);
  397. }
  398. };
  399. #endif // _GLIBCXX_COMPATIBILITY_CXX0X
  400. #if __cplusplus >= 201703L
  401. // DR 2686.
  402. /// std::hash specialization for error_condition.
  403. /// @relates error_condition
  404. template<>
  405. struct hash<error_condition>
  406. : public __hash_base<size_t, error_condition>
  407. {
  408. size_t
  409. operator()(const error_condition& __e) const noexcept
  410. {
  411. const size_t __tmp = std::_Hash_impl::hash(__e.value());
  412. return std::_Hash_impl::__hash_combine(&__e.category(), __tmp);
  413. }
  414. };
  415. #endif
  416. _GLIBCXX_END_NAMESPACE_VERSION
  417. } // namespace
  418. #endif // C++11
  419. #endif // _GLIBCXX_SYSTEM_ERROR