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