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