Exception.h

Go to the documentation of this file.
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-7 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 
00047 namespace SimTK {
00048 
00049 namespace Exception {
00050     
00051 // SimTK::Exception::Base   
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     // override virtual function from std::exception
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;   // where the exception was thrown
00069     int         lineNo; 
00070     std::string msg;        // a message formatted for display by catcher
00071     std::string text;      // the original passed-in 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,    // e.g., ClassName::methodName()
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 // SimTK::Exception::Cant
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 } // namespace Exception
00302 } // namespace SimTK
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 

Generated on Thu Aug 12 16:37:06 2010 for SimTKcore by  doxygen 1.6.1