Simbody
|
00001 #ifndef SimTK_SimTKCOMMON_EXCEPTION_H_ 00002 #define SimTK_SimTKCOMMON_EXCEPTION_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-10 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 00035 // Keeps MS VC++ 8 quiet about sprintf, strcpy, etc. 00036 #ifdef _MSC_VER 00037 #pragma warning(disable:4996) 00038 #endif 00039 00040 #include "SimTKcommon/internal/common.h" 00041 00042 #include <string> 00043 #include <iostream> 00044 #include <exception> 00045 #include <cstdarg> 00046 #include <cstdio> 00047 00048 namespace SimTK { 00049 00050 namespace Exception { 00051 00052 // SimTK::Exception::Base 00053 class Base : public std::exception { 00054 public: 00055 explicit Base(const char* fn="<UNKNOWN>", int ln=0) 00056 : fileName(fn), lineNo(ln) { } 00057 virtual ~Base() throw() { } 00058 const std::string& getMessage() const { return msg; } 00059 const std::string& getMessageText() const { return text; } 00060 00061 // override virtual function from std::exception 00062 const char* what() const throw() {return getMessage().c_str();} 00063 protected: 00064 void setMessage(const std::string& msgin) { 00065 text = msgin; 00066 msg = "SimTK Exception thrown at " + where() + ":\n " + msgin; 00067 } 00068 private: 00069 std::string fileName; // where the exception was thrown 00070 int lineNo; 00071 std::string msg; // a message formatted for display by catcher 00072 std::string text; // the original passed-in text 00073 00074 static std::string shortenFileName(const std::string& fn) 00075 { std::string::size_type pos = fn.find_last_of("/\\"); 00076 if (pos+1>=fn.size()) pos=0; 00077 return std::string(fn,(int)(pos+1),(int)(fn.size()-(pos+1))); 00078 } 00079 00080 std::string where() const { 00081 char buf[32]; 00082 sprintf(buf,"%d",lineNo); 00083 return shortenFileName(fileName) + ":" + std::string(buf); 00084 } 00085 }; 00086 00093 class Assert : public Base { 00094 public: 00095 Assert(const char* fn, int ln, const char* assertion, 00096 const char* fmt ...) : Base(fn,ln) 00097 { 00098 char buf[1024]; 00099 va_list args; 00100 va_start(args, fmt); 00101 vsprintf(buf, fmt, args); 00102 00103 setMessage("Internal SimTK bug detected: " + std::string(buf) 00104 + "\n (Assertion '" + std::string(assertion) + "' failed).\n" 00105 " Please file a SimTKcore bug report at https://simtk.org/home/simtkcore (Advanced tab).\n" 00106 " Include the above information and anything else needed to reproduce the problem."); 00107 va_end(args); 00108 } 00109 virtual ~Assert() throw() { } 00110 }; 00111 00120 class ErrorCheck : public Base { 00121 public: 00122 ErrorCheck(const char* fn, int ln, const char* assertion, 00123 const char* whereChecked, // e.g., ClassName::methodName() 00124 const char* fmt ...) : Base(fn,ln) 00125 { 00126 char buf[1024]; 00127 va_list args; 00128 va_start(args, fmt); 00129 vsprintf(buf, fmt, args); 00130 00131 setMessage("Error detected by SimTK method " 00132 + std::string(whereChecked) + ": " 00133 + std::string(buf) 00134 + "\n (Required condition '" + std::string(assertion) + "' was not met.)\n"); 00135 va_end(args); 00136 } 00137 virtual ~ErrorCheck() throw() { } 00138 }; 00139 00147 class APIArgcheckFailed : public Base { 00148 public: 00149 APIArgcheckFailed(const char* fn, int ln, const char* assertion, 00150 const char* className, const char* methodName, 00151 const char* fmt ...) : Base(fn,ln) 00152 { 00153 char buf[1024]; 00154 va_list args; 00155 va_start(args, fmt); 00156 vsprintf(buf, fmt, args); 00157 setMessage("Bad call to SimTK API method " 00158 + std::string(className) + "::" + std::string(methodName) + "(): " 00159 + std::string(buf) 00160 + "\n (Required condition '" + std::string(assertion) + "' was not met.)"); 00161 va_end(args); 00162 } 00163 virtual ~APIArgcheckFailed() throw() { } 00164 }; 00165 00166 00167 class IndexOutOfRange : public Base { 00168 public: 00169 IndexOutOfRange(const char* fn, int ln, const char* indexName, 00170 long long lb, long long index, long long ub, const char* where) 00171 : Base(fn,ln) 00172 { 00173 char buf[1024]; 00174 00175 sprintf(buf, "Index out of range in %s: expected %lld <= %s < %lld but %s=%lld.", 00176 where,lb,indexName,ub,indexName,index); 00177 setMessage(std::string(buf)); 00178 } 00179 virtual ~IndexOutOfRange() throw() { } 00180 }; 00181 00182 class SizeOutOfRange : public Base { 00183 public: 00184 SizeOutOfRange(const char* fn, int ln, const char* szName, 00185 unsigned long long sz, unsigned long long maxsz, const char* where) 00186 : Base(fn,ln) 00187 { 00188 char buf[1024]; 00189 00190 sprintf(buf, "Size out of range in %s: expected 0 <= %s <= %llu but %s=%llu.", 00191 where,szName,maxsz,szName,sz); 00192 setMessage(std::string(buf)); 00193 } 00194 virtual ~SizeOutOfRange() throw() { } 00195 }; 00196 00197 class SizeWasNegative : public Base { 00198 public: 00199 SizeWasNegative(const char* fn, int ln, const char* szName, 00200 unsigned long long sz, const char* where) 00201 : Base(fn,ln) 00202 { 00203 char buf[1024]; 00204 00205 sprintf(buf, "Size argument was negative in %s: expected 0 <= %s but %s=%llu.", 00206 where,szName,szName,sz); 00207 setMessage(std::string(buf)); 00208 } 00209 virtual ~SizeWasNegative() throw() { } 00210 }; 00211 00212 class ValueOutOfRange : public Base { 00213 public: 00214 ValueOutOfRange(const char* fn, int ln, const char* valueName, 00215 Real lowerBound, Real value, Real upperBound, 00216 const char* where) 00217 : Base(fn,ln) 00218 { 00219 char buf[1024]; 00220 00221 sprintf(buf, "Value out of range in %s: expected %g <= %s <= %g but %s=%g.", 00222 where,lowerBound,valueName,upperBound,valueName,value); 00223 setMessage(std::string(buf)); 00224 } 00225 virtual ~ValueOutOfRange() throw() { } 00226 }; 00227 00228 class ValueWasNegative : public Base { 00229 public: 00230 ValueWasNegative(const char* fn, int ln, const char* valueName, 00231 Real value, const char* where) 00232 : Base(fn,ln) 00233 { 00234 char buf[1024]; 00235 00236 sprintf(buf, "Expected non-negative value for %s in %s but got %g.", 00237 valueName,where,value); 00238 setMessage(std::string(buf)); 00239 } 00240 virtual ~ValueWasNegative() throw() { } 00241 }; 00242 00243 class UnimplementedVirtualMethod : public Base { 00244 public: 00245 UnimplementedVirtualMethod(const char* fn, int ln, 00246 std::string baseClass, std::string methodName) 00247 : Base(fn,ln) 00248 { 00249 setMessage("The base class " + baseClass + 00250 " dummy implementation of method " + methodName 00251 + "() was invoked because a derived class did not provide an implementation."); 00252 } 00253 virtual ~UnimplementedVirtualMethod() throw() { } 00254 }; 00255 00256 class IncompatibleValues : public Base { 00257 public: 00258 IncompatibleValues(const char* fn, int ln, std::string src, std::string dest) : Base(fn,ln) 00259 { 00260 setMessage("Attempt to assign a Value<"+src+"> to a Value<"+dest+">"); 00261 } 00262 virtual ~IncompatibleValues() throw() { } 00263 }; 00264 00265 class OperationNotAllowedOnView : public Base { 00266 public: 00267 OperationNotAllowedOnView(const char* fn, int ln, const std::string& op) : Base(fn,ln) 00268 { 00269 setMessage("Operation '" + op + "' allowed only for owners, not views"); 00270 } 00271 virtual ~OperationNotAllowedOnView() throw() { } 00272 }; 00273 00274 class OperationNotAllowedOnOwner : public Base { 00275 public: 00276 OperationNotAllowedOnOwner(const char* fn, int ln, const std::string& op) : Base(fn,ln) 00277 { 00278 setMessage("Operation '" + op + "' allowed only for views, not owners"); 00279 } 00280 virtual ~OperationNotAllowedOnOwner() throw() { } 00281 }; 00282 00283 class OperationNotAllowedOnNonconstReadOnlyView : public Base { 00284 public: 00285 OperationNotAllowedOnNonconstReadOnlyView(const char* fn, int ln, const std::string& op) : Base(fn,ln) 00286 { 00287 setMessage("Operation '" + op + "' not allowed on non-const readonly view"); 00288 } 00289 virtual ~OperationNotAllowedOnNonconstReadOnlyView() throw() { } 00290 }; 00291 00292 // SimTK::Exception::Cant 00293 class Cant : public Base { 00294 public: 00295 Cant(const char* fn, int ln, const std::string& s) : Base(fn,ln) 00296 { 00297 setMessage("Can't perform operation: " + s); 00298 } 00299 virtual ~Cant() throw() { } 00300 }; 00301 00302 } // namespace Exception 00303 } // namespace SimTK 00304 00305 #define SimTK_THROW(exc) \ 00306 throw exc(__FILE__, __LINE__) 00307 #define SimTK_THROW1(exc,a1) \ 00308 throw exc(__FILE__, __LINE__,a1) 00309 #define SimTK_THROW2(exc,a1,a2) \ 00310 throw exc(__FILE__, __LINE__,a1,a2) 00311 #define SimTK_THROW3(exc,a1,a2,a3) \ 00312 throw exc(__FILE__, __LINE__,a1,a2,a3) 00313 #define SimTK_THROW4(exc,a1,a2,a3,a4) \ 00314 throw exc(__FILE__, __LINE__,a1,a2,a3,a4) 00315 #define SimTK_THROW5(exc,a1,a2,a3,a4,a5) \ 00316 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5) 00317 #define SimTK_THROW6(exc,a1,a2,a3,a4,a5,a6) \ 00318 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5,a6) 00319 #define SimTK_THROW7(exc,a1,a2,a3,a4,a5,a6,a7) \ 00320 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5,a6,a7) 00321 #define SimTK_THROW8(exc,a1,a2,a3,a4,a5,a6,a7,a8) \ 00322 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5,a6,a7,a8) 00323 #define SimTK_THROW9(exc,a1,a2,a3,a4,a5,a6,a7,a8,a9) \ 00324 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5,a6,a7,a8,a9) 00325 #define SimTK_THROW10(exc,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) \ 00326 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) 00327 00328 #endif // SimTK_SimTKCOMMON_EXCEPTION_H_ 00329