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