Simbody
3.4 (development)
|
00001 #ifndef SimTK_SimTKCOMMON_EXCEPTION_H_ 00002 #define SimTK_SimTKCOMMON_EXCEPTION_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * Simbody(tm): SimTKcommon * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK 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/home/simbody. * 00011 * * 00012 * Portions copyright (c) 2005-12 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 00014 * Contributors: * 00015 * * 00016 * Licensed under the Apache License, Version 2.0 (the "License"); you may * 00017 * not use this file except in compliance with the License. You may obtain a * 00018 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 00019 * * 00020 * Unless required by applicable law or agreed to in writing, software * 00021 * distributed under the License is distributed on an "AS IS" BASIS, * 00022 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 00023 * See the License for the specific language governing permissions and * 00024 * limitations under the License. * 00025 * -------------------------------------------------------------------------- */ 00026 00027 // Keeps MS VC++ 8 quiet about sprintf, strcpy, etc. 00028 #ifdef _MSC_VER 00029 #pragma warning(disable:4996) 00030 #endif 00031 00032 #include "SimTKcommon/internal/common.h" 00033 00034 #include <string> 00035 #include <iostream> 00036 #include <exception> 00037 #include <cstdarg> 00038 #include <cstdio> 00039 00040 namespace SimTK { 00041 00042 namespace Exception { 00043 00044 // SimTK::Exception::Base 00045 class Base : public std::exception { 00046 public: 00047 explicit Base(const char* fn="<UNKNOWN>", int ln=0) 00048 : fileName(fn), lineNo(ln) { } 00049 virtual ~Base() throw() { } 00050 const std::string& getMessage() const { return msg; } 00051 const std::string& getMessageText() const { return text; } 00052 00053 // override virtual function from std::exception 00054 const char* what() const throw() {return getMessage().c_str();} 00055 protected: 00056 void setMessage(const std::string& msgin) { 00057 text = msgin; 00058 msg = "SimTK Exception thrown at " + where() + ":\n " + msgin; 00059 } 00060 private: 00061 std::string fileName; // where the exception was thrown 00062 int lineNo; 00063 std::string msg; // a message formatted for display by catcher 00064 std::string text; // the original passed-in text 00065 00066 static std::string shortenFileName(const std::string& fn) 00067 { std::string::size_type pos = fn.find_last_of("/\\"); 00068 if (pos+1>=fn.size()) pos=0; 00069 return std::string(fn,(int)(pos+1),(int)(fn.size()-(pos+1))); 00070 } 00071 00072 std::string where() const { 00073 char buf[32]; 00074 sprintf(buf,"%d",lineNo); 00075 return shortenFileName(fileName) + ":" + std::string(buf); 00076 } 00077 }; 00078 00085 class Assert : public Base { 00086 public: 00087 Assert(const char* fn, int ln, const char* assertion, 00088 const char* fmt ...) : Base(fn,ln) 00089 { 00090 char buf[1024]; 00091 va_list args; 00092 va_start(args, fmt); 00093 vsprintf(buf, fmt, args); 00094 00095 setMessage("Internal bug detected: " + std::string(buf) 00096 + "\n (Assertion '" + std::string(assertion) + "' failed).\n" 00097 " Please file a bug report at https://simtk.org/home/simbody (Advanced tab).\n" 00098 " Include the above information and anything else needed to reproduce the problem."); 00099 va_end(args); 00100 } 00101 virtual ~Assert() throw() { } 00102 }; 00103 00112 class ErrorCheck : public Base { 00113 public: 00114 ErrorCheck(const char* fn, int ln, const char* assertion, 00115 const char* whereChecked, // e.g., ClassName::methodName() 00116 const char* fmt ...) : Base(fn,ln) 00117 { 00118 char buf[1024]; 00119 va_list args; 00120 va_start(args, fmt); 00121 vsprintf(buf, fmt, args); 00122 00123 setMessage("Error detected by Simbody method " 00124 + std::string(whereChecked) + ": " 00125 + std::string(buf) 00126 + "\n (Required condition '" + std::string(assertion) + "' was not met.)\n"); 00127 va_end(args); 00128 } 00129 virtual ~ErrorCheck() throw() { } 00130 }; 00131 00139 class APIArgcheckFailed : public Base { 00140 public: 00141 APIArgcheckFailed(const char* fn, int ln, const char* assertion, 00142 const char* className, const char* methodName, 00143 const char* fmt ...) : Base(fn,ln) 00144 { 00145 char buf[1024]; 00146 va_list args; 00147 va_start(args, fmt); 00148 vsprintf(buf, fmt, args); 00149 setMessage("Bad call to Simbody API method " 00150 + std::string(className) + "::" + std::string(methodName) + "(): " 00151 + std::string(buf) 00152 + "\n (Required condition '" + std::string(assertion) + "' was not met.)"); 00153 va_end(args); 00154 } 00155 virtual ~APIArgcheckFailed() throw() { } 00156 }; 00157 00158 00159 class IndexOutOfRange : public Base { 00160 public: 00161 IndexOutOfRange(const char* fn, int ln, const char* indexName, 00162 long long lb, long long index, long long ub, const char* where) 00163 : Base(fn,ln) 00164 { 00165 char buf[1024]; 00166 00167 sprintf(buf, "Index out of range in %s: expected %lld <= %s < %lld but %s=%lld.", 00168 where,lb,indexName,ub,indexName,index); 00169 setMessage(std::string(buf)); 00170 } 00171 virtual ~IndexOutOfRange() throw() { } 00172 }; 00173 00174 class SizeOutOfRange : public Base { 00175 public: 00176 SizeOutOfRange(const char* fn, int ln, const char* szName, 00177 unsigned long long sz, unsigned long long maxsz, const char* where) 00178 : Base(fn,ln) 00179 { 00180 char buf[1024]; 00181 00182 sprintf(buf, "Size out of range in %s: expected 0 <= %s <= %llu but %s=%llu.", 00183 where,szName,maxsz,szName,sz); 00184 setMessage(std::string(buf)); 00185 } 00186 virtual ~SizeOutOfRange() throw() { } 00187 }; 00188 00189 class SizeWasNegative : public Base { 00190 public: 00191 SizeWasNegative(const char* fn, int ln, const char* szName, 00192 unsigned long long sz, const char* where) 00193 : Base(fn,ln) 00194 { 00195 char buf[1024]; 00196 00197 sprintf(buf, "Size argument was negative in %s: expected 0 <= %s but %s=%llu.", 00198 where,szName,szName,sz); 00199 setMessage(std::string(buf)); 00200 } 00201 virtual ~SizeWasNegative() throw() { } 00202 }; 00203 00204 class ValueOutOfRange : public Base { 00205 public: 00206 ValueOutOfRange(const char* fn, int ln, const char* valueName, 00207 double lowerBound, double value, double upperBound, 00208 const char* where) 00209 : Base(fn,ln) 00210 { 00211 char buf[1024]; 00212 00213 sprintf(buf, "Value out of range in %s: expected %g <= %s <= %g but %s=%g.", 00214 where,lowerBound,valueName,upperBound,valueName,value); 00215 setMessage(std::string(buf)); 00216 } 00217 virtual ~ValueOutOfRange() throw() { } 00218 }; 00219 00220 class ValueWasNegative : public Base { 00221 public: 00222 ValueWasNegative(const char* fn, int ln, const char* valueName, 00223 double value, const char* where) 00224 : Base(fn,ln) 00225 { 00226 char buf[1024]; 00227 00228 sprintf(buf, "Expected non-negative value for %s in %s but got %g.", 00229 valueName,where,value); 00230 setMessage(std::string(buf)); 00231 } 00232 virtual ~ValueWasNegative() throw() { } 00233 }; 00234 00235 class UnimplementedMethod : public Base { 00236 public: 00237 UnimplementedMethod(const char* fn, int ln, std::string methodName) 00238 : Base(fn,ln) 00239 { 00240 setMessage("The method " + methodName 00241 + "is not yet implemented. Please post to the Simbody forum" 00242 " to find a workaround or request implementation."); 00243 } 00244 virtual ~UnimplementedMethod() throw() { } 00245 }; 00246 00247 class UnimplementedVirtualMethod : public Base { 00248 public: 00249 UnimplementedVirtualMethod(const char* fn, int ln, 00250 std::string baseClass, std::string methodName) 00251 : Base(fn,ln) 00252 { 00253 setMessage("The base class " + baseClass + 00254 " dummy implementation of method " + methodName 00255 + "() was invoked because a derived class did not provide an implementation."); 00256 } 00257 virtual ~UnimplementedVirtualMethod() throw() { } 00258 }; 00259 00260 class IncompatibleValues : public Base { 00261 public: 00262 IncompatibleValues(const char* fn, int ln, std::string src, std::string dest) : Base(fn,ln) 00263 { 00264 setMessage("Attempt to assign a Value<"+src+"> to a Value<"+dest+">"); 00265 } 00266 virtual ~IncompatibleValues() throw() { } 00267 }; 00268 00269 class OperationNotAllowedOnView : public Base { 00270 public: 00271 OperationNotAllowedOnView(const char* fn, int ln, const std::string& op) : Base(fn,ln) 00272 { 00273 setMessage("Operation '" + op + "' allowed only for owners, not views"); 00274 } 00275 virtual ~OperationNotAllowedOnView() throw() { } 00276 }; 00277 00278 class OperationNotAllowedOnOwner : public Base { 00279 public: 00280 OperationNotAllowedOnOwner(const char* fn, int ln, const std::string& op) : Base(fn,ln) 00281 { 00282 setMessage("Operation '" + op + "' allowed only for views, not owners"); 00283 } 00284 virtual ~OperationNotAllowedOnOwner() throw() { } 00285 }; 00286 00287 class OperationNotAllowedOnNonconstReadOnlyView : public Base { 00288 public: 00289 OperationNotAllowedOnNonconstReadOnlyView(const char* fn, int ln, const std::string& op) : Base(fn,ln) 00290 { 00291 setMessage("Operation '" + op + "' not allowed on non-const readonly view"); 00292 } 00293 virtual ~OperationNotAllowedOnNonconstReadOnlyView() throw() { } 00294 }; 00295 00296 // SimTK::Exception::Cant 00297 class Cant : public Base { 00298 public: 00299 Cant(const char* fn, int ln, const std::string& s) : Base(fn,ln) 00300 { 00301 setMessage("Can't perform operation: " + s); 00302 } 00303 virtual ~Cant() throw() { } 00304 }; 00305 00306 } // namespace Exception 00307 } // namespace SimTK 00308 00309 #define SimTK_THROW(exc) \ 00310 throw exc(__FILE__, __LINE__) 00311 #define SimTK_THROW1(exc,a1) \ 00312 throw exc(__FILE__, __LINE__,a1) 00313 #define SimTK_THROW2(exc,a1,a2) \ 00314 throw exc(__FILE__, __LINE__,a1,a2) 00315 #define SimTK_THROW3(exc,a1,a2,a3) \ 00316 throw exc(__FILE__, __LINE__,a1,a2,a3) 00317 #define SimTK_THROW4(exc,a1,a2,a3,a4) \ 00318 throw exc(__FILE__, __LINE__,a1,a2,a3,a4) 00319 #define SimTK_THROW5(exc,a1,a2,a3,a4,a5) \ 00320 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5) 00321 #define SimTK_THROW6(exc,a1,a2,a3,a4,a5,a6) \ 00322 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5,a6) 00323 #define SimTK_THROW7(exc,a1,a2,a3,a4,a5,a6,a7) \ 00324 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5,a6,a7) 00325 #define SimTK_THROW8(exc,a1,a2,a3,a4,a5,a6,a7,a8) \ 00326 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5,a6,a7,a8) 00327 #define SimTK_THROW9(exc,a1,a2,a3,a4,a5,a6,a7,a8,a9) \ 00328 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5,a6,a7,a8,a9) 00329 #define SimTK_THROW10(exc,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) \ 00330 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) 00331 00332 #endif // SimTK_SimTKCOMMON_EXCEPTION_H_ 00333