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 00008 #ifndef vassert_h 00009 #define vassert_h 00010 00013 #include "vtypes.h" 00014 00015 #include "vstring.h" 00016 #include "vcodepoint.h" 00017 #include "vchar.h" 00018 #include "vinstant.h" 00019 #include "vcolor.h" 00020 00021 /* 00022 These macros log an error and throw a VStackTraceException containing a stack crawl if the assertion fails. 00023 00024 Note: the "do { ... } while (false)" macro syntax is the preferred way to ensure proper expansion regardless 00025 of caller's conditional branching syntax. 00026 00027 We separate out the testing of the assertion from the processing of the assertion failure so that the label 00028 supplied to the macro does not have to be evaluated in the success case. For example, a complicated string 00029 formatting operation to form the label will have no overhead until actual use in a failed assertion. 00030 00031 Usage Notes 00032 00033 The preprocessor symbol V_ASSERT_ENABLED determines whether the macros do anything at all. 00034 By default it is on if V_DEBUG is on. Normally this means for debug builds. 00035 However, if you #define V_ASSERT_ENABLED 1 then it will be on all the time. This is actually recommended. 00036 00037 The preprocessor symbol VAULT_THROW_ON_ASSERTION_FAILURE determines whether a failed assertion 00038 throws a stack trace exception in addition to logging an error. 00039 00040 You can assert any boolean condition with the VASSERT() macro. However, the more specific macros will yield 00041 more informative output when the assertion fails. For example, compare the output on failure of these two 00042 similar tests: 00043 00044 VASSERT(nameOfOwner == nameOfParticipant); 00045 Assertion failed: nameOfOwner == nameOfParticipant 00046 00047 VASSERT_EQUAL(nameOfOwner, nameOfParticipant); 00048 Equal assertion failed. (nameOfOwner = Flavio) (nameOfParticipant = Fernando) 00049 00050 You can use VASSERT_VALUE if you have a complex boolean to evaluate and want to supply a value string or other 00051 information to be included if the assertion fails, for example: 00052 VASSERT_VALUE(x == 1 || x == 20 || x > 50, x, VSTRING_INT(x)); 00053 Assertion failed: x == 1 || x == 20 || x > 50 (x = 42) 00054 Arg 1 is the boolean expression to test. 00055 Arg 2 gets stringified to form the label. (x) 00056 Arg 3 is a string used for the value. (42) 00057 00058 Another example, with good/better/best output: 00059 00060 VASSERT(balance < 100); 00061 Assertion failed: balance < 100 00062 00063 VASSERT_LESS_THAN(balance, 100); 00064 Less Than assertion failed. (balance = 250) (100 = 100) 00065 00066 VASSERT_LESS_THAN(balance, MAX_BALANCE); 00067 Less Than assertion failed. (balance = 250) (MAX_BALANCE = 100) 00068 00069 */ 00070 00071 #ifdef V_ASSERT_ACTIVE 00072 #define VASSERT(expression) do { if (!(expression)) VAssert::failedAssert(#expression, __FILE__, __LINE__); } while (false) 00073 #define VASSERT_VALUE(expression, valName, valString) do { if (!(expression)) VAssert::failedAssertValue(#expression, #valName, valString, __FILE__, __LINE__); } while (false) 00074 #define VASSERT_NULL(pointer) do { if (pointer != NULL) VAssert::failedAssertNull(pointer, #pointer, __FILE__, __LINE__); } while (false) 00075 #define VASSERT_NOT_NULL(pointer) do { if (pointer == NULL) VAssert::failedAssertNotNull(#pointer, __FILE__, __LINE__); } while (false) 00076 #define VASSERT_ZERO(i) do { if (i != 0) VAssert::failedAssertZero((Vs64)i, #i, __FILE__, __LINE__); } while (false) 00077 #define VASSERT_NON_ZERO(i) do { if (i == 0) VAssert::failedAssertNonZero(#i, __FILE__, __LINE__); } while (false) 00078 #define VASSERT_EQUAL(a, b) do { if (a != b) VAssert::failedAssertEqual(a, b, #a, #b, __FILE__, __LINE__); } while (false) 00079 #define VASSERT_NOT_EQUAL(a, b) do { if (a == b) VAssert::failedAssertNotEqual(a, #a, #b, __FILE__, __LINE__); } while (false) 00080 #define VASSERT_LESS_THAN(a, b) do { if (!(a < b)) VAssert::failedLessGreaterComparison(true, false, a, b, #a, #b, __FILE__, __LINE__); } while (false) 00081 #define VASSERT_LESS_THAN_OR_EQUAL(a, b) do { if (!(a <= b)) VAssert::failedLessGreaterComparison(true, true, a, b, #a, #b, __FILE__, __LINE__); } while (false) 00082 #define VASSERT_GREATER_THAN(a, b) do { if (!(a > b)) VAssert::failedLessGreaterComparison(false, false, a, b, #a, #b, __FILE__, __LINE__); } while (false) 00083 #define VASSERT_GREATER_THAN_OR_EQUAL(a, b) do { if (!(a >= b)) VAssert::failedLessGreaterComparison(false, true, a, b, #a, #b, __FILE__, __LINE__); } while (false) 00084 #define VASSERT_IN_RANGE(i, minVal, maxVal) do { if (!((i >= minVal) && (i <= maxVal))) VAssert::failedRangeCheck(i, minVal, maxVal, #i, #minVal, #maxVal, __FILE__, __LINE__); } while (false) 00085 #else 00086 #define VASSERT(expression) ((void) 0) 00087 #define VASSERT_VALUE(expression, valName, valString) ((void) 0) 00088 #define VASSERT_NULL(pointer) ((void) 0) 00089 #define VASSERT_NOT_NULL(pointer) ((void) 0) 00090 #define VASSERT_ZERO(i) ((void) 0) 00091 #define VASSERT_NON_ZERO(i) ((void) 0) 00092 #define VASSERT_EQUAL(a, b) ((void) 0) 00093 #define VASSERT_NOT_EQUAL(a, b) ((void) 0) 00094 #define VASSERT_LESS_THAN(a, b) ((void) 0) 00095 #define VASSERT_LESS_THAN_OR_EQUAL(a, b) ((void) 0) 00096 #define VASSERT_GREATER_THAN(a, b) ((void) 0) 00097 #define VASSERT_GREATER_THAN_OR_EQUAL(a, b) ((void) 0) 00098 #define VASSERT_IN_RANGE(i, minVal, maxVal) ((void) 0) 00099 #endif 00100 00105 class VAssert { 00106 public: 00107 00108 // Note: The reason that 'expressions' are passed as raw (const char*) rather than (const VString&) is that they are always formed 00109 // by the # stringifier from one of the macros defined above, are therefore compile-time constants, and constructing a VString to wrap 00110 // each of them as we pass them along to the string formatter would be needlessly wasteful. 00111 00112 // For convenience, each numeric non-int version of failedAssertEqual(), failedLessGreaterComparison(), and failedRangeCheck() has 00113 // an alternate where the values other than a are declared as int. This allows you to assert a non-int variable to be some int value, 00114 // e.g. VASSERT_EQUAL(x, 5) where x is not an int. Otherwise, you'd have to carefully cast int constants to particular types. 00115 00116 static void failedAssert(const char* expression, const char* file, int line); 00117 static void failedAssertValue(const char* expression, const char* valName, const VString& valString, const char* file, int line); 00118 static void failedAssertNull(const void* p, const char* expression, const char* file, int line); 00119 static void failedAssertNotNull(const char* expression, const char* file, int line); 00120 static void failedAssertZero(Vs64 i, const char* expression, const char* file, int line); // we always upcast to Vs64 00121 static void failedAssertNonZero(const char* expression, const char* file, int line); 00122 00123 static void failedAssertEqual(int a, int b, const char* expressionA, const char* expressionB, const char* file, int line); 00124 static void failedAssertEqual(unsigned int a, unsigned int b, const char* expressionA, const char* expressionB, const char* file, int line); 00125 static void failedAssertEqual(unsigned int a, int b, const char* expressionA, const char* expressionB, const char* file, int line); 00126 static void failedAssertEqual(const void* a, const void* b, const char* expressionA, const char* expressionB, const char* file, int line); 00127 static void failedAssertEqual(bool a, bool b, const char* expressionA, const char* expressionB, const char* file, int line); 00128 static void failedAssertEqual(Vs8 a, Vs8 b, const char* expressionA, const char* expressionB, const char* file, int line); 00129 static void failedAssertEqual(Vs8 a, int b, const char* expressionA, const char* expressionB, const char* file, int line); 00130 static void failedAssertEqual(Vu8 a, Vu8 b, const char* expressionA, const char* expressionB, const char* file, int line); 00131 static void failedAssertEqual(Vu8 a, int b, const char* expressionA, const char* expressionB, const char* file, int line); 00132 static void failedAssertEqual(Vs16 a, Vs16 b, const char* expressionA, const char* expressionB, const char* file, int line); 00133 static void failedAssertEqual(Vs16 a, int b, const char* expressionA, const char* expressionB, const char* file, int line); 00134 static void failedAssertEqual(Vu16 a, Vu16 b, const char* expressionA, const char* expressionB, const char* file, int line); 00135 static void failedAssertEqual(Vu16 a, int b, const char* expressionA, const char* expressionB, const char* file, int line); 00136 00137 #ifndef Vx32_IS_xINT /* don't redefine if types are same */ 00138 static void failedAssertEqual(Vs32 a, Vs32 b, const char* expressionA, const char* expressionB, const char* file, int line); 00139 static void failedAssertEqual(Vs32 a, int b, const char* expressionA, const char* expressionB, const char* file, int line); 00140 static void failedAssertEqual(Vu32 a, Vu32 b, const char* expressionA, const char* expressionB, const char* file, int line); 00141 static void failedAssertEqual(Vu32 a, int b, const char* expressionA, const char* expressionB, const char* file, int line); 00142 #endif /* not Vx32_IS_xINT */ 00143 00144 #ifndef Vx64_IS_xINT /* don't redefine if types are same */ 00145 static void failedAssertEqual(Vs64 a, Vs64 b, const char* expressionA, const char* expressionB, const char* file, int line); 00146 static void failedAssertEqual(Vs64 a, int b, const char* expressionA, const char* expressionB, const char* file, int line); 00147 static void failedAssertEqual(Vu64 a, Vu64 b, const char* expressionA, const char* expressionB, const char* file, int line); 00148 static void failedAssertEqual(Vu64 a, int b, const char* expressionA, const char* expressionB, const char* file, int line); 00149 #endif /* not Vx64_IS_xINT */ 00150 00151 static void failedAssertEqual(VDouble a, VDouble b, const char* expressionA, const char* expressionB, const char* file, int line); 00152 static void failedAssertEqual(const VString& a, const VString& b, const char* expressionA, const char* expressionB, const char* file, int line); 00153 static void failedAssertEqual(const VString& a, const char* b, const char* expressionA, const char* expressionB, const char* file, int line); 00154 static void failedAssertEqual(const char* a, const VString& b, const char* expressionA, const char* expressionB, const char* file, int line); 00155 static void failedAssertEqual(const VCodePoint& a, const VCodePoint& b, const char* expressionA, const char* expressionB, const char* file, int line); 00156 static void failedAssertEqual(const VChar& a, const VChar& b, const char* expressionA, const char* expressionB, const char* file, int line); 00157 static void failedAssertEqual(const VChar& a, char b, const char* expressionA, const char* expressionB, const char* file, int line); 00158 static void failedAssertEqual(const VDuration& a, const VDuration& b, const char* expressionA, const char* expressionB, const char* file, int line); 00159 static void failedAssertEqual(const VInstant& a, const VInstant& b, const char* expressionA, const char* expressionB, const char* file, int line); 00160 static void failedAssertEqual(const VColor& a, const VColor& b, const char* expressionA, const char* expressionB, const char* file, int line); 00161 static void failedAssertEqual(const VColorPair& a, const VColorPair& b, const char* expressionA, const char* expressionB, const char* file, int line); 00162 00163 static void failedAssertNotEqual(int val, const char* expressionA, const char* expressionB, const char* file, int line); 00164 static void failedAssertNotEqual(unsigned int val, const char* expressionA, const char* expressionB, const char* file, int line); 00165 static void failedAssertNotEqual(const void* val, const char* expressionA, const char* expressionB, const char* file, int line); 00166 static void failedAssertNotEqual(bool val, const char* expressionA, const char* expressionB, const char* file, int line); 00167 static void failedAssertNotEqual(Vs8 val, const char* expressionA, const char* expressionB, const char* file, int line); 00168 static void failedAssertNotEqual(Vu8 val, const char* expressionA, const char* expressionB, const char* file, int line); 00169 static void failedAssertNotEqual(Vs16 val, const char* expressionA, const char* expressionB, const char* file, int line); 00170 static void failedAssertNotEqual(Vu16 val, const char* expressionA, const char* expressionB, const char* file, int line); 00171 00172 #ifndef Vx32_IS_xINT /* don't redefine if types are same */ 00173 static void failedAssertNotEqual(Vs32 val, const char* expressionA, const char* expressionB, const char* file, int line); 00174 static void failedAssertNotEqual(Vu32 val, const char* expressionA, const char* expressionB, const char* file, int line); 00175 #endif /* not Vx32_IS_xINT */ 00176 00177 #ifndef Vx64_IS_xINT /* don't redefine if types are same */ 00178 static void failedAssertNotEqual(Vs64 val, const char* expressionA, const char* expressionB, const char* file, int line); 00179 static void failedAssertNotEqual(Vu64 val, const char* expressionA, const char* expressionB, const char* file, int line); 00180 #endif /* not Vx64_IS_xINT */ 00181 00182 static void failedAssertNotEqual(VDouble val, const char* expressionA, const char* expressionB, const char* file, int line); 00183 static void failedAssertNotEqual(const VString& val, const char* expressionA, const char* expressionB, const char* file, int line); 00184 static void failedAssertNotEqual(const VCodePoint& val, const char* expressionA, const char* expressionB, const char* file, int line); 00185 static void failedAssertNotEqual(const VChar& val, const char* expressionA, const char* expressionB, const char* file, int line); 00186 static void failedAssertNotEqual(const VDuration& val, const char* expressionA, const char* expressionB, const char* file, int line); 00187 static void failedAssertNotEqual(const VInstant& val, const char* expressionA, const char* expressionB, const char* file, int line); 00188 static void failedAssertNotEqual(const VColor& val, const char* expressionA, const char* expressionB, const char* file, int line); 00189 static void failedAssertNotEqual(const VColorPair& val, const char* expressionA, const char* expressionB, const char* file, int line); 00190 00191 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, int a, int b, const char* expressionA, const char* expressionB, const char* file, int line); 00192 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, unsigned int a, unsigned int b, const char* expressionA, const char* expressionB, const char* file, int line); 00193 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, unsigned int a, int b, const char* expressionA, const char* expressionB, const char* file, int line); 00194 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, Vs8 a, Vs8 b, const char* expressionA, const char* expressionB, const char* file, int line); 00195 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, Vs8 a, int b, const char* expressionA, const char* expressionB, const char* file, int line); 00196 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, Vu8 a, Vu8 b, const char* expressionA, const char* expressionB, const char* file, int line); 00197 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, Vu8 a, int b, const char* expressionA, const char* expressionB, const char* file, int line); 00198 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, Vs16 a, Vs16 b, const char* expressionA, const char* expressionB, const char* file, int line); 00199 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, Vs16 a, int b, const char* expressionA, const char* expressionB, const char* file, int line); 00200 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, Vu16 a, Vu16 b, const char* expressionA, const char* expressionB, const char* file, int line); 00201 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, Vu16 a, int b, const char* expressionA, const char* expressionB, const char* file, int line); 00202 00203 #ifndef Vx32_IS_xINT /* don't redefine if types are same */ 00204 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, Vs32 a, Vs32 b, const char* expressionA, const char* expressionB, const char* file, int line); 00205 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, Vs32 a, int b, const char* expressionA, const char* expressionB, const char* file, int line); 00206 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, Vu32 a, Vu32 b, const char* expressionA, const char* expressionB, const char* file, int line); 00207 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, Vu32 a, int b, const char* expressionA, const char* expressionB, const char* file, int line); 00208 #endif /* not Vx32_IS_xINT */ 00209 00210 #ifndef Vx64_IS_xINT /* don't redefine if types are same */ 00211 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, Vs64 a, Vs64 b, const char* expressionA, const char* expressionB, const char* file, int line); 00212 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, Vs64 a, int b, const char* expressionA, const char* expressionB, const char* file, int line); 00213 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, Vu64 a, Vu64 b, const char* expressionA, const char* expressionB, const char* file, int line); 00214 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, Vu64 a, int b, const char* expressionA, const char* expressionB, const char* file, int line); 00215 #endif /* not Vx64_IS_xINT */ 00216 00217 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, VDouble a, VDouble b, const char* expressionA, const char* expressionB, const char* file, int line); 00218 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, const VString& a, const VString& b, const char* expressionA, const char* expressionB, const char* file, int line); 00219 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, const VString& a, const char* b, const char* expressionA, const char* expressionB, const char* file, int line); 00220 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, const char* a, const VString& b, const char* expressionA, const char* expressionB, const char* file, int line); 00221 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, const VCodePoint& a, const VCodePoint& b, const char* expressionA, const char* expressionB, const char* file, int line); 00222 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, const VChar& a, const VChar& b, const char* expressionA, const char* expressionB, const char* file, int line); 00223 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, const VChar& a, char b, const char* expressionA, const char* expressionB, const char* file, int line); 00224 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, const VDuration& a, const VDuration& b, const char* expressionA, const char* expressionB, const char* file, int line); 00225 static void failedLessGreaterComparison(bool comparingLessThan, bool comparingOrEqualTo, const VInstant& a, const VInstant& b, const char* expressionA, const char* expressionB, const char* file, int line); 00226 00227 static void failedRangeCheck(int val, int minVal, int maxVal, const char* valExpression, const char* minValExpression, const char* maxValExpression, const char* file, int line); 00228 static void failedRangeCheck(unsigned int val, unsigned int minVal, unsigned int maxVal, const char* valExpression, const char* minValExpression, const char* maxValExpression, const char* file, int line); 00229 static void failedRangeCheck(unsigned int val, int minVal, int maxVal, const char* valExpression, const char* minValExpression, const char* maxValExpression, const char* file, int line); 00230 // Note: 8- and 16-bit overloads seem to be unnecessary due to up-conversion. 00231 00232 #ifndef Vx32_IS_xINT /* don't redefine if types are same */ 00233 static void failedRangeCheck(Vs32 val, Vs32 minVal, Vs32 maxVal, const char* valExpression, const char* minValExpression, const char* maxValExpression, const char* file, int line); 00234 static void failedRangeCheck(Vs32 val, int minVal, int maxVal, const char* valExpression, const char* minValExpression, const char* maxValExpression, const char* file, int line); 00235 static void failedRangeCheck(Vu32 val, Vu32 minVal, Vu32 maxVal, const char* valExpression, const char* minValExpression, const char* maxValExpression, const char* file, int line); 00236 static void failedRangeCheck(Vu32 val, int minVal, int maxVal, const char* valExpression, const char* minValExpression, const char* maxValExpression, const char* file, int line); 00237 #endif /* not Vx32_IS_xINT */ 00238 00239 #ifndef Vx64_IS_xINT /* don't redefine if types are same */ 00240 static void failedRangeCheck(Vs64 val, Vs64 minVal, Vs64 maxVal, const char* valExpression, const char* minValExpression, const char* maxValExpression, const char* file, int line); 00241 static void failedRangeCheck(Vs64 val, int minVal, int maxVal, const char* valExpression, const char* minValExpression, const char* maxValExpression, const char* file, int line); 00242 static void failedRangeCheck(Vu64 val, Vu64 minVal, Vu64 maxVal, const char* valExpression, const char* minValExpression, const char* maxValExpression, const char* file, int line); 00243 static void failedRangeCheck(Vu64 val, int minVal, int maxVal, const char* valExpression, const char* minValExpression, const char* maxValExpression, const char* file, int line); 00244 #endif /* not Vx64_IS_xINT */ 00245 00246 static void failedRangeCheck(VDouble val, VDouble minVal, VDouble maxVal, const char* valExpression, const char* minValExpression, const char* maxValExpression, const char* file, int line); 00247 static void failedRangeCheck(const VString& val, const VString& minVal, const VString& maxVal, const char* valExpression, const char* minValExpression, const char* maxValExpression, const char* file, int line); 00248 static void failedRangeCheck(const VCodePoint& val, const VCodePoint& minVal, const VCodePoint& maxVal, const char* valExpression, const char* minValExpression, const char* maxValExpression, const char* file, int line); 00249 static void failedRangeCheck(const VChar& val, const VChar& minVal, const VChar& maxVal, const char* valExpression, const char* minValExpression, const char* maxValExpression, const char* file, int line); 00250 static void failedRangeCheck(const VDuration& val, const VDuration& minVal, const VDuration& maxVal, const char* valExpression, const char* minValExpression, const char* maxValExpression, const char* file, int line); 00251 static void failedRangeCheck(const VInstant& val, const VInstant& minVal, const VInstant& maxVal, const char* valExpression, const char* minValExpression, const char* maxValExpression, const char* file, int line); 00252 00253 private: 00254 00255 VAssert() {} 00256 ~VAssert() {} 00257 }; 00258 00259 #endif /* vassert_h */