PageRenderTime 32ms CodeModel.GetById 2ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 1ms

/Src/Dependencies/Boost/boost/system/error_code.hpp

http://hadesmem.googlecode.com/
C++ Header | 513 lines | 340 code | 93 blank | 80 comment | 29 complexity | cbd83d263fea6db2034904684f172d47 MD5 | raw file
  1//  boost/system/error_code.hpp  ---------------------------------------------//
  2
  3//  Copyright Beman Dawes 2006, 2007
  4//  Copyright Christoper Kohlhoff 2007
  5
  6//  Distributed under the Boost Software License, Version 1.0. (See accompanying
  7//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  8
  9//  See library home page at http://www.boost.org/libs/system
 10
 11#ifndef BOOST_ERROR_CODE_HPP
 12#define BOOST_ERROR_CODE_HPP
 13
 14#include <boost/system/config.hpp>
 15#include <boost/cstdint.hpp>
 16#include <boost/assert.hpp>
 17#include <boost/operators.hpp>
 18#include <boost/noncopyable.hpp>
 19#include <boost/utility/enable_if.hpp>
 20#include <ostream>
 21#include <string>
 22#include <stdexcept>
 23#include <functional>
 24
 25// TODO: undef these macros if not already defined
 26#include <boost/cerrno.hpp> 
 27
 28#if !defined(BOOST_POSIX_API) && !defined(BOOST_WINDOWS_API)
 29#  error BOOST_POSIX_API or BOOST_WINDOWS_API must be defined
 30#endif
 31
 32#include <boost/config/abi_prefix.hpp> // must be the last #include
 33
 34namespace boost
 35{
 36  namespace system
 37  {
 38
 39    class error_code;
 40    class error_condition;
 41
 42    //  "Concept" helpers  ---------------------------------------------------//
 43
 44    template< class T >
 45    struct is_error_code_enum { static const bool value = false; };
 46
 47    template< class T >
 48    struct is_error_condition_enum { static const bool value = false; };
 49
 50    //  generic error_conditions  --------------------------------------------//
 51
 52    namespace errc
 53    {
 54      enum errc_t
 55      {
 56        success = 0,
 57        address_family_not_supported = EAFNOSUPPORT,
 58        address_in_use = EADDRINUSE,
 59        address_not_available = EADDRNOTAVAIL,
 60        already_connected = EISCONN,
 61        argument_list_too_long = E2BIG,
 62        argument_out_of_domain = EDOM,
 63        bad_address = EFAULT,
 64        bad_file_descriptor = EBADF,
 65        bad_message = EBADMSG,
 66        broken_pipe = EPIPE,
 67        connection_aborted = ECONNABORTED,
 68        connection_already_in_progress = EALREADY,
 69        connection_refused = ECONNREFUSED,
 70        connection_reset = ECONNRESET,
 71        cross_device_link = EXDEV,
 72        destination_address_required = EDESTADDRREQ,
 73        device_or_resource_busy = EBUSY,
 74        directory_not_empty = ENOTEMPTY,
 75        executable_format_error = ENOEXEC,
 76        file_exists = EEXIST,
 77        file_too_large = EFBIG,
 78        filename_too_long = ENAMETOOLONG,
 79        function_not_supported = ENOSYS,
 80        host_unreachable = EHOSTUNREACH,
 81        identifier_removed = EIDRM,
 82        illegal_byte_sequence = EILSEQ,
 83        inappropriate_io_control_operation = ENOTTY,
 84        interrupted = EINTR,
 85        invalid_argument = EINVAL,
 86        invalid_seek = ESPIPE,
 87        io_error = EIO,
 88        is_a_directory = EISDIR,
 89        message_size = EMSGSIZE,
 90        network_down = ENETDOWN,
 91        network_reset = ENETRESET,
 92        network_unreachable = ENETUNREACH,
 93        no_buffer_space = ENOBUFS,
 94        no_child_process = ECHILD,
 95        no_link = ENOLINK,
 96        no_lock_available = ENOLCK,
 97        no_message_available = ENODATA,
 98        no_message = ENOMSG,
 99        no_protocol_option = ENOPROTOOPT,
100        no_space_on_device = ENOSPC,
101        no_stream_resources = ENOSR,
102        no_such_device_or_address = ENXIO,
103        no_such_device = ENODEV,
104        no_such_file_or_directory = ENOENT,
105        no_such_process = ESRCH,
106        not_a_directory = ENOTDIR,
107        not_a_socket = ENOTSOCK,
108        not_a_stream = ENOSTR,
109        not_connected = ENOTCONN,
110        not_enough_memory = ENOMEM,
111        not_supported = ENOTSUP,
112        operation_canceled = ECANCELED,
113        operation_in_progress = EINPROGRESS,
114        operation_not_permitted = EPERM,
115        operation_not_supported = EOPNOTSUPP,
116        operation_would_block = EWOULDBLOCK,
117        owner_dead = EOWNERDEAD,
118        permission_denied = EACCES,
119        protocol_error = EPROTO,
120        protocol_not_supported = EPROTONOSUPPORT,
121        read_only_file_system = EROFS,
122        resource_deadlock_would_occur = EDEADLK,
123        resource_unavailable_try_again = EAGAIN,
124        result_out_of_range = ERANGE,
125        state_not_recoverable = ENOTRECOVERABLE,
126        stream_timeout = ETIME,
127        text_file_busy = ETXTBSY,
128        timed_out = ETIMEDOUT,
129        too_many_files_open_in_system = ENFILE,
130        too_many_files_open = EMFILE,
131        too_many_links = EMLINK,
132        too_many_symbolic_link_levels = ELOOP,
133        value_too_large = EOVERFLOW,
134        wrong_protocol_type = EPROTOTYPE
135      };
136
137    } // namespace errc
138
139# ifndef BOOST_SYSTEM_NO_DEPRECATED
140    namespace posix = errc;
141    namespace posix_error = errc;
142# endif
143
144    template<> struct is_error_condition_enum<errc::errc_t>
145      { static const bool value = true; };
146
147
148    //  ----------------------------------------------------------------------//
149
150    //  Operating system specific interfaces  --------------------------------//
151
152
153    //  The interface is divided into general and system-specific portions to
154    //  meet these requirements:
155    //
156    //  * Code calling an operating system API can create an error_code with
157    //    a single category (system_category), even for POSIX-like operating
158    //    systems that return some POSIX errno values and some native errno
159    //    values. This code should not have to pay the cost of distinguishing
160    //    between categories, since it is not yet known if that is needed.
161    //
162    //  * Users wishing to write system-specific code should be given enums for
163    //    at least the common error cases.
164    //
165    //  * System specific code should fail at compile time if moved to another
166    //    operating system.
167
168    //  The system specific portions of the interface are located in headers
169    //  with names reflecting the operating system. For example,
170    //
171    //       <boost/system/cygwin_error.hpp>
172    //       <boost/system/linux_error.hpp>
173    //       <boost/system/windows_error.hpp>
174    //
175    //  These headers are effectively empty for compiles on operating systems
176    //  where they are not applicable.
177
178    //  ----------------------------------------------------------------------//
179
180    //  class error_category  ------------------------------------------------//
181
182    class error_category : public noncopyable
183    {
184    public:
185      virtual ~error_category(){}
186
187      virtual const char *     name() const = 0;
188      virtual std::string      message( int ev ) const = 0;
189      virtual error_condition  default_error_condition( int ev ) const;
190      virtual bool             equivalent( int code, 
191                                           const error_condition & condition ) const;
192      virtual bool             equivalent( const error_code & code,
193                                           int condition ) const;
194
195      bool operator==(const error_category & rhs) const { return this == &rhs; }
196      bool operator!=(const error_category & rhs) const { return this != &rhs; }
197      bool operator<( const error_category & rhs ) const
198      {
199        return std::less<const error_category*>()( this, &rhs );
200      }
201    };
202
203    //  predefined error categories  -----------------------------------------//
204
205    BOOST_SYSTEM_DECL const error_category &  system_category();
206    BOOST_SYSTEM_DECL const error_category &  generic_category();
207
208    //  deprecated synonyms --------------------------------------------------//
209
210# ifndef BOOST_SYSTEM_NO_DEPRECATED
211    inline const error_category &  get_system_category() { return system_category(); }
212    inline const error_category &  get_generic_category() { return generic_category(); }
213    inline const error_category &  get_posix_category() { return generic_category(); }
214    static const error_category &  posix_category = generic_category();
215    static const error_category &  errno_ecat     = generic_category();
216    static const error_category &  native_ecat    = system_category();
217# endif
218
219    //  class error_condition  -----------------------------------------------//
220
221    //  error_conditions are portable, error_codes are system or library specific
222
223    class error_condition
224    {
225    public:
226
227      // constructors:
228      error_condition() : m_val(0), m_cat(&generic_category()) {}
229      error_condition( int val, const error_category & cat ) : m_val(val), m_cat(&cat) {}
230
231      template <class ErrorConditionEnum>
232        error_condition(ErrorConditionEnum e,
233          typename boost::enable_if<is_error_condition_enum<ErrorConditionEnum> >::type* = 0)
234      {
235        *this = make_error_condition(e);
236      }
237
238      // modifiers:
239
240      void assign( int val, const error_category & cat )
241      { 
242        m_val = val;
243        m_cat = &cat;
244      }
245                                             
246      template<typename ErrorConditionEnum>
247        typename boost::enable_if<is_error_condition_enum<ErrorConditionEnum>, error_condition>::type &
248          operator=( ErrorConditionEnum val )
249      { 
250        *this = make_error_condition(val);
251        return *this;
252      }
253
254      void clear()
255      {
256        m_val = 0;
257        m_cat = &generic_category();
258      }
259
260      // observers:
261      int                     value() const    { return m_val; }
262      const error_category &  category() const { return *m_cat; }
263      std::string             message() const  { return m_cat->message(value()); }
264
265      typedef void (*unspecified_bool_type)();
266      static void unspecified_bool_true() {}
267
268      operator unspecified_bool_type() const  // true if error
269      { 
270        return m_val == 0 ? 0 : unspecified_bool_true;
271      }
272
273      bool operator!() const  // true if no error
274      {
275        return m_val == 0;
276      }
277
278      // relationals:
279      //  the more symmetrical non-member syntax allows enum
280      //  conversions work for both rhs and lhs.
281      inline friend bool operator==( const error_condition & lhs,
282                                     const error_condition & rhs )
283      {
284        return lhs.m_cat == rhs.m_cat && lhs.m_val == rhs.m_val;
285      }                  
286
287      inline friend bool operator<( const error_condition & lhs,
288                                    const error_condition & rhs )
289        //  the more symmetrical non-member syntax allows enum
290        //  conversions work for both rhs and lhs.
291      {
292        return lhs.m_cat < rhs.m_cat
293          || (lhs.m_cat == rhs.m_cat && lhs.m_val < rhs.m_val);
294      }
295
296    private:
297      int                     m_val;
298      const error_category *  m_cat;
299
300    };
301
302    //  class error_code  ----------------------------------------------------//
303
304    //  We want error_code to be a value type that can be copied without slicing
305    //  and without requiring heap allocation, but we also want it to have
306    //  polymorphic behavior based on the error category. This is achieved by
307    //  abstract base class error_category supplying the polymorphic behavior,
308    //  and error_code containing a pointer to an object of a type derived
309    //  from error_category.
310    class error_code
311    {
312    public:
313
314      // constructors:
315      error_code() : m_val(0), m_cat(&system_category()) {}
316      error_code( int val, const error_category & cat ) : m_val(val), m_cat(&cat) {}
317
318      template <class ErrorCodeEnum>
319        error_code(ErrorCodeEnum e,
320          typename boost::enable_if<is_error_code_enum<ErrorCodeEnum> >::type* = 0)
321      {
322        *this = make_error_code(e);
323      }
324
325      // modifiers:
326      void assign( int val, const error_category & cat )
327      { 
328        m_val = val;
329        m_cat = &cat;
330      }
331                                             
332      template<typename ErrorCodeEnum>
333        typename boost::enable_if<is_error_code_enum<ErrorCodeEnum>, error_code>::type &
334          operator=( ErrorCodeEnum val )
335      { 
336        *this = make_error_code(val);
337        return *this;
338      }
339
340      void clear()
341      {
342        m_val = 0;
343        m_cat = &system_category();
344      }
345
346      // observers:
347      int                     value() const    { return m_val; }
348      const error_category &  category() const { return *m_cat; }
349      error_condition         default_error_condition() const  { return m_cat->default_error_condition(value()); }
350      std::string             message() const  { return m_cat->message(value()); }
351
352      typedef void (*unspecified_bool_type)();
353      static void unspecified_bool_true() {}
354
355      operator unspecified_bool_type() const  // true if error
356      { 
357        return m_val == 0 ? 0 : unspecified_bool_true;
358      }
359
360      bool operator!() const  // true if no error
361      {
362        return m_val == 0;
363      }
364
365      // relationals:
366      inline friend bool operator==( const error_code & lhs,
367                                     const error_code & rhs )
368        //  the more symmetrical non-member syntax allows enum
369        //  conversions work for both rhs and lhs.
370      {
371        return lhs.m_cat == rhs.m_cat && lhs.m_val == rhs.m_val;
372      }
373
374      inline friend bool operator<( const error_code & lhs,
375                                    const error_code & rhs )
376        //  the more symmetrical non-member syntax allows enum
377        //  conversions work for both rhs and lhs.
378      {
379        return lhs.m_cat < rhs.m_cat
380          || (lhs.m_cat == rhs.m_cat && lhs.m_val < rhs.m_val);
381      }
382                  
383      private:
384      int                     m_val;
385      const error_category *  m_cat;
386
387    };
388
389    //  predefined error_code object used as "throw on error" tag
390# ifndef BOOST_SYSTEM_NO_DEPRECATED
391    BOOST_SYSTEM_DECL extern error_code throws;
392# endif
393
394    //  Moving from a "throws" object to a "throws" function without breaking
395    //  existing code is a bit of a problem. The workaround is to place the
396    //  "throws" function in namespace boost rather than namespace boost::system.
397
398  }  // namespace system
399
400  namespace detail { inline system::error_code * throws() { return 0; } }
401    //  Misuse of the error_code object is turned into a noisy failure by
402    //  poisoning the reference. This particular implementation doesn't
403    //  produce warnings or errors from popular compilers, is very efficient
404    //  (as determined by inspecting generated code), and does not suffer
405    //  from order of initialization problems. In practice, it also seems
406    //  cause user function error handling implementation errors to be detected
407    //  very early in the development cycle.
408
409  inline system::error_code & throws()
410    { return *detail::throws(); }
411
412  namespace system
413  {
414    //  non-member functions  ------------------------------------------------//
415
416    inline bool operator!=( const error_code & lhs,
417                            const error_code & rhs )
418    {
419      return !(lhs == rhs);
420    }
421
422    inline bool operator!=( const error_condition & lhs,
423                            const error_condition & rhs )
424    {
425      return !(lhs == rhs);
426    }
427
428    inline bool operator==( const error_code & code,
429                            const error_condition & condition )
430    {
431      return code.category().equivalent( code.value(), condition )
432        || condition.category().equivalent( code, condition.value() );
433    }
434                
435    inline bool operator!=( const error_code & lhs,
436                            const error_condition & rhs )
437    {
438      return !(lhs == rhs);
439    }
440                
441    inline bool operator==( const error_condition & condition,
442                            const error_code & code )
443    {
444      return condition.category().equivalent( code, condition.value() )
445        || code.category().equivalent( code.value(), condition );
446    }
447                
448    inline bool operator!=( const error_condition & lhs,
449                            const error_code & rhs )
450    {
451      return !(lhs == rhs);
452    }
453                  
454    // TODO: both of these may move elsewhere, but the LWG hasn't spoken yet.
455
456    template <class charT, class traits>
457    inline std::basic_ostream<charT,traits>&
458      operator<< (std::basic_ostream<charT,traits>& os, error_code ec)
459    {
460      os << ec.category().name() << ':' << ec.value();
461      return os;
462    }
463
464    inline std::size_t hash_value( const error_code & ec )
465    {
466      return static_cast<std::size_t>(ec.value())
467        + reinterpret_cast<std::size_t>(&ec.category());
468    }
469
470    //  make_* functions for errc::errc_t  -----------------------------//
471
472    namespace errc
473    {
474      //  explicit conversion:
475      inline error_code make_error_code( errc_t e )
476        { return error_code( e, generic_category() ); }
477
478      //  implicit conversion:
479      inline error_condition make_error_condition( errc_t e )
480        { return error_condition( e, generic_category() ); }
481    }
482
483    //  error_category default implementation  -------------------------------//
484
485    inline error_condition error_category::default_error_condition( int ev ) const
486    { 
487      return error_condition( ev, *this );
488    }
489
490    inline bool error_category::equivalent( int code,
491      const error_condition & condition ) const
492    {
493      return default_error_condition( code ) == condition;
494    }
495
496    inline bool error_category::equivalent( const error_code & code,
497      int condition ) const
498    {
499      return *this == code.category() && code.value() == condition;
500    }
501
502  } // namespace system
503} // namespace boost
504
505#include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
506
507# ifdef BOOST_ERROR_CODE_HEADER_ONLY
508#   include <boost/../libs/system/src/error_code.cpp>
509# endif
510
511#endif // BOOST_ERROR_CODE_HPP
512
513