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() noexcept {};
70 
71  const char* what() const noexcept override { return mess_d.c_str(); }
72  std::string getMessage() const noexcept { return mess_d; }
73 
74  const char* getFile() const { return file_dp; }
75 
76  std::string getExpression() const { return expr_d; }
77 
78  int getLine() const { return line_d; }
79 
80  std::string toString() const;
81  std::string toUserString() const; // strips build info, adds version
82 
83  private:
84  std::string mess_d, expr_d, prefix_d;
85 
86  const char* const file_dp;
87 
88  int line_d;
89 };
90 RDKIT_RDGENERAL_EXPORT std::ostream& operator<<(std::ostream& s,
91  const Invariant& inv);
92 } // end of namespace Invar
93 
94 #define ASSERT_INVARIANT(expr, mess) assert(expr)
95 
96 //
97 // Set desired reporting method
98 //
99 
100 #if INVARIANT_EXCEPTION_METHOD
101 
102 #define CHECK_INVARIANT(expr, mess) \
103  if (!(expr)) { \
104  Invar::Invariant inv("Invariant Violation", mess, #expr, __FILE__, \
105  __LINE__); \
106  BOOST_LOG(rdErrorLog) << "\n\n****\n" << inv << "****\n\n"; \
107  throw inv; \
108  }
109 
110 #define PRECONDITION(expr, mess) \
111  if (!(expr)) { \
112  Invar::Invariant inv("Pre-condition Violation", mess, #expr, __FILE__, \
113  __LINE__); \
114  BOOST_LOG(rdErrorLog) << "\n\n****\n" << inv << "****\n\n"; \
115  throw inv; \
116  }
117 
118 #define POSTCONDITION(expr, mess) \
119  if (!(expr)) { \
120  Invar::Invariant inv("Post-condition Violation", mess, #expr, __FILE__, \
121  __LINE__); \
122  BOOST_LOG(rdErrorLog) << "\n\n****\n" << inv << "****\n\n"; \
123  throw inv; \
124  }
125 
126 #define UNDER_CONSTRUCTION(fn) \
127  Invar::Invariant inv("Incomplete Code", \
128  "This routine is still under development", fn, \
129  __FILE__, __LINE__); \
130  BOOST_LOG(rdErrorLog) << "\n\n****\n" << inv << "****\n\n"; \
131  throw inv;
132 
133 #define RANGE_CHECK(lo, x, hi) \
134  if ((lo) > (hi) || (x) < (lo) || (x) > (hi)) { \
135  std::stringstream errstr; \
136  errstr << lo << " <= " << x << " <= " << hi; \
137  Invar::Invariant inv("Range Error", #x, errstr.str().c_str(), __FILE__, \
138  __LINE__); \
139  BOOST_LOG(rdErrorLog) << "\n\n****\n" << inv << "****\n\n"; \
140  throw inv; \
141  }
142 
143 #define URANGE_CHECK(x, hi) \
144  if (x >= (hi)) { \
145  std::stringstream errstr; \
146  errstr << x << " < " << hi; \
147  Invar::Invariant inv("Range Error", #x, errstr.str().c_str(), __FILE__, \
148  __LINE__); \
149  BOOST_LOG(rdErrorLog) << "\n\n****\n" << inv << "****\n\n"; \
150  throw inv; \
151  }
152 
153 #define TEST_ASSERT(expr) \
154  if (!(expr)) { \
155  Invar::Invariant inv("Test Assert", "Expression Failed: ", #expr, \
156  __FILE__, __LINE__); \
157  BOOST_LOG(rdErrorLog) << "\n\n****\n" << inv << "****\n\n"; \
158  throw inv; \
159  }
160 
161 #elif INVARIANT_ASSERT_METHOD
162 
163 #define CHECK_INVARIANT(expr, mess) assert(expr);
164 #define PRECONDITION(expr, mess) assert(expr);
165 #define POSTCONDITION(expr, mess) assert(expr);
166 #define UNDER_CONSTRUCTION(fn) assert(0);
167 #define RANGE_CHECK(lo, x, hi) \
168  assert((lo) <= (hi) && (x) >= (lo) && (x) <= (hi));
169 #define URANGE_CHECK(lo, x, hi) assert((hi > 0) && (x < hi));
170 #define TEST_ASSERT(expr) assert(expr);
171 
172 #elif INVARIANT_SILENT_METHOD
173 
174 #define CHECK_INVARIANT(expr, mess)
175 #define PRECONDITION(expr, mess)
176 #define POSTCONDITION(expr, mess)
177 #define UNDER_CONSTRUCTION(fn)
178 #define RANGE_CHECK(lo, x, hi)
179 #define URANGE_CHECK(x, hi)
180 #define TEST_ASSERT(expr)
181 
182 #endif
183 
184 #ifdef RDDEBUG
185 // use rdcast to convert between types
186 // when RDDEBUG is defined, this checks for
187 // validity (overflow, etc)
188 // when RDDEBUG is off, the cast is a no-cost
189 // static_cast
190 #define rdcast boost::numeric_cast
191 #else
192 #define rdcast static_cast
193 #endif
194 
195 // Silence warnings for unused params while
196 // still indicating that they are unused
197 #define RDUNUSED_PARAM(x) (void)x;
198 
199 #endif
Invar::Invariant::getMessage
std::string getMessage() const noexcept
Definition: Invariant.h:72
Invar::operator<<
RDKIT_RDGENERAL_EXPORT std::ostream & operator<<(std::ostream &s, const Invariant &inv)
BoostStartInclude.h
Invar::Invariant::getFile
const char * getFile() const
Definition: Invariant.h:74
Invar::Invariant::Invariant
Invariant(const char *prefix, const char *mess, const char *expr, const char *const file, int line)
Definition: Invariant.h:53
BoostEndInclude.h
Invar
Definition: Invariant.h:49
Invar::Invariant::getExpression
std::string getExpression() const
Definition: Invariant.h:76
Invar::Invariant::what
const char * what() const noexcept override
Definition: Invariant.h:71
Invar::Invariant::toString
std::string toString() const
Invar::Invariant::~Invariant
~Invariant() noexcept
Definition: Invariant.h:69
Invar::Invariant::getLine
int getLine() const
Definition: Invariant.h:78
Invar::Invariant
Definition: Invariant.h:51
RDLog.h
Invar::Invariant::toUserString
std::string toUserString() const
RDKIT_RDGENERAL_EXPORT
#define RDKIT_RDGENERAL_EXPORT
Definition: export.h:502
Invar::Invariant::Invariant
Invariant(const char *prefix, const std::string &mess, const char *expr, const char *const file, int line)
Definition: Invariant.h:61
export.h