# BasicException.h

Go to the documentation of this file.

    00001 /*******************************************************************\
    00002
    00003               Copyright (C) 2003 Joseph Coffland
    00004
    00005     This program is free software; you can redistribute it and/or
    00006      modify it under the terms of the GNU General Public License
    00007     as published by the Free Software Foundation; either version 2
    00008         of the License, or (at your option) any later version.
    00009
    00010    This program is distributed in the hope that it will be useful,
    00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00013              GNU General Public License for more details.
    00014
    00015   You should have received a copy of the GNU General Public License
    00016      along with this program; if not, write to the Free Software
    00017       Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
    00018                            02111-1307, USA.
    00019
    00020             For information regarding this software email
    00021                    jcofflan@users.sourceforge.net
    00022
    00023 \*******************************************************************/
    00024
    00025
    00026 #ifndef BASICEXCEPTION_H
    00027 #define BASICEXCEPTION_H
    00028
    00029 #include "BasicFileLocation.h"
    00030 #include "BasicSmartPointer.h"
    00031 #include "BasicDebugger.h"
    00032 #include "Zap.h"
    00033
    00034 #include <string>
    00035 #include <iostream>
    00036
    00037 // Forward Declarations
    00038 template <class T, sp_alloc_t alloc_t>
    00039 class BasicSmartPointer;
    00040
    00061 class BasicException {
    00062   std::string message;
    00063   BasicFileLocation location;
    00064   BasicSmartPointer<BasicException> cause;
    00065   BasicSmartPointer<std::list<std::string> > trace;
    00066
    00067 public:
    00068   static unsigned int causePrintLevel;
    00069   static bool enableStackTraces;
    00070
    00071   BasicException() {init();}
    00072
    00073   BasicException(const std::string message) : message(message) {
    00074     init();
    00075   }
    00076
    00077   BasicException(const std::string message, const BasicFileLocation &location)
    00078     : message(message), location(location) {
    00079     init();
    00080   }
    00081
    00082   BasicException(const std::string message, BasicException &cause) :
    00083     message(message) {
    00084     this->cause = new BasicException(cause);
    00085     init();
    00086   }
    00087
    00088   BasicException(const std::string message, const BasicFileLocation &location,
    00089                  BasicException &cause) :
    00090     message(message), location(location) {
    00091     this->cause = new BasicException(cause);
    00092     init();
    00093   }
    00094
    00096   BasicException(const BasicException &e) :
    00097     message(e.message), location(e.location), cause(e.cause), trace(e.trace) {}
    00098
    00099   virtual ~BasicException() {}
    00100
    00101   const std::string getMessage() const {return message;}
    00102   BasicFileLocation getLocation() const {return location;}
    00103
    00108   BasicSmartPointer<BasicException> getCause() const {return cause;}
    00109
    00110   BasicSmartPointer<std::list<std::string> > getTrace() const {return trace;}
    00111
    00124   std::ostream &print(std::ostream &stream,
    00125                       bool printLocations = true,
    00126                       unsigned int printLevel = 0) const {
    00127
    00128     if (printLocations && !location.isEmpty())
    00129       stream << "@ " << location << " ";
    00130
    00131     stream << message;
    00132
    00133     if (enableStackTraces && !trace.isNull()) {
    00134       std::list<std::string>::iterator it;
    00135       for (it = trace->begin(); it != trace->end(); it++)
    00136         stream << std::endl << "  " << *it;
    00137     }
    00138
    00139     if (!cause.isNull()) {
    00140       stream << std::endl << " ";
    00141
    00142       if (printLevel > causePrintLevel) {
    00143         stream << "Aborting exception dump due to causePrintLevel limit! "
    00144                << "Increase BasicException::causePrintLevel to see more.";
    00145
    00146       } else {
    00147         stream << "caused by: ";
    00148         cause->print(stream, printLocations, printLevel);
    00149       }
    00150     }
    00151
    00152     return stream;
    00153   }
    00154
    00155 protected:
    00156   void init() {
    00157     if (enableStackTraces) {
    00158       trace = new std::list<std::string>;
    00159
    00160       // When Optimization is turned on functions such as this
    00161       // one are often inlined and not visable to the debugger.
    00162       // This means stack traces for optimized code will often
    00163       // be incomplete.  Here we remove the offset in order
    00164       // to get as much of the stack trace as possible.
    00165 #     ifdef __OPTIMIZE__
    00166       BasicDebugger::getStackTrace(*trace, 0);
    00167       trace->push_front("Warning: Optimization can cause incomplete traces.");
    00168 #     else
    00169       BasicDebugger::getStackTrace(*trace, 2);
    00170 #     endif
    00171     }
    00172   }
    00173
    00174   friend std::ostream &operator<<(std::ostream &, const BasicException &);
    00175 };
    00176
    00187 inline std::ostream &operator<<(std::ostream &stream,
    00188                                 const BasicException &e) {
    00189   e.print(stream);
    00190   return stream;
    00191 }
    00192
    00193 #define THROW(msg) throw BasicException((msg), FILE_LOCATION)
    00194 #define THROWC(msg, cause) throw BasicException((msg), FILE_LOCATION, (cause))
    00195 #define ASSERT_OR_THROW(msg, condition) {if (!(condition)) THROW(msg);}
    00196
    00197 #endif