error.hh 5.56 KB
Newer Older
smorlat's avatar
smorlat committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
/* HornetsEye - Computer Vision with Ruby
   Copyright (C) 2006, 2007   Jan Wedekind
   
   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
#ifndef HORNETSEYE_ERROR_HH
#define HORNETSEYE_ERROR_HH

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <exception>
#include <sstream>
#include <string>
#ifdef WIN32
#include <stdio.h>
#include <windef.h>
#include <wchar.h>
#include <winsock.h>
#endif

namespace Hornetseye {

  /** Exception class deriving from std::exception.
      This class provides a syntax similar to output-streams for convenience.
      For compability with other libraries it is inheriting the class
      \c std::exception.
    
      Here is an example how to use an instance of this class in C++:
      \include exceptiontest/exceptiontest.cc
      
      Exception-handling also can be done using the macro \c ERRORMACRO:
      \include exceptiontest/macrotest.cc
      
      Mind that the macro uses a variable with the name \c _e. Make sure, that
      you don't use this variable-name in any of the macro-arguments!

      Ruby already comes with exception classes:
      \include exceptiontest/exceptiontest.rb
      
      @date Mon Aug 23 14:37:05 UTC 2004 */
  class Error: public std::exception
  {
  public:
    /// Constructor.
    Error(void) {}
    /// Copy constructor.
    Error( Error &e ): std::exception( e )
      { m_message << e.m_message.str(); }
    /// Destructor.
    virtual ~Error(void) throw() {}
    ///
    template< typename T >
    std::ostream &operator<<( const T &t )
      { m_message << t; return m_message; }
    /** Interface for manipulators.
        Manipulators such as \c std::endl and \c std::hex use these
        functions in constructs like "Error e; e << std::endl".
        For more information, see the iomanip header. */
    std::ostream &operator<<( std::ostream& (*__pf)( std::ostream&) )
      { (*__pf)( m_message ); return m_message; }
    /// Returns error message (not thread safe).
    virtual const char* what(void) const throw() {
      temp = m_message.str();
      return temp.c_str();
      return NULL;
    }
  protected:
    /// Memory-stream containing the error message.
    std::ostringstream m_message;
    /** Temporary to do null-termination.
        The method \c what() requires a null-terminated string. */
    static std::string temp;
  };
  
};

#define ERRORMACRO( condition, class, params, message ) \
  if ( !( condition ) ) {                               \
    class _e params;                                    \
    _e << message;                                      \
    throw _e;                                           \
  };

#ifdef WIN32
#define COERRORMACRO( condition, class, params, message )                     \
  {                                                                           \
    HRESULT _hr = condition;                                                  \
    if ( FAILED( _hr ) ) {                                                    \
      class _e params;                                                        \
      _e << message;                                                          \
      TCHAR *_msg;                                                            \
      if ( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |                    \
                          FORMAT_MESSAGE_FROM_SYSTEM, 0, _hr, 0,              \
                          (LPTSTR)&_msg, 0, NULL ) != 0 ) {                   \
        _e << ": " << _msg;                                                   \
        LocalFree( _msg );                                                    \
      };                                                                      \
      throw _e;                                                               \
    };                                                                        \
  };

#define W32ERRORMACRO( condition, class, params, message )                    \
  {                                                                           \
    if ( !( condition ) ) {                                                   \
      class _e params;                                                        \
      _e << message;                                                          \
      TCHAR *_msg;                                                            \
      DWORD _errCode = GetLastError();                                        \
      if ( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |                    \
                          FORMAT_MESSAGE_FROM_SYSTEM, 0, _errCode, 0,         \
                          (LPTSTR)&_msg, 0, NULL ) != 0 ) {                   \
        _e << ": " << _msg;                                                   \
        LocalFree( _msg );                                                    \
      };                                                                      \
      throw _e;                                                               \
    };                                                                        \
  };

#endif

#endif