ExceptionMacros.h

Go to the documentation of this file.
00001 #ifndef SimTK_SimTKCOMMON_EXCEPTION_MACROS_H_
00002 #define SimTK_SimTKCOMMON_EXCEPTION_MACROS_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                      SimTK Core: SimTKcommon                               *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK Core biosimulation toolkit originating from      *
00008  * Simbios, the NIH National Center for Physics-Based Simulation of           *
00009  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
00010  * Medical Research, grant U54 GM072970. See https://simtk.org.               *
00011  *                                                                            *
00012  * Portions copyright (c) 2005-7 Stanford University and the Authors.         *
00013  * Authors: Michael Sherman                                                   *
00014  * Contributors:                                                              *
00015  *                                                                            *
00016  * Permission is hereby granted, free of charge, to any person obtaining a    *
00017  * copy of this software and associated documentation files (the "Software"), *
00018  * to deal in the Software without restriction, including without limitation  *
00019  * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
00020  * and/or sell copies of the Software, and to permit persons to whom the      *
00021  * Software is furnished to do so, subject to the following conditions:       *
00022  *                                                                            *
00023  * The above copyright notice and this permission notice shall be included in *
00024  * all copies or substantial portions of the Software.                        *
00025  *                                                                            *
00026  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
00027  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
00028  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
00029  * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
00030  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
00031  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
00032  * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
00033  * -------------------------------------------------------------------------- */
00034 
00075 // Here are the symbols you can define to force various checks to remain
00076 // while in release mode.
00077 
00078 // SimTK_KEEP_ASSERT
00079 // SimTK_KEEP_RANGECHECK
00080 // SimTK_KEEP_STAGECHECK
00081 // SimTK_KEEP_APIARGCHECK
00082 // ...
00083 
00084 #include "SimTKcommon/internal/common.h"
00085 #include "SimTKcommon/internal/Exception.h"
00086 
00087 #include <string>
00088 #include <iostream>
00089 #include <exception>
00090 
00091 // TODO: SHAPECHECK, DOMAINCHECK
00092 
00093     // RANGECHECKs: these exception are to be used for situations in which a
00094     // user of an API screws up by providing bad indices or dimensions. 
00095     //   INDEXCHECK: Note that we allow the index to be equal to the lower
00096     //     bound but it must be strictly less than the upper bound.
00097     //   SIZECHECK: A size or size expression must be >= 0 and less than OR EQUAL
00098     //     to the maximum size.
00099     //   SIZECHECK_NONNEG: An size argument must be >= 0.
00100 
00101 // This is a rangecheck that is always present, even in Release mode.
00102 #define SimTK_INDEXCHECK_ALWAYS(lb,ix,ub,where) \
00103     do{if(!((lb)<=(ix)&&(ix)<(ub)))SimTK_THROW5(SimTK::Exception::IndexOutOfRange,   \
00104                     #ix,(lb),(ix),(ub),(where));}while(false)
00105 
00106 // This is a rangecheck that is always present, even in Release mode.
00107 #define SimTK_SIZECHECK_ALWAYS(sz,maxsz,where) \
00108     do{if(!(0<=(sz)&&(sz)<=(maxsz)))SimTK_THROW4(SimTK::Exception::SizeOutOfRange,   \
00109                     #sz,(sz),(maxsz),(where));}while(false)
00110 
00111 // This is a rangecheck that is always present, even in Release mode.
00112 #define SimTK_SIZECHECK_NONNEG_ALWAYS(sz,where) \
00113     do{if((sz)<0)SimTK_THROW3(SimTK::Exception::SizeWasNegative,   \
00114                     #sz,(sz),(where));}while(false)
00115 
00116     // Similar checks for floating point values.
00117 
00118 #define SimTK_VALUECHECK_ALWAYS(lb,val,ub,valName,where) \
00119     do{if(!(lb)<=(val)&&(val)<=(ub)))SimTK_THROW5(SimTK::Exception::ValueOutOfRange,   \
00120                     (valName),(lb),(val),(ub),(where));}while(false)
00121 
00122 
00123 #define SimTK_VALUECHECK_NONNEG_ALWAYS(val,valName,where) \
00124     do{if((val)<0)SimTK_THROW3(SimTK::Exception::ValueWasNegative,   \
00125                     (valName),(val),(where));}while(false)
00126 
00127 
00128     // APIARGCHECKs: these should be used to catch all manner of problems with
00129     // a user's call to a method that is part of a SimTK API. Note that these
00130     // are intended for direct consumption by an application programmer using
00131     // a SimTK API, so should be wordy and helpful. These macros accept
00132     // printf-style format strings and arguments of whatever are the 
00133     // appropriate types for those formats.
00134 
00135 #define SimTK_APIARGCHECK_ALWAYS(cond,className,methodName,msg)     \
00136     do{if(!(cond))SimTK_THROW3(SimTK::Exception::APIArgcheckFailed, \
00137                     (className),(methodName),(msg));                \
00138     }while(false)
00139 #define SimTK_APIARGCHECK1_ALWAYS(cond,className,methodName,fmt,a1) \
00140     do{if(!(cond))SimTK_THROW4(SimTK::Exception::APIArgcheckFailed, \
00141                     (className),(methodName),(fmt),(a1));           \
00142     }while(false)
00143 #define SimTK_APIARGCHECK2_ALWAYS(cond,className,methodName,fmt,a1,a2)      \
00144     do{if(!(cond))SimTK_THROW5(SimTK::Exception::APIArgcheckFailed,         \
00145                     (className),(methodName),(fmt),(a1),(a2));              \
00146     }while(false)
00147 #define SimTK_APIARGCHECK3_ALWAYS(cond,className,methodName,fmt,a1,a2,a3)   \
00148     do{if(!(cond))SimTK_THROW6(SimTK::Exception::APIArgcheckFailed,         \
00149                     (className),(methodName),(fmt),(a1),(a2),(a3));         \
00150     }while(false)
00151 #define SimTK_APIARGCHECK4_ALWAYS(cond,className,methodName,fmt,a1,a2,a3,a4)    \
00152     do{if(!(cond))SimTK_THROW7(SimTK::Exception::APIArgcheckFailed,             \
00153                     (className),(methodName),(fmt),(a1),(a2),(a3),(a4));        \
00154     }while(false)
00155 #define SimTK_APIARGCHECK5_ALWAYS(cond,className,methodName,fmt,a1,a2,a3,a4,a5) \
00156     do{if(!(cond))SimTK_THROW8(SimTK::Exception::APIArgcheckFailed,             \
00157                     (className),(methodName),(fmt),(a1),(a2),(a3),(a4),(a5));   \
00158     }while(false)
00159 
00160 
00161 #if defined(NDEBUG) && !defined(SimTK_KEEP_RANGECHECK)
00162     #define SimTK_INDEXCHECK(lb,ix,ub,where)
00163     #define SimTK_SIZECHECK(sz,maxsz,where)
00164     #define SimTK_SIZECHECK_NONNEG(sz,where)
00165     #define SimTK_VALUECHECK(lb,val,ub,valName,where)
00166     #define SimTK_VALUECHECK_NONNEG(val,valName,where)
00167 #else
00168     #define SimTK_INDEXCHECK(lb,ix,ub,where) SimTK_INDEXCHECK_ALWAYS(lb,ix,ub,where)
00169     #define SimTK_SIZECHECK(sz,maxsz,where)  SimTK_SIZECHECK_ALWAYS(sz,maxsz,where)
00170     #define SimTK_SIZECHECK_NONNEG(sz,where) SimTK_SIZECHECK_NONNEG_ALWAYS(sz,where)
00171     #define SimTK_VALUECHECK(lb,val,ub,valName,where)  SimTK_VALUECHECK_ALWAYS(lb,val,ub,valName,where)
00172     #define SimTK_VALUECHECK_NONNEG(val,valName,where) SimTK_VALUECHECK_NONNEG_ALWAYS(val,valName,where)
00173 #endif
00174 
00175 #if defined(NDEBUG) && !defined(SimTK_KEEP_APIARGCHECK)
00176     #define SimTK_APIARGCHECK(cond,className,methodName,msg)
00177     #define SimTK_APIARGCHECK1(cond,className,methodName,fmt,a1)
00178     #define SimTK_APIARGCHECK2(cond,className,methodName,fmt,a1,a2)
00179     #define SimTK_APIARGCHECK3(cond,className,methodName,fmt,a1,a2,a3)
00180     #define SimTK_APIARGCHECK4(cond,className,methodName,fmt,a1,a2,a3,a4)
00181     #define SimTK_APIARGCHECK5(cond,className,methodName,fmt,a1,a2,a3,a4,a5)
00182 #else
00183     #define SimTK_APIARGCHECK(cond,className,methodName,msg)                       \
00184         SimTK_APIARGCHECK_ALWAYS(cond,className,methodName,msg)
00185     #define SimTK_APIARGCHECK1(cond,className,methodName,fmt,a1)                   \
00186         SimTK_APIARGCHECK1_ALWAYS(cond,className,methodName,fmt,a1)
00187     #define SimTK_APIARGCHECK2(cond,className,methodName,fmt,a1,a2)                \
00188         SimTK_APIARGCHECK2_ALWAYS(cond,className,methodName,fmt,a1,a2)
00189     #define SimTK_APIARGCHECK3(cond,className,methodName,fmt,a1,a2,a3)             \
00190         SimTK_APIARGCHECK3_ALWAYS(cond,className,methodName,fmt,a1,a2,a3)
00191     #define SimTK_APIARGCHECK4(cond,className,methodName,fmt,a1,a2,a3,a4)          \
00192         SimTK_APIARGCHECK4_ALWAYS(cond,className,methodName,fmt,a1,a2,a3,a4)
00193     #define SimTK_APIARGCHECK5(cond,className,methodName,fmt,a1,a2,a3,a4,a5)       \
00194         SimTK_APIARGCHECK5_ALWAYS(cond,className,methodName,fmt,a1,a2,a3,a4,a5)
00195 #endif
00196 
00197     // STAGECHECKs: these exception are to be used for situations in which a
00198     // user of an API screws up by attempting to access something in the 
00199     // state before it has been realized to the appropriate stage.
00200     //
00201     //   STAGECHECK_EQ: Check that the current stage is == a particular stage.
00202     //   STAGECHECK_GE: Check that the current stage is >= a particular stage.
00203     //   STAGECHECK_LT: Check that the current stage is <  a particular stage.
00204     //   STAGECHECK_RANGE: Check that lower <= stage <= upper.
00205 
00206 // These are stagechecks that is always present, even in Release mode.
00207 #define SimTK_STAGECHECK_TOPOLOGY_REALIZED_ALWAYS(cond,objType,objName,methodNm)  \
00208     do{if(!(cond)) SimTK_THROW3(SimTK::Exception::RealizeTopologyMustBeCalledFirst, \
00209         (objType),(objName),(methodNm));}while(false)
00210 #define SimTK_STAGECHECK_EQ_ALWAYS(currentStage,targetStage,methodNm) \
00211     do{if((currentStage)!=(targetStage)) SimTK_THROW3(SimTK::Exception::StageIsWrong,   \
00212         (currentStage),(targetStage),(methodNm));}while(false)
00213 #define SimTK_STAGECHECK_GE_ALWAYS(currentStage,targetStage,methodNm) \
00214     do{if(!((currentStage)>=(targetStage))) SimTK_THROW3(SimTK::Exception::StageTooLow,   \
00215         (currentStage),(targetStage),(methodNm));}while(false)
00216 #define SimTK_STAGECHECK_LT_ALWAYS(currentStage,targetStage,methodNm) \
00217     do{if((currentStage)>=(targetStage)) SimTK_THROW3(SimTK::Exception::StageTooHigh,   \
00218         (currentStage),(targetStage),(methodNm));}while(false)
00219 #define SimTK_STAGECHECK_RANGE_ALWAYS(lower,current,upper,methodNm) \
00220     do{if(!((lower)<=(current)&&(current)<=(upper))) SimTK_THROW4(SimTK::Exception::StageOutOfRange,   \
00221         (lower),(current),(upper),(methodNm));}while(false)
00222 
00223 // This one is present only in Debug mode or if SimTK_KEEP_STAGECHECK is explicitly defined.
00224 #if defined(NDEBUG) && !defined(SimTK_KEEP_STAGECHECK)
00225     #define SimTK_STAGECHECK_TOPOLOGY_REALIZED(cond,objType,objName,methodName)
00226     #define SimTK_STAGECHECK_EQ(currentStage,targetStage,methodNm)
00227     #define SimTK_STAGECHECK_GE(currentStage,targetStage,methodNm)
00228     #define SimTK_STAGECHECK_LE(currentStage,targetStage,methodNm)
00229     #define SimTK_STAGECHECK_RANGE(lower,current,upper,methodNm)
00230 #else
00231     #define SimTK_STAGECHECK_TOPOLOGY_REALIZED(cond,objType,objName,methodName) \
00232         SimTK_STAGECHECK_TOPOLOGY_REALIZED_ALWAYS(cond,objType,objName,methodName)
00233     #define SimTK_STAGECHECK_EQ(currentStage,targetStage,methodNm) \
00234         SimTK_STAGECHECK_EQ_ALWAYS(currentStage,targetStage,methodNm)
00235     #define SimTK_STAGECHECK_GE(currentStage,targetStage,methodNm) \
00236         SimTK_STAGECHECK_GE_ALWAYS(currentStage,targetStage,methodNm)
00237     #define SimTK_STAGECHECK_LE(currentStage,targetStage,methodNm) \
00238         SimTK_STAGECHECK_LE_ALWAYS(currentStage,targetStage,methodNm)
00239     #define SimTK_STAGECHECK_RANGE(lower,current,upper,methodNm) \
00240         SimTK_STAGECHECK_RANGE_ALWAYS(lower,current,upper,methodNm)
00241 #endif
00242 
00243 
00244 
00245     // ASSERT: use this *only* for internal errors, that is, bugs. This must
00246     // not be used to catch usage errors by clients; if you want to catch
00247     // user errors use different exceptions.
00248 
00249 // This is an assertion that is always active, even in Release mode.
00250 #define SimTK_ASSERT_ALWAYS(cond,msg) \
00251     do{if(!(cond))SimTK_THROW2(SimTK::Exception::Assert,#cond,(msg));}while(false)
00252 #define SimTK_ASSERT1_ALWAYS(cond,msg,a1) \
00253     do{if(!(cond))SimTK_THROW3(SimTK::Exception::Assert,#cond,(msg),(a1));}while(false)
00254 #define SimTK_ASSERT2_ALWAYS(cond,msg,a1,a2) \
00255     do{if(!(cond))SimTK_THROW4(SimTK::Exception::Assert,#cond,(msg),(a1),(a2));}while(false)
00256 #define SimTK_ASSERT3_ALWAYS(cond,msg,a1,a2,a3) \
00257     do{if(!(cond))SimTK_THROW5(SimTK::Exception::Assert,#cond,(msg),(a1),(a2),(a3));}while(false)
00258 #define SimTK_ASSERT4_ALWAYS(cond,msg,a1,a2,a3,a4) \
00259     do{if(!(cond))SimTK_THROW6(SimTK::Exception::Assert,#cond,(msg),(a1),(a2),(a3),(a4));}while(false)
00260 
00261 // Note: unlike the system assert() we're putting ours within the header guards.
00262 // So if you want to override NDEBUG do it at the *beginning* (that is, before
00263 // the first #include or #ifdef) of whatever compilation unit you are fiddling with.
00264 #if defined(NDEBUG) && !defined(SimTK_KEEP_ASSERT)
00265     #define SimTK_ASSERT(cond,msg)
00266     #define SimTK_ASSERT(cond,msg)
00267     #define SimTK_ASSERT1(cond,msg,a1)
00268     #define SimTK_ASSERT2(cond,msg,a1,a2)
00269     #define SimTK_ASSERT3(cond,msg,a1,a2,a3)
00270     #define SimTK_ASSERT4(cond,msg,a1,a2,a3,a4)
00271 #else
00272     #define SimTK_ASSERT(cond,msg) SimTK_ASSERT_ALWAYS(cond,msg)
00273     #define SimTK_ASSERT1(cond,msg,a1) SimTK_ASSERT1_ALWAYS(cond,msg,a1)
00274     #define SimTK_ASSERT2(cond,msg,a1,a2) SimTK_ASSERT2_ALWAYS(cond,msg,a1,a2)
00275     #define SimTK_ASSERT3(cond,msg,a1,a2,a3) SimTK_ASSERT3_ALWAYS(cond,msg,a1,a2,a3)
00276     #define SimTK_ASSERT4(cond,msg,a1,a2,a3,a4) SimTK_ASSERT4_ALWAYS(cond,msg,a1,a2,a3,a4)
00277 #endif
00278 
00279 
00280 #endif // SimTK_SimTKCOMMON_EXCEPTION_MACROS_H_
00281 
00282 
00283 

Generated on Fri Sep 26 07:44:10 2008 for SimTKcore by  doxygen 1.5.6