diff options
| author | Konstantin <const@const.me> | 2023-01-16 14:52:43 +0100 |
|---|---|---|
| committer | Konstantin <const@const.me> | 2023-01-16 14:52:43 +0100 |
| commit | 8c4603c73675958efc960fbd4bb599a2909d106a (patch) | |
| tree | 714dc6fc9a1672d5fd7f89676b97e10959662abc /Whisper/Utils/Logger.cpp | |
| parent | 990a8d0dbaefc996244097397259e92758b15cce (diff) | |
Source codes
Diffstat (limited to 'Whisper/Utils/Logger.cpp')
| -rw-r--r-- | Whisper/Utils/Logger.cpp | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/Whisper/Utils/Logger.cpp b/Whisper/Utils/Logger.cpp new file mode 100644 index 0000000..1b4b233 --- /dev/null +++ b/Whisper/Utils/Logger.cpp @@ -0,0 +1,240 @@ +#include "stdafx.h" +#include "Logger.h" +#include "../API/iContext.cl.h" +#include <cstdarg> +#include <atlstr.h> + +namespace +{ + wchar_t* formatMessage( HRESULT hr ) + { + wchar_t* err; + if( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + hr, + MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), + (LPTSTR)&err, + 0, + nullptr ) ) + return err; + return nullptr; + } + + class Utf + { + CStringA utf8; + CStringW utf16; + + void appendError( HRESULT hr ) + { + const wchar_t* err = formatMessage( hr ); + if( nullptr != err ) + { + utf16 += err; + LocalFree( (HLOCAL)err ); + utf16.TrimRight(); + } + else + utf16.AppendFormat( L"error code %i (0x%08X)", hr, hr ); + } + + public: + const char* print( const char* pszFormat, std::va_list va ) + { + utf8.FormatV( pszFormat, va ); + return utf8; + } + const wchar_t* print( const wchar_t* pszFormat, std::va_list va ) + { + utf16.FormatV( pszFormat, va ); + return utf16; + } + const wchar_t* upcast( const char* message, int len ) + { + int count = MultiByteToWideChar( CP_UTF8, 0, message, len, nullptr, 0 ); + if( count == 0 ) + return nullptr; + wchar_t* b = utf16.GetBufferSetLength( len + 1 ); + count = MultiByteToWideChar( CP_UTF8, 0, message, len, b, len ); + utf16.ReleaseBuffer( count ); + return utf16; + } + int utf8Length() const + { + return utf8.GetLength(); + } + const wchar_t* printError( HRESULT hr, const char* pszFormat, std::va_list va ) + { + print( pszFormat, va ); + upcast( utf8, utf8.GetLength() ); + utf16 += L": "; + appendError( hr ); + return utf16; + } + const char* downcast() + { + int count = WideCharToMultiByte( CP_UTF8, 0, utf16, utf16.GetLength(), nullptr, 0, nullptr, nullptr ); + char* s = utf8.GetBufferSetLength( count + 1 ); + count = WideCharToMultiByte( CP_UTF8, 0, utf16, utf16.GetLength(), s, count, nullptr, nullptr ); + utf8.ReleaseBufferSetLength( count ); + return utf8; + } + }; + thread_local Utf ts_utf; + using Whisper::eLoggerFlags; + + class Logger : Whisper::sLoggerSetup + { + inline bool hasFlag( eLoggerFlags bit ) const + { + return 0 != ( (uint8_t)flags & (uint8_t)bit ); + } + + bool useStdError() const + { + return hasFlag( eLoggerFlags::UseStandardError ); + } + + static void writeStdError( Whisper::eLogLevel lvl, const char* message, int len ) + { + const wchar_t* w = ts_utf.upcast( message, len ); + if( nullptr != w ) + fwprintf( stderr, L"%s\n", w ); + } + + public: + Logger() + { + memset( this, 0, sizeof( Logger ) ); + } + + bool willLog( Whisper::eLogLevel lvl ) const + { + if( (uint8_t)lvl > (uint8_t)level ) + return false; + if( useStdError() ) + return true; + return nullptr != sink; + } + + void message( Whisper::eLogLevel lvl, const char8_t* pszFormat, std::va_list va ) const + { + const char* s = ts_utf.print( (const char*)pszFormat, va ); + auto pfn = sink; + if( nullptr != pfn ) + pfn( context, lvl, s ); + if( useStdError() ) + writeStdError( lvl, s, ts_utf.utf8Length() ); + } + void message( Whisper::eLogLevel lvl, const wchar_t* pszFormat, std::va_list va ) const + { + Utf& u = ts_utf; + const wchar_t* w = u.print( pszFormat, va ); + auto pfn = sink; + if( nullptr != pfn ) + pfn( context, lvl, u.downcast() ); + if( useStdError() ) + fwprintf( stderr, L"%s\n", w ); + } + void message( Whisper::eLogLevel lvl, HRESULT hr, const char* pszFormat, std::va_list va ) const + { + if( hasFlag( eLoggerFlags::SkipFormatMessage ) ) + { + message( lvl, (const char8_t*)pszFormat, va ); + return; + } + Utf& u = ts_utf; + const wchar_t* w = ts_utf.printError( hr, (const char*)pszFormat, va ); + auto pfn = sink; + if( nullptr != pfn ) + pfn( context, lvl, u.downcast() ); + if( useStdError() ) + fwprintf( stderr, L"%s\n", w ); + } + + void operator=( const sLoggerSetup& rsi ) + { + sink = rsi.sink; + context = rsi.context; + level = rsi.level; + flags = rsi.flags; + } + }; + + static Logger s_logger; +} + +bool willLogMessage( Whisper::eLogLevel lvl ) +{ + return s_logger.willLog( lvl ); +} + +using Whisper::eLogLevel; + +#define LOG_MESSAGE_IMPL( lvl ) \ + if( !s_logger.willLog( lvl ) ) \ + return; \ + std::va_list args; \ + va_start( args, pszFormat ); \ + s_logger.message( lvl, pszFormat, args ); \ + va_end( args ); + +void logError( const char8_t* pszFormat, ... ) +{ + LOG_MESSAGE_IMPL( eLogLevel::Error ); +} +void logError16( const wchar_t* pszFormat, ... ) +{ + LOG_MESSAGE_IMPL( eLogLevel::Error ); +} +void logWarning( const char8_t* pszFormat, ... ) +{ + LOG_MESSAGE_IMPL( eLogLevel::Warning ); +} +void logWarning16( const wchar_t* pszFormat, ... ) +{ + LOG_MESSAGE_IMPL( eLogLevel::Warning ); +} +void logInfo( const char8_t* pszFormat, ... ) +{ + LOG_MESSAGE_IMPL( eLogLevel::Info ); +} +void logInfo16( const wchar_t* pszFormat, ... ) +{ + LOG_MESSAGE_IMPL( eLogLevel::Info ); +} +void logDebug( const char8_t* pszFormat, ... ) +{ + LOG_MESSAGE_IMPL( eLogLevel::Debug ); +} +void logDebug16( const wchar_t* pszFormat, ... ) +{ + LOG_MESSAGE_IMPL( eLogLevel::Debug ); +} +#undef LOG_MESSAGE_IMPL + +#define LOG_MESSAGE_IMPL( lvl ) \ + if( !s_logger.willLog( lvl ) ) \ + return; \ + std::va_list args; \ + va_start( args, pszFormat ); \ + s_logger.message( lvl, hr, (const char*)pszFormat, args ); \ + va_end( args ); + +void logErrorHr( long hr, const char8_t* pszFormat, ... ) +{ + LOG_MESSAGE_IMPL( eLogLevel::Error ); +} +void logWarningHr( long hr, const char8_t* pszFormat, ... ) +{ + LOG_MESSAGE_IMPL( eLogLevel::Warning ); +} + +#undef LOG_MESSAGE_IMPL + +// DLL entry point +HRESULT COMLIGHTCALL Whisper::setupLogger( const sLoggerSetup& setup ) +{ + s_logger = setup; + return S_OK; +}
\ No newline at end of file |
