1 //------------------------------------------------------------------------ 2 // Project : SDK Base 3 // Version : 1.0 4 // 5 // Category : Helpers 6 // Filename : base/source/fdebug.h 7 // Created by : Steinberg, 1995 8 // Description : There are 2 levels of debugging messages: 9 // DEVELOPMENT During development 10 // RELEASE Program is shipping. 11 // 12 //----------------------------------------------------------------------------- 13 // LICENSE 14 // (c) 2019, Steinberg Media Technologies GmbH, All Rights Reserved 15 //----------------------------------------------------------------------------- 16 // Redistribution and use in source and binary forms, with or without modification, 17 // are permitted provided that the following conditions are met: 18 // 19 // * Redistributions of source code must retain the above copyright notice, 20 // this list of conditions and the following disclaimer. 21 // * Redistributions in binary form must reproduce the above copyright notice, 22 // this list of conditions and the following disclaimer in the documentation 23 // and/or other materials provided with the distribution. 24 // * Neither the name of the Steinberg Media Technologies nor the names of its 25 // contributors may be used to endorse or promote products derived from this 26 // software without specific prior written permission. 27 // 28 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 29 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 30 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 31 // IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 32 // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 33 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 34 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 35 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 36 // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 37 // OF THE POSSIBILITY OF SUCH DAMAGE. 38 //----------------------------------------------------------------------------- 39 40 //----------------------------------------------------------------------------- 41 /** @file base/source/fdebug.h 42 Debugging tools. 43 44 There are 2 levels of debugging messages: 45 - DEVELOPMENT 46 - During development 47 - RELEASE 48 - Program is shipping. 49 */ 50 //----------------------------------------------------------------------------- 51 #pragma once 52 53 #include "pluginterfaces/base/ftypes.h" 54 #include <string.h> 55 56 #if SMTG_OS_MACOS 57 #include <new> 58 #endif 59 60 //----------------------------------------------------------------------------- 61 // development / release 62 //----------------------------------------------------------------------------- 63 #if !defined (DEVELOPMENT) && !defined (RELEASE) 64 #ifdef _DEBUG 65 #define DEVELOPMENT 1 66 #elif defined (NDEBUG) 67 #define RELEASE 1 68 #else 69 #error DEVELOPMENT, RELEASE, _DEBUG, or NDEBUG must be defined! 70 #endif 71 #endif 72 73 //----------------------------------------------------------------------------- 74 #if SMTG_OS_WINDOWS 75 76 /** Disable compiler warning: 77 * C4291: "No matching operator delete found; memory will not be freed if initialization throws an 78 * exception. A placement new is used for which there is no placement delete." */ 79 #if DEVELOPMENT && defined(_MSC_VER) 80 #pragma warning(disable : 4291) 81 #pragma warning(disable : 4985) 82 #endif 83 84 #endif // SMTG_OS_WINDOWS 85 86 #if DEVELOPMENT 87 //----------------------------------------------------------------------------- 88 /** If "f" is not true and a debugger is present, send an error string to the debugger for display 89 and cause a breakpoint exception to occur in the current process. SMTG_ASSERT is removed 90 completely in RELEASE configuration. So do not pass methods calls to this macro that are expected 91 to exist in the RELEASE build (for method calls that need to be present in a RELEASE build, use 92 the VERIFY macros instead)*/ 93 #define SMTG_ASSERT(f) \ 94 if (!(f)) \ 95 FDebugBreak ("%s(%d) : Assert failed: %s\n", __FILE__, __LINE__, #f); 96 97 /** Send "comment" string to the debugger for display. */ 98 #define SMTG_WARNING(comment) FDebugPrint ("%s(%d) : %s\n", __FILE__, __LINE__, comment); 99 100 /** Send the last error string to the debugger for display. */ 101 #define SMTG_PRINTSYSERROR FPrintLastError (__FILE__, __LINE__); 102 103 /** If a debugger is present, send string "s" to the debugger for display and 104 cause a breakpoint exception to occur in the current process. */ 105 #define SMTG_DEBUGSTR(s) FDebugBreak (s); 106 107 /** Use VERIFY for calling methods "f" having a bool result (expecting them to return 'true') 108 The call of "f" is not removed in RELEASE builds, only the result verification. eg: SMTG_VERIFY 109 (isValid ()) */ 110 #define SMTG_VERIFY(f) SMTG_ASSERT (f) 111 112 /** Use VERIFY_IS for calling methods "f" and expect a certain result "r". 113 The call of "f" is not removed in RELEASE builds, only the result verification. eg: 114 SMTG_VERIFY_IS (callMethod (), kResultOK) */ 115 #define SMTG_VERIFY_IS(f, r) \ 116 if ((f) != (r)) \ 117 FDebugBreak ("%s(%d) : Assert failed: %s\n", __FILE__, __LINE__, #f); 118 119 /** Use VERIFY_NOT for calling methods "f" and expect the result to be anything else but "r". 120 The call of "f" is not removed in RELEASE builds, only the result verification. eg: 121 SMTG_VERIFY_NOT (callMethod (), kResultError) */ 122 #define SMTG_VERIFY_NOT(f, r) \ 123 if ((f) == (r)) \ 124 FDebugBreak ("%s(%d) : Assert failed: %s\n", __FILE__, __LINE__, #f); 125 126 /** @name Shortcut macros for sending strings to the debugger for display. 127 First parameter is always the format string (printf like). 128 */ 129 130 ///@{ 131 #define SMTG_DBPRT0(a) FDebugPrint (a); 132 #define SMTG_DBPRT1(a, b) FDebugPrint (a, b); 133 #define SMTG_DBPRT2(a, b, c) FDebugPrint (a, b, c); 134 #define SMTG_DBPRT3(a, b, c, d) FDebugPrint (a, b, c, d); 135 #define SMTG_DBPRT4(a, b, c, d, e) FDebugPrint (a, b, c, d, e); 136 #define SMTG_DBPRT5(a, b, c, d, e, f) FDebugPrint (a, b, c, d, e, f); 137 ///@} 138 139 /** @name Helper functions for the above defined macros. 140 141 You shouldn't use them directly (if you do so, don't forget "#if DEVELOPMENT")! 142 It is recommended to use the macros instead. 143 */ 144 ///@{ 145 void FDebugPrint (const char* format, ...); 146 void FDebugBreak (const char* format, ...); 147 void FPrintLastError (const char* file, int line); 148 ///@} 149 150 /** @name Provide a custom assertion handler and debug print handler, eg 151 so that we can provide an assert with a custom dialog, or redirect 152 the debug output to a file or stream. 153 */ 154 ///@{ 155 typedef bool (*AssertionHandler) (const char* message); 156 extern AssertionHandler gAssertionHandler; 157 extern AssertionHandler gPreAssertionHook; 158 typedef void (*DebugPrintLogger) (const char* message); 159 extern DebugPrintLogger gDebugPrintLogger; 160 ///@} 161 162 /** Definition of memory allocation macros: 163 Use "NEW" to allocate storage for individual objects. 164 Use "NEWVEC" to allocate storage for an array of objects. */ 165 #if SMTG_OS_MACOS 166 void* operator new (size_t, int, const char*, int); 167 void* operator new[] (size_t, int, const char*, int); 168 void operator delete (void* p, int, const char* file, int line); 169 void operator delete[] (void* p, int, const char* file, int line); 170 #ifndef NEW 171 #define NEW new (1, __FILE__, __LINE__) 172 #define NEWVEC new (1, __FILE__, __LINE__) 173 #endif 174 175 #define DEBUG_NEW DEBUG_NEW_LEAKS 176 177 #elif SMTG_OS_WINDOWS && defined(_MSC_VER) 178 #ifndef NEW 179 void* operator new (size_t, int, const char*, int); 180 #define NEW new (1, __FILE__, __LINE__) 181 #define NEWVEC new (1, __FILE__, __LINE__) 182 #endif 183 184 #else 185 #ifndef NEW 186 #define NEW new 187 #define NEWVEC new 188 #endif 189 #endif 190 191 #else 192 /** if DEVELOPMENT is not set, these macros will do nothing. */ 193 #define SMTG_ASSERT(f) 194 #define SMTG_WARNING(s) 195 #define SMTG_PRINTSYSERROR 196 #define SMTG_DEBUGSTR(s) 197 #define SMTG_VERIFY(f) f; 198 #define SMTG_VERIFY_IS(f, r) f; 199 #define SMTG_VERIFY_NOT(f, r) f; 200 201 #define SMTG_DBPRT0(a) 202 #define SMTG_DBPRT1(a, b) 203 #define SMTG_DBPRT2(a, b, c) 204 #define SMTG_DBPRT3(a, b, c, d) 205 #define SMTG_DBPRT4(a, b, c, d, e) 206 #define SMTG_DBPRT5(a, b, c, d, e, f) 207 208 #ifndef NEW 209 #define NEW new 210 #define NEWVEC new 211 212 #endif 213 #endif 214 215 #if SMTG_CPPUNIT_TESTING 216 #define SMTG_IS_TEST true 217 #else 218 #define SMTG_IS_TEST false 219 #endif 220 221 #if !SMTG_RENAME_ASSERT 222 #if SMTG_OS_WINDOWS 223 #undef ASSERT 224 #endif 225 226 #define ASSERT SMTG_ASSERT 227 #define WARNING SMTG_WARNING 228 #define DEBUGSTR SMTG_DEBUGSTR 229 #define VERIFY SMTG_VERIFY 230 #define VERIFY_IS SMTG_VERIFY_IS 231 #define VERIFY_NOT SMTG_VERIFY_NOT 232 #define PRINTSYSERROR SMTG_PRINTSYSERROR 233 234 #define DBPRT0 SMTG_DBPRT0 235 #define DBPRT1 SMTG_DBPRT1 236 #define DBPRT2 SMTG_DBPRT2 237 #define DBPRT3 SMTG_DBPRT3 238 #define DBPRT4 SMTG_DBPRT4 239 #define DBPRT5 SMTG_DBPRT5 240 #endif 241