RDKit
Open-source cheminformatics and machine learning.
Invariant.h
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2013 Greg Landrum, Randal M. Henne and Rational Discovery
3 // LLC
4 //
5 // @@ All Rights Reserved @@
6 // This file is part of the RDKit.
7 // The contents are covered by the terms of the BSD license
8 // which is included in the file license.txt, found at the root
9 // of the RDKit source tree.
10 //
11 
12 #include <RDGeneral/export.h>
13 #ifndef __RD_INVARIANT_H__
14 #define __RD_INVARIANT_H__
15 
16 #include <assert.h>
17 #include <string>
18 #include <iostream>
19 #include <stdexcept>
20 
21 #include "BoostStartInclude.h"
22 #include <RDGeneral/RDLog.h>
23 #include "BoostEndInclude.h"
24 
25 #ifdef RDDEBUG
26 // Enable RDDEBUG for testing whether rdcast
27 // conversions are within numerical limits
29 #include <boost/numeric/conversion/cast.hpp>
31 #endif
32 //
33 // What if no invariant method is defined?
34 //
35 #if !defined INVARIANT_EXCEPTION_METHOD && !defined INVARIANT_ASSERT_METHOD && \
36  !defined INVARIANT_SILENT_METHOD
37 #define INVARIANT_EXCEPTION_METHOD 1
38 #endif
39 
40 //
41 // What if an invariant method is defined, but none are true?
42 //
43 #if !INVARIANT_EXCEPTION_METHOD && !INVARIANT_ASSERT_METHOD && \
44  !INVARIANT_SILENT_METHOD
45 #undef INVARIANT_EXCEPTION_METHOD
46 #define INVARIANT_EXCEPTION_METHOD 1
47 #endif
48 
49 namespace Invar {
50 
51 class RDKIT_RDGENERAL_EXPORT Invariant : public std::runtime_error {
52  public:
53  Invariant(const char* prefix, const char* mess, const char* expr,
54  const char* const file, int line)
55  : std::runtime_error(prefix),
56  mess_d(mess),
57  expr_d(expr),
58  prefix_d(prefix),
59  file_dp(file),
60  line_d(line) {}
61  Invariant(const char* prefix, const std::string& mess, const char* expr,
62  const char* const file, int line)
63  : std::runtime_error(prefix),
64  mess_d(mess.c_str()),
65  expr_d(expr),
66  prefix_d(prefix),
67  file_dp(file),
68  line_d(line) {}
69  ~Invariant() throw(){};
70 
71  std::string getMessage() const { return mess_d; }
72 
73  const char* getFile() const { return file_dp; }
74 
75  std::string getExpression() const { return expr_d; }
76 
77  int getLine() const { return line_d; }
78 
79  std::string toString() const;
80  std::string toUserString() const; // strips build info, adds version
81 
82  private:
83  std::string mess_d, expr_d, prefix_d;
84 
85  const char* const file_dp;
86 
87  int line_d;
88 };
89 RDKIT_RDGENERAL_EXPORT std::ostream& operator<<(std::ostream& s, const Invariant& inv);
90 } // end of namespace Invar
91 
92 #define ASSERT_INVARIANT(expr, mess) assert(expr)
93 
94 //
95 // Set desired reporting method
96 //
97 
98 #if INVARIANT_EXCEPTION_METHOD
99 
100 #define CHECK_INVARIANT(expr, mess) \
101  if (!(expr)) { \
102  Invar::Invariant inv("Invariant Violation", mess, #expr, __FILE__, \
103  __LINE__); \
104  BOOST_LOG(rdErrorLog) << "\n\n****\n" << inv << "****\n\n"; \
105  throw inv; \
106  }
107 
108 #define PRECONDITION(expr, mess) \
109  if (!(expr)) { \
110  Invar::Invariant inv("Pre-condition Violation", mess, #expr, __FILE__, \
111  __LINE__); \
112  BOOST_LOG(rdErrorLog) << "\n\n****\n" << inv << "****\n\n"; \
113  throw inv; \
114  }
115 
116 #define POSTCONDITION(expr, mess) \
117  if (!(expr)) { \
118  Invar::Invariant inv("Post-condition Violation", mess, #expr, __FILE__, \
119  __LINE__); \
120  BOOST_LOG(rdErrorLog) << "\n\n****\n" << inv << "****\n\n"; \
121  throw inv; \
122  }
123 
124 #define UNDER_CONSTRUCTION(fn) \
125  Invar::Invariant inv("Incomplete Code", \
126  "This routine is still under development", fn, \
127  __FILE__, __LINE__); \
128  BOOST_LOG(rdErrorLog) << "\n\n****\n" << inv << "****\n\n"; \
129  throw inv;
130 
131 #define RANGE_CHECK(lo, x, hi) \
132  if ((lo) > (hi) || (x) < (lo) || (x) > (hi)) { \
133  std::stringstream errstr; \
134  errstr << lo << " <= " << x << " <= " << hi; \
135  Invar::Invariant inv("Range Error", #x, errstr.str().c_str(), __FILE__, \
136  __LINE__); \
137  BOOST_LOG(rdErrorLog) << "\n\n****\n" << inv << "****\n\n"; \
138  throw inv; \
139  }
140 
141 #define URANGE_CHECK(x, hi) \
142  if (x >= (hi)) { \
143  std::stringstream errstr; \
144  errstr << x << " < " << hi; \
145  Invar::Invariant inv("Range Error", #x, errstr.str().c_str(), __FILE__, \
146  __LINE__); \
147  BOOST_LOG(rdErrorLog) << "\n\n****\n" << inv << "****\n\n"; \
148  throw inv; \
149  }
150 
151 #define TEST_ASSERT(expr) \
152  if (!(expr)) { \
153  Invar::Invariant inv("Test Assert", "Expression Failed: ", #expr, \
154  __FILE__, __LINE__); \
155  BOOST_LOG(rdErrorLog) << "\n\n****\n" << inv << "****\n\n"; \
156  throw inv; \
157  }
158 
159 #elif INVARIANT_ASSERT_METHOD
160 
161 #define CHECK_INVARIANT(expr, mess) assert(expr);
162 #define PRECONDITION(expr, mess) assert(expr);
163 #define POSTCONDITION(expr, mess) assert(expr);
164 #define UNDER_CONSTRUCTION(fn) assert(0);
165 #define RANGE_CHECK(lo, x, hi) \
166  assert((lo) <= (hi) && (x) >= (lo) && (x) <= (hi));
167 #define URANGE_CHECK(lo, x, hi) assert((hi > 0) && (x < hi));
168 #define TEST_ASSERT(expr) assert(expr);
169 
170 #elif INVARIANT_SILENT_METHOD
171 
172 #define CHECK_INVARIANT(expr, mess)
173 #define PRECONDITION(expr, mess)
174 #define POSTCONDITION(expr, mess)
175 #define UNDER_CONSTRUCTION(fn)
176 #define RANGE_CHECK(lo, x, hi)
177 #define URANGE_CHECK(x, hi)
178 #define TEST_ASSERT(expr)
179 
180 #endif
181 
182 #ifdef RDDEBUG
183 // use rdcast to convert between types
184 // when RDDEBUG is defined, this checks for
185 // validity (overflow, etc)
186 // when RDDEBUG is off, the cast is a no-cost
187 // static_cast
188 #define rdcast boost::numeric_cast
189 #else
190 #define rdcast static_cast
191 #endif
192 
193 // Silence warnings for unused params while
194 // still indicating that they are unused
195 #define RDUNUSED_PARAM(x) (void) x;
196 
197 #endif
Invariant(const char *prefix, const std::string &mess, const char *expr, const char *const file, int line)
Definition: Invariant.h:61
#define RDKIT_RDGENERAL_EXPORT
Definition: export.h:489
const char * getFile() const
Definition: Invariant.h:73
STL namespace.
std::string getMessage() const
Definition: Invariant.h:71
std::string getExpression() const
Definition: Invariant.h:75
RDKIT_RDGENERAL_EXPORT std::ostream & operator<<(std::ostream &s, const Invariant &inv)
Invariant(const char *prefix, const char *mess, const char *expr, const char *const file, int line)
Definition: Invariant.h:53
int getLine() const
Definition: Invariant.h:77