3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
22 //! \ingroup exceptions
24 //! \brief Basic exception classes and error handling.
35 /// \addtogroup exceptions
38 /// \brief Exception safe wrapper class.
40 /// Exception safe wrapper class to implement the members of exceptions.
41 template <typename _Type>
42 class ExceptionMember {
46 ExceptionMember() throw () {
48 ptr.reset(new Type());
52 ExceptionMember(const Type& type) throw () {
54 ptr.reset(new Type());
55 if (ptr.get() == 0) return;
60 ExceptionMember(const ExceptionMember& copy) throw() {
62 if (!copy.valid()) return;
63 ptr.reset(new Type());
64 if (ptr.get() == 0) return;
69 ExceptionMember& operator=(const ExceptionMember& copy) {
70 if (ptr.get() == 0) return;
72 if (!copy.valid()) return;
77 void set(const Type& type) {
78 if (ptr.get() == 0) return;
84 const Type& get() const {
89 return ptr.get() != 0;
93 std::auto_ptr<_Type> ptr;
96 /// Exception-safe convenient "error message" class.
98 /// Helper class which provides a convenient ostream-like (operator <<
99 /// based) interface to create a string message. Mostly useful in
100 /// exception classes (therefore the name).
105 ///\todo The good solution is boost::shared_ptr...
108 std::auto_ptr<std::ostringstream> buf;
111 bool init() throw() {
113 buf.reset(new std::ostringstream);
124 ErrorMessage() throw() { init(); }
126 ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { }
129 ErrorMessage(const char *message) throw() {
135 ErrorMessage(const std::string &message) throw() {
141 template <typename T>
142 ErrorMessage& operator<<(const T &t) throw() {
143 if( ! buf.get() ) return *this;
155 const char* message() throw() {
156 if( ! buf.get() ) return 0;
160 mes = buf->str().c_str();
169 * \brief Generic exception class.
171 * Base class for exceptions used in LEMON.
173 class Exception : public std::exception {
178 virtual ~Exception() throw() {}
181 virtual const char* exceptionName() const {
182 return "lemon::Exception";
186 virtual const char* what() const throw() {
187 return exceptionName();
192 * \brief One of the two main subclasses of \ref Exception.
194 * Logic errors represent problems in the internal logic of a program;
195 * in theory, these are preventable, and even detectable before the
196 * program runs (e.g., violations of class invariants).
198 * A typical example for this is \ref UninitializedParameter.
200 class LogicError : public Exception {
202 virtual const char* exceptionName() const {
203 return "lemon::LogicError";
208 * \brief \ref Exception for uninitialized parameters.
210 * This error represents problems in the initialization
211 * of the parameters of the algorithms.
213 class UninitializedParameter : public LogicError {
215 virtual const char* exceptionName() const {
216 return "lemon::UninitializedParameter";
222 * \brief One of the two main subclasses of \ref Exception.
224 * Runtime errors represent problems outside the scope of a program;
225 * they cannot be easily predicted and can generally only be caught as
226 * the program executes.
228 class RuntimeError : public Exception {
230 virtual const char* exceptionName() const {
231 return "lemon::RuntimeError";
236 class RangeError : public RuntimeError {
238 virtual const char* exceptionName() const {
239 return "lemon::RangeError";
244 class IOError : public RuntimeError {
246 virtual const char* exceptionName() const {
247 return "lemon::IOError";
252 class DataFormatError : public IOError {
254 ExceptionMember<std::string> _message;
255 ExceptionMember<std::string> _file;
258 mutable ExceptionMember<std::string> _message_holder;
261 DataFormatError(const DataFormatError &dfe) :
262 IOError(dfe), _message(dfe._message), _file(dfe._file),
266 explicit DataFormatError(const char *the_message)
267 : _message(the_message), _line(0) {}
270 DataFormatError(const std::string &file_name, int line_num,
271 const char *the_message)
272 : _message(the_message), _line(line_num) { file(file_name); }
275 void line(int line) { _line = line; }
277 void message(const std::string& message) { _message.set(message); }
279 void file(const std::string &file) { _file.set(file); }
282 int line() const { return _line; }
284 const char* message() const {
285 if (_message.valid() && !_message.get().empty()) {
286 return _message.get().c_str();
292 /// \brief Returns the filename.
294 /// Returns \e null if the filename was not specified.
295 const char* file() const {
296 if (_file.valid() && !_file.get().empty()) {
297 return _file.get().c_str();
304 virtual const char* what() const throw() {
306 std::ostringstream ostr;
307 ostr << exceptionName() << ": ";
308 if (message()) ostr << message();
309 if( file() || line() != 0 ) {
311 if( file() ) ostr << "in file '" << file() << "'";
312 if( file() && line() != 0 ) ostr << " ";
313 if( line() != 0 ) ostr << "at line " << line();
316 _message_holder.set(ostr.str());
319 if( _message_holder.valid()) return _message_holder.get().c_str();
320 return exceptionName();
323 virtual const char* exceptionName() const {
324 return "lemon::DataFormatError";
327 virtual ~DataFormatError() throw() {}
331 class FileOpenError : public IOError {
333 ExceptionMember<std::string> _file;
335 mutable ExceptionMember<std::string> _message_holder;
338 FileOpenError(const FileOpenError &foe) :
339 IOError(foe), _file(foe._file) {}
342 explicit FileOpenError(const std::string& file)
347 void file(const std::string &file) { _file.set(file); }
349 /// \brief Returns the filename.
351 /// Returns \e null if the filename was not specified.
352 const char* file() const {
353 if (_file.valid() && !_file.get().empty()) {
354 return _file.get().c_str();
361 virtual const char* what() const throw() {
363 std::ostringstream ostr;
364 ostr << exceptionName() << ": ";
365 ostr << "Cannot open file - " << file();
366 _message_holder.set(ostr.str());
369 if( _message_holder.valid()) return _message_holder.get().c_str();
370 return exceptionName();
373 virtual const char* exceptionName() const {
374 return "lemon::FileOpenError";
377 virtual ~FileOpenError() throw() {}
380 class IOParameterError : public IOError {
382 ExceptionMember<std::string> _message;
383 ExceptionMember<std::string> _file;
385 mutable ExceptionMember<std::string> _message_holder;
388 IOParameterError(const IOParameterError &ile) :
389 IOError(ile), _message(ile._message), _file(ile._file) {}
392 explicit IOParameterError(const char *the_message)
393 : _message(the_message) {}
396 IOParameterError(const char *file_name, const char *the_message)
397 : _message(the_message), _file(file_name) {}
400 void message(const std::string& message) { _message.set(message); }
402 void file(const std::string &file) { _file.set(file); }
405 const char* message() const {
406 if (_message.valid()) {
407 return _message.get().c_str();
413 /// \brief Returns the filename.
415 /// Returns \e null if the filename was not specified.
416 const char* file() const {
418 return _file.get().c_str();
425 virtual const char* what() const throw() {
427 std::ostringstream ostr;
428 if (message()) ostr << message();
429 if (file()) ostr << "(when reading file '" << file() << "')";
430 _message_holder.set(ostr.str());
433 if( _message_holder.valid() ) return _message_holder.get().c_str();
434 return exceptionName();
437 virtual const char* exceptionName() const {
438 return "lemon::IOParameterError";
441 virtual ~IOParameterError() throw() {}
446 class AssertionFailedError : public LogicError {
448 const char *assertion;
451 const char *function;
454 mutable ExceptionMember<std::string> _message_holder;
457 AssertionFailedError(const char *_file, int _line, const char *func,
458 const char *msg, const char *_assertion = 0) :
459 assertion(_assertion), file(_file), line(_line), function(func),
463 const char* get_assertion() const { return assertion; }
465 const char* get_message() const { return message; }
467 const char* get_file() const { return file; }
469 const char* get_function() const { return function; }
471 int get_line() const { return line; }
474 virtual const char* what() const throw() {
476 std::ostringstream ostr;
477 ostr << file << ":" << line << ": ";
479 ostr << function << ": ";
482 ostr << " (assertion '" << assertion << "' failed)";
483 _message_holder.set(ostr.str());
484 return ostr.str().c_str();
487 if( _message_holder.valid() ) return _message_holder.get().c_str();
488 return exceptionName();
491 virtual const char* exceptionName() const {
492 return "lemon::AssertionFailedError";
495 virtual ~AssertionFailedError() throw() {}
499 /**************** Macros ****************/
502 template <typename Exception>
503 inline void assert_fail(const char *file, int line, const char *func,
504 Exception exception, const char *assertion = 0,
508 cerr << file << ":" << line << ": ";
510 cerr << func << ": ";
511 cerr << exception.what();
513 cerr << " (assertion '" << assertion << "' failed)";
520 inline void assert_fail<const char *>(const char *file, int line, const char *func,
522 const char *assertion,
526 cerr << file << ":" << line << ": ";
528 cerr << func << ": ";
531 cerr << " (assertion '" << assertion << "' failed)";
537 template <typename Exception>
538 inline void assert_fail_failure(const char *file, int line, const char *func,
540 const char *assertion = 0,
543 throw AssertionFailedError(file, line, func, exception.what(), assertion);
547 inline void assert_fail_failure<const char *>(const char *file, int line,
550 const char *assertion,
553 throw AssertionFailedError(file, line, func, message, assertion);
556 template <typename Exception>
557 inline void assert_fail_exception(const char *file, int line, const char *func,
559 const char *assertion = 0, bool = true)
565 inline void assert_fail_exception<const char *>(const char *file, int line,
568 const char *assertion,
571 throw AssertionFailedError(file, line, func, message, assertion);
577 #endif // LEMON_ERROR_H
582 #ifndef LEMON_ASSERT_ABORT
583 # define LEMON_ASSERT_ABORT 1
586 #ifndef LEMON_ASSERT_HANDLER
587 # if defined LEMON_ASSERT_EXCEPTION
588 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception
589 # elif defined LEMON_ASSERT_FAILURE
590 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_failure
592 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail
596 #if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS)
598 # define LEMON_ASSERT(exp, msg) (static_cast<void> (0))
603 * \brief Macro for assertions with customizable message
605 * Macro for assertions with customizable message.
607 * The behaviour can be customized with LEMON_ASSERT_HANDLER,
608 * LEMON_ASSERT_EXCEPTION and LEMON_ASSERT_ABORT defines. Asserts can be
609 * disabled by defining either NDEBUG or LEMON_DISABLE_ASSERTS macros.
611 * \todo We should provide some way to reset to the default behaviour,
614 * \todo This whole 'assert' business should be placed in a separate
615 * include file. The boost assert is not guarded by header sentries
616 * which may help to change the behaviour of the assertions in
619 * \todo __PRETTY_FUNCTION__ should be replaced by something
620 * compiler-independent, like BOOST_CURRENT_FUNCTION
623 # define LEMON_ASSERT(exp, msg) \
624 (static_cast<void> (!!(exp) ? 0 : ( \
625 LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
626 __PRETTY_FUNCTION__, \
627 msg, #exp, LEMON_ASSERT_ABORT), 0)))
629 #endif // NDEBUG || LEMON_DISABLE_ASSERTS
632 * \brief Macro for mark not yet implemented features.
634 * \todo Is this the right place for this? It should be used only in
635 * modules under development.
637 * \todo __PRETTY_FUNCTION__ should be replaced by something
638 * compiler-independent, like BOOST_CURRENT_FUNCTION
641 # define LEMON_FIXME(msg) \
642 (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \