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 

Generated on Fri Apr 3 06:03:02 2009 for RDCode by  doxygen 1.5.6