Simbody
3.7
ExceptionMacros.h
Go to the documentation of this file.
1
#ifndef SimTK_SimTKCOMMON_EXCEPTION_MACROS_H_
2
#define SimTK_SimTKCOMMON_EXCEPTION_MACROS_H_
3
4
/* -------------------------------------------------------------------------- *
5
* Simbody(tm): SimTKcommon *
6
* -------------------------------------------------------------------------- *
7
* This is part of the SimTK biosimulation toolkit originating from *
8
* Simbios, the NIH National Center for Physics-Based Simulation of *
9
* Biological Structures at Stanford, funded under the NIH Roadmap for *
10
* Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. *
11
* *
12
* Portions copyright (c) 2005-12 Stanford University and the Authors. *
13
* Authors: Michael Sherman *
14
* Contributors: *
15
* *
16
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
17
* not use this file except in compliance with the License. You may obtain a *
18
* copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
19
* *
20
* Unless required by applicable law or agreed to in writing, software *
21
* distributed under the License is distributed on an "AS IS" BASIS, *
22
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
23
* See the License for the specific language governing permissions and *
24
* limitations under the License. *
25
* -------------------------------------------------------------------------- */
26
76
#include "
SimTKcommon/internal/common.h
"
77
#include "
SimTKcommon/internal/Exception.h
"
78
79
#include <string>
80
#include <iostream>
81
#include <exception>
82
83
// --------------------------------- RANGECHECK --------------------------------
84
// These exceptions are to be used for situations in which a user of a SimTK
85
// API method screws up by providing bad indices or dimensions. These are special
86
// cases of the more general APIARGCHECK macros, providing "canned" error messages
87
// for several common situations. Although there are several different macro
88
// names here, all are controlled by SimTK_KEEP_RANGECHECK to allow enabling of
89
// these index- and size-validating tests together in Release mode.
90
//
91
// INDEXCHECK: Note that we allow the index to be equal to the lower
92
// bound (zero) but it must be strictly less than the upper bound.
93
// SIZECHECK: A size or size expression must be >= 0 and less than OR EQUAL
94
// to the maximum size.
95
// SIZECHECK_NONNEG: A size argument must be >= 0.
96
// VALUECHECK: A floating point is required to be within a certain range.
97
// VALUECHECK_NONNEG: A floating point argument must be non-negative.
98
//
99
// TODO: SHAPECHECK, DOMAINCHECK
100
// -----------------------------------------------------------------------------
101
102
// This is a rangecheck that is always present, even in Release mode. This may be
103
// applied both to signed and unsigned types (the latter are always nonnegative) so
104
// to avoid warnings we use the isIndexInRange() method which doesn't perform
105
// a nonnegativity check on unsigned quantities.
106
#define SimTK_INDEXCHECK_ALWAYS(ix,ub,where) \
107
do{if(!isIndexInRange((ix),(ub)))SimTK_THROW5(SimTK::Exception::IndexOutOfRange, \
108
#ix,0,(ix),(ub),(where));}while(false)
109
110
// This is a rangecheck that is always present, even in Release mode. This may be
111
// applied both to signed and unsigned types (the latter are always nonnegative) so
112
// to avoid warnings we use the isSizeInRange() method which doesn't perform
113
// a nonnegativity check on unsigned quantities.
114
#define SimTK_SIZECHECK_ALWAYS(sz,maxsz,where) \
115
do{if(!isSizeInRange((sz),(maxsz)))SimTK_THROW4(SimTK::Exception::SizeOutOfRange, \
116
#sz,(sz),(maxsz),(where));}while(false)
117
118
// This is a rangecheck that is always present, even in Release mode. Use
119
// isNonnegative() here in case sz is an unsigned type to avoid compiler
120
// warning.
121
#define SimTK_SIZECHECK_NONNEG_ALWAYS(sz,where) \
122
do{if(!isNonnegative(sz))SimTK_THROW3(SimTK::Exception::SizeWasNegative, \
123
#sz,(sz),(where));}while(false)
124
125
// Similar checks for floating point values.
126
127
#define SimTK_VALUECHECK_ALWAYS(lb,val,ub,valName,where) \
128
do{if(!((lb)<=(val)&&(val)<=(ub)))SimTK_THROW5(SimTK::Exception::ValueOutOfRange, \
129
(valName),(lb),(val),(ub),(where));}while(false)
130
131
132
#define SimTK_VALUECHECK_NONNEG_ALWAYS(val,valName,where) \
133
do{if((val)<0)SimTK_THROW3(SimTK::Exception::ValueWasNegative, \
134
(valName),(val),(where));}while(false)
135
136
137
138
#if defined(NDEBUG) && !defined(SimTK_KEEP_RANGECHECK)
139
#define SimTK_INDEXCHECK(ix,ub,where)
140
#define SimTK_SIZECHECK(sz,maxsz,where)
141
#define SimTK_SIZECHECK_NONNEG(sz,where)
142
#define SimTK_VALUECHECK(lb,val,ub,valName,where)
143
#define SimTK_VALUECHECK_NONNEG(val,valName,where)
144
#else
145
#define SimTK_INDEXCHECK(ix,ub,where) SimTK_INDEXCHECK_ALWAYS(ix,ub,where)
146
#define SimTK_SIZECHECK(sz,maxsz,where) SimTK_SIZECHECK_ALWAYS(sz,maxsz,where)
147
#define SimTK_SIZECHECK_NONNEG(sz,where) SimTK_SIZECHECK_NONNEG_ALWAYS(sz,where)
148
#define SimTK_VALUECHECK(lb,val,ub,valName,where) SimTK_VALUECHECK_ALWAYS(lb,val,ub,valName,where)
149
#define SimTK_VALUECHECK_NONNEG(val,valName,where) SimTK_VALUECHECK_NONNEG_ALWAYS(val,valName,where)
150
#endif
151
152
153
// --------------------------------- STAGECHECK --------------------------------
154
// These exceptions are to be used for situations in which a
155
// user of an API screws up by attempting to access something in the
156
// state before it has been realized to the appropriate stage.
157
//
158
// STAGECHECK_TOPOLOGY_REALIZED: Check that realizeTopology() has been done
159
// since the last topological change.
160
// STAGECHECK_EQ: Check that the current stage is == a particular stage.
161
// STAGECHECK_GE: Check that the current stage is >= a particular stage.
162
// STAGECHECK_LT: Check that the current stage is < a particular stage.
163
// STAGECHECK_RANGE: Check that lower <= stage <= upper.
164
// -----------------------------------------------------------------------------
165
166
// These are stagechecks that is always present, even in Release mode.
167
#define SimTK_STAGECHECK_TOPOLOGY_REALIZED_ALWAYS(cond,objType,objName,methodNm) \
168
do{if(!(cond)) SimTK_THROW3(SimTK::Exception::RealizeTopologyMustBeCalledFirst, \
169
(objType),(objName),(methodNm));}while(false)
170
#define SimTK_STAGECHECK_TOPOLOGY_VERSION_ALWAYS(sysTopoVersion, \
171
stateTopoVersion,objType,objName,methodNm) \
172
do{if((stateTopoVersion)!=(sysTopoVersion)) \
173
SimTK_THROW5(SimTK::Exception::StateAndSystemTopologyVersionsMustMatch, \
174
(objType),(objName),(methodNm), \
175
(int)(sysTopoVersion),(int)(stateTopoVersion));} \
176
while(false)
177
#define SimTK_STAGECHECK_EQ_ALWAYS(currentStage,targetStage,methodNm) \
178
do{if((currentStage)!=(targetStage)) SimTK_THROW3(SimTK::Exception::StageIsWrong, \
179
(currentStage),(targetStage),(methodNm));}while(false)
180
#define SimTK_STAGECHECK_GE_ALWAYS(currentStage,targetStage,methodNm) \
181
do{if(!((currentStage)>=(targetStage))) SimTK_THROW3(SimTK::Exception::StageTooLow, \
182
(currentStage),(targetStage),(methodNm));}while(false)
183
#define SimTK_STAGECHECK_LT_ALWAYS(currentStage,targetStage,methodNm) \
184
do{if((currentStage)>=(targetStage)) SimTK_THROW3(SimTK::Exception::StageTooHigh, \
185
(currentStage),(targetStage),(methodNm));}while(false)
186
#define SimTK_STAGECHECK_RANGE_ALWAYS(lower,current,upper,methodNm) \
187
do{if(!((lower)<=(current)&&(current)<=(upper))) SimTK_THROW4(SimTK::Exception::StageOutOfRange, \
188
(lower),(current),(upper),(methodNm));}while(false)
189
190
// This one is present only in Debug mode or if SimTK_KEEP_STAGECHECK is explicitly defined.
191
#if defined(NDEBUG) && !defined(SimTK_KEEP_STAGECHECK)
192
#define SimTK_STAGECHECK_TOPOLOGY_REALIZED(cond,objType,objName,methodName)
193
#define SimTK_STAGECHECK_TOPOLOGY_VERSIONS(sysTopoVersion,stateTopoVersion,\
194
objType,objName,methodNm)
195
#define SimTK_STAGECHECK_EQ(currentStage,targetStage,methodNm)
196
#define SimTK_STAGECHECK_GE(currentStage,targetStage,methodNm)
197
#define SimTK_STAGECHECK_LT(currentStage,targetStage,methodNm)
198
#define SimTK_STAGECHECK_RANGE(lower,current,upper,methodNm)
199
#else
200
#define SimTK_STAGECHECK_TOPOLOGY_REALIZED(cond,objType,objName,methodName) \
201
SimTK_STAGECHECK_TOPOLOGY_REALIZED_ALWAYS(cond,objType,objName,methodName)
202
#define SimTK_STAGECHECK_TOPOLOGY_VERSION(sysTopoVersion,stateTopoVersion, \
203
objType,objName,methodNm) \
204
SimTK_STAGECHECK_TOPOLOGY_VERSION_ALWAYS(sysTopoVersion,stateTopoVersion,\
205
objType,objName,methodNm)
206
#define SimTK_STAGECHECK_EQ(currentStage,targetStage,methodNm) \
207
SimTK_STAGECHECK_EQ_ALWAYS(currentStage,targetStage,methodNm)
208
#define SimTK_STAGECHECK_GE(currentStage,targetStage,methodNm) \
209
SimTK_STAGECHECK_GE_ALWAYS(currentStage,targetStage,methodNm)
210
#define SimTK_STAGECHECK_LT(currentStage,targetStage,methodNm) \
211
SimTK_STAGECHECK_LE_ALWAYS(currentStage,targetStage,methodNm)
212
#define SimTK_STAGECHECK_RANGE(lower,current,upper,methodNm) \
213
SimTK_STAGECHECK_RANGE_ALWAYS(lower,current,upper,methodNm)
214
#endif
215
216
// -------------------------------- APIARGCHECK --------------------------------
217
// These should be used to catch all manner of problems with the arguments passed
218
// in an API user's call to a method that is part of a SimTK API. Note that these
219
// are intended for direct consumption by an application programmer using a SimTK
220
// API, so should be wordy and helpful. These macros accept printf-style format
221
// strings and arguments of whatever are the appropriate types for those formats.
222
// -----------------------------------------------------------------------------
223
224
#define SimTK_APIARGCHECK_ALWAYS(cond,className,methodName,msg) \
225
do{if(!(cond))SimTK_THROW4(SimTK::Exception::APIArgcheckFailed, \
226
#cond,(className),(methodName),(msg)); \
227
}while(false)
228
#define SimTK_APIARGCHECK1_ALWAYS(cond,className,methodName,fmt,a1) \
229
do{if(!(cond))SimTK_THROW5(SimTK::Exception::APIArgcheckFailed, \
230
#cond,(className),(methodName),(fmt),(a1)); \
231
}while(false)
232
#define SimTK_APIARGCHECK2_ALWAYS(cond,className,methodName,fmt,a1,a2) \
233
do{if(!(cond))SimTK_THROW6(SimTK::Exception::APIArgcheckFailed, \
234
#cond,(className),(methodName),(fmt),(a1),(a2)); \
235
}while(false)
236
#define SimTK_APIARGCHECK3_ALWAYS(cond,className,methodName,fmt,a1,a2,a3) \
237
do{if(!(cond))SimTK_THROW7(SimTK::Exception::APIArgcheckFailed, \
238
#cond,(className),(methodName),(fmt),(a1),(a2),(a3)); \
239
}while(false)
240
#define SimTK_APIARGCHECK4_ALWAYS(cond,className,methodName,fmt,a1,a2,a3,a4) \
241
do{if(!(cond))SimTK_THROW8(SimTK::Exception::APIArgcheckFailed, \
242
#cond,(className),(methodName),(fmt),(a1),(a2),(a3),(a4)); \
243
}while(false)
244
#define SimTK_APIARGCHECK5_ALWAYS(cond,className,methodName,fmt,a1,a2,a3,a4,a5) \
245
do{if(!(cond))SimTK_THROW9(SimTK::Exception::APIArgcheckFailed, \
246
#cond,(className),(methodName),(fmt),(a1),(a2),(a3),(a4),(a5)); \
247
}while(false)
248
249
#if defined(NDEBUG) && !defined(SimTK_KEEP_APIARGCHECK)
250
#define SimTK_APIARGCHECK(cond,className,methodName,msg)
251
#define SimTK_APIARGCHECK1(cond,className,methodName,fmt,a1)
252
#define SimTK_APIARGCHECK2(cond,className,methodName,fmt,a1,a2)
253
#define SimTK_APIARGCHECK3(cond,className,methodName,fmt,a1,a2,a3)
254
#define SimTK_APIARGCHECK4(cond,className,methodName,fmt,a1,a2,a3,a4)
255
#define SimTK_APIARGCHECK5(cond,className,methodName,fmt,a1,a2,a3,a4,a5)
256
#else
257
#define SimTK_APIARGCHECK(cond,className,methodName,msg) \
258
SimTK_APIARGCHECK_ALWAYS(cond,className,methodName,msg)
259
#define SimTK_APIARGCHECK1(cond,className,methodName,fmt,a1) \
260
SimTK_APIARGCHECK1_ALWAYS(cond,className,methodName,fmt,a1)
261
#define SimTK_APIARGCHECK2(cond,className,methodName,fmt,a1,a2) \
262
SimTK_APIARGCHECK2_ALWAYS(cond,className,methodName,fmt,a1,a2)
263
#define SimTK_APIARGCHECK3(cond,className,methodName,fmt,a1,a2,a3) \
264
SimTK_APIARGCHECK3_ALWAYS(cond,className,methodName,fmt,a1,a2,a3)
265
#define SimTK_APIARGCHECK4(cond,className,methodName,fmt,a1,a2,a3,a4) \
266
SimTK_APIARGCHECK4_ALWAYS(cond,className,methodName,fmt,a1,a2,a3,a4)
267
#define SimTK_APIARGCHECK5(cond,className,methodName,fmt,a1,a2,a3,a4,a5) \
268
SimTK_APIARGCHECK5_ALWAYS(cond,className,methodName,fmt,a1,a2,a3,a4,a5)
269
#endif
270
271
272
// ----------------------------------- ERRCHK ----------------------------------
273
// ERRCHK: these should be used to catch all manner of problems that occur
274
// during execution of an API user's request by a method that is part of
275
// a SimTK API. Note that these are intended for direct consumption by
276
// an application programmer using a SimTK API, so should be wordy and
277
// helpful. These macros accept printf-style format strings and arguments
278
// of whatever are the appropriate types for those formats.
279
// -----------------------------------------------------------------------------
280
281
#define SimTK_ERRCHK_ALWAYS(cond,whereChecked,msg) \
282
do{if(!(cond))SimTK_THROW3(SimTK::Exception::ErrorCheck, \
283
#cond,(whereChecked),(msg)); \
284
}while(false)
285
#define SimTK_ERRCHK1_ALWAYS(cond,whereChecked,fmt,a1) \
286
do{if(!(cond))SimTK_THROW4(SimTK::Exception::ErrorCheck, \
287
#cond,(whereChecked),(fmt),(a1)); \
288
}while(false)
289
#define SimTK_ERRCHK2_ALWAYS(cond,whereChecked,fmt,a1,a2) \
290
do{if(!(cond))SimTK_THROW5(SimTK::Exception::ErrorCheck, \
291
#cond,(whereChecked),(fmt),(a1),(a2)); \
292
}while(false)
293
#define SimTK_ERRCHK3_ALWAYS(cond,whereChecked,fmt,a1,a2,a3) \
294
do{if(!(cond))SimTK_THROW6(SimTK::Exception::ErrorCheck, \
295
#cond,(whereChecked),(fmt),(a1),(a2),(a3)); \
296
}while(false)
297
#define SimTK_ERRCHK4_ALWAYS(cond,whereChecked,fmt,a1,a2,a3,a4) \
298
do{if(!(cond))SimTK_THROW7(SimTK::Exception::ErrorCheck, \
299
#cond,(whereChecked),(fmt),(a1),(a2),(a3),(a4)); \
300
}while(false)
301
#define SimTK_ERRCHK5_ALWAYS(cond,whereChecked,fmt,a1,a2,a3,a4,a5) \
302
do{if(!(cond))SimTK_THROW8(SimTK::Exception::ErrorCheck, \
303
#cond,(whereChecked),(fmt),(a1),(a2),(a3),(a4),(a5)); \
304
}while(false)
305
#define SimTK_ERRCHK6_ALWAYS(cond,whereChecked,fmt,a1,a2,a3,a4,a5,a6) \
306
do{if(!(cond))SimTK_THROW9(SimTK::Exception::ErrorCheck, \
307
#cond,(whereChecked),(fmt),(a1),(a2),(a3),(a4),(a5),(a6)); \
308
}while(false)
309
#define SimTK_ERRCHK7_ALWAYS(cond,whereChecked,fmt,a1,a2,a3,a4,a5,a6,a7) \
310
do{if(!(cond))SimTK_THROW10(SimTK::Exception::ErrorCheck, \
311
#cond,(whereChecked),(fmt),(a1),(a2),(a3),(a4),(a5),(a6),(a7)); \
312
}while(false)
313
314
#if defined(NDEBUG) && !defined(SimTK_KEEP_ERRCHK)
315
#define SimTK_ERRCHK(cond,whereChecked,msg)
316
#define SimTK_ERRCHK1(cond,whereChecked,fmt,a1)
317
#define SimTK_ERRCHK2(cond,whereChecked,fmt,a1,a2)
318
#define SimTK_ERRCHK3(cond,whereChecked,fmt,a1,a2,a3)
319
#define SimTK_ERRCHK4(cond,whereChecked,fmt,a1,a2,a3,a4)
320
#define SimTK_ERRCHK5(cond,whereChecked,fmt,a1,a2,a3,a4,a5)
321
#define SimTK_ERRCHK6(cond,whereChecked,fmt,a1,a2,a3,a4,a5,a6)
322
#define SimTK_ERRCHK7(cond,whereChecked,fmt,a1,a2,a3,a4,a5,a6)
323
#else
324
#define SimTK_ERRCHK(cond,whereChecked,msg) \
325
SimTK_ERRCHK_ALWAYS(cond,whereChecked,msg)
326
#define SimTK_ERRCHK1(cond,whereChecked,fmt,a1) \
327
SimTK_ERRCHK1_ALWAYS(cond,whereChecked,fmt,a1)
328
#define SimTK_ERRCHK2(cond,whereChecked,fmt,a1,a2) \
329
SimTK_ERRCHK2_ALWAYS(cond,whereChecked,fmt,a1,a2)
330
#define SimTK_ERRCHK3(cond,whereChecked,fmt,a1,a2,a3) \
331
SimTK_ERRCHK3_ALWAYS(cond,whereChecked,fmt,a1,a2,a3)
332
#define SimTK_ERRCHK4(cond,whereChecked,fmt,a1,a2,a3,a4) \
333
SimTK_ERRCHK4_ALWAYS(cond,whereChecked,fmt,a1,a2,a3,a4)
334
#define SimTK_ERRCHK5(cond,whereChecked,fmt,a1,a2,a3,a4,a5) \
335
SimTK_ERRCHK5_ALWAYS(cond,whereChecked,fmt,a1,a2,a3,a4,a5)
336
#define SimTK_ERRCHK6(cond,whereChecked,fmt,a1,a2,a3,a4,a5,a6) \
337
SimTK_ERRCHK6_ALWAYS(cond,whereChecked,fmt,a1,a2,a3,a4,a5,a6)
338
#define SimTK_ERRCHK7(cond,whereChecked,fmt,a1,a2,a3,a4,a5,a6,a7) \
339
SimTK_ERRCHK7_ALWAYS(cond,whereChecked,fmt,a1,a2,a3,a4,a5,a6,a7)
340
#endif
341
342
// ----------------------------------- ASSERT ----------------------------------
343
// ASSERT: use this *only* for internal errors, that is, bugs. This must
344
// not be used to catch usage errors by clients; if you want to catch
345
// user errors use different exceptions.
346
// -----------------------------------------------------------------------------
347
348
// This is an assertion that is always active, even in Release mode.
349
#define SimTK_ASSERT_ALWAYS(cond,msg) \
350
do{if(!(cond))SimTK_THROW2(SimTK::Exception::Assert,#cond,(msg));}while(false)
351
#define SimTK_ASSERT1_ALWAYS(cond,msg,a1) \
352
do{if(!(cond))SimTK_THROW3(SimTK::Exception::Assert,#cond,(msg),(a1));}while(false)
353
#define SimTK_ASSERT2_ALWAYS(cond,msg,a1,a2) \
354
do{if(!(cond))SimTK_THROW4(SimTK::Exception::Assert,#cond,(msg),(a1),(a2));}while(false)
355
#define SimTK_ASSERT3_ALWAYS(cond,msg,a1,a2,a3) \
356
do{if(!(cond))SimTK_THROW5(SimTK::Exception::Assert,#cond,(msg),(a1),(a2),(a3));}while(false)
357
#define SimTK_ASSERT4_ALWAYS(cond,msg,a1,a2,a3,a4) \
358
do{if(!(cond))SimTK_THROW6(SimTK::Exception::Assert,#cond,(msg),(a1),(a2),(a3),(a4));}while(false)
359
#define SimTK_ASSERT5_ALWAYS(cond,msg,a1,a2,a3,a4,a5) \
360
do{if(!(cond))SimTK_THROW7(SimTK::Exception::Assert,#cond,(msg),(a1),(a2),(a3),(a4),(a5));}while(false)
361
362
// Note: unlike the system assert() we're putting ours within the header guards.
363
// So if you want to override NDEBUG do it at the *beginning* (that is, before
364
// the first #include or #ifdef) of whatever compilation unit you are fiddling with.
365
#if defined(NDEBUG) && !defined(SimTK_KEEP_ASSERT)
366
#define SimTK_ASSERT(cond,msg)
367
#define SimTK_ASSERT1(cond,msg,a1)
368
#define SimTK_ASSERT2(cond,msg,a1,a2)
369
#define SimTK_ASSERT3(cond,msg,a1,a2,a3)
370
#define SimTK_ASSERT4(cond,msg,a1,a2,a3,a4)
371
#define SimTK_ASSERT5(cond,msg,a1,a2,a3,a4,a5)
372
#else
373
#define SimTK_ASSERT(cond,msg) SimTK_ASSERT_ALWAYS(cond,msg)
374
#define SimTK_ASSERT1(cond,msg,a1) SimTK_ASSERT1_ALWAYS(cond,msg,a1)
375
#define SimTK_ASSERT2(cond,msg,a1,a2) SimTK_ASSERT2_ALWAYS(cond,msg,a1,a2)
376
#define SimTK_ASSERT3(cond,msg,a1,a2,a3) SimTK_ASSERT3_ALWAYS(cond,msg,a1,a2,a3)
377
#define SimTK_ASSERT4(cond,msg,a1,a2,a3,a4) SimTK_ASSERT4_ALWAYS(cond,msg,a1,a2,a3,a4)
378
#define SimTK_ASSERT5(cond,msg,a1,a2,a3,a4,a5) SimTK_ASSERT5_ALWAYS(cond,msg,a1,a2,a3,a4,a5)
379
#endif
380
381
382
#endif // SimTK_SimTKCOMMON_EXCEPTION_MACROS_H_
383
384
385
common.h
Mandatory first inclusion for any Simbody source or header file.
Exception.h
SimTKcommon
include
SimTKcommon
internal
ExceptionMacros.h
Generated on Fri Dec 6 2019 17:27:59 for Simbody by
1.8.14