411 return "lemon:IoParameterError"; |
411 return "lemon:IoParameterError"; |
412 } |
412 } |
413 virtual ~IoParameterError() throw() {} |
413 virtual ~IoParameterError() throw() {} |
414 }; |
414 }; |
415 |
415 |
416 |
416 /// @} |
417 ///\e |
|
418 class AssertionFailedError : public LogicError { |
|
419 protected: |
|
420 const char *assertion; |
|
421 const char *file; |
|
422 int line; |
|
423 const char *function; |
|
424 const char *message; |
|
425 |
|
426 mutable ExceptionMember<std::string> _message_holder; |
|
427 public: |
|
428 ///\e |
|
429 AssertionFailedError(const char *_file, int _line, const char *func, |
|
430 const char *msg, const char *_assertion = 0) : |
|
431 assertion(_assertion), file(_file), line(_line), function(func), |
|
432 message(msg) {} |
|
433 |
|
434 ///\e |
|
435 const char* get_assertion() const { return assertion; } |
|
436 ///\e |
|
437 const char* get_message() const { return message; } |
|
438 ///\e |
|
439 const char* get_file() const { return file; } |
|
440 ///\e |
|
441 const char* get_function() const { return function; } |
|
442 ///\e |
|
443 int get_line() const { return line; } |
|
444 |
|
445 |
|
446 virtual const char* what() const throw() { |
|
447 try { |
|
448 std::ostringstream ostr; |
|
449 ostr << file << ":" << line << ": "; |
|
450 if( function ) |
|
451 ostr << function << ": "; |
|
452 ostr << message; |
|
453 if( assertion ) |
|
454 ostr << " (assertion '" << assertion << "' failed)"; |
|
455 _message_holder.set(ostr.str()); |
|
456 return ostr.str().c_str(); |
|
457 } |
|
458 catch(...) {} |
|
459 if( _message_holder.valid() ) return _message_holder.get().c_str(); |
|
460 return "lemon::AssertionFailedError"; |
|
461 } |
|
462 virtual ~AssertionFailedError() throw() {} |
|
463 }; |
|
464 |
|
465 |
|
466 /**************** Macros ****************/ |
|
467 |
|
468 |
|
469 template <typename Exception> |
|
470 inline void assert_fail(const char *file, int line, |
|
471 const char *func, |
|
472 Exception exception, |
|
473 const char *assertion = 0, |
|
474 bool do_abort=true) |
|
475 { |
|
476 using namespace std; |
|
477 cerr << file << ":" << line << ": "; |
|
478 if (func) |
|
479 cerr << func << ": "; |
|
480 cerr << exception.what(); |
|
481 if (assertion) |
|
482 cerr << " (assertion '" << assertion << "' failed)"; |
|
483 cerr << endl; |
|
484 if (do_abort) |
|
485 abort(); |
|
486 } |
|
487 |
|
488 template <> |
|
489 inline void assert_fail<const char *>(const char *file, int line, |
|
490 const char *func, |
|
491 const char *message, |
|
492 const char *assertion, |
|
493 bool do_abort) |
|
494 { |
|
495 using namespace std; |
|
496 cerr << file << ":" << line << ": "; |
|
497 if (func) |
|
498 cerr << func << ": "; |
|
499 cerr << message; |
|
500 if (assertion) |
|
501 cerr << " (assertion '" << assertion << "' failed)"; |
|
502 cerr << endl; |
|
503 if (do_abort) |
|
504 abort(); |
|
505 } |
|
506 |
|
507 template <> |
|
508 inline void assert_fail<std::string>(const char *file, int line, |
|
509 const char *func, |
|
510 std::string message, |
|
511 const char *assertion, |
|
512 bool do_abort) |
|
513 { |
|
514 assert_fail(file, line, func, message.c_str(), assertion, do_abort); |
|
515 } |
|
516 |
|
517 template <typename Exception> |
|
518 inline void assert_fail_failure(const char *file, int line, const char *func, |
|
519 Exception exception, |
|
520 const char *assertion = 0, |
|
521 bool = true) |
|
522 { |
|
523 throw AssertionFailedError(file, line, func, exception.what(), assertion); |
|
524 } |
|
525 |
|
526 template <> |
|
527 inline void assert_fail_failure<const char *>(const char *file, int line, |
|
528 const char *func, |
|
529 const char *message, |
|
530 const char *assertion, |
|
531 bool) |
|
532 { |
|
533 throw AssertionFailedError(file, line, func, message, assertion); |
|
534 } |
|
535 |
|
536 template <> |
|
537 inline void assert_fail_failure<std::string>(const char *file, int line, |
|
538 const char *func, |
|
539 std::string message, |
|
540 const char *assertion, |
|
541 bool) |
|
542 { |
|
543 assert_fail_failure(file, line, func, message.c_str(), assertion, true); |
|
544 } |
|
545 |
|
546 template <typename Exception> |
|
547 inline void assert_fail_exception(const char *file, int line, const char *func, |
|
548 Exception exception, |
|
549 const char *assertion = 0, bool = true) |
|
550 { |
|
551 throw exception; |
|
552 } |
|
553 |
|
554 template <> |
|
555 inline void assert_fail_exception<const char *>(const char *file, int line, |
|
556 const char *func, |
|
557 const char *message, |
|
558 const char *assertion, |
|
559 bool) |
|
560 { |
|
561 throw AssertionFailedError(file, line, func, message, assertion); |
|
562 } |
|
563 |
|
564 template <> |
|
565 inline void assert_fail_exception<std::string>(const char *file, int line, |
|
566 const char *func, |
|
567 std::string message, |
|
568 const char *assertion, |
|
569 bool) |
|
570 { |
|
571 assert_fail_exception(file, line, func, message.c_str(), assertion, true); |
|
572 } |
|
573 |
|
574 /// @} |
|
575 |
417 |
576 } |
418 } |
|
419 |
577 #endif // LEMON_ERROR_H |
420 #endif // LEMON_ERROR_H |
578 |
|
579 #undef LEMON_ASSERT |
|
580 #undef LEMON_FIXME |
|
581 |
|
582 #ifdef LEMON_ENABLE_ASSERTS |
|
583 # define LEMON_ASSERT_ABORT |
|
584 #endif |
|
585 |
|
586 #ifndef LEMON_ASSERT_DO_ABORT |
|
587 # define LEMON_ASSERT_DO_ABORT 1 |
|
588 #endif |
|
589 |
|
590 #ifndef LEMON_ASSERT_HANDLER |
|
591 # if defined LEMON_ASSERT_EXCEPTION |
|
592 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception |
|
593 # elif defined LEMON_ASSERT_FAILURE |
|
594 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_failure |
|
595 # elif defined LEMON_ASSERT_ABORT |
|
596 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail |
|
597 # else |
|
598 # define LEMON_DISABLE_ASSERTS |
|
599 # endif |
|
600 #endif |
|
601 |
|
602 #ifdef DOXYGEN |
|
603 |
|
604 /// \brief Macro for assertions with customizable message |
|
605 /// |
|
606 /// Macro for assertions with customizable message. |
|
607 /// |
|
608 /// The assertions are disabled in the default behaviour. You can |
|
609 /// enable the assertions with the |
|
610 /// \code |
|
611 /// #define LEMON_ENABLE_ASSERTS |
|
612 /// \endcode |
|
613 /// Then an assert |
|
614 /// provides a log on the standard error about the assertion and aborts |
|
615 /// the program if LEMON_ASSERT_DO_ABORT is also defined (otherwise the |
|
616 /// program keeps on running). |
|
617 /// By defining LEMON_ASSERT_FAILURE or |
|
618 /// LEMON_ASSERT_EXCEPTION, you can set other behaviour to the |
|
619 /// assertions. In case LEMON_ASSERT_FAILURE is given, LEMON_ASSERT |
|
620 /// will always throw an \c AssertionFailedError exception with |
|
621 /// the \c msg error message. By using |
|
622 /// LEMON_ASSERT_EXCEPTION, one can define an arbitrary exception to be thrown. |
|
623 /// |
|
624 /// The LEMON_ASSERT macro should be called with the \c exp parameter |
|
625 /// which should be an expression convertible to bool. If the given |
|
626 /// parameter is false the assertion is raised and one of the assertion |
|
627 /// behaviour will be activated. The \c msg should be either a const |
|
628 /// char* message or an exception. When the \c msg is an exception the |
|
629 /// \ref lemon::Exception::what() "what()" function is called to retrieve and |
|
630 /// display the error message. |
|
631 /// |
|
632 /// \todo We should provide some way to reset to the default behaviour, |
|
633 /// shouldn't we? |
|
634 /// |
|
635 /// \todo This whole 'assert' business should be placed in a separate |
|
636 /// include file. The boost assert is not guarded by header sentries |
|
637 /// which may help to change the behaviour of the assertions in |
|
638 /// the files. |
|
639 /// |
|
640 /// \todo __PRETTY_FUNCTION__ should be replaced by something |
|
641 /// compiler-independent, like BOOST_CURRENT_FUNCTION |
|
642 |
|
643 # define LEMON_ASSERT(exp, msg) \ |
|
644 (static_cast<void> (!!(exp) ? 0 : ( \ |
|
645 LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ |
|
646 __PRETTY_FUNCTION__, \ |
|
647 msg, #exp, LEMON_ASSERT_DO_ABORT), 0))) |
|
648 |
|
649 #else |
|
650 # if defined LEMON_DISABLE_ASSERTS |
|
651 |
|
652 # define LEMON_ASSERT(exp, msg) (static_cast<void> (0)) |
|
653 |
|
654 # else |
|
655 # define LEMON_ASSERT(exp, msg) \ |
|
656 (static_cast<void> (!!(exp) ? 0 : ( \ |
|
657 LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ |
|
658 __PRETTY_FUNCTION__, \ |
|
659 msg, #exp, LEMON_ASSERT_DO_ABORT), 0))) |
|
660 # endif |
|
661 #endif |
|
662 |
|
663 /** |
|
664 * \brief Macro for mark not yet implemented features. |
|
665 * |
|
666 * \todo Is this the right place for this? It should be used only in |
|
667 * modules under development. |
|
668 * |
|
669 * \todo __PRETTY_FUNCTION__ should be replaced by something |
|
670 * compiler-independent, like BOOST_CURRENT_FUNCTION |
|
671 */ |
|
672 |
|
673 #define LEMON_FIXME(msg) \ |
|
674 (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \ |
|
675 "FIXME: " msg)) |
|