Simbody  3.4 (development)
Exception.h
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines