src/work/klao/error.h
author klao
Fri, 07 Jan 2005 00:43:54 +0000
changeset 1056 cbc27743e17a
parent 993 src/lemon/error.h@21d1b4fa1b24
child 1061 e3433c024123
permissions -rw-r--r--
Exception hierarchy sketch.
Exception safe exception classes.
alpar@906
     1
/* -*- C++ -*-
alpar@921
     2
 * src/lemon/error.h - Part of LEMON, a generic C++ optimization library
alpar@906
     3
 *
alpar@906
     4
 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@906
     5
 * (Egervary Combinatorial Optimization Research Group, EGRES).
alpar@906
     6
 *
alpar@906
     7
 * Permission to use, modify and distribute this software is granted
alpar@906
     8
 * provided that this copyright notice appears in all copies. For
alpar@906
     9
 * precise terms see the accompanying LICENSE file.
alpar@906
    10
 *
alpar@906
    11
 * This software is provided "AS IS" with no warranty of any kind,
alpar@906
    12
 * express or implied, and with no claim as to its suitability for any
alpar@906
    13
 * purpose.
alpar@906
    14
 *
alpar@906
    15
 */
alpar@883
    16
alpar@921
    17
#ifndef LEMON_ERROR_H
alpar@921
    18
#define LEMON_ERROR_H
alpar@883
    19
alpar@883
    20
//! \ingroup misc
alpar@883
    21
//! \file
alpar@883
    22
//! \brief Basic error handling (signaling) routines.
alpar@883
    23
alpar@883
    24
#include <exception>
alpar@883
    25
#include <string>
alpar@883
    26
#include <sstream>
alpar@883
    27
klao@1056
    28
#include <boost/shared_ptr.hpp>
alpar@883
    29
alpar@921
    30
namespace lemon {
alpar@883
    31
klao@1056
    32
  /// Exception-safe convenient "error message" class.
klao@1056
    33
  class ErrorMessage {
klao@1056
    34
  protected:
klao@1056
    35
    boost::shared_ptr<std::ostringstream> buf;
klao@1056
    36
    
klao@1056
    37
    bool init() throw() {
klao@1056
    38
      try {
klao@1056
    39
	buf.reset(new std::ostringstream);
klao@1056
    40
      }
klao@1056
    41
      catch(...) {
klao@1056
    42
	buf.reset();
klao@1056
    43
      }
klao@1056
    44
      return buf;
klao@1056
    45
    }
klao@1056
    46
klao@1056
    47
  public:
klao@1056
    48
klao@1056
    49
    ErrorMessage() throw() { init(); }
klao@1056
    50
klao@1056
    51
    ErrorMessage(const char *message) throw() {
klao@1056
    52
      init();
klao@1056
    53
      *this << message;
klao@1056
    54
    }
klao@1056
    55
klao@1056
    56
    ErrorMessage(const std::string &message) throw() {
klao@1056
    57
      init();
klao@1056
    58
      *this << message;
klao@1056
    59
    }
klao@1056
    60
klao@1056
    61
    template <typename T>
klao@1056
    62
    ErrorMessage& operator<<(const T &t) throw() {
klao@1056
    63
      if( !buf ) return *this;
klao@1056
    64
klao@1056
    65
      try {
klao@1056
    66
	*buf << t;
klao@1056
    67
      }
klao@1056
    68
      catch(...) {
klao@1056
    69
	buf.reset();
klao@1056
    70
      }
klao@1056
    71
    }
klao@1056
    72
klao@1056
    73
    const char* message() throw() {
klao@1056
    74
      if( !buf ) return 0;
klao@1056
    75
klao@1056
    76
      const char* mes = 0;
klao@1056
    77
      try {
klao@1056
    78
	mes = buf->str().c_str();
klao@1056
    79
      }
klao@1056
    80
      catch(...) {}
klao@1056
    81
      return mes;
klao@1056
    82
    }
klao@1056
    83
    
klao@1056
    84
  };
klao@1056
    85
alpar@883
    86
  /**
alpar@883
    87
   * \brief Generic exception class.
alpar@883
    88
   *
klao@1056
    89
   * Base class for exceptions used in LEMON.
alpar@883
    90
   */
klao@1056
    91
  class Exception : public std::exception, public ErrorMessage {
alpar@883
    92
  public:
klao@1056
    93
    Exception() throw() {}
klao@1056
    94
    explicit Exception(const std::string &s) throw()
klao@1056
    95
      : ErrorMessage(s) {}
alpar@883
    96
    virtual ~Exception() throw() {}
alpar@883
    97
    
alpar@883
    98
    virtual const char* what() const throw() {
klao@1056
    99
      const char *mes = message();
klao@1056
   100
      if( mes ) return mes;
klao@1056
   101
      return "lemon::Exception";
klao@1056
   102
    }
klao@1056
   103
  };
klao@1056
   104
klao@1056
   105
klao@1056
   106
  class LogicError : public Exception {
klao@1056
   107
    explicit LogicError(const std::string &s)
klao@1056
   108
      : Exception(s) {}
klao@1056
   109
  };
klao@1056
   110
klao@1056
   111
  class RuntimeError : public Exception {
klao@1056
   112
    explicit RuntimeError(const std::string &s)
klao@1056
   113
      : Exception(s) {}
klao@1056
   114
  };
klao@1056
   115
klao@1056
   116
  class RangeError : public RuntimeError {
klao@1056
   117
    explicit RangeError(const std::string &s)
klao@1056
   118
      : RuntimeError(s) {}
klao@1056
   119
  };
klao@1056
   120
klao@1056
   121
  class IOError : public RuntimeError {
klao@1056
   122
    explicit IOError(const std::string &s)
klao@1056
   123
      : RuntimeError(s) {}
klao@1056
   124
  };
klao@1056
   125
klao@1056
   126
  class DataFormatError : public IOError {
klao@1056
   127
    explicit DataFormatError(const std::string &message)
klao@1056
   128
      : IOError(message) : line(0) {}
klao@1056
   129
    DataFormatError(const std::string &file_name, int line_num,
klao@1056
   130
		    sconst std::string &message)
klao@1056
   131
      : IOError(message), line(line_num) { set_file(file_name); }
klao@1056
   132
klao@1056
   133
    void set_line(int line_num) { line=line_num; }
klao@1056
   134
    void set_file(const std::string &file_name) {
klao@1056
   135
      try {
klao@1056
   136
	file.reset(new std::string);
klao@1056
   137
	*file = file_name;
klao@1056
   138
      }
klao@1056
   139
      catch(...) {
klao@1056
   140
	file.reset();
klao@1056
   141
      }
alpar@883
   142
    }
alpar@883
   143
klao@1056
   144
    virtual const char* what() const {
klao@1056
   145
      const char *mes = 0;
klao@1056
   146
      try {
klao@1056
   147
	std::ostringstream ostr;
klao@1056
   148
	ostr << IOError::what();
klao@1056
   149
	if( file || line ) {
klao@1056
   150
	  ostr << " (";
klao@1056
   151
	  if( file ) ostr << "in file" << *file;
klao@1056
   152
	  if( line ) ostr << " at line" << line;
klao@1056
   153
	}
klao@1056
   154
	mes = ostr.str().c_str();
klao@1056
   155
      }
klao@1056
   156
      catch(...) {}
klao@1056
   157
      if( mes ) return mes;
klao@1056
   158
      return "lemon::DataFormatError";
klao@1056
   159
    }
alpar@883
   160
  };
alpar@883
   161
klao@1056
   162
klao@1056
   163
klao@1056
   164
  /****************  Macros  ****************/
klao@1056
   165
klao@1056
   166
alpar@883
   167
  /**
klao@1056
   168
   * \brief Macro for assertions with customizable message
alpar@883
   169
   */
klao@1056
   170
klao@1056
   171
# define lemon_assert(exp, msg) \
klao@1056
   172
    if(!(exp)) { \
klao@1056
   173
      std::cerr << __FILE__ ":" << __LINE__ << ": " << (msg) << std::endl; \
klao@1056
   174
      abort; \
klao@1056
   175
    }
klao@1056
   176
alpar@883
   177
alpar@883
   178
  /**
alpar@883
   179
   * \brief Macro for mark not yet implemented features.
alpar@883
   180
   *
alpar@883
   181
   * \todo Is this the right place for this? It should be used only in
alpar@883
   182
   * modules under development.
alpar@883
   183
   */
alpar@883
   184
klao@1056
   185
# define FIXME(msg) lemon_assert(0, "FIXME: " msg)
alpar@883
   186
alpar@883
   187
}
alpar@921
   188
#endif // LEMON_ERROR_H