1    	// <system_error> -*- C++ -*-
2    	
3    	// Copyright (C) 2007-2017 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   	    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  	    operator==(const error_category& __other) const noexcept
126  	    { 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  	    value() const noexcept { return _M_value; }
179  	
180  	    const error_category&
181  	    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  	    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  	    value() const noexcept { return _M_value; }
258  	
259  	    const error_category&
260  	    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  	  operator==(const error_condition& __lhs,
312  		     const error_condition& __rhs) noexcept
313  	  {
314  	    return (__lhs.category() == __rhs.category()
315  		    && __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  	    virtual ~system_error() noexcept;
368  	
369  	    const error_code&
370  	    code() const noexcept { return _M_code; }
371  	  };
372  	
373  	_GLIBCXX_END_NAMESPACE_VERSION
374  	} // namespace
375  	
376  	#include <bits/functional_hash.h>
377  	
378  	namespace std _GLIBCXX_VISIBILITY(default)
379  	{
380  	_GLIBCXX_BEGIN_NAMESPACE_VERSION
381  	
382  	#ifndef _GLIBCXX_COMPATIBILITY_CXX0X
383  	  // DR 1182.
384  	  /// std::hash specialization for error_code.
385  	  template<>
386  	    struct hash<error_code>
387  	    : public __hash_base<size_t, error_code>
388  	    {
389  	      size_t
390  	      operator()(const error_code& __e) const noexcept
391  	      {
392  		const size_t __tmp = std::_Hash_impl::hash(__e._M_value);
393  		return std::_Hash_impl::__hash_combine(__e._M_cat, __tmp);
394  	      }
395  	    };
396  	#endif // _GLIBCXX_COMPATIBILITY_CXX0X
397  	
398  	#if __cplusplus > 201402L
399  	  // DR 2686.
400  	  /// std::hash specialization for error_condition.
401  	  template<>
402  	    struct hash<error_condition>
403  	    : public __hash_base<size_t, error_condition>
404  	    {
405  	      size_t
406  	      operator()(const error_condition& __e) const noexcept
407  	      {
408  		const size_t __tmp = std::_Hash_impl::hash(__e.value());
409  		return std::_Hash_impl::__hash_combine(__e.category(), __tmp);
410  	      }
411  	    };
412  	#endif
413  	
414  	_GLIBCXX_END_NAMESPACE_VERSION
415  	} // namespace
416  	
417  	#endif // C++11
418  	
419  	#endif // _GLIBCXX_SYSTEM_ERROR
420