00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef BASICEXCEPTION_H
00027 #define BASICEXCEPTION_H
00028
00029 #include "BasicFileLocation.h"
00030 #include "BasicSmartPointer.h"
00031 #include "Zap.h"
00032
00033 #include <string>
00034 #include <iostream>
00035 #include <list>
00036
00037
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
00161
00162
00163
00164
00165 }
00166 }
00167
00168 friend std::ostream &operator<<(std::ostream &, const BasicException &);
00169 };
00170
00181 inline std::ostream &operator<<(std::ostream &stream,
00182 const BasicException &e) {
00183 e.print(stream);
00184 return stream;
00185 }
00186
00187 #define THROW(msg) throw BasicException((msg), FILE_LOCATION)
00188 #define THROWC(msg, cause) throw BasicException((msg), FILE_LOCATION, (cause))
00189 #define ASSERT_OR_THROW(msg, condition) {if (!(condition)) THROW(msg);}
00190
00191 #endif