Vault
4.1
|
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 }