1// <system_error> -*- C++ -*- 2 3// Copyright (C) 2007, 2008, 2009, 2010 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 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#ifndef __GXX_EXPERIMENTAL_CXX0X__ 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_GLIBCXX_BEGIN_NAMESPACE(std) 44 45 class error_code; 46 class error_condition; 47 class error_category; 48 class system_error; 49 50 /// is_error_code_enum 51 template<typename _Tp> 52 struct is_error_code_enum : public false_type { }; 53 54 /// is_error_condition_enum 55 template<typename _Tp> 56 struct is_error_condition_enum : public false_type { }; 57 58 template<> 59 struct is_error_condition_enum<errc> 60 : public true_type { }; 61 62 63 /// error_category 64 class error_category 65 { 66 protected: 67 error_category(); 68 69 public: 70 virtual ~error_category() { } 71 72 error_category(const error_category&) = delete; 73 error_category& operator=(const error_category&) = delete; 74 75 virtual const char* 76 name() const = 0; 77 78 virtual string 79 message(int) const = 0; 80 81 virtual error_condition 82 default_error_condition(int __i) const; 83 84 virtual bool 85 equivalent(int __i, const error_condition& __cond) const; 86 87 virtual bool 88 equivalent(const error_code& __code, int __i) const; 89 90 bool 91 operator<(const error_category& __other) const 92 { return less<const error_category*>()(this, &__other); } 93 94 bool 95 operator==(const error_category& __other) const 96 { return this == &__other; } 97 98 bool 99 operator!=(const error_category& __other) const 100 { return this != &__other; } 101 }; 102 103 inline error_category::error_category() = default; 104 105 // DR 890. 106 _GLIBCXX_CONST const error_category& system_category() throw(); 107 _GLIBCXX_CONST const error_category& generic_category() throw(); 108 109 error_code make_error_code(errc); 110 111 template<typename _Tp> 112 struct hash; 113 114 /// error_code 115 // Implementation-specific error identification 116 struct error_code 117 { 118 error_code() 119 : _M_value(0), _M_cat(&system_category()) { } 120 121 error_code(int __v, const error_category& __cat) 122 : _M_value(__v), _M_cat(&__cat) { } 123 124 template<typename _ErrorCodeEnum> 125 error_code(_ErrorCodeEnum __e, 126 typename enable_if<is_error_code_enum<_ErrorCodeEnum>::value>::type* = 0) 127 { *this = make_error_code(__e); } 128 129 void 130 assign(int __v, const error_category& __cat) 131 { 132 _M_value = __v; 133 _M_cat = &__cat; 134 } 135 136 void 137 clear() 138 { assign(0, system_category()); } 139 140 // DR 804. 141 template<typename _ErrorCodeEnum> 142 typename enable_if<is_error_code_enum<_ErrorCodeEnum>::value, 143 error_code&>::type 144 operator=(_ErrorCodeEnum __e) 145 { return *this = make_error_code(__e); } 146 147 int 148 value() const { return _M_value; } 149 150 const error_category& 151 category() const { return *_M_cat; } 152 153 error_condition 154 default_error_condition() const; 155 156 string 157 message() const 158 { return category().message(value()); } 159 160 explicit operator bool() const 161 { return _M_value != 0 ? true : false; } 162 163 // DR 804. 164 private: 165 friend class hash<error_code>; 166 167 int _M_value; 168 const error_category* _M_cat; 169 }; 170 171 // 19.4.2.6 non-member functions 172 inline error_code 173 make_error_code(errc __e) 174 { return error_code(static_cast<int>(__e), generic_category()); } 175 176 inline bool 177 operator<(const error_code& __lhs, const error_code& __rhs) 178 { 179 return (__lhs.category() < __rhs.category() 180 || (__lhs.category() == __rhs.category() 181 && __lhs.value() < __rhs.value())); 182 } 183 184 template<typename _CharT, typename _Traits> 185 basic_ostream<_CharT, _Traits>& 186 operator<<(basic_ostream<_CharT, _Traits>& __os, const error_code& __e) 187 { return (__os << __e.category().name() << ':' << __e.value()); } 188 189 error_condition make_error_condition(errc); 190 191 /// error_condition 192 // Portable error identification 193 struct error_condition 194 { 195 error_condition() 196 : _M_value(0), _M_cat(&generic_category()) { } 197 198 error_condition(int __v, const error_category& __cat) 199 : _M_value(__v), _M_cat(&__cat) { } 200 201 template<typename _ErrorConditionEnum> 202 error_condition(_ErrorConditionEnum __e, 203 typename enable_if<is_error_condition_enum 204 <_ErrorConditionEnum>::value>::type* = 0) 205 { *this = make_error_condition(__e); } 206 207 void 208 assign(int __v, const error_category& __cat) 209 { 210 _M_value = __v; 211 _M_cat = &__cat; 212 } 213 214 // DR 804. 215 template<typename _ErrorConditionEnum> 216 typename enable_if<is_error_condition_enum 217 <_ErrorConditionEnum>::value, error_condition&>::type 218 operator=(_ErrorConditionEnum __e) 219 { return *this = make_error_condition(__e); } 220 221 void 222 clear() 223 { assign(0, generic_category()); } 224 225 // 19.4.3.4 observers 226 int 227 value() const { return _M_value; } 228 229 const error_category& 230 category() const { return *_M_cat; } 231 232 string 233 message() const 234 { return category().message(value()); } 235 236 explicit operator bool() const 237 { return _M_value != 0 ? true : false; } 238 239 // DR 804. 240 private: 241 int _M_value; 242 const error_category* _M_cat; 243 }; 244 245 // 19.4.3.6 non-member functions 246 inline error_condition 247 make_error_condition(errc __e) 248 { return error_condition(static_cast<int>(__e), generic_category()); } 249 250 inline bool 251 operator<(const error_condition& __lhs, const error_condition& __rhs) 252 { 253 return (__lhs.category() < __rhs.category() 254 || (__lhs.category() == __rhs.category() 255 && __lhs.value() < __rhs.value())); 256 } 257 258 // 19.4.4 Comparison operators 259 inline bool 260 operator==(const error_code& __lhs, const error_code& __rhs) 261 { return (__lhs.category() == __rhs.category() 262 && __lhs.value() == __rhs.value()); } 263 264 inline bool 265 operator==(const error_code& __lhs, const error_condition& __rhs) 266 { 267 return (__lhs.category().equivalent(__lhs.value(), __rhs) 268 || __rhs.category().equivalent(__lhs, __rhs.value())); 269 } 270 271 inline bool 272 operator==(const error_condition& __lhs, const error_code& __rhs) 273 { 274 return (__rhs.category().equivalent(__rhs.value(), __lhs) 275 || __lhs.category().equivalent(__rhs, __lhs.value())); 276 } 277 278 inline bool 279 operator==(const error_condition& __lhs, const error_condition& __rhs) 280 { 281 return (__lhs.category() == __rhs.category() 282 && __lhs.value() == __rhs.value()); 283 } 284 285 inline bool 286 operator!=(const error_code& __lhs, const error_code& __rhs) 287 { return !(__lhs == __rhs); } 288 289 inline bool 290 operator!=(const error_code& __lhs, const error_condition& __rhs) 291 { return !(__lhs == __rhs); } 292 293 inline bool 294 operator!=(const error_condition& __lhs, const error_code& __rhs) 295 { return !(__lhs == __rhs); } 296 297 inline bool 298 operator!=(const error_condition& __lhs, const error_condition& __rhs) 299 { return !(__lhs == __rhs); } 300 301 302 /** 303 * @brief Thrown to indicate error code of underlying system. 304 * 305 * @ingroup exceptions 306 */ 307 class system_error : public std::runtime_error 308 { 309 private: 310 error_code _M_code; 311 312 public: 313 system_error(error_code __ec = error_code()) 314 : runtime_error(""), _M_code(__ec) { } 315 316 system_error(error_code __ec, const string& __what) 317 : runtime_error(__what), _M_code(__ec) { } 318 319 /* 320 * TODO: Add const char* ctors to all exceptions. 321 * 322 * system_error(error_code __ec, const char* __what) 323 * : runtime_error(__what), _M_code(__ec) { } 324 * 325 * system_error(int __v, const error_category& __ecat, const char* __what) 326 * : runtime_error(__what), _M_code(error_code(__v, __ecat)) { } 327 */ 328 329 system_error(int __v, const error_category& __ecat) 330 : runtime_error(""), _M_code(error_code(__v, __ecat)) { } 331 332 system_error(int __v, const error_category& __ecat, const string& __what) 333 : runtime_error(__what), _M_code(error_code(__v, __ecat)) { } 334 335 virtual ~system_error() throw(); 336 337 const error_code& 338 code() const throw() { return _M_code; } 339 }; 340 341_GLIBCXX_END_NAMESPACE 342 343#ifndef _GLIBCXX_COMPATIBILITY_CXX0X 344 345#include <bits/functional_hash.h> 346 347_GLIBCXX_BEGIN_NAMESPACE(std) 348 349 // DR 1182. 350 /// std::hash specialization for error_code. 351 template<> 352 struct hash<error_code> 353 : public std::unary_function<error_code, size_t> 354 { 355 size_t 356 operator()(const error_code& __e) const 357 { 358 const size_t __tmp = std::_Fnv_hash::hash(__e._M_value); 359 return std::_Fnv_hash::__hash_combine(__e._M_cat, __tmp); 360 } 361 }; 362 363_GLIBCXX_END_NAMESPACE 364 365#endif // _GLIBCXX_COMPATIBILITY_CXX0X 366 367#endif // __GXX_EXPERIMENTAL_CXX0X__ 368 369#endif // _GLIBCXX_SYSTEM_ERROR 370 371