From e4f5e2a1effe5e88654ffaf0b90fa6c340a72382 Mon Sep 17 00:00:00 2001 From: Sylvain Pion Date: Thu, 13 Jul 2006 17:46:18 +0000 Subject: [PATCH] - Introduce exception throwing as assertion behavior. - Make it the default. - FIXME : the exception classes are not yet documented. --- Manual/doc_tex/Introduction_ref/checks.tex | 7 +- STL_Extension/include/CGAL/assertions.h | 3 +- STL_Extension/include/CGAL/exceptions.h | 208 +++++++++++++++++++++ STL_Extension/src/CGAL/assertions.cpp | 18 +- 4 files changed, 227 insertions(+), 9 deletions(-) create mode 100644 STL_Extension/include/CGAL/exceptions.h diff --git a/Manual/doc_tex/Introduction_ref/checks.tex b/Manual/doc_tex/Introduction_ref/checks.tex index de15f02b788..9361560740b 100644 --- a/Manual/doc_tex/Introduction_ref/checks.tex +++ b/Manual/doc_tex/Introduction_ref/checks.tex @@ -102,11 +102,12 @@ set_error_behaviour(Failure_behaviour eb);} The parameter should have one of the following values. \ccGlobalEnum{enum Failure_behaviour -{ ABORT, EXIT, EXIT_WITH_SUCCESS, CONTINUE };} -The first value is the default. +{ ABORT, EXIT, EXIT_WITH_SUCCESS, CONTINUE, THROW_EXCEPTION };} +The \ccc{THROW_EXCEPTION} value is the default, which throws an exception. + If the \ccStyle{EXIT} value is set, the program will stop and return a value indicating failure, but not dump the core. -The last value tells the checks to go on after diagnosing the error. +The \ccc{CONTINUE} value tells the checks to go on after diagnosing the error. \begin{ccAdvanced} If the \ccStyle{EXIT_WITH_SUCCESS} value is set, the program will stop and diff --git a/STL_Extension/include/CGAL/assertions.h b/STL_Extension/include/CGAL/assertions.h index af368672748..99573646b6b 100644 --- a/STL_Extension/include/CGAL/assertions.h +++ b/STL_Extension/include/CGAL/assertions.h @@ -31,7 +31,8 @@ CGAL_BEGIN_NAMESPACE // types // ===== -enum Failure_behaviour { ABORT, EXIT, EXIT_WITH_SUCCESS, CONTINUE }; +enum Failure_behaviour { ABORT, EXIT, EXIT_WITH_SUCCESS, CONTINUE, + THROW_EXCEPTION }; // function declarations // ===================== diff --git a/STL_Extension/include/CGAL/exceptions.h b/STL_Extension/include/CGAL/exceptions.h new file mode 100644 index 00000000000..4eefeb22002 --- /dev/null +++ b/STL_Extension/include/CGAL/exceptions.h @@ -0,0 +1,208 @@ +// Copyright (c) 2006 INRIA Sophia-Antipolis (France) and +// Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Lutz Kettner, Sylvain Pion + +#ifndef CGAL_EXCEPTIONS_H +#define CGAL_EXCEPTIONS_H + +#include +#include +#include + +CGAL_BEGIN_NAMESPACE + +// [Sylvain] This was originaly written in the Exacus library. +// I kept most doxygen comments. + + +/*! \defgroup CGAL_assert Assertions + \brief \#include for pre- and postconditions, + assertions, warnings, and error handler. + + \c CGAL/basic.h provides macros for pre- and postconditions, assertions, + warnings, and errors that are active by default. There are variants + for expensive checks that are inactive by default. + + A failed precondition, postcondition or assertion is a fatal error + and the library aborts by default the program execution. For warnings + the program continues to run. Both can be changed with the respective + \c error_behavior or \c warning_behavior, or with the corresponding + \c error_handler or \c warning_handler. + + However, if the checks are disabled with corresponding + preprocessor symbols or \c NDEBUG, none of this error handling + will happen and the program execution continues with potentially + disastrous results. So, these checks are not for normal error + handling, for example testing proper user input or file + formats. Furthermore, it is recommended to keep the checks also in + the production version of the program, keeping in mind that they + should not cost too much runtime overhead, maybe 10%. + + \see \c CGAL_test for checks that cannot be disabled and + \c CGAL_error for an unconditional error message that cannot + be disabled with macros. +*/ +//@{ + +namespace CGALi { +// I hope the following will go away at some point. +inline std::string int_to_string( int i) { + // not at all exciting but I don't want to invoke stringstreams for this. + std::string s; + bool negative = false; + if ( i < 0) { + negative = true; + i = -i; + } + while ( i != 0 ) { + s.append( 1, char( '0' + i % 10)); + i = i / 10; + } + if ( negative) + s.append( 1, '-'); + std::reverse( s.begin(), s.end()); + return s; +} +} // CGALi + +// Failure types and exceptions +// ============================ + +//! Exception base class for all failure types of assertions etc. +class Failure_exception : public std::logic_error { + std::string m_lib; + std::string m_expr; // can be empty + std::string m_file; + int m_line; + std::string m_msg; // can be empty +public: + //! initializes local members and the std::logic_error with + //! a suitable message. + Failure_exception( std::string lib, + std::string expr, + std::string file, + int line, + std::string msg, + std::string kind = "Unknown kind") : + std::logic_error( lib + std::string( " ERROR: ") + kind + std::string( "!") + + ((expr.empty()) ? (std::string("")) : (std::string("\nExpr: ")+expr)) + + std::string( "\nFile: ") + file + + std::string( "\nLine: ") + CGALi::int_to_string( line) + + ((msg.empty()) ? (std::string("")) + : (std::string("\nExplanation: ") + msg))), + m_lib( lib), + m_expr( expr), + m_file( file), + m_line( line), + m_msg( msg) + {} + + ~Failure_exception() throw() {} + + //! the name of the library that issues this message. + std::string library() const { return m_lib; } + + //! expression that failed in assertion, pre-, or postcondition. + std::string expression() const { return m_expr; } + + //! source code filename where the failure was detected. + std::string filename() const { return m_file; } + + //! line number in source code file where the failure was detected. + int line_number() const { return m_line; } + + //! an optional message explaining the kind of failure. + std::string message() const { return m_msg; } +}; + +//! Exception thrown for \c CGAL_error. +class Error_exception : public Failure_exception { +public: + Error_exception( std::string lib, + std::string msg, + std::string file, + int line) + : Failure_exception( lib, "", file, line, msg, "failure" ) {} +}; + +//! Exception thrown for \c CGAL_precond. +class Precondition_exception : public Failure_exception { +public: + Precondition_exception( std::string lib, + std::string expr, + std::string file, + int line, + std::string msg) + : Failure_exception( lib, expr, file, line, msg, + "precondition violation") {} +}; + +//! Exception thrown for \c CGAL_postcond. +class Postcondition_exception : public Failure_exception { +public: + Postcondition_exception( std::string lib, + std::string expr, + std::string file, + int line, + std::string msg) + : Failure_exception( lib, expr, file, line, msg, + "postcondition violation") {} +}; + +//! Exception thrown for \c CGAL_assert. +class Assertion_exception : public Failure_exception { +public: + Assertion_exception( std::string lib, + std::string expr, + std::string file, + int line, + std::string msg) + : Failure_exception( lib, expr, file, line, msg, + "assertion violation") {} +}; + +//! Exception thrown for \c CGAL_test. +class Test_exception : public Failure_exception { +public: + Test_exception( std::string lib, + std::string expr, + std::string file, + int line, + std::string msg) + : Failure_exception( lib, expr, file, line, msg, + "test in test-suite violation") {} +}; + +//! Exception thrown for \c CGAL_warning. +class Warning_exception : public Failure_exception { +public: + Warning_exception( std::string lib, + std::string expr, + std::string file, + int line, + std::string msg) + : Failure_exception( lib, expr, file, line, msg, + "warning condition failed") {} +}; + + +CGAL_END_NAMESPACE + +#endif // CGAL_EXCEPTIONS_H diff --git a/STL_Extension/src/CGAL/assertions.cpp b/STL_Extension/src/CGAL/assertions.cpp index 1e4fc4fd2e0..343ac3e818c 100644 --- a/STL_Extension/src/CGAL/assertions.cpp +++ b/STL_Extension/src/CGAL/assertions.cpp @@ -23,13 +23,15 @@ #include -#include #include -#include +#include +#include +#include #include CGAL_BEGIN_NAMESPACE + // not_implemented function // ------------------------ void @@ -41,7 +43,7 @@ not_implemented() // static behaviour variables // -------------------------- -static Failure_behaviour _error_behaviour = ABORT; +static Failure_behaviour _error_behaviour = THROW_EXCEPTION; static Failure_behaviour _warning_behaviour = CONTINUE; // standard error handlers @@ -107,6 +109,8 @@ assertion_fail( const char* expr, CGAL_CLIB_STD::exit(1); // EXIT_FAILURE case EXIT_WITH_SUCCESS: CGAL_CLIB_STD::exit(0); // EXIT_SUCCESS + case THROW_EXCEPTION: + throw Assertion_exception("CGAL", expr, file, line, msg); case CONTINUE: ; } @@ -126,6 +130,8 @@ precondition_fail( const char* expr, CGAL_CLIB_STD::exit(1); // EXIT_FAILURE case EXIT_WITH_SUCCESS: CGAL_CLIB_STD::exit(0); // EXIT_SUCCESS + case THROW_EXCEPTION: + throw Precondition_exception("CGAL", expr, file, line, msg); case CONTINUE: ; } @@ -145,6 +151,8 @@ postcondition_fail(const char* expr, CGAL_CLIB_STD::exit(1); // EXIT_FAILURE case EXIT_WITH_SUCCESS: CGAL_CLIB_STD::exit(0); // EXIT_SUCCESS + case THROW_EXCEPTION: + throw Postcondition_exception("CGAL", expr, file, line, msg); case CONTINUE: ; } @@ -167,6 +175,8 @@ warning_fail( const char* expr, CGAL_CLIB_STD::exit(1); // EXIT_FAILURE case EXIT_WITH_SUCCESS: CGAL_CLIB_STD::exit(0); // EXIT_SUCCESS + case THROW_EXCEPTION: + throw Warning_exception("CGAL", expr, file, line, msg); case CONTINUE: ; } @@ -208,5 +218,3 @@ set_warning_behaviour(Failure_behaviour eb) } CGAL_END_NAMESPACE - -