[416] | 1 | //////////////////////////////////////////////////////////// |
---|
| 2 | // Copyright (C) Roman Ryltsov, 2015 |
---|
| 3 | // Created by Roman Ryltsov roman@alax.info |
---|
| 4 | // |
---|
| 5 | // A permission to use the source code is granted as long as reference to |
---|
| 6 | // source website http://alax.info is retained. |
---|
| 7 | |
---|
| 8 | #pragma once |
---|
| 9 | |
---|
| 10 | //////////////////////////////////////////////////////////// |
---|
| 11 | // CDebugTrace, ATLTRACE, ATLTRACE2 |
---|
| 12 | |
---|
| 13 | #if !defined(_TRACELEVEL) |
---|
| 14 | #define _TRACELEVEL 4 |
---|
| 15 | #endif // !defined(_TRACELEVEL) |
---|
| 16 | |
---|
| 17 | class CDebugTraceBase |
---|
| 18 | { |
---|
| 19 | public: |
---|
| 20 | // CDebugTraceBase |
---|
| 21 | static const CHAR* ShortFileNameFromFileName(const CHAR* pszFileName) |
---|
| 22 | { |
---|
| 23 | if(pszFileName) |
---|
| 24 | { |
---|
| 25 | const CHAR* pszShortFileName = strrchr(pszFileName, '\\'); |
---|
| 26 | if(pszShortFileName) |
---|
| 27 | return pszShortFileName + 1; |
---|
| 28 | } |
---|
| 29 | return pszFileName; |
---|
| 30 | } |
---|
| 31 | }; |
---|
| 32 | |
---|
| 33 | class CDebugTrace : |
---|
| 34 | public CDebugTraceBase |
---|
| 35 | { |
---|
| 36 | private: |
---|
| 37 | LPCSTR m_pszFileName; |
---|
| 38 | INT m_nLineNumber; |
---|
| 39 | LPCSTR m_pszFunctionName; |
---|
| 40 | |
---|
| 41 | CDebugTrace& __cdecl operator = (const CDebugTrace&); // Not implemented |
---|
| 42 | |
---|
| 43 | static VOID TraceV(LPCSTR pszFileName, INT nLineNumber, LPCSTR pszFunctionName, DWORD_PTR nCategory, UINT nLevel, LPCSTR pszFormat, va_list& Arguments) |
---|
| 44 | { |
---|
| 45 | nCategory; |
---|
| 46 | nLevel; |
---|
| 47 | pszFileName = ShortFileNameFromFileName(pszFileName); |
---|
| 48 | static const SIZE_T g_nTextLength = 8 << 10; // 8 KB |
---|
| 49 | CHAR pszText[g_nTextLength] = { 0 }; |
---|
| 50 | SIZE_T nTextLength = 0; |
---|
| 51 | if(pszFileName) |
---|
| 52 | nTextLength += sprintf_s(pszText + nTextLength, _countof(pszText) - nTextLength, "%hs(%d): %hs: ", pszFileName, nLineNumber, pszFunctionName); |
---|
| 53 | nTextLength += vsprintf_s(pszText + nTextLength, _countof(pszText) - nTextLength, pszFormat, Arguments); |
---|
| 54 | OutputDebugStringA(pszText); |
---|
| 55 | } |
---|
| 56 | static VOID TraceV(LPCSTR pszFileName, INT nLineNumber, LPCSTR pszFunctionName, DWORD_PTR nCategory, UINT nLevel, LPCWSTR pszFormat, va_list& Arguments) |
---|
| 57 | { |
---|
| 58 | nCategory; |
---|
| 59 | nLevel; |
---|
| 60 | pszFileName = ShortFileNameFromFileName(pszFileName); |
---|
| 61 | static const SIZE_T g_nTextLength = 8 << 10; // 8 KB |
---|
| 62 | WCHAR pszText[g_nTextLength] = { 0 }; |
---|
| 63 | SIZE_T nTextLength = 0; |
---|
| 64 | if(pszFileName) |
---|
| 65 | nTextLength += swprintf_s(pszText + nTextLength, _countof(pszText) - nTextLength, L"%hs(%d): %hs: ", pszFileName, nLineNumber, pszFunctionName); |
---|
| 66 | nTextLength += vswprintf_s(pszText + nTextLength, _countof(pszText) - nTextLength, pszFormat, Arguments); |
---|
| 67 | OutputDebugStringW(pszText); |
---|
| 68 | } |
---|
| 69 | |
---|
| 70 | public: |
---|
[417] | 71 | // CDebugTrace |
---|
[416] | 72 | CDebugTrace(LPCSTR pszFileName, INT nLineNumber, LPCSTR pszFunctionName) : |
---|
| 73 | m_pszFileName(pszFileName), |
---|
| 74 | m_nLineNumber(nLineNumber), |
---|
| 75 | m_pszFunctionName(pszFunctionName) |
---|
| 76 | { |
---|
| 77 | } |
---|
| 78 | __forceinline VOID __cdecl operator () (DWORD_PTR nCategory, UINT nLevel, LPCSTR pszFormat, ...) |
---|
| 79 | { |
---|
| 80 | #if defined(_DEBUG) |
---|
| 81 | if(!nCategory) |
---|
| 82 | return; |
---|
| 83 | #endif // defined(_DEBUG) |
---|
| 84 | if(nLevel > _TRACELEVEL) |
---|
| 85 | return; |
---|
| 86 | va_list Arguments; |
---|
| 87 | va_start(Arguments, pszFormat); |
---|
| 88 | __try |
---|
| 89 | { |
---|
| 90 | TraceV(m_pszFileName, m_nLineNumber, m_pszFunctionName, nCategory, nLevel, pszFormat, Arguments); |
---|
| 91 | } |
---|
| 92 | __except(EXCEPTION_EXECUTE_HANDLER) |
---|
| 93 | { |
---|
| 94 | } |
---|
| 95 | va_end(Arguments); |
---|
| 96 | } |
---|
| 97 | __forceinline VOID __cdecl operator () (LPCSTR pszFormat, ...) |
---|
| 98 | { |
---|
| 99 | //#if defined(_DEBUG) |
---|
| 100 | // if(!nCategory) |
---|
| 101 | // return; |
---|
| 102 | //#endif // defined(_DEBUG) |
---|
| 103 | //if(nLevel > _TRACELEVEL) |
---|
| 104 | // return; |
---|
| 105 | va_list Arguments; |
---|
| 106 | va_start(Arguments, pszFormat); |
---|
| 107 | __try |
---|
| 108 | { |
---|
| 109 | static const DWORD_PTR g_nCategory = 1; |
---|
| 110 | static const DWORD_PTR g_nLevel = 2; |
---|
| 111 | TraceV(m_pszFileName, m_nLineNumber, m_pszFunctionName, g_nCategory, g_nLevel, pszFormat, Arguments); |
---|
| 112 | } |
---|
| 113 | __except(EXCEPTION_EXECUTE_HANDLER) |
---|
| 114 | { |
---|
| 115 | } |
---|
| 116 | va_end(Arguments); |
---|
| 117 | } |
---|
| 118 | __forceinline VOID __cdecl operator () (DWORD_PTR nCategory, UINT nLevel, LPCWSTR pszFormat, ...) |
---|
| 119 | { |
---|
| 120 | #if defined(_DEBUG) |
---|
| 121 | if(!nCategory) |
---|
| 122 | return; |
---|
| 123 | #endif // defined(_DEBUG) |
---|
| 124 | if(nLevel > _TRACELEVEL) |
---|
| 125 | return; |
---|
| 126 | va_list Arguments; |
---|
| 127 | va_start(Arguments, pszFormat); |
---|
| 128 | __try |
---|
| 129 | { |
---|
| 130 | TraceV(m_pszFileName, m_nLineNumber, m_pszFunctionName, nCategory, nLevel, pszFormat, Arguments); |
---|
| 131 | } |
---|
| 132 | __except(EXCEPTION_EXECUTE_HANDLER) |
---|
| 133 | { |
---|
| 134 | } |
---|
| 135 | va_end(Arguments); |
---|
| 136 | } |
---|
| 137 | __forceinline VOID __cdecl operator () (LPCWSTR pszFormat, ...) |
---|
| 138 | { |
---|
| 139 | //#if defined(_DEBUG) |
---|
| 140 | // if(!nCategory) |
---|
| 141 | // return; |
---|
| 142 | //#endif // defined(_DEBUG) |
---|
| 143 | //if(nLevel > _TRACELEVEL) |
---|
| 144 | // return; |
---|
| 145 | va_list Arguments; |
---|
| 146 | va_start(Arguments, pszFormat); |
---|
| 147 | __try |
---|
| 148 | { |
---|
| 149 | static const DWORD_PTR g_nCategory = 1; |
---|
| 150 | static const DWORD_PTR g_nLevel = 2; |
---|
| 151 | TraceV(m_pszFileName, m_nLineNumber, m_pszFunctionName, g_nCategory, g_nLevel, pszFormat, Arguments); |
---|
| 152 | } |
---|
| 153 | __except(EXCEPTION_EXECUTE_HANDLER) |
---|
| 154 | { |
---|
| 155 | } |
---|
| 156 | va_end(Arguments); |
---|
| 157 | } |
---|
| 158 | }; |
---|
| 159 | |
---|
| 160 | #undef ATLTRACE |
---|
| 161 | #undef ATLTRACE2 |
---|
| 162 | #define ATLTRACE CDebugTrace(__FILE__, __LINE__, __FUNCTION__) |
---|
| 163 | #define ATLTRACE2 ATLTRACE |
---|
| 164 | |
---|
| 165 | #define _Z ATLTRACE |
---|
| 166 | #define _Z0 ATLTRACE |
---|
| 167 | #define _Z1 ATLTRACE |
---|
| 168 | #define _Z2 ATLTRACE |
---|
| 169 | #define _Z3 ATLTRACE |
---|
| 170 | #define _Z4 ATLTRACE |
---|
| 171 | #define _Z5 ATLTRACE |
---|
| 172 | #define _Z6 ATLTRACE |
---|
[417] | 173 | |
---|
[418] | 174 | //////////////////////////////////////////////////////////// |
---|
| 175 | // ATLASSERT, ATLVERIFY |
---|
| 176 | |
---|
| 177 | #undef ATLASSERT |
---|
| 178 | #undef ATLVERIFY |
---|
| 179 | #define ATLASSERT(x) { const BOOL bAssertValue = (x) != 0; if(!bAssertValue) { _ATLTRY { _Z1(atlTraceException, 1, _T("Assertion failed: %hs\n"), #x); AtlThrow(E_FAIL); } _ATLCATCHALL() { } } } |
---|
| 180 | #define ATLVERIFY(x) ATLASSERT(x) |
---|
| 181 | |
---|
| 182 | #define _A ATLASSERT |
---|
| 183 | #define _W ATLVERIFY |
---|
| 184 | |
---|
| 185 | //////////////////////////////////////////////////////////// |
---|
| 186 | // CDebugTraceContext |
---|
| 187 | |
---|
[417] | 188 | class CDebugTraceContext : |
---|
| 189 | public CDebugTraceBase |
---|
| 190 | { |
---|
| 191 | private: |
---|
| 192 | LPCSTR m_pszFileName; |
---|
| 193 | INT m_nLineNumber; |
---|
| 194 | LPCSTR m_pszFunctionName; |
---|
| 195 | CString m_sText; |
---|
| 196 | BOOL m_bTerminated; |
---|
| 197 | |
---|
| 198 | public: |
---|
| 199 | // CDebugTraceContext |
---|
| 200 | CDebugTraceContext(LPCSTR pszFileName, INT nLineNumber, LPCSTR pszFunctionName) : |
---|
| 201 | m_pszFileName(pszFileName), |
---|
| 202 | m_nLineNumber(nLineNumber), |
---|
| 203 | m_pszFunctionName(pszFunctionName), |
---|
| 204 | m_bTerminated(FALSE) |
---|
| 205 | { |
---|
| 206 | } |
---|
| 207 | ~CDebugTraceContext() |
---|
| 208 | { |
---|
| 209 | if(!m_bTerminated) |
---|
| 210 | { |
---|
| 211 | CString sText; |
---|
| 212 | sText.Format(_T("%hs(%d): %hs: Context not terminated"), ShortFileNameFromFileName(m_pszFileName), m_nLineNumber, m_pszFunctionName); |
---|
| 213 | if(!m_sText.IsEmpty()) |
---|
| 214 | sText.AppendFormat(_T(", %s"), m_sText); |
---|
| 215 | sText.Append(_T("\r\n")); |
---|
| 216 | OutputDebugString(sText); |
---|
| 217 | } |
---|
| 218 | } |
---|
| 219 | VOID Terminate() |
---|
| 220 | { |
---|
| 221 | m_bTerminated = TRUE; |
---|
| 222 | } |
---|
| 223 | __forceinline VOID __cdecl operator () (LPCSTR pszFormat, ...) |
---|
| 224 | { |
---|
| 225 | va_list Arguments; |
---|
| 226 | va_start(Arguments, pszFormat); |
---|
| 227 | CStringA sText; |
---|
| 228 | sText.FormatV(pszFormat, Arguments); |
---|
| 229 | m_sText.Append(CString(sText)); |
---|
| 230 | va_end(Arguments); |
---|
| 231 | } |
---|
| 232 | __forceinline VOID __cdecl operator () (LPCWSTR pszFormat, ...) |
---|
| 233 | { |
---|
| 234 | va_list Arguments; |
---|
| 235 | va_start(Arguments, pszFormat); |
---|
| 236 | CStringW sText; |
---|
| 237 | sText.FormatV(pszFormat, Arguments); |
---|
| 238 | m_sText.Append(CString(sText)); |
---|
| 239 | va_end(Arguments); |
---|
| 240 | } |
---|
| 241 | }; |
---|
| 242 | |
---|
| 243 | #define _Y1 CDebugTraceContext DebugTraceContext(__FILE__, __LINE__, __FUNCTION__); DebugTraceContext |
---|
| 244 | #define _Y2 DebugTraceContext.Terminate |
---|