RDCode: Invariant.h Source File

# Invariant.h

Go to the documentation of this file.

    00001 //
    00002 // Copyright (C)  2001-2008 Greg Landrum, Randal M. Henne and Rational Discovery LLC
    00003 //
    00004 //  @@ All Rights Reserved @@
    00005 //
    00006
    00007 #ifndef __RD_INVARIANT_H__
    00008 #define __RD_INVARIANT_H__
    00009
    00010 #include <assert.h>
    00011 #include <string>
    00012 #include <iostream>
    00013 #include <stdexcept>
    00014
    00015 #include <RDGeneral/RDLog.h>
    00016 //
    00017 // What if no invariant method is defined?
    00018 //
    00019 #if !defined INVARIANT_EXCEPTION_METHOD && \
    00020     !defined INVARIANT_ASSERT_METHOD && \
    00021     !defined INVARIANT_SILENT_METHOD
    00022 #define INVARIANT_EXCEPTION_METHOD 1
    00023 #endif
    00024
    00025 //
    00026 // What if an invariant method is defined, but none are true?
    00027 //
    00028 #if !INVARIANT_EXCEPTION_METHOD && \
    00029     !INVARIANT_ASSERT_METHOD && \
    00030     !INVARIANT_SILENT_METHOD
    00031 #undef  INVARIANT_EXCEPTION_METHOD
    00032 #define INVARIANT_EXCEPTION_METHOD 1
    00033 #endif
    00034
    00035
    00036 namespace Invar {
    00037
    00038   class Invariant : public std::runtime_error {
    00039
    00040   public:
    00041
    00042     Invariant( const char * prefix, const char * mess, const char * expr, const char * const file, int line )
    00043       : std::runtime_error( prefix ),
    00044         mess_d( mess ),
    00045         expr_d( expr ),
    00046         stringRep_d( prefix ),
    00047         file_dp( file ),
    00048         line_d( line )
    00049     {
    00050     }
    00051     Invariant( const char * prefix, std::string mess, const char * expr, const char * const file, int line )
    00052       : std::runtime_error( prefix ),
    00053         mess_d( mess.c_str() ),
    00054         expr_d( expr ),
    00055         stringRep_d( prefix ),
    00056         file_dp( file ),
    00057         line_d( line )
    00058     {
    00059     }
    00060     ~Invariant() throw () {};
    00061
    00062     std::string&
    00063     getMessage()
    00064     { return mess_d; }
    00065
    00066     const char * const
    00067     getFile()
    00068     { return file_dp; }
    00069
    00070     std::string&
    00071     getExpression()
    00072     { return expr_d; }
    00073
    00074     int
    00075     getLine()
    00076     { return line_d; }
    00077
    00078     std::string &
    00079     toString();
    00080
    00081
    00082   private:
    00083
    00084     std::string
    00085       mess_d,
    00086       expr_d,
    00087       stringRep_d;    // Used internally for string representation
    00088
    00089     const char
    00090       * const file_dp;
    00091
    00092     int
    00093       line_d;
    00094   };
    00095
    00096   std::ostream& operator<<( std::ostream & s, Invariant & inv );
    00097
    00098 };
    00099
    00100
    00101
    00102 #define ASSERT_INVARIANT( expr, mess ) \
    00103     assert( expr )
    00104
    00105 //
    00106 // Set desired reporting method
    00107 //
    00108
    00109 #if INVARIANT_EXCEPTION_METHOD
    00110
    00111 #define CHECK_INVARIANT( expr, mess ) if ( !(expr) ) {\
    00112      Invar::Invariant inv( "Invariant Violation", mess, \
    00113      #expr, __FILE__, __LINE__ ); \
    00114      BOOST_LOG(rdErrorLog) << "\n\n****\n" << inv << "****\n\n"; throw inv; }
    00115
    00116 #define PRECONDITION( expr, mess ) if ( !(expr) ) {\
    00117      Invar::Invariant inv( "Pre-condition Violation", mess, \
    00118      #expr, __FILE__, __LINE__ ); \
    00119      BOOST_LOG(rdErrorLog) << "\n\n****\n" << inv << "****\n\n"; throw inv; }
    00120
    00121 #define POSTCONDITION( expr, mess ) if ( !(expr) ) { \
    00122      Invar::Invariant inv( "Post-condition Violation", mess, \
    00123      #expr, __FILE__, __LINE__ );\
    00124      BOOST_LOG(rdErrorLog) << "\n\n****\n" << inv << "****\n\n"; throw inv; }
    00125
    00126 #define UNDER_CONSTRUCTION( fn ) Invar::Invariant inv( "Incomplete Code", \
    00127      "This routine is still under development", fn, __FILE__, __LINE__ ); \
    00128      BOOST_LOG(rdErrorLog) << "\n\n****\n" << inv << "****\n\n"; throw inv;
    00129
    00130 #define RANGE_CHECK( lo, x, hi ) if ( (lo)>(hi) || (x)<(lo) || (x)>(hi) ) {\
    00131      std::stringstream errstr;\
    00132      errstr << lo << " <= " << x <<" <= "<<hi;\
    00133      Invar::Invariant inv( "Range Error", #x, errstr.str().c_str(), __FILE__, __LINE__ );\
    00134      BOOST_LOG(rdErrorLog) << "\n\n****\n" << inv << "****\n\n"; throw inv; }
    00135
    00136 #define TEST_ASSERT( expr ) if ( !(expr) ) {\
    00137      Invar::Invariant inv( "Test Assert", "Expression Failed: ", \
    00138      #expr, __FILE__, __LINE__ ); \
    00139      BOOST_LOG(rdErrorLog) << "\n\n****\n" << inv << "****\n\n"; throw inv; }
    00140
    00141
    00142 #elif INVARIANT_ASSERT_METHOD
    00143
    00144 #define CHECK_INVARIANT( expr, mess ) assert( expr );
    00145 #define PRECONDITION( expr, mess ) assert( expr );
    00146 #define POSTCONDITION( expr, mess ) assert( expr );
    00147 #define UNDER_CONSTRUCTION(fn ) assert(0);
    00148 #define RANGE_CHECK( lo, x, hi ) assert( (lo)<=(hi) && (x)>=(lo) && (x)<=(hi) );
    00149 #define TEST_ASSERT( expr ) assert(expr);
    00150
    00151 #elif INVARIANT_SILENT_METHOD
    00152
    00153 #define CHECK_INVARIANT( expr, mess )
    00154 #define PRECONDITION( expr, mess )
    00155 #define POSTCONDITION( expr, mess )
    00156 #define UNDER_CONSTRUCTION( fn )
    00157 #define RANGE_CHECK( lo, x, hi )
    00158 #define TEST_ASSERT( expr )
    00159
    00160 #endif
    00161
    00162 #endif
    00163