| Index: src/plugin/PluginDebug.cpp |
| =================================================================== |
| --- a/src/plugin/PluginDebug.cpp |
| +++ b/src/plugin/PluginDebug.cpp |
| @@ -4,6 +4,7 @@ |
| #include "PluginMutex.h" |
| #include "PluginSettings.h" |
| +#include <iomanip> |
| class CPluginDebugLock : public CPluginMutex |
| { |
| @@ -14,7 +15,7 @@ |
| public: |
| - CPluginDebugLock() : CPluginMutex("DebugFile", PLUGIN_ERROR_MUTEX_DEBUG_FILE) |
| + CPluginDebugLock() : CPluginMutex( L"DebugFile", PLUGIN_ERROR_MUTEX_DEBUG_FILE ) |
| { |
| s_criticalSectionDebugLock.Lock(); |
| } |
| @@ -27,29 +28,71 @@ |
| CComAutoCriticalSection CPluginDebugLock::s_criticalSectionDebugLock; |
| +std::wstring ABP::debug::widen( std::string s ) |
| +{ |
| + return std::wstring( s.begin(), s.end() ); |
|
sergei
2014/07/08 11:58:34
Please, get acquainted with the concept of utf-8.
Eric
2014/07/08 17:46:37
I am fully acquainted with UTF-8.
This isn't a fu
|
| +} |
| + |
| +std::string ABP::debug::narrow( std::wstring s ) |
| +{ |
| + return std::string( s.begin(), s.end() ); |
| +} |
| + |
| +void ABP::debug::truncate_source( std::wstring & src ) |
| +{ |
| + size_t len = src.length(); |
| + if ( len <= 100 ) |
| + { |
| + return; |
| + } |
| + // Preserve [0..67) length=67 |
| + // Replace [67..70) with ellipsis length=3 |
| + // Erase positions [70..len-30) length=len-100 |
| + // Preverse as shifted [len-30,len) length=30 |
| + src.replace( 67, 3, L"..." ); |
| + src.erase( 70, len - 100 ); |
| +} |
| + |
| +namespace { |
| + /** |
| + * Output a timestamp into a stream. |
| + */ |
| + void add_timestamp( std::wostream & ss ) |
| + { |
| + SYSTEMTIME st; |
| + ::GetSystemTime(&st); |
| + |
| + ss << std::setfill(L'0'); |
| + ss << std::setw(2) << st.wHour << ':'; |
| + ss << std::setw(2) << st.wMinute << ':'; |
| + ss << std::setw(2) << st.wSecond << '.'; |
| + ss << std::setw(3) << st.wMilliseconds << " - "; |
| + } |
| +} |
| #ifdef ENABLE_DEBUG_INFO |
| -void CPluginDebug::Debug(const CString& text, DWORD dwProcessId, DWORD dwThreadId) |
| +void CPluginDebug::Debug(const std::wstring & text, DWORD dwProcessId, DWORD dwThreadId) |
| +{ |
| + std::wstring t[1]; |
| + t[0] = text; |
| + CPluginDebug::Debug( t, dwProcessId, dwThreadId ); |
| +} |
| + |
| +void CPluginDebug::Debug(const std::wstring lines[], size_t n_lines, DWORD dwProcessId, DWORD dwThreadId) |
| { |
| #ifdef USE_CONSOLE |
| - CONSOLE(CT2A(text.GetString(), CP_UTF8)); |
| + // CT2A is a shared MFC/ATL macro, so we can leave it in for now |
| + CONSOLE(CT2A(text.c_str(), CP_UTF8)); |
| #endif |
| if (CPluginSettings::HasInstance()) |
| { |
| #ifdef ENABLE_DEBUG_SPLIT_FILE |
| - CPluginSettings* settings = CPluginSettings::GetInstance(); |
| - |
| - bool isWorkingThread = settings->IsWorkingThread(dwThreadId); |
| - |
| - CString processor; |
| - wchar_t tmp[10]; |
| - _itow_s(::GetCurrentProcessId(), tmp, 10); |
| - if (isWorkingThread) |
| - processor = L"tab" + CString(tmp) + L"_thread"; |
| - else |
| - processor = L"tab" + CString(tmp) + L"_ui"; |
| + std::wostringstream logfile_name; |
| + logfile_name << L"debug_tab"; |
| + logfile_name << ::GetCurrentProcessId(); |
| + logfile_name << ( ( CPluginSettings::GetInstance()->IsWorkingThread(dwThreadId) ) ? L"_thread.txt" : L"_ui.txt" ); |
| #else |
| if (dwProcessId == 0) |
| { |
| @@ -59,42 +102,26 @@ |
| { |
| dwThreadId = ::GetCurrentThreadId(); |
| } |
| + std::wstring logfile_name = L"debug.txt"; |
| +#endif |
| - CStringA processInfo; |
| - processInfo.Format("%4.4u.%4.4u - ", dwProcessId, dwThreadId); |
| + std::wostringstream prefix ; |
| + add_timestamp( prefix ); |
| +#ifndef ENABLE_DEBUG_SPLIT_FILE |
| + prefix << std::setw(4) << dwProcessId << '.'; |
| + prefix << std::setw(4) << dwThreadId << " - "; |
| #endif |
| - SYSTEMTIME st; |
| - ::GetSystemTime(&st); |
| - |
| - CStringA sysTime; |
| - sysTime.Format("%2.2d:%2.2d:%2.2d.%3.3d - ", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); |
| CPluginDebugLock lock; |
| if (lock.IsLocked()) |
| { |
| - std::ofstream debugFile; |
| - |
| -#ifdef ENABLE_DEBUG_SPLIT_FILE |
| - debugFile.open(CPluginSettings::GetDataPath(L"debug_" + processor + L".txt"), std::ios::app); |
| -#else |
| - debugFile.open(CPluginSettings::GetDataPath(L"debug.txt"), std::ios::app); |
| -#endif |
| - int pos = 0; |
| - CStringA line = text.Tokenize(L"\n\r", pos); |
| - |
| - while (pos >= 0) |
| + std::wofstream debugFile; |
| + debugFile.open(CPluginSettings::GetDataPath(logfile_name.str()), std::ios::app); |
| + for ( size_t i = 0 ; i < n_lines ; ++i ) |
| { |
| - debugFile.write(sysTime.GetBuffer(), sysTime.GetLength()); |
| -#ifndef ENABLE_DEBUG_SPLIT_FILE |
| - debugFile.write(processInfo.GetBuffer(), processInfo.GetLength()); |
| -#endif |
| - debugFile.write(line.GetBuffer(), line.GetLength()); |
| - debugFile.write("\n", 1); |
| - |
| - line = text.Tokenize(L"\n\r", pos); |
| + debugFile << prefix.str() << lines[i] << std::endl; |
| } |
| - |
| - debugFile.flush(); |
| + debugFile.close(); |
| } |
| } |
| } |
| @@ -104,17 +131,17 @@ |
| CPluginDebugLock lock; |
| if (lock.IsLocked()) |
| { |
| - ::DeleteFile(CPluginSettings::GetDataPath(L"debug.txt")); |
| - ::DeleteFile(CPluginSettings::GetDataPath(L"debug_main_ui.txt")); |
| - ::DeleteFile(CPluginSettings::GetDataPath(L"debug_main_thread.txt")); |
| + ::DeleteFile(CPluginSettings::GetDataPath(L"debug.txt").c_str()); |
| + ::DeleteFile(CPluginSettings::GetDataPath(L"debug_main_ui.txt").c_str()); |
| + ::DeleteFile(CPluginSettings::GetDataPath(L"debug_main_thread.txt").c_str()); |
| + // DEFECT: This needs to use FindFirst/FindNext, since the numbers in the file names are process ID's. |
| for (int i = 1; i <= 10; i++) |
| { |
| - CString x; |
| - x.Format(L"%d", i); |
| - |
| - ::DeleteFile(CPluginSettings::GetDataPath(L"debug_tab" + x + L"_ui.txt")); |
| - ::DeleteFile(CPluginSettings::GetDataPath(L"debug_tab" + x + L"_thread.txt")); |
| + std::wostringstream s; |
| + s << L"debug_tab" << i ; |
| + ::DeleteFile(CPluginSettings::GetDataPath(s.str() + L"_ui.txt").c_str()); |
| + ::DeleteFile(CPluginSettings::GetDataPath(s.str() + L"_thread.txt").c_str()); |
| } |
| } |
| } |
| @@ -123,27 +150,42 @@ |
| #if (defined ENABLE_DEBUG_INFO || defined ENABLE_DEBUG_SELFTEST) |
| -void CPluginDebug::DebugError(const CString& error) |
| +void CPluginDebug::DebugError(std::string error) |
| { |
| + /* |
| + * Convert the narrow string to a wide one. |
| + * This method assumes that the original string is plain ASCII, with no multibyte sequences (such as UTF-8). |
| + */ |
| + std::wstring werror (error.begin(), error.end()); |
| + |
| #ifdef ENABLE_DEBUG_ERROR |
| - Debug(error); |
| + Debug(werror); |
| #endif |
| - DEBUG_SELFTEST("********************************************************************************\n" + error + "\n********************************************************************************") |
| + std::wstring t[] = { |
| + L"********************************************************************************", |
| + werror, |
| + L"********************************************************************************", |
| + }; |
| + DEBUG_SELFTEST( t ); |
| } |
| -void CPluginDebug::DebugErrorCode(DWORD errorCode, const CString& error, DWORD dwProcessId, DWORD dwThreadId) |
| +void CPluginDebug::DebugErrorCode(DWORD errorCode, const std::wstring & error, DWORD dwProcessId, DWORD dwThreadId) |
| { |
| - CString errorCodeText; |
| - errorCodeText.Format(L"%u (0x%8.8x)", errorCode, errorCode); |
| - |
| - CString finalError = error + L". error=" + errorCodeText; |
| - |
| + std::wostringstream line; |
| + line << error << L". error="; |
| + line << errorCode << L" (0x"; |
| + line << std::setw( 8 ) << std::setfill( L'0' ) << std::hex << errorCode << L")"; |
| #ifdef ENABLE_DEBUG_ERROR |
| - Debug(finalError, dwProcessId, dwThreadId); |
| + Debug( line.str(), dwProcessId, dwThreadId ); |
| #endif |
| - DEBUG_SELFTEST(L"********************************************************************************\n" + finalError + "\n********************************************************************************") |
| + std::wstring t[] = { |
| + L"********************************************************************************", |
| + line.str(), |
| + L"********************************************************************************" |
| + }; |
| + DEBUG_SELFTEST( t ); |
| } |
| #endif |
| @@ -154,30 +196,21 @@ |
| #ifdef ENABLE_DEBUG_RESULT |
| -void CPluginDebug::DebugResult(const CString& text) |
| +void CPluginDebug::DebugResult(const std::wstring & text) |
| { |
| - SYSTEMTIME st; |
| - ::GetSystemTime(&st); |
| - |
| - CStringA sysTime; |
| - sysTime.Format("%2.2d:%2.2d:%2.2d.%3.3d - ", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); |
| - |
| - CStringA textA = text; |
| - |
| CPluginDebugLock lock; |
| if (lock.IsLocked()) |
| { |
| - std::ofstream debugFile; |
| - |
| - debugFile.open(CPluginSettings::GetDataPath("debug_result.txt"), std::ios::app); |
| - debugFile.write(sysTime.GetBuffer(), sysTime.GetLength()); |
| - debugFile.write(LPCSTR(textA), textA.GetLength()); |
| - debugFile.write("\n", 1); |
| + std::wofstream debugFile; |
| + debugFile.open(CPluginSettings::GetDataPath(L"debug_result.txt"), std::ios::app); |
| + add_timestamp( debugFile ); |
| + debugFile << text << std::endl; |
| debugFile.flush(); |
| + debugFile.close(); |
| } |
| } |
| -void CPluginDebug::DebugResultDomain(const CString& domain) |
| +void CPluginDebug::DebugResultDomain(const std::wstring & domain) |
| { |
| DebugResult(L"==========================================================================================================================================================================================="); |
| DebugResult(domain); |
| @@ -185,33 +218,33 @@ |
| } |
| -void CPluginDebug::DebugResultBlocking(const CString& type, const CString& src, const CString& domain) |
| +void CPluginDebug::DebugResultBlocking(const std::wstring & type, const std::wstring & src, const std::wstring & domain) |
| { |
| - CString srcTrunc = src; |
| - if (srcTrunc.GetLength() > 100) |
| - { |
| - srcTrunc = src.Left(67) + L"..." + src.Right(30); |
| - } |
| + std::wstring src_truncated( src ); |
| + ABP::debug::truncate_source( src_truncated ); |
| - CString blocking; |
| - blocking.Format(L"Blocked %-12s %-20s %s", type, domain.IsEmpty()? L"-" : domain, srcTrunc); |
| + std::wostringstream line; |
| + line << L"Blocked "; |
| + line << std::setw( 12 ) << std::left << type << L" "; |
| + line << std::setw( 20 ) << std::left << ( domain.empty() ? L"-" : domain ) << L" "; |
| + line << src_truncated; |
| - DebugResult(blocking); |
| + DebugResult( line.str() ); |
| } |
| -void CPluginDebug::DebugResultHiding(const CString& tag, const CString& src, const CString& filter) |
| +void CPluginDebug::DebugResultHiding(const std::wstring & tag, const std::wstring & src, const std::wstring & filter) |
| { |
| - CString srcTrunc = src; |
| - if (srcTrunc.GetLength() > 100) |
| - { |
| - srcTrunc = src.Left(67) + L"..." + src.Right(30); |
| - } |
| + std::wstring src_truncated( src ); |
| + ABP::debug::truncate_source( src_truncated ); |
| - CString blocking; |
| - blocking.Format(L"Hidden %-12s - %s %s", tag, srcTrunc, filter); |
| + std::wostringstream line; |
| + line << L"Hidden "; |
| + line << std::setw( 12 ) << std::left << tag << L" - "; |
| + line << src_truncated << L" "; |
| + line << filter; |
| - DebugResult(blocking); |
| + DebugResult( line.str() ); |
| } |
| @@ -220,7 +253,7 @@ |
| CPluginDebugLock lock; |
| if (lock.IsLocked()) |
| { |
| - ::DeleteFile(CPluginSettings::GetDataPath("debug_result.txt")); |
| + ::DeleteFile(CPluginSettings::GetDataPath(L"debug_result.txt").c_str()); |
| } |
| } |
| @@ -229,18 +262,18 @@ |
| #ifdef ENABLE_DEBUG_RESULT_IGNORED |
| -void CPluginDebug::DebugResultIgnoring(const CString& type, const CString& src, const CString& domain) |
| +void CPluginDebug::DebugResultIgnoring(const std::wstring & type, const std::wstring & src, const std::wstring & domain) |
| { |
| - CString srcTrunc = src; |
| - if (srcTrunc.GetLength() > 100) |
| - { |
| - srcTrunc = src.Left(67) + L"..." + src.Right(30); |
| - } |
| + std::wstring src_truncated( src ); |
| + ABP::debug::truncate_source( src_truncated ); |
| - CString blocking; |
| - blocking.Format(L"Ignored %-12s %s %s", type, domain.IsEmpty()? L"-" : domain, srcTrunc); |
| + std::wostringstream line; |
| + line << L"Ignored "; |
| + line << std::setw( 12 ) << std::left << type << L" "; |
| + line << ( domain.empty() ? L"-" : domain ); |
| + line << src_truncated; |
| - DebugResult(blocking); |
| + DebugResult( line.str() ); |
| } |
| #endif // ENABLE_DEBUG_RESULT_IGNORED |