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
00086
00087
00088 class Assert : public Base {
00089 public:
00090 Assert(const char* fn, int ln, const char* assertion,
00091 const char* fmt ...) : Base(fn,ln)
00092 {
00093 char buf[1024];
00094 va_list args;
00095 va_start(args, fmt);
00096 vsprintf(buf, fmt, args);
00097
00098 setMessage("Internal SimTK bug detected: " + std::string(buf)
00099 + " (Assertion '" + std::string(assertion) + "' failed). "
00100 "Please report this to the appropriate authorities at SimTK.org.");
00101 va_end(args);
00102 }
00103 private:
00104 };
00105
00106
00107 class APIArgcheckFailed : public Base {
00108 public:
00109 APIArgcheckFailed(const char* fn, int ln, const char* className, const char* methodName,
00110 const char* fmt ...) : Base(fn,ln)
00111 {
00112 char buf[1024];
00113 va_list args;
00114 va_start(args, fmt);
00115 vsprintf(buf, fmt, args);
00116 setMessage("Bad call to SimTK API method "
00117 + std::string(className) + "::" + std::string(methodName) + "(): "
00118 + std::string(buf) + ".");
00119 va_end(args);
00120 }
00121 private:
00122 };
00123
00124
00125 class IndexOutOfRange : public Base {
00126 public:
00127 IndexOutOfRange(const char* fn, int ln, const char* indexName,
00128 long lb, long index, long ub, const char* where)
00129 : Base(fn,ln)
00130 {
00131 char buf[1024];
00132
00133 sprintf(buf, "Index out of range in %s: expected %ld <= %s < %ld but %s=%ld.",
00134 where,lb,indexName,ub,indexName,index);
00135 setMessage(std::string(buf));
00136 }
00137 private:
00138 };
00139
00140 class SizeOutOfRange : public Base {
00141 public:
00142 SizeOutOfRange(const char* fn, int ln, const char* szName,
00143 long sz, long maxsz, const char* where)
00144 : Base(fn,ln)
00145 {
00146 char buf[1024];
00147
00148 sprintf(buf, "Size out of range in %s: expected 0 <= %s <= %ld but %s=%ld.",
00149 where,szName,maxsz,szName,sz);
00150 setMessage(std::string(buf));
00151 }
00152 private:
00153 };
00154
00155 class SizeWasNegative : public Base {
00156 public:
00157 SizeWasNegative(const char* fn, int ln, const char* szName,
00158 long sz, const char* where)
00159 : Base(fn,ln)
00160 {
00161 char buf[1024];
00162
00163 sprintf(buf, "Size argument was negative in %s: expected 0 <= %s but %s=%ld.",
00164 where,szName,szName,sz);
00165 setMessage(std::string(buf));
00166 }
00167 private:
00168 };
00169
00170 class ValueOutOfRange : public Base {
00171 public:
00172 ValueOutOfRange(const char* fn, int ln, const char* valueName,
00173 Real lowerBound, Real value, Real upperBound,
00174 const char* where)
00175 : Base(fn,ln)
00176 {
00177 char buf[1024];
00178
00179 sprintf(buf, "Value out of range in %s: expected %g <= %s <= %g but %s=%g.",
00180 where,lowerBound,valueName,upperBound,valueName,value);
00181 setMessage(std::string(buf));
00182 }
00183 private:
00184 };
00185
00186 class ValueWasNegative : public Base {
00187 public:
00188 ValueWasNegative(const char* fn, int ln, const char* valueName,
00189 Real value, const char* where)
00190 : Base(fn,ln)
00191 {
00192 char buf[1024];
00193
00194 sprintf(buf, "Expected non-negative value for %s in %s but got %g.",
00195 valueName,where,value);
00196 setMessage(std::string(buf));
00197 }
00198 private:
00199 };
00200
00201 class UnimplementedVirtualMethod : public Base {
00202 public:
00203 UnimplementedVirtualMethod(const char* fn, int ln,
00204 std::string baseClass, std::string methodName)
00205 : Base(fn,ln)
00206 {
00207 setMessage("The base class " + baseClass +
00208 " dummy implementation of method " + methodName
00209 + "() was invoked because a derived class did not provide an implementation.");
00210 }
00211 };
00212
00213 class IncompatibleValues : public Base {
00214 public:
00215 IncompatibleValues(const char* fn, int ln, std::string src, std::string dest) : Base(fn,ln)
00216 {
00217 setMessage("Attempt to assign a Value<"+src+"> to a Value<"+dest+">");
00218 }
00219 private:
00220 };
00221
00222 class OperationNotAllowedOnView : public Base {
00223 public:
00224 OperationNotAllowedOnView(const char* fn, int ln, const std::string& op) : Base(fn,ln)
00225 {
00226 setMessage("Operation '" + op + "' allowed only for owners, not views");
00227 }
00228 };
00229
00230 class OperationNotAllowedOnOwner : public Base {
00231 public:
00232 OperationNotAllowedOnOwner(const char* fn, int ln, const std::string& op) : Base(fn,ln)
00233 {
00234 setMessage("Operation '" + op + "' allowed only for views, not owners");
00235 }
00236 };
00237
00238 class OperationNotAllowedOnNonconstReadOnlyView : public Base {
00239 public:
00240 OperationNotAllowedOnNonconstReadOnlyView(const char* fn, int ln, const std::string& op) : Base(fn,ln)
00241 {
00242 setMessage("Operation '" + op + "' not allowed on non-const readonly view");
00243 }
00244 };
00245
00246
00247 class Cant : public Base {
00248 public:
00249 Cant(const char* fn, int ln, const std::string& s) : Base(fn,ln)
00250 {
00251 setMessage("Can't perform operation: " + s);
00252 }
00253 };
00254
00255 }
00256 }
00257
00258 #define SimTK_THROW(exc) \
00259 throw exc(__FILE__, __LINE__)
00260 #define SimTK_THROW1(exc,a1) \
00261 throw exc(__FILE__, __LINE__,a1)
00262 #define SimTK_THROW2(exc,a1,a2) \
00263 throw exc(__FILE__, __LINE__,a1,a2)
00264 #define SimTK_THROW3(exc,a1,a2,a3) \
00265 throw exc(__FILE__, __LINE__,a1,a2,a3)
00266 #define SimTK_THROW4(exc,a1,a2,a3,a4) \
00267 throw exc(__FILE__, __LINE__,a1,a2,a3,a4)
00268 #define SimTK_THROW5(exc,a1,a2,a3,a4,a5) \
00269 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5)
00270 #define SimTK_THROW6(exc,a1,a2,a3,a4,a5,a6) \
00271 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5,a6)
00272 #define SimTK_THROW7(exc,a1,a2,a3,a4,a5,a6,a7) \
00273 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5,a6,a7)
00274 #define SimTK_THROW8(exc,a1,a2,a3,a4,a5,a6,a7,a8) \
00275 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5,a6,a7,a8)
00276 #define SimTK_THROW9(exc,a1,a2,a3,a4,a5,a6,a7,a8,a9) \
00277 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5,a6,a7,a8,a9)
00278 #define SimTK_THROW10(exc,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) \
00279 throw exc(__FILE__, __LINE__,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
00280
00281 #endif // SimTK_SimTKCOMMON_EXCEPTION_H_
00282