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 };
00109
00118 class ErrorCheck : public Base {
00119 public:
00120 ErrorCheck(const char* fn, int ln, const char* assertion,
00121 const char* whereChecked,
00122 const char* fmt ...) : Base(fn,ln)
00123 {
00124 char buf[1024];
00125 va_list args;
00126 va_start(args, fmt);
00127 vsprintf(buf, fmt, args);
00128
00129 setMessage("Error detected by SimTK method "
00130 + std::string(whereChecked) + ": "
00131 + std::string(buf)
00132 + "\n (Required condition '" + std::string(assertion) + "' was not met.)\n");
00133 va_end(args);
00134 }
00135 private:
00136 };
00137
00145 class APIArgcheckFailed : public Base {
00146 public:
00147 APIArgcheckFailed(const char* fn, int ln, const char* assertion,
00148 const char* className, const char* methodName,
00149 const char* fmt ...) : Base(fn,ln)
00150 {
00151 char buf[1024];
00152 va_list args;
00153 va_start(args, fmt);
00154 vsprintf(buf, fmt, args);
00155 setMessage("Bad call to SimTK API method "
00156 + std::string(className) + "::" + std::string(methodName) + "(): "
00157 + std::string(buf)
00158 + "\n (Required condition '" + std::string(assertion) + "' was not met.)");
00159 va_end(args);
00160 }
00161 };
00162
00163
00164 class IndexOutOfRange : public Base {
00165 public:
00166 IndexOutOfRange(const char* fn, int ln, const char* indexName,
00167 long lb, long index, long ub, const char* where)
00168 : Base(fn,ln)
00169 {
00170 char buf[1024];
00171
00172 sprintf(buf, "Index out of range in %s: expected %ld <= %s < %ld but %s=%ld.",
00173 where,lb,indexName,ub,indexName,index);
00174 setMessage(std::string(buf));
00175 }
00176 private:
00177 };
00178
00179 class SizeOutOfRange : public Base {
00180 public:
00181 SizeOutOfRange(const char* fn, int ln, const char* szName,
00182 long sz, long maxsz, const char* where)
00183 : Base(fn,ln)
00184 {
00185 char buf[1024];
00186
00187 sprintf(buf, "Size out of range in %s: expected 0 <= %s <= %ld but %s=%ld.",
00188 where,szName,maxsz,szName,sz);
00189 setMessage(std::string(buf));
00190 }
00191 private:
00192 };
00193
00194 class SizeWasNegative : public Base {
00195 public:
00196 SizeWasNegative(const char* fn, int ln, const char* szName,
00197 long sz, const char* where)
00198 : Base(fn,ln)
00199 {
00200 char buf[1024];
00201
00202 sprintf(buf, "Size argument was negative in %s: expected 0 <= %s but %s=%ld.",
00203 where,szName,szName,sz);
00204 setMessage(std::string(buf));
00205 }
00206 private:
00207 };
00208
00209 class ValueOutOfRange : public Base {
00210 public:
00211 ValueOutOfRange(const char* fn, int ln, const char* valueName,
00212 Real lowerBound, Real value, Real upperBound,
00213 const char* where)
00214 : Base(fn,ln)
00215 {
00216 char buf[1024];
00217
00218 sprintf(buf, "Value out of range in %s: expected %g <= %s <= %g but %s=%g.",
00219 where,lowerBound,valueName,upperBound,valueName,value);
00220 setMessage(std::string(buf));
00221 }
00222 private:
00223 };
00224
00225 class ValueWasNegative : public Base {
00226 public:
00227 ValueWasNegative(const char* fn, int ln, const char* valueName,
00228 Real value, const char* where)
00229 : Base(fn,ln)
00230 {
00231 char buf[1024];
00232
00233 sprintf(buf, "Expected non-negative value for %s in %s but got %g.",
00234 valueName,where,value);
00235 setMessage(std::string(buf));
00236 }
00237 private:
00238 };
00239
00240 class UnimplementedVirtualMethod : public Base {
00241 public:
00242 UnimplementedVirtualMethod(const char* fn, int ln,
00243 std::string baseClass, std::string methodName)
00244 : Base(fn,ln)
00245 {
00246 setMessage("The base class " + baseClass +
00247 " dummy implementation of method " + methodName
00248 + "() was invoked because a derived class did not provide an implementation.");
00249 }
00250 };
00251
00252 class IncompatibleValues : public Base {
00253 public:
00254 IncompatibleValues(const char* fn, int ln, std::string src, std::string dest) : Base(fn,ln)
00255 {
00256 setMessage("Attempt to assign a Value<"+src+"> to a Value<"+dest+">");
00257 }
00258 private:
00259 };
00260
00261 class OperationNotAllowedOnView : public Base {
00262 public:
00263 OperationNotAllowedOnView(const char* fn, int ln, const std::string& op) : Base(fn,ln)
00264 {
00265 setMessage("Operation '" + op + "' allowed only for owners, not views");
00266 }
00267 };
00268
00269 class OperationNotAllowedOnOwner : public Base {
00270 public:
00271 OperationNotAllowedOnOwner(const char* fn, int ln, const std::string& op) : Base(fn,ln)
00272 {
00273 setMessage("Operation '" + op + "' allowed only for views, not owners");
00274 }
00275 };
00276
00277 class OperationNotAllowedOnNonconstReadOnlyView : public Base {
00278 public:
00279 OperationNotAllowedOnNonconstReadOnlyView(const char* fn, int ln, const std::string& op) : Base(fn,ln)
00280 {
00281 setMessage("Operation '" + op + "' not allowed on non-const readonly view");
00282 }
00283 };
00284
00285
00286 class Cant : public Base {
00287 public:
00288 Cant(const char* fn, int ln, const std::string& s) : Base(fn,ln)
00289 {
00290 setMessage("Can't perform operation: " + s);
00291 }
00292 };
00293
00294 }
00295 }
00296
00297 #define SimTK_THROW(exc) \
00298 throw exc(__FILE__, __LINE__)
00299 #define SimTK_THROW1(exc,a1) \
00300 throw exc(__FILE__, __LINE__,a1)
00301 #define SimTK_THROW2(exc,a1,a2) \
00302 throw exc(__FILE__, __LINE__,a1,a2)
00303 #define SimTK_THROW3(exc,a1,a2,a3) \
00304 throw exc(__FILE__, __LINE__,a1,a2,a3)
00305 #define SimTK_THROW4(exc,a1,a2,a3,a4) \
00306 throw exc(__FILE__, __LINE__,a1,a2,a3,a4)
00307 #define SimTK_THROW5(exc,a1,a2,a3,a4,a5) \
00308 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5)
00309 #define SimTK_THROW6(exc,a1,a2,a3,a4,a5,a6) \
00310 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5,a6)
00311 #define SimTK_THROW7(exc,a1,a2,a3,a4,a5,a6,a7) \
00312 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5,a6,a7)
00313 #define SimTK_THROW8(exc,a1,a2,a3,a4,a5,a6,a7,a8) \
00314 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5,a6,a7,a8)
00315 #define SimTK_THROW9(exc,a1,a2,a3,a4,a5,a6,a7,a8,a9) \
00316 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5,a6,a7,a8,a9)
00317 #define SimTK_THROW10(exc,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) \
00318 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
00319
00320 #endif // SimTK_SimTKCOMMON_EXCEPTION_H_
00321