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 |