Vault  4.1
vexception.cpp
Go to the documentation of this file.
00001 /*
00002 Copyright c1997-2014 Trygve Isaacson. All rights reserved.
00003 This file is part of the Code Vault version 4.1
00004 http://www.bombaydigital.com/
00005 License: MIT. See LICENSE.md in the Vault top level directory.
00006 */
00007 
00010 #include "vexception.h"
00011 
00012 #include "vassert.h"
00013 #include "vtypes_internal.h"
00014 
00015 // VSystemError ---------------------------------------------------------------
00016 
00017 //static
00018 VSystemError VSystemError::getSocketError() {
00019     return VSystemError(VSystemError::_getSocketErrorCode());
00020 }
00021 
00022 VSystemError::VSystemError()
00023     : mErrorCode(VSystemError::_getSystemErrorCode())
00024     , mErrorMessage(VSystemError::_getSystemErrorMessage(mErrorCode))
00025     {
00026 }
00027 
00028 VSystemError::VSystemError(int errorCode)
00029     : mErrorCode(errorCode)
00030     , mErrorMessage(VSystemError::_getSystemErrorMessage(errorCode))
00031     {
00032 }
00033 
00034 VSystemError::VSystemError(int errorCode, const VString& errorMessage)
00035     : mErrorCode(errorCode)
00036     , mErrorMessage(errorMessage)
00037     {
00038 }
00039 
00040 // VException -----------------------------------------------------------------
00041 
00042 // Is ASSERT_INVARIANT enabled/disabled specifically for VException?
00043 #ifdef V_ASSERT_INVARIANT_VEXCEPTION_ENABLED
00044     #undef ASSERT_INVARIANT
00045     #if V_ASSERT_INVARIANT_VEXCEPTION_ENABLED == 1
00046         #define ASSERT_INVARIANT() this->_assertInvariant() ///< Macro to call this->_assertInvariant().
00047     #else
00048         #define ASSERT_INVARIANT() ((void) 0) ///< No-op.
00049     #endif
00050 #endif
00051 
00052 // static
00053 void VException::_breakpointLocation() {
00054     // Put a breakpoint here if you want to break on all VExceptions.
00055 }
00056 
00057 VException::VException(bool recordStackTrace)
00058     : std::exception()
00059     , mError(kGenericError)
00060     , mErrorString()
00061     , mErrorMessage("") // if mErrorString is empty, we assert that mErrorMessage is not null, so assign it something
00062     , mStackTrace()
00063     {
00064     ASSERT_INVARIANT();
00065 
00066     VException::_breakpointLocation();
00067 
00068     if (recordStackTrace) {
00069         this->_recordStackTrace();
00070     }
00071 }
00072 
00073 VException::VException(const VException& other, bool recordStackTrace)
00074     : std::exception()
00075     , mError(other.getError())
00076     , mErrorString(other.mErrorString)
00077     , mErrorMessage(other.mErrorMessage)
00078     , mStackTrace(other.mStackTrace)
00079     {
00080     ASSERT_INVARIANT();
00081 
00082     VException::_breakpointLocation();
00083 
00084     if (recordStackTrace) {
00085         this->_recordStackTrace();
00086     }
00087 }
00088 
00089 VException::VException(int error, const char* errorMessage, bool recordStackTrace)
00090     : std::exception()
00091     , mError(error)
00092     , mErrorString()
00093     , mErrorMessage(errorMessage)
00094     , mStackTrace()
00095     {
00096     ASSERT_INVARIANT();
00097 
00098     VException::_breakpointLocation();
00099 
00100     if (recordStackTrace) {
00101         this->_recordStackTrace();
00102     }
00103 }
00104 
00105 VException::VException(int error, const VString& errorString, bool recordStackTrace)
00106     : std::exception()
00107     , mError(error)
00108     , mErrorString(errorString)
00109     , mErrorMessage(NULL)
00110     , mStackTrace()
00111     {
00112     ASSERT_INVARIANT();
00113 
00114     VException::_breakpointLocation();
00115 
00116     if (recordStackTrace) {
00117         this->_recordStackTrace();
00118     }
00119 }
00120 
00121 VException::VException(const char* errorMessage, bool recordStackTrace)
00122     : std::exception()
00123     , mError(kGenericError)
00124     , mErrorString()
00125     , mErrorMessage(errorMessage)
00126     , mStackTrace()
00127     {
00128     ASSERT_INVARIANT();
00129 
00130     VException::_breakpointLocation();
00131 
00132     if (recordStackTrace) {
00133         this->_recordStackTrace();
00134     }
00135 }
00136 
00137 VException::VException(const VString& errorString, bool recordStackTrace)
00138     : std::exception()
00139     , mError(kGenericError)
00140     , mErrorString(errorString)
00141     , mErrorMessage(NULL)
00142     , mStackTrace()
00143     {
00144     ASSERT_INVARIANT();
00145 
00146     VException::_breakpointLocation();
00147 
00148     if (recordStackTrace) {
00149         this->_recordStackTrace();
00150     }
00151 }
00152 
00153 VException::VException(const VSystemError& error, const VString& errorString, bool recordStackTrace)
00154     : std::exception()
00155     , mError(error.getErrorCode())
00156     , mErrorString(VSTRING_FORMAT("%s Error %d: %s.", errorString.chars(), error.getErrorCode(), error.getErrorMessage().chars()))
00157     , mErrorMessage(NULL)
00158     , mStackTrace()
00159     {
00160     ASSERT_INVARIANT();
00161 
00162     VException::_breakpointLocation();
00163 
00164     if (recordStackTrace) {
00165         this->_recordStackTrace();
00166     }
00167 }
00168 
00169 VException::~VException() throw() {
00170     // do NOT delete mErrorMessage, it's someone's static string constant
00171     mErrorMessage = NULL;
00172 }
00173 
00174 VException& VException::operator=(const VException& other) {
00175     ASSERT_INVARIANT();
00176 
00177     mError = other.getError();
00178     mErrorString = other.mErrorString;
00179     mErrorMessage = other.mErrorMessage;
00180     mStackTrace = other.mStackTrace;
00181 
00182     ASSERT_INVARIANT();
00183 
00184     return *this;
00185 }
00186 
00187 const char* VException::what() const throw() {
00188     ASSERT_INVARIANT();
00189 
00190     if (mErrorMessage == NULL)
00191         return mErrorString;
00192     else
00193         return mErrorMessage;
00194 }
00195 
00196 int VException::getError() const {
00197     ASSERT_INVARIANT();
00198 
00199     return mError;
00200 }
00201 
00202 const VStringVector& VException::getStackTrace() const {
00203     ASSERT_INVARIANT();
00204 
00205     return mStackTrace;
00206 }
00207 
00208 void VException::_assertInvariant() const {
00209     /*
00210     Either mErrorString is used, or mErrorMessage is used. I guess the
00211     real way of detecting trouble is if mErrorString contains something,
00212     and mErrorMessage is non-null, then it's a good assumption that
00213     mErrorMessage is uninitialized.
00214     */
00215     VASSERT_NOT_EQUAL(mErrorMessage, VCPP_DEBUG_BAD_POINTER_VALUE);
00216     if (mErrorString.isEmpty())
00217         VASSERT_NOT_NULL(mErrorMessage);
00218     else
00219         VASSERT_NULL(mErrorMessage);
00220 }
00221 
00222 void VException::_recordStackTrace() {
00223 #ifdef VAULT_USER_STACKCRAWL_SUPPORT
00224     // If error supplied as literal, move it to our VString error message to combine with stack trace.
00225     if (mErrorMessage != NULL) {
00226         mErrorString += mErrorMessage;
00227         mErrorMessage = NULL;
00228     }
00229 
00230     // Use a VStringLogger so we can log directly to it and then capture its lines and add them to the exception.
00231     VSharedPtr<VStringLogger> logger(new VStringLogger(VString::EMPTY(), VLoggerLevel::TRACE));
00232     VThread::logStackCrawl("Stack:", logger, false);
00233     mErrorString += VString::NATIVE_LINE_ENDING();
00234     mErrorString += logger->getLines();
00235 #endif
00236 }

Copyright ©1997-2014 Trygve Isaacson. All rights reserved. This documentation was generated with Doxygen.