Home | History | Annotate | Download | only in include
      1 // <system_error> -*- C++ -*-
      2 
      3 // Copyright (C) 2007, 2008, 2009 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 <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() = default;
     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   // DR 890.
    104   const error_category& system_category();
    105   const error_category& generic_category();
    106 
    107   error_code make_error_code(errc);
    108 
    109   /// error_code
    110   // Implementation-specific error identification
    111   struct error_code
    112   {
    113     error_code()
    114     : _M_value(0), _M_cat(&system_category()) { }
    115 
    116     error_code(int __v, const error_category& __cat)
    117     : _M_value(__v), _M_cat(&__cat) { }
    118 
    119     template<typename _ErrorCodeEnum>
    120       error_code(_ErrorCodeEnum __e,
    121       typename enable_if<is_error_code_enum<_ErrorCodeEnum>::value>::type* = 0)
    122       { *this = make_error_code(__e); }
    123 
    124     void 
    125     assign(int __v, const error_category& __cat)
    126     {
    127       _M_value = __v;
    128       _M_cat = &__cat; 
    129     }
    130 
    131     void 
    132     clear()
    133     { assign(0, system_category()); }
    134 
    135     // DR 804.
    136     template<typename _ErrorCodeEnum>
    137       typename enable_if<is_error_code_enum<_ErrorCodeEnum>::value,
    138 			 error_code&>::type
    139       operator=(_ErrorCodeEnum __e)
    140       { return *this = make_error_code(__e); }
    141 
    142     int
    143     value() const { return _M_value; }
    144       
    145     const error_category&  
    146     category() const { return *_M_cat; }
    147 
    148     error_condition 
    149     default_error_condition() const;
    150 
    151     string 
    152     message() const
    153     { return category().message(value()); }
    154 
    155     // Safe bool idiom.
    156     // explicit operator bool() const throw()
    157     // { return _M_value != 0; }
    158     typedef void (*__bool_type)();
    159 
    160     static void __not_bool_type() { }
    161 
    162     operator __bool_type() const
    163     { return _M_value != 0 ? &__not_bool_type : false; }
    164 
    165     // DR 804.
    166   private:
    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     // Safe bool idiom.
    237     // explicit operator bool() const throw()
    238     // { return _M_value != 0; }
    239     typedef void (*__bool_type)();
    240 
    241     static void __not_bool_type() { }
    242 
    243     operator __bool_type() const
    244     { return _M_value != 0 ? &__not_bool_type : false; }
    245 
    246     // DR 804.
    247   private:
    248     int 			_M_value;
    249     const error_category* 	_M_cat;
    250   };
    251 
    252   // 19.4.3.6 non-member functions
    253   inline error_condition
    254   make_error_condition(errc __e)
    255   { return error_condition(static_cast<int>(__e), generic_category()); }
    256 
    257   inline bool 
    258   operator<(const error_condition& __lhs, const error_condition& __rhs)
    259   {
    260     return (__lhs.category() < __rhs.category()
    261 	    || (__lhs.category() == __rhs.category()
    262 		&& __lhs.value() < __rhs.value()));
    263   }
    264 
    265   // 19.4.4 Comparison operators
    266   inline bool
    267   operator==(const error_code& __lhs, const error_code& __rhs)
    268   { return (__lhs.category() == __rhs.category()
    269 	    && __lhs.value() == __rhs.value()); }
    270 
    271   inline bool
    272   operator==(const error_code& __lhs, const error_condition& __rhs)
    273   {
    274     return (__lhs.category().equivalent(__lhs.value(), __rhs)
    275 	    || __rhs.category().equivalent(__lhs, __rhs.value()));
    276   }
    277 
    278   inline bool
    279   operator==(const error_condition& __lhs, const error_code& __rhs)
    280   {
    281     return (__rhs.category().equivalent(__rhs.value(), __lhs)
    282 	    || __lhs.category().equivalent(__rhs, __lhs.value()));
    283   }
    284 
    285   inline bool
    286   operator==(const error_condition& __lhs, const error_condition& __rhs)
    287   {
    288     return (__lhs.category() == __rhs.category()
    289 	    && __lhs.value() == __rhs.value());
    290   }
    291 
    292   inline bool
    293   operator!=(const error_code& __lhs, const error_code& __rhs)
    294   { return !(__lhs == __rhs); }
    295 
    296   inline bool
    297   operator!=(const error_code& __lhs, const error_condition& __rhs)
    298   { return !(__lhs == __rhs); }
    299 
    300   inline bool
    301   operator!=(const error_condition& __lhs, const error_code& __rhs)
    302   { return !(__lhs == __rhs); }
    303 
    304   inline bool
    305   operator!=(const error_condition& __lhs, const error_condition& __rhs)
    306   { return !(__lhs == __rhs); }
    307 
    308 
    309   /** 
    310    *  @brief Thrown to indicate error code of underlying system.
    311    *
    312    *  @ingroup exceptions
    313    */
    314   class system_error : public std::runtime_error
    315   {
    316   private:
    317     error_code 	_M_code;
    318 
    319   public:
    320     system_error(error_code __ec = error_code())
    321     : runtime_error(""), _M_code(__ec) { }
    322 
    323     system_error(error_code __ec, const string& __what)
    324     : runtime_error(__what), _M_code(__ec) { }
    325     
    326     /*
    327      * TODO: Add const char* ctors to all exceptions.
    328      *
    329      * system_error(error_code __ec, const char* __what)
    330      * : runtime_error(__what), _M_code(__ec) { }
    331      *
    332      * system_error(int __v, const error_category& __ecat, const char* __what)
    333      * : runtime_error(__what), _M_code(error_code(__v, __ecat)) { }
    334      */
    335 
    336     system_error(int __v, const error_category& __ecat)
    337     : runtime_error(""), _M_code(error_code(__v, __ecat)) { }
    338 
    339     system_error(int __v, const error_category& __ecat, const string& __what)
    340     : runtime_error(__what), _M_code(error_code(__v, __ecat)) { }
    341 
    342     virtual ~system_error() throw();
    343 
    344     const error_code& 
    345     code() const throw() { return _M_code; }
    346   };
    347 
    348 _GLIBCXX_END_NAMESPACE
    349 
    350 #endif // __GXX_EXPERIMENTAL_CXX0X__
    351 
    352 #endif // _GLIBCXX_SYSTEM_ERROR
    353 
    354