Last active
August 2, 2021 21:05
-
-
Save dwcullop/1b8633614b1b21d14e935b557818b6de to your computer and use it in GitHub Desktop.
Debug Logging on Windows in Modern C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// DebuggingHelpers.h : Debug Logging on Windows in Modern C++ | |
// | |
// Author Name : | |
// Darrin W. Cullop ([email protected]) | |
// | |
// License : | |
// CC-BY 4.0 (https://creativecommons.org/licenses/by/4.0/) | |
// | |
// Abstract : | |
// Simple "PrintF" Logging to the Debugger on Windows. Works with ANSI and Wide Strings (use %S when mixing). | |
// Use "DebugTrace" to only emit in Debug Builds. Use "Trace" to always emit. | |
// | |
// Example Usages: | |
// dwc::Trace( "Hello, World! The number is %d!\r\n", 37 ); | |
// dwc::DebugTrace( L"Hello, World! The number is %d!\r\n", 42 ); | |
// dwc::Trace( "Received Wide String: [%S]\r\n", lpszWideString ); // Uses wide with a skinny format | |
// dwc::Trace( L"Received Wide String: [%s]\r\n", lpszWideString ); | |
// dwc::DebugTrace( L"Received Skinny String: [%S]\r\n", lpszSkinnyString ); // Uses skinny with a wide format | |
// dwc::DebugTrace( "Received Skinny String: [%s]\r\n", lpszSkinnyString ); | |
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
#pragma once | |
#include <string> | |
#include <cstdio> | |
#include <cwchar> | |
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// dwc Namespace | |
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
namespace dwc | |
{ | |
template<typename... Args> | |
inline void Trace( const char* const lpszFormat, Args&&... args ) noexcept | |
{ | |
try | |
{ | |
// Don't allocate a buffer unless extra arguments are provided | |
if constexpr ( sizeof...( args ) > 0 ) | |
{ | |
const auto charsNeeded = std::snprintf( nullptr, 0, lpszFormat, args... ); | |
auto output = std::string( charsNeeded + 1UL, '\0' ); | |
const auto charsUsed = std::snprintf( output.data(), output.size(), lpszFormat, args... ); | |
// Emit the formatted buffer | |
::OutputDebugStringA( output.c_str() ); | |
} | |
else | |
{ | |
// Only one argument provided, so just emit the string | |
::OutputDebugStringA( lpszFormat ); | |
} | |
return; | |
} | |
catch( ... ) | |
{ | |
::OutputDebugStringA( "Trace Failure!" ); | |
return; | |
} | |
} | |
template<typename... Args> | |
inline void Trace( const wchar_t* const lpszFormat, Args&&... args ) noexcept | |
{ | |
try | |
{ | |
// Don't allocate a buffer unless extra arguments are provided | |
if constexpr ( sizeof...( args ) > 0 ) | |
{ | |
const auto charsNeeded = std::swprintf( nullptr, 0, lpszFormat, args... ); | |
auto output = std::wstring( charsNeeded + 1ULL, L'\0' ); | |
const auto charsUsed = std::swprintf( output.data(), output.size(), lpszFormat, args... ); | |
// Emit the formatted buffer | |
::OutputDebugStringW( output.c_str() ); | |
} | |
else | |
{ | |
// Only one argument provided, so just emit the string | |
::OutputDebugStringW( lpszFormat ); | |
} | |
return; | |
} | |
catch (...) | |
{ | |
::OutputDebugStringW( L"Trace Failure!" ); | |
return; | |
} | |
} | |
template<typename... Args> | |
inline void DebugTrace( Args&&... args ) noexcept | |
{ | |
#if defined(_DEBUG) || defined(DEBUG) | |
// If the caller forgot something, help them out with a better error message | |
static_assert( (sizeof...( args ) > 0), "Please provide at least one parameter" ); | |
// Will dispatch to the correct overload | |
Trace( std::forward<Args>(args)... ); | |
#endif | |
} | |
////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
} // namespace dwc | |
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// End of DebuggingHelpers.h | |
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment