Line data Source code
1 : // <system_error> -*- C++ -*-
2 :
3 : // Copyright (C) 2007-2019 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 :
43 : namespace std _GLIBCXX_VISIBILITY(default)
44 : {
45 : _GLIBCXX_BEGIN_NAMESPACE_VERSION
46 :
47 : class error_code;
48 : class error_condition;
49 : class system_error;
50 :
51 : /// is_error_code_enum
52 : template<typename _Tp>
53 : struct is_error_code_enum : public false_type { };
54 :
55 : /// is_error_condition_enum
56 : template<typename _Tp>
57 : struct is_error_condition_enum : public false_type { };
58 :
59 : template<>
60 : struct is_error_condition_enum<errc>
61 : : public true_type { };
62 :
63 : #if __cplusplus > 201402L
64 : template <typename _Tp>
65 : inline constexpr bool is_error_code_enum_v =
66 : is_error_code_enum<_Tp>::value;
67 : template <typename _Tp>
68 : inline constexpr bool is_error_condition_enum_v =
69 : is_error_condition_enum<_Tp>::value;
70 : #endif // C++17
71 : inline namespace _V2 {
72 :
73 : /// error_category
74 : class error_category
75 : {
76 : public:
77 0 : constexpr error_category() noexcept = default;
78 :
79 : virtual ~error_category();
80 :
81 : error_category(const error_category&) = delete;
82 : error_category& operator=(const error_category&) = delete;
83 :
84 : virtual const char*
85 : name() const noexcept = 0;
86 :
87 : // We need two different virtual functions here, one returning a
88 : // COW string and one returning an SSO string. Their positions in the
89 : // vtable must be consistent for dynamic dispatch to work, but which one
90 : // the name "message()" finds depends on which ABI the caller is using.
91 : #if _GLIBCXX_USE_CXX11_ABI
92 : private:
93 : _GLIBCXX_DEFAULT_ABI_TAG
94 : virtual __cow_string
95 : _M_message(int) const;
96 :
97 : public:
98 : _GLIBCXX_DEFAULT_ABI_TAG
99 : virtual string
100 : message(int) const = 0;
101 : #else
102 : virtual string
103 : message(int) const = 0;
104 :
105 : private:
106 : virtual __sso_string
107 : _M_message(int) const;
108 : #endif
109 :
110 : public:
111 : virtual error_condition
112 : default_error_condition(int __i) const noexcept;
113 :
114 : virtual bool
115 : equivalent(int __i, const error_condition& __cond) const noexcept;
116 :
117 : virtual bool
118 : equivalent(const error_code& __code, int __i) const noexcept;
119 :
120 : bool
121 : operator<(const error_category& __other) const noexcept
122 : { return less<const error_category*>()(this, &__other); }
123 :
124 : bool
125 0 : operator==(const error_category& __other) const noexcept
126 0 : { return this == &__other; }
127 :
128 : bool
129 : operator!=(const error_category& __other) const noexcept
130 : { return this != &__other; }
131 : };
132 :
133 : // DR 890.
134 : _GLIBCXX_CONST const error_category& system_category() noexcept;
135 : _GLIBCXX_CONST const error_category& generic_category() noexcept;
136 :
137 : } // end inline namespace
138 :
139 : error_code make_error_code(errc) noexcept;
140 :
141 : template<typename _Tp>
142 : struct hash;
143 :
144 : /// error_code
145 : // Implementation-specific error identification
146 : struct error_code
147 : {
148 : error_code() noexcept
149 : : _M_value(0), _M_cat(&system_category()) { }
150 :
151 : error_code(int __v, const error_category& __cat) noexcept
152 : : _M_value(__v), _M_cat(&__cat) { }
153 :
154 : template<typename _ErrorCodeEnum, typename = typename
155 : enable_if<is_error_code_enum<_ErrorCodeEnum>::value>::type>
156 : error_code(_ErrorCodeEnum __e) noexcept
157 : { *this = make_error_code(__e); }
158 :
159 : void
160 : assign(int __v, const error_category& __cat) noexcept
161 : {
162 : _M_value = __v;
163 : _M_cat = &__cat;
164 : }
165 :
166 : void
167 : clear() noexcept
168 : { assign(0, system_category()); }
169 :
170 : // DR 804.
171 : template<typename _ErrorCodeEnum>
172 : typename enable_if<is_error_code_enum<_ErrorCodeEnum>::value,
173 : error_code&>::type
174 : operator=(_ErrorCodeEnum __e) noexcept
175 : { return *this = make_error_code(__e); }
176 :
177 : int
178 0 : value() const noexcept { return _M_value; }
179 :
180 : const error_category&
181 0 : category() const noexcept { return *_M_cat; }
182 :
183 : error_condition
184 : default_error_condition() const noexcept;
185 :
186 : _GLIBCXX_DEFAULT_ABI_TAG
187 : string
188 : message() const
189 : { return category().message(value()); }
190 :
191 : explicit operator bool() const noexcept
192 : { return _M_value != 0; }
193 :
194 : // DR 804.
195 : private:
196 : friend class hash<error_code>;
197 :
198 : int _M_value;
199 : const error_category* _M_cat;
200 : };
201 :
202 : // 19.4.2.6 non-member functions
203 : inline error_code
204 : make_error_code(errc __e) noexcept
205 : { return error_code(static_cast<int>(__e), generic_category()); }
206 :
207 : inline bool
208 : operator<(const error_code& __lhs, const error_code& __rhs) noexcept
209 : {
210 : return (__lhs.category() < __rhs.category()
211 : || (__lhs.category() == __rhs.category()
212 : && __lhs.value() < __rhs.value()));
213 : }
214 :
215 : template<typename _CharT, typename _Traits>
216 : basic_ostream<_CharT, _Traits>&
217 : operator<<(basic_ostream<_CharT, _Traits>& __os, const error_code& __e)
218 : { return (__os << __e.category().name() << ':' << __e.value()); }
219 :
220 : error_condition make_error_condition(errc) noexcept;
221 :
222 : /// error_condition
223 : // Portable error identification
224 : struct error_condition
225 : {
226 : error_condition() noexcept
227 : : _M_value(0), _M_cat(&generic_category()) { }
228 :
229 0 : error_condition(int __v, const error_category& __cat) noexcept
230 : : _M_value(__v), _M_cat(&__cat) { }
231 :
232 : template<typename _ErrorConditionEnum, typename = typename
233 : enable_if<is_error_condition_enum<_ErrorConditionEnum>::value>::type>
234 : error_condition(_ErrorConditionEnum __e) noexcept
235 : { *this = make_error_condition(__e); }
236 :
237 : void
238 : assign(int __v, const error_category& __cat) noexcept
239 : {
240 : _M_value = __v;
241 : _M_cat = &__cat;
242 : }
243 :
244 : // DR 804.
245 : template<typename _ErrorConditionEnum>
246 : typename enable_if<is_error_condition_enum
247 : <_ErrorConditionEnum>::value, error_condition&>::type
248 : operator=(_ErrorConditionEnum __e) noexcept
249 : { return *this = make_error_condition(__e); }
250 :
251 : void
252 : clear() noexcept
253 : { assign(0, generic_category()); }
254 :
255 : // 19.4.3.4 observers
256 : int
257 0 : value() const noexcept { return _M_value; }
258 :
259 : const error_category&
260 0 : category() const noexcept { return *_M_cat; }
261 :
262 : _GLIBCXX_DEFAULT_ABI_TAG
263 : string
264 : message() const
265 : { return category().message(value()); }
266 :
267 : explicit operator bool() const noexcept
268 : { return _M_value != 0; }
269 :
270 : // DR 804.
271 : private:
272 : int _M_value;
273 : const error_category* _M_cat;
274 : };
275 :
276 : // 19.4.3.6 non-member functions
277 : inline error_condition
278 : make_error_condition(errc __e) noexcept
279 : { return error_condition(static_cast<int>(__e), generic_category()); }
280 :
281 : inline bool
282 : operator<(const error_condition& __lhs,
283 : const error_condition& __rhs) noexcept
284 : {
285 : return (__lhs.category() < __rhs.category()
286 : || (__lhs.category() == __rhs.category()
287 : && __lhs.value() < __rhs.value()));
288 : }
289 :
290 : // 19.4.4 Comparison operators
291 : inline bool
292 : operator==(const error_code& __lhs, const error_code& __rhs) noexcept
293 : { return (__lhs.category() == __rhs.category()
294 : && __lhs.value() == __rhs.value()); }
295 :
296 : inline bool
297 : operator==(const error_code& __lhs, const error_condition& __rhs) noexcept
298 : {
299 : return (__lhs.category().equivalent(__lhs.value(), __rhs)
300 : || __rhs.category().equivalent(__lhs, __rhs.value()));
301 : }
302 :
303 : inline bool
304 : operator==(const error_condition& __lhs, const error_code& __rhs) noexcept
305 : {
306 : return (__rhs.category().equivalent(__rhs.value(), __lhs)
307 : || __lhs.category().equivalent(__rhs, __lhs.value()));
308 : }
309 :
310 : inline bool
311 0 : operator==(const error_condition& __lhs,
312 : const error_condition& __rhs) noexcept
313 : {
314 0 : return (__lhs.category() == __rhs.category()
315 0 : && __lhs.value() == __rhs.value());
316 : }
317 :
318 : inline bool
319 : operator!=(const error_code& __lhs, const error_code& __rhs) noexcept
320 : { return !(__lhs == __rhs); }
321 :
322 : inline bool
323 : operator!=(const error_code& __lhs, const error_condition& __rhs) noexcept
324 : { return !(__lhs == __rhs); }
325 :
326 : inline bool
327 : operator!=(const error_condition& __lhs, const error_code& __rhs) noexcept
328 : { return !(__lhs == __rhs); }
329 :
330 : inline bool
331 : operator!=(const error_condition& __lhs,
332 : const error_condition& __rhs) noexcept
333 : { return !(__lhs == __rhs); }
334 :
335 :
336 : /**
337 : * @brief Thrown to indicate error code of underlying system.
338 : *
339 : * @ingroup exceptions
340 : */
341 : class system_error : public std::runtime_error
342 : {
343 : private:
344 : error_code _M_code;
345 :
346 : public:
347 : system_error(error_code __ec = error_code())
348 : : runtime_error(__ec.message()), _M_code(__ec) { }
349 :
350 : system_error(error_code __ec, const string& __what)
351 : : runtime_error(__what + ": " + __ec.message()), _M_code(__ec) { }
352 :
353 : system_error(error_code __ec, const char* __what)
354 : : runtime_error(__what + (": " + __ec.message())), _M_code(__ec) { }
355 :
356 : system_error(int __v, const error_category& __ecat, const char* __what)
357 : : system_error(error_code(__v, __ecat), __what) { }
358 :
359 : system_error(int __v, const error_category& __ecat)
360 : : runtime_error(error_code(__v, __ecat).message()),
361 : _M_code(__v, __ecat) { }
362 :
363 : system_error(int __v, const error_category& __ecat, const string& __what)
364 : : runtime_error(__what + ": " + error_code(__v, __ecat).message()),
365 : _M_code(__v, __ecat) { }
366 :
367 : #if __cplusplus >= 201103L
368 0 : system_error (const system_error &) = default;
369 : system_error &operator= (const system_error &) = default;
370 : #endif
371 :
372 : virtual ~system_error() noexcept;
373 :
374 : const error_code&
375 : code() const noexcept { return _M_code; }
376 : };
377 :
378 : _GLIBCXX_END_NAMESPACE_VERSION
379 : } // namespace
380 :
381 : #include <bits/functional_hash.h>
382 :
383 : namespace std _GLIBCXX_VISIBILITY(default)
384 : {
385 : _GLIBCXX_BEGIN_NAMESPACE_VERSION
386 :
387 : #ifndef _GLIBCXX_COMPATIBILITY_CXX0X
388 : // DR 1182.
389 : /// std::hash specialization for error_code.
390 : template<>
391 : struct hash<error_code>
392 : : public __hash_base<size_t, error_code>
393 : {
394 : size_t
395 : operator()(const error_code& __e) const noexcept
396 : {
397 : const size_t __tmp = std::_Hash_impl::hash(__e._M_value);
398 : return std::_Hash_impl::__hash_combine(__e._M_cat, __tmp);
399 : }
400 : };
401 : #endif // _GLIBCXX_COMPATIBILITY_CXX0X
402 :
403 : #if __cplusplus > 201402L
404 : // DR 2686.
405 : /// std::hash specialization for error_condition.
406 : template<>
407 : struct hash<error_condition>
408 : : public __hash_base<size_t, error_condition>
409 : {
410 : size_t
411 : operator()(const error_condition& __e) const noexcept
412 : {
413 : const size_t __tmp = std::_Hash_impl::hash(__e.value());
414 : return std::_Hash_impl::__hash_combine(__e.category(), __tmp);
415 : }
416 : };
417 : #endif
418 :
419 : _GLIBCXX_END_NAMESPACE_VERSION
420 : } // namespace
421 :
422 : #endif // C++11
423 :
424 : #endif // _GLIBCXX_SYSTEM_ERROR
|