summaryrefslogtreecommitdiff
path: root/StormLib/test/TLogHelper.cpp
diff options
context:
space:
mode:
authorNicholas Estelami <NEstelami@users.noreply.github.com>2022-06-01 16:05:05 -0400
committerNicholas Estelami <NEstelami@users.noreply.github.com>2022-06-16 20:35:52 -0400
commitb3e299dbdee829c12ada556a1c3aa1f109a0e05b (patch)
treea6e647da673ba7df9389cb1f382a11fc8350bc23 /StormLib/test/TLogHelper.cpp
parent941c19f2c33a0d1af75a10a64fe0905387d1e440 (diff)
Replaced StormLib .lib files with source code.
Some modifications to handle backslashes and forward slashes, along with some optimizations to speed up OTR generation.
Diffstat (limited to 'StormLib/test/TLogHelper.cpp')
-rw-r--r--StormLib/test/TLogHelper.cpp441
1 files changed, 441 insertions, 0 deletions
diff --git a/StormLib/test/TLogHelper.cpp b/StormLib/test/TLogHelper.cpp
new file mode 100644
index 000000000..003b0f532
--- /dev/null
+++ b/StormLib/test/TLogHelper.cpp
@@ -0,0 +1,441 @@
+/*****************************************************************************/
+/* TLogHelper.cpp Copyright (c) Ladislav Zezula 2013 */
+/*---------------------------------------------------------------------------*/
+/* Helper class for reporting StormLib tests */
+/* This file should be included directly from StormTest.cpp using #include */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 26.11.13 1.00 Lad The first version of TLogHelper.cpp */
+/*****************************************************************************/
+
+//-----------------------------------------------------------------------------
+// Definition of the TLogHelper class
+
+class TLogHelper
+{
+ public:
+
+ TLogHelper(const char * szNewMainTitle = NULL, const TCHAR * szNewSubTitle1 = NULL, const TCHAR * szNewSubTitle2 = NULL);
+ ~TLogHelper();
+
+#if defined(UNICODE) || defined(UNICODE)
+ // TCHAR-based functions. They are only needed on UNICODE builds.
+ // On ANSI builds is TCHAR = char, so we don't need them at all
+ int PrintWithClreol(const TCHAR * szFormat, va_list argList, bool bPrintPrefix, bool bPrintLastError, bool bPrintEndOfLine);
+ void PrintProgress(const TCHAR * szFormat, ...);
+ void PrintMessage(const TCHAR * szFormat, ...);
+ int PrintErrorVa(const TCHAR * szFormat, ...);
+ int PrintError(const TCHAR * szFormat, const TCHAR * szFileName = NULL);
+#endif // defined(UNICODE) || defined(UNICODE)
+
+ // ANSI functions
+ DWORD PrintWithClreol(const char * szFormat, va_list argList, bool bPrintPrefix, bool bPrintLastError, bool bPrintEndOfLine);
+ void PrintProgress(const char * szFormat, ...);
+ void PrintMessage(const char * szFormat, ...);
+ DWORD PrintErrorVa(const char * szFormat, ...);
+ DWORD PrintError(const char * szFormat, const char * szFileName = NULL);
+
+ const char * UserString;
+ unsigned int UserCount;
+ unsigned int UserTotal;
+ bool bDontPrintResult;
+
+ protected:
+
+#if defined(UNICODE) || defined(UNICODE)
+ TCHAR * CopyFormatCharacter(TCHAR * szBuffer, const TCHAR *& szFormat);
+#endif
+ char * CopyFormatCharacter(char * szBuffer, const char *& szFormat);
+ int GetConsoleWidth();
+
+ const char * szMainTitle; // Title of the text (usually name)
+ const TCHAR * szSubTitle1; // Title of the text (can be name of the tested file)
+ const TCHAR * szSubTitle2; // Title of the text (can be name of the tested file)
+ size_t nTextLength; // Length of the previous progress message
+ bool bMessagePrinted;
+};
+
+//-----------------------------------------------------------------------------
+// String replacements for format strings
+
+#ifdef _MSC_VER
+#define I64u_t _T("%I64u")
+#define I64u_a "%I64u"
+#define I64X_t _T("%I64X")
+#define I64X_a "%I64X"
+#else
+#define I64u_t _T("%llu")
+#define I64u_a "%llu"
+#define I64X_t _T("%llX")
+#define I64X_a "%llX"
+#endif
+
+//-----------------------------------------------------------------------------
+// Constructor and destructor
+
+
+TLogHelper::TLogHelper(const char * szNewMainTitle, const TCHAR * szNewSubTitle1, const TCHAR * szNewSubTitle2)
+{
+ TCHAR szMainTitleT[0x80];
+
+ UserString = "";
+ UserCount = 1;
+ UserTotal = 1;
+
+ // Fill the test line structure
+ szMainTitle = szNewMainTitle;
+ szSubTitle1 = szNewSubTitle1;
+ szSubTitle2 = szNewSubTitle2;
+ nTextLength = 0;
+ bMessagePrinted = false;
+ bDontPrintResult = false;
+
+ // Copy the UNICODE main title
+ StringCopy(szMainTitleT, _countof(szMainTitleT), szMainTitle);
+
+ // Print the initial information
+ if(szMainTitle != NULL)
+ {
+ if(szSubTitle1 != NULL && szSubTitle2 != NULL)
+ _tprintf(_T("Running %s (%s+%s) ..."), szMainTitleT, szSubTitle1, szSubTitle2);
+ else if(szSubTitle1 != NULL)
+ _tprintf(_T("Running %s (%s) ..."), szMainTitleT, szSubTitle1);
+ else
+ _tprintf(_T("Running %s ..."), szMainTitleT);
+ }
+}
+
+TLogHelper::~TLogHelper()
+{
+ const TCHAR * szSaveSubTitle1 = szSubTitle1;
+ const TCHAR * szSaveSubTitle2 = szSubTitle2;
+ TCHAR szSaveMainTitle[0x80];
+
+ // Set both to NULL so they won't be printed
+ StringCopy(szSaveMainTitle, _countof(szSaveMainTitle), szMainTitle);
+ szSubTitle1 = NULL;
+ szSubTitle2 = NULL;
+ szMainTitle = NULL;
+
+ // Print the final information
+ if(szSaveMainTitle != NULL && bMessagePrinted == false)
+ {
+ if(bDontPrintResult == false)
+ {
+ if(szSaveSubTitle1 != NULL && szSaveSubTitle2 != NULL)
+ PrintMessage(_T("%s (%s+%s) succeeded."), szSaveMainTitle, szSaveSubTitle1, szSaveSubTitle2);
+ else if(szSaveSubTitle1 != NULL)
+ PrintMessage(_T("%s (%s) succeeded."), szSaveMainTitle, szSaveSubTitle1);
+ else
+ PrintMessage(_T("%s succeeded."), szSaveMainTitle);
+ }
+ else
+ {
+ PrintProgress(" ");
+ printf("\r");
+ }
+ }
+
+#if defined(_MSC_VER) && defined(_DEBUG)
+ if(_CrtDumpMemoryLeaks())
+ {
+ PrintMessage(_T("Memory leak(s) detected after %s.\n"), szSaveMainTitle);
+ }
+#endif // _MSC_VER
+}
+
+//-----------------------------------------------------------------------------
+// TCHAR-based functions. They are only needed on UNICODE builds.
+// On ANSI builds is TCHAR = char, so we don't need them at all
+
+#if defined(UNICODE) || defined(UNICODE)
+int TLogHelper::PrintWithClreol(const TCHAR * szFormat, va_list argList, bool bPrintPrefix, bool bPrintLastError, bool bPrintEndOfLine)
+{
+ TCHAR szFormatBuff[0x200];
+ TCHAR szMessage[0x200];
+ TCHAR * szBuffer = szFormatBuff;
+ int nRemainingWidth;
+ int nConsoleWidth = GetConsoleWidth();
+ int nLength = 0;
+ int nError = GetLastError();
+
+ // Always start the buffer with '\r'
+ *szBuffer++ = '\r';
+
+ // Print the prefix, if needed
+ if(szMainTitle != NULL && bPrintPrefix)
+ {
+ while(szMainTitle[nLength] != 0)
+ *szBuffer++ = szMainTitle[nLength++];
+
+ *szBuffer++ = ':';
+ *szBuffer++ = ' ';
+ }
+
+ // Copy the message format itself. Replace %s with "%s", unless it's (%s)
+ if(szFormat != NULL)
+ {
+ while(szFormat[0] != 0)
+ {
+ szBuffer = CopyFormatCharacter(szBuffer, szFormat);
+ }
+ }
+
+ // Append the last error
+ if(bPrintLastError)
+ {
+ nLength = _stprintf(szBuffer, _T(" (error code: %u)"), nError);
+ szBuffer += nLength;
+ }
+
+ // Create the result string
+ szBuffer[0] = 0;
+ nLength = _vstprintf(szMessage, szFormatBuff, argList);
+ szBuffer = szMessage + nLength;
+
+ // Shall we pad the string?
+ if(nLength < nConsoleWidth)
+ {
+ // Calculate the remaining width
+ nRemainingWidth = nConsoleWidth - nLength - 1;
+
+ // Pad the string with spaces to fill it up to the end of the line
+ for(int i = 0; i < nRemainingWidth; i++)
+ *szBuffer++ = 0x20;
+ }
+
+ // Put the newline, if requested
+ *szBuffer++ = bPrintEndOfLine ? '\n' : 0;
+ *szBuffer = 0;
+
+ // Remember if we printed a message
+ if(bPrintEndOfLine)
+ bMessagePrinted = true;
+
+ // Spit out the text in one single printf
+ _tprintf(_T("%s"), szMessage);
+ return nError;
+}
+
+void TLogHelper::PrintProgress(const TCHAR * szFormat, ...)
+{
+ va_list argList;
+
+ va_start(argList, szFormat);
+ PrintWithClreol(szFormat, argList, true, false, false);
+ va_end(argList);
+}
+
+void TLogHelper::PrintMessage(const TCHAR * szFormat, ...)
+{
+ va_list argList;
+
+ va_start(argList, szFormat);
+ PrintWithClreol(szFormat, argList, true, false, true);
+ va_end(argList);
+}
+
+int TLogHelper::PrintErrorVa(const TCHAR * szFormat, ...)
+{
+ va_list argList;
+ int nResult;
+
+ va_start(argList, szFormat);
+ nResult = PrintWithClreol(szFormat, argList, true, true, true);
+ va_end(argList);
+
+ return nResult;
+}
+
+int TLogHelper::PrintError(const TCHAR * szFormat, const TCHAR * szFileName)
+{
+ return PrintErrorVa(szFormat, szFileName);
+}
+#endif // defined(UNICODE) || defined(UNICODE)
+
+//-----------------------------------------------------------------------------
+// ANSI functions
+
+DWORD TLogHelper::PrintWithClreol(const char * szFormat, va_list argList, bool bPrintPrefix, bool bPrintLastError, bool bPrintEndOfLine)
+{
+ char szFormatBuff[0x200];
+ char szMessage[0x200];
+ char * szBuffer = szFormatBuff;
+ int nRemainingWidth;
+ int nConsoleWidth = GetConsoleWidth();
+ int nLength = 0;
+ DWORD dwErrCode = GetLastError();
+
+ // Always start the buffer with '\r'
+ *szBuffer++ = '\r';
+
+ // Print the prefix, if needed
+ if(szMainTitle != NULL && bPrintPrefix)
+ {
+ while(szMainTitle[nLength] != 0)
+ *szBuffer++ = (char)szMainTitle[nLength++];
+
+ *szBuffer++ = ':';
+ *szBuffer++ = ' ';
+ }
+
+ // Copy the message format itself. Replace %s with "%s", unless it's (%s)
+ if(szFormat != NULL)
+ {
+ while(szFormat[0] != 0)
+ {
+ szBuffer = CopyFormatCharacter(szBuffer, szFormat);
+ }
+ }
+
+ // Append the last error
+ if(bPrintLastError)
+ {
+ nLength = sprintf(szBuffer, " (error code: %u)", dwErrCode);
+ szBuffer += nLength;
+ }
+
+ // Create the result string
+ szBuffer[0] = 0;
+ nLength = vsprintf(szMessage, szFormatBuff, argList);
+
+ // Shall we pad the string?
+ szBuffer = szMessage + nLength;
+ if(nLength < nConsoleWidth)
+ {
+ // Calculate the remaining width
+ nRemainingWidth = nConsoleWidth - nLength - 1;
+
+ // Pad the string with spaces to fill it up to the end of the line
+ for(int i = 0; i < nRemainingWidth; i++)
+ *szBuffer++ = 0x20;
+ }
+
+ // Put the newline, if requested
+ *szBuffer++ = bPrintEndOfLine ? '\n' : '\r';
+ *szBuffer = 0;
+
+ // Remember if we printed a message
+ if(bPrintEndOfLine)
+ bMessagePrinted = true;
+
+ // Spit out the text in one single printf
+ printf("%s", szMessage);
+ return dwErrCode;
+}
+
+void TLogHelper::PrintProgress(const char * szFormat, ...)
+{
+ va_list argList;
+
+ va_start(argList, szFormat);
+ PrintWithClreol(szFormat, argList, true, false, false);
+ va_end(argList);
+}
+
+void TLogHelper::PrintMessage(const char * szFormat, ...)
+{
+ va_list argList;
+
+ va_start(argList, szFormat);
+ PrintWithClreol(szFormat, argList, true, false, true);
+ va_end(argList);
+}
+
+DWORD TLogHelper::PrintErrorVa(const char * szFormat, ...)
+{
+ va_list argList;
+ DWORD dwErrCode;
+
+ va_start(argList, szFormat);
+ dwErrCode = PrintWithClreol(szFormat, argList, true, true, true);
+ va_end(argList);
+
+ return dwErrCode;
+}
+
+DWORD TLogHelper::PrintError(const char * szFormat, const char * szFileName)
+{
+ return PrintErrorVa(szFormat, szFileName);
+}
+
+//-----------------------------------------------------------------------------
+// Protected functions
+
+#ifdef _UNICODE
+TCHAR * TLogHelper::CopyFormatCharacter(TCHAR * szBuffer, const TCHAR *& szFormat)
+{
+ static const TCHAR * szStringFormat = _T("\"%s\"");
+ static const TCHAR * szUint64Format = I64u_t;
+
+ // String format
+ if(szFormat[0] == '%')
+ {
+ if(szFormat[1] == 's' && szFormat[2] != ')')
+ {
+ _tcscpy(szBuffer, szStringFormat);
+ szFormat += 2;
+ return szBuffer + _tcslen(szStringFormat);
+ }
+
+ // Replace %I64u with the proper platform-dependent suffix
+ if(szFormat[1] == 'I' && szFormat[2] == '6' && szFormat[3] == '4' && szFormat[4] == 'u')
+ {
+ _tcscpy(szBuffer, szUint64Format);
+ szFormat += 5;
+ return szBuffer + _tcslen(szUint64Format);
+ }
+ }
+
+ // Copy the character as-is
+ *szBuffer++ = *szFormat++;
+ return szBuffer;
+}
+#endif
+
+char * TLogHelper::CopyFormatCharacter(char * szBuffer, const char *& szFormat)
+{
+ static const char * szStringFormat = "\"%s\"";
+ static const char * szUint64Format = I64u_a;
+
+ // String format
+ if(szFormat[0] == '%')
+ {
+ if(szFormat[1] == 's' && szFormat[2] != ')')
+ {
+ strcpy(szBuffer, szStringFormat);
+ szFormat += 2;
+ return szBuffer + strlen(szStringFormat);
+ }
+
+ // Replace %I64u with the proper platform-dependent suffix
+ if(szFormat[1] == 'I' && szFormat[2] == '6' && szFormat[3] == '4' && szFormat[4] == 'u')
+ {
+ strcpy(szBuffer, szUint64Format);
+ szFormat += 5;
+ return szBuffer + strlen(szUint64Format);
+ }
+ }
+
+ // Copy the character as-is
+ *szBuffer++ = *szFormat++;
+ return szBuffer;
+}
+
+int TLogHelper::GetConsoleWidth()
+{
+#ifdef STORMLIB_WINDOWS
+
+ CONSOLE_SCREEN_BUFFER_INFO ScreenInfo;
+ GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &ScreenInfo);
+ return (int)(ScreenInfo.srWindow.Right - ScreenInfo.srWindow.Left);
+
+#else
+
+ // On non-Windows platforms, we assume that width of the console line
+ // is 80 characters
+ return 120;
+
+#endif
+}