2021-12-25 22:36:38 +01:00
|
|
|
/*-----------------------------------------------------------------------------
|
|
|
|
* _utility
|
|
|
|
*-----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
#include "core/stdafx.h"
|
|
|
|
#include "core/logdef.h"
|
|
|
|
#include "public/include/utility.h"
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For checking if a specific file exists.
|
2021-12-26 02:30:20 +01:00
|
|
|
BOOL FileExists(const char* szPath)
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
2022-04-10 19:59:34 +02:00
|
|
|
return fs::exists(szPath);
|
2021-12-25 22:36:38 +01:00
|
|
|
}
|
|
|
|
|
2022-01-04 11:53:54 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For checking if pointer is valid or bad.
|
|
|
|
BOOL IsBadReadPtrV2(void* ptr)
|
|
|
|
{
|
|
|
|
MEMORY_BASIC_INFORMATION mbi = { 0 };
|
|
|
|
if (::VirtualQuery(ptr, &mbi, sizeof(mbi)))
|
|
|
|
{
|
|
|
|
DWORD mask = (PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY);
|
|
|
|
bool b = !(mbi.Protect & mask);
|
|
|
|
// check the page is not a guard page
|
|
|
|
if (mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS)) b = true;
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-12-25 22:36:38 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For getting information about the executing module.
|
|
|
|
MODULEINFO GetModuleInfo(const char* szModule)
|
|
|
|
{
|
|
|
|
MODULEINFO modinfo = { 0 };
|
2021-12-26 02:30:20 +01:00
|
|
|
|
2022-03-04 12:22:17 +01:00
|
|
|
wchar_t szWtext[256]{};
|
|
|
|
mbstowcs(szWtext, szModule, strlen(szModule) + 1);
|
|
|
|
|
|
|
|
HMODULE hModule = GetModuleHandle(szWtext);
|
2021-12-26 02:30:20 +01:00
|
|
|
if (hModule == INVALID_HANDLE_VALUE)
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
|
|
|
return modinfo;
|
|
|
|
}
|
2022-03-04 12:22:17 +01:00
|
|
|
if (hModule)
|
|
|
|
{
|
|
|
|
GetModuleInformation(GetCurrentProcess(), hModule, &modinfo, sizeof(MODULEINFO));
|
|
|
|
}
|
2021-12-25 22:36:38 +01:00
|
|
|
return modinfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For finding a pattern in memory of the process with SIMD.
|
|
|
|
DWORD64 FindPatternSIMD(const char* szModule, const unsigned char* szPattern, const char* szMask)
|
|
|
|
{
|
|
|
|
MODULEINFO mInfo = GetModuleInfo(szModule);
|
|
|
|
DWORD64 dwBase = (DWORD64)mInfo.lpBaseOfDll;
|
|
|
|
DWORD64 dwSize = (DWORD64)mInfo.SizeOfImage;
|
|
|
|
|
|
|
|
unsigned char* pData = (unsigned char*)dwBase;
|
|
|
|
unsigned int length = (unsigned int)dwSize;
|
|
|
|
|
|
|
|
const unsigned char* end = pData + length - strlen(szMask);
|
|
|
|
int num_masks = (int)ceil((float)strlen(szMask) / (float)16);
|
2022-04-02 02:48:54 +02:00
|
|
|
int masks[64]; // 64*16 = enough masks for 1024 bytes.
|
2021-12-25 22:36:38 +01:00
|
|
|
memset(masks, 0, num_masks * sizeof(int));
|
2022-04-02 02:48:54 +02:00
|
|
|
for (int i = 0; i < num_masks; ++i)
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
2022-04-02 02:48:54 +02:00
|
|
|
for (int j = strnlen(szMask + i * 16, 16) - 1; j >= 0; --j)
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
|
|
|
if (szMask[i * 16 + j] == 'x')
|
|
|
|
{
|
|
|
|
masks[i] |= 1 << j;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
__m128i xmm1 = _mm_loadu_si128((const __m128i*) szPattern);
|
|
|
|
__m128i xmm2, xmm3, msks;
|
|
|
|
for (; pData != end; _mm_prefetch((const char*)(++pData + 64), _MM_HINT_NTA))
|
|
|
|
{
|
|
|
|
if (szPattern[0] == pData[0])
|
|
|
|
{
|
|
|
|
xmm2 = _mm_loadu_si128((const __m128i*) pData);
|
|
|
|
msks = _mm_cmpeq_epi8(xmm1, xmm2);
|
|
|
|
if ((_mm_movemask_epi8(msks) & masks[0]) == masks[0])
|
|
|
|
{
|
|
|
|
for (DWORD64 i = 1; i < num_masks; ++i)
|
|
|
|
{
|
|
|
|
xmm2 = _mm_loadu_si128((const __m128i*) (pData + i * 16));
|
|
|
|
xmm3 = _mm_loadu_si128((const __m128i*) (szPattern + i * 16));
|
|
|
|
msks = _mm_cmpeq_epi8(xmm2, xmm3);
|
|
|
|
if ((_mm_movemask_epi8(msks) & masks[i]) == masks[i])
|
|
|
|
{
|
|
|
|
if ((i + 1) == num_masks)
|
|
|
|
{
|
|
|
|
return (DWORD64)pData;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else goto cont;
|
|
|
|
}
|
|
|
|
return (DWORD64)pData;
|
|
|
|
}
|
|
|
|
}cont:;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For printing output to the debugger.
|
|
|
|
void DbgPrint(LPCSTR sFormat, ...)
|
|
|
|
{
|
|
|
|
CHAR sBuffer[512] = { 0 };
|
|
|
|
va_list sArgs = {};
|
|
|
|
|
|
|
|
// Get the variable arg pointer.
|
|
|
|
va_start(sArgs, sFormat);
|
|
|
|
|
|
|
|
// Format print the string.
|
|
|
|
int length = vsnprintf(sBuffer, sizeof(sBuffer), sFormat, sArgs);
|
|
|
|
va_end(sArgs);
|
|
|
|
|
2022-03-04 12:22:17 +01:00
|
|
|
wchar_t szWtext[512]{}; // Convert to LPCWSTR.
|
|
|
|
mbstowcs(szWtext, sBuffer, strlen(sBuffer) + 1);
|
|
|
|
|
2021-12-25 22:36:38 +01:00
|
|
|
// Output the string to the debugger.
|
2022-03-04 12:22:17 +01:00
|
|
|
OutputDebugString(szWtext);
|
2021-12-25 22:36:38 +01:00
|
|
|
}
|
|
|
|
|
2022-01-19 23:14:50 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For printing the last error to the console if any.
|
|
|
|
void PrintLastError(void)
|
|
|
|
{
|
|
|
|
DWORD errorMessageID = ::GetLastError();
|
|
|
|
if (errorMessageID != NULL)
|
|
|
|
{
|
|
|
|
LPSTR messageBuffer = nullptr;
|
|
|
|
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
|
|
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
|
|
|
|
|
|
|
|
spdlog::error("{}\n", messageBuffer);
|
|
|
|
LocalFree(messageBuffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-25 22:36:38 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2022-05-10 23:32:44 +02:00
|
|
|
// For dumping data from a buffer to a file on the disk.
|
2022-04-24 19:32:47 +02:00
|
|
|
void HexDump(const char* szHeader, const char* szLogger, const void* pData, int nSize)
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
|
|
|
static unsigned char szAscii[17] = {};
|
2022-05-16 21:41:15 +02:00
|
|
|
static std::mutex m;
|
2021-12-25 22:36:38 +01:00
|
|
|
static std::atomic<int> i = {}, j = {}, k = {};
|
|
|
|
static std::shared_ptr<spdlog::logger> logger = spdlog::get("default_logger");
|
|
|
|
|
2022-05-16 21:41:15 +02:00
|
|
|
m.lock();
|
2021-12-25 22:36:38 +01:00
|
|
|
szAscii[16] = '\0';
|
|
|
|
|
2022-04-24 19:32:47 +02:00
|
|
|
if (szLogger)
|
|
|
|
{
|
|
|
|
logger = spdlog::get(szLogger);
|
|
|
|
if (!logger)
|
|
|
|
{
|
2022-05-16 21:48:32 +02:00
|
|
|
m.unlock();
|
2022-04-24 19:32:47 +02:00
|
|
|
assert(logger == nullptr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2021-12-25 22:36:38 +01:00
|
|
|
|
|
|
|
// Add timestamp.
|
|
|
|
logger->set_level(spdlog::level::trace);
|
|
|
|
logger->set_pattern("%v [%H:%M:%S.%f]\n");
|
|
|
|
logger->trace("---------------------------------------------------------");
|
|
|
|
|
|
|
|
// Disable EOL and create block header.
|
|
|
|
logger->set_pattern("%v");
|
2022-04-24 19:32:47 +02:00
|
|
|
logger->trace("{:s} ---- LEN BYTES: {:d}\n:\n", szHeader, nSize);
|
2021-12-25 22:36:38 +01:00
|
|
|
logger->trace("-------- 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF\n");
|
|
|
|
|
|
|
|
// Output the buffer to the file.
|
|
|
|
for (i = 0; i < nSize; i++)
|
|
|
|
{
|
|
|
|
if (i % nSize == 0) { logger->trace(" 0x{:04X} ", i); }
|
|
|
|
logger->trace("{:02x} ", ((unsigned char*)pData)[i]);
|
|
|
|
|
2022-04-10 19:59:34 +02:00
|
|
|
if ((reinterpret_cast<rsig_t>(pData))[i] >= ' ' &&
|
|
|
|
(reinterpret_cast<rsig_t>(pData))[i] <= '~')
|
|
|
|
{
|
|
|
|
szAscii[i % 16] = (reinterpret_cast<rsig_t>(pData))[i];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
szAscii[i % 16] = '.';
|
|
|
|
}
|
2021-12-25 22:36:38 +01:00
|
|
|
|
|
|
|
if ((i + 1) % 8 == 0 || i + 1 == nSize)
|
|
|
|
{
|
|
|
|
logger->trace(" ");
|
|
|
|
|
|
|
|
if ((i + 1) % 16 == 0)
|
|
|
|
{
|
|
|
|
if (i + 1 == nSize)
|
|
|
|
{
|
|
|
|
logger->trace("{:s}\n", szAscii);
|
|
|
|
logger->trace("---------------------------------------------------------------------------\n");
|
|
|
|
logger->trace("\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
logger->trace("{:s}\n ", szAscii);
|
|
|
|
logger->trace("0x{:04X} ", i--);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (i + 1 == nSize)
|
|
|
|
{
|
|
|
|
szAscii[(i + 1) % 16] = '\0';
|
|
|
|
if ((i + 1) % 16 <= 8)
|
|
|
|
{
|
|
|
|
logger->trace(" ");
|
|
|
|
}
|
|
|
|
for (j = (i + 1) % 16; j < 16; j++)
|
|
|
|
{
|
|
|
|
logger->trace(" ");
|
|
|
|
}
|
|
|
|
logger->trace("{:s}\n", szAscii);
|
|
|
|
logger->trace("---------------------------------------------------------------------------\n");
|
|
|
|
logger->trace("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-05-16 21:41:15 +02:00
|
|
|
m.unlock();
|
2021-12-25 22:36:38 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
}
|
|
|
|
|
2022-05-30 01:50:21 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For removing file names from the extension.
|
|
|
|
string GetExtension(const string& svInput)
|
|
|
|
{
|
|
|
|
string::size_type nPos = svInput.rfind('.');
|
|
|
|
if (nPos != std::string::npos)
|
|
|
|
{
|
|
|
|
return svInput.substr(nPos + 1);
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For removing extensions from file names.
|
|
|
|
string RemoveExtension(const string& svInput)
|
|
|
|
{
|
|
|
|
string::size_type nPos = svInput.find_last_of(".");
|
|
|
|
if (nPos == string::npos)
|
|
|
|
{
|
|
|
|
return svInput;
|
|
|
|
}
|
|
|
|
return svInput.substr(0, nPos);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For removing the path from file names.
|
|
|
|
string GetFileName(const string& svInput, bool bRemoveExtension, bool bWindows)
|
|
|
|
{
|
|
|
|
string::size_type nPos;
|
|
|
|
if (bWindows)
|
|
|
|
{
|
|
|
|
nPos = svInput.rfind('\\');
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nPos = svInput.rfind('/');
|
|
|
|
}
|
|
|
|
if (nPos != std::string::npos)
|
|
|
|
{
|
|
|
|
if (bRemoveExtension)
|
|
|
|
{
|
|
|
|
return RemoveExtension(svInput.substr(nPos + 1));
|
|
|
|
}
|
|
|
|
return svInput.substr(nPos + 1);
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For removing file names from the path.
|
|
|
|
string RemoveFileName(const string& svInput, bool bWindows)
|
|
|
|
{
|
|
|
|
string::size_type nPos;
|
|
|
|
if (bWindows)
|
|
|
|
{
|
|
|
|
nPos = svInput.find_last_of("\\");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nPos = svInput.find_last_of("/");
|
|
|
|
}
|
|
|
|
if (nPos == string::npos)
|
|
|
|
{
|
|
|
|
return svInput;
|
|
|
|
}
|
|
|
|
return svInput.substr(0, nPos);
|
|
|
|
}
|
|
|
|
|
2022-04-10 19:59:34 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For creating directories for output streams.
|
|
|
|
string CreateDirectories(string svInput)
|
|
|
|
{
|
|
|
|
fs::path fspPathOut(svInput);
|
|
|
|
string results = fspPathOut.u8string();
|
|
|
|
|
|
|
|
StringReplace(svInput, "\\ \\", "\\");
|
|
|
|
fspPathOut = fspPathOut.parent_path();
|
|
|
|
|
|
|
|
fs::create_directories(fspPathOut);
|
|
|
|
|
|
|
|
return results;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For converting filepaths to windows filepaths.
|
|
|
|
string ConvertToWinPath(const string& svInput)
|
|
|
|
{
|
|
|
|
char szFilePath[MAX_PATH] = { 0 };
|
|
|
|
string results;
|
|
|
|
sprintf_s(szFilePath, MAX_PATH, "%s", svInput.c_str());
|
|
|
|
|
|
|
|
// Flip forward slashes in filepath to windows-style backslash
|
|
|
|
for (int i = 0; i < strlen(szFilePath); i++)
|
|
|
|
{
|
|
|
|
if (szFilePath[i] == '/')
|
|
|
|
{
|
|
|
|
szFilePath[i] = '\\';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return results = szFilePath;
|
|
|
|
}
|
|
|
|
|
2022-04-29 05:30:06 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For converting filepaths to unix filepaths.
|
|
|
|
string ConvertToUnixPath(const string& svInput)
|
|
|
|
{
|
|
|
|
char szFilePath[MAX_PATH] = { 0 };
|
|
|
|
string results;
|
|
|
|
sprintf_s(szFilePath, MAX_PATH, "%s", svInput.c_str());
|
|
|
|
|
|
|
|
// Flip forward slashes in filepath to windows-style backslash
|
|
|
|
for (int i = 0; i < strlen(szFilePath); i++)
|
|
|
|
{
|
|
|
|
if (szFilePath[i] == '\\')
|
|
|
|
{
|
|
|
|
szFilePath[i] = '/';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return results = szFilePath;
|
|
|
|
}
|
|
|
|
|
2021-12-25 22:36:38 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2022-05-30 01:50:21 +02:00
|
|
|
// For encoding data in Base64.
|
2022-04-10 19:59:34 +02:00
|
|
|
string Base64Encode(const string& svInput)
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
2022-04-10 19:59:34 +02:00
|
|
|
string results;
|
2021-12-25 22:36:38 +01:00
|
|
|
int val = 0, valb = -6;
|
|
|
|
|
2022-04-10 19:59:34 +02:00
|
|
|
for (unsigned char c : svInput)
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
|
|
|
val = (val << 8) + c;
|
|
|
|
valb += 8;
|
|
|
|
while (valb >= 0)
|
|
|
|
{
|
|
|
|
results.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(val >> valb) & 0x3F]);
|
|
|
|
valb -= 6;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (valb > -6)
|
|
|
|
{
|
|
|
|
results.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[((val << 8) >> (valb + 8)) & 0x3F]);
|
|
|
|
}
|
|
|
|
while (results.size() % 4)
|
|
|
|
{
|
|
|
|
results.push_back('=');
|
|
|
|
}
|
|
|
|
return results;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2022-05-30 01:50:21 +02:00
|
|
|
// For decoding data in Base64.
|
2022-04-10 19:59:34 +02:00
|
|
|
string Base64Decode(const string& svInput)
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
2022-04-10 19:59:34 +02:00
|
|
|
string results;
|
2021-12-25 22:36:38 +01:00
|
|
|
int val = 0, valb = -8;
|
|
|
|
|
2022-04-10 19:59:34 +02:00
|
|
|
vector<int> T(256, -1);
|
2021-12-25 22:36:38 +01:00
|
|
|
for (int i = 0; i < 64; i++)
|
|
|
|
{
|
|
|
|
T["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i;
|
|
|
|
}
|
|
|
|
|
2022-04-10 19:59:34 +02:00
|
|
|
for (unsigned char c : svInput)
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
|
|
|
if (T[c] == -1)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
val = (val << 6) + T[c];
|
|
|
|
valb += 6;
|
|
|
|
if (valb >= 0)
|
|
|
|
{
|
|
|
|
results.push_back(char((val >> valb) & 0xFF));
|
|
|
|
valb -= 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return results;
|
|
|
|
}
|
|
|
|
|
2022-05-30 01:50:21 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For encoding data in UTF8.
|
|
|
|
string UTF8Encode(const wstring& wsvInput)
|
|
|
|
{
|
|
|
|
string results;
|
|
|
|
int nLen = WideCharToMultiByte(CP_UTF8, 0, wsvInput.c_str(), wsvInput.length(), NULL, 0, NULL, NULL);
|
|
|
|
if (nLen > 0)
|
|
|
|
{
|
|
|
|
results.resize(nLen);
|
|
|
|
WideCharToMultiByte(CP_UTF8, 0, wsvInput.c_str(), wsvInput.length(), &results[0], nLen, NULL, NULL);
|
|
|
|
}
|
|
|
|
return results;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For decoding data in UTF8.
|
|
|
|
u32string UTF8Decode(const string& svInput)
|
|
|
|
{
|
|
|
|
//struct destructible_codecvt : public std::codecvt<char32_t, char, std::mbstate_t>
|
|
|
|
//{
|
|
|
|
// using std::codecvt<char32_t, char, std::mbstate_t>::codecvt;
|
|
|
|
// ~destructible_codecvt() = default;
|
|
|
|
//};
|
|
|
|
//std::wstring_convert<destructible_codecvt, char32_t> utf32_converter;
|
|
|
|
//return utf32_converter.from_bytes(svInput);
|
|
|
|
}
|
|
|
|
|
2022-05-24 02:23:37 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For checking if a string is a number.
|
|
|
|
bool StringIsDigit(const string& svInput)
|
|
|
|
{
|
|
|
|
for (char const& c : svInput)
|
|
|
|
{
|
|
|
|
if (std::isdigit(c) == 0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-04-18 16:45:26 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2022-05-10 23:32:44 +02:00
|
|
|
// For comparing input strings alphabetically.
|
2022-04-18 16:45:26 +02:00
|
|
|
bool CompareStringAlphabetically(const string& svA, const string& svB)
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
while (svA[i] != '\0' && svA[i] == svB[i])
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (svA[i] - svB[i]) < 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2022-05-10 23:32:44 +02:00
|
|
|
// For comparing input strings lexicographically.
|
2022-04-18 16:45:26 +02:00
|
|
|
bool CompareStringLexicographically(const string& svA, const string& svB)
|
|
|
|
{
|
|
|
|
return svA < svB;
|
|
|
|
}
|
|
|
|
|
2021-12-25 22:36:38 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For replacing parts of a given string.
|
2022-04-10 19:59:34 +02:00
|
|
|
bool StringReplace(string& svInput, const string& svFrom, const string& svTo)
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
2022-05-30 01:50:21 +02:00
|
|
|
string::size_type nPos = svInput.find(svFrom);
|
|
|
|
if (nPos == string::npos)
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-05-30 01:50:21 +02:00
|
|
|
svInput.replace(nPos, svFrom.length(), svTo);
|
2021-12-25 22:36:38 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-01-16 01:18:36 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For escaping special characters in a string.
|
2022-04-10 19:59:34 +02:00
|
|
|
string StringEscape(const string& svInput)
|
2022-01-16 01:18:36 +01:00
|
|
|
{
|
2022-04-10 19:59:34 +02:00
|
|
|
string results;
|
|
|
|
results.reserve(svInput.size());
|
2022-05-10 23:32:44 +02:00
|
|
|
|
2022-04-10 19:59:34 +02:00
|
|
|
for (const char c : svInput)
|
2022-01-16 01:18:36 +01:00
|
|
|
{
|
|
|
|
switch (c)
|
|
|
|
{
|
2022-01-22 15:42:35 +01:00
|
|
|
//case '\'': results += "\\'"; break;
|
2022-01-16 01:18:36 +01:00
|
|
|
case '\a': results += "\\a"; break;
|
|
|
|
case '\b': results += "\\b"; break;
|
|
|
|
case '\f': results += "\\f"; break;
|
|
|
|
case '\n': results += "\\n"; break;
|
|
|
|
case '\r': results += "\\r"; break;
|
|
|
|
case '\t': results += "\\t"; break;
|
|
|
|
case '\v': results += "\\v"; break;
|
|
|
|
default: results += c; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return results;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For unescaping special characters in a string.
|
2022-04-10 19:59:34 +02:00
|
|
|
string StringUnescape(const string& svInput)
|
2022-01-16 01:18:36 +01:00
|
|
|
{
|
2022-04-10 19:59:34 +02:00
|
|
|
string results;
|
|
|
|
results.reserve(svInput.size());
|
2022-05-10 23:32:44 +02:00
|
|
|
|
2022-04-10 19:59:34 +02:00
|
|
|
for (const char c : svInput)
|
2022-01-16 01:18:36 +01:00
|
|
|
{
|
|
|
|
switch (c)
|
|
|
|
{
|
2022-01-22 15:42:35 +01:00
|
|
|
//case '\\': results += "\'"; break;
|
2022-01-16 01:18:36 +01:00
|
|
|
case '\\a': results += "\a"; break;
|
|
|
|
case '\\b': results += "\b"; break;
|
|
|
|
case '\\f': results += "\f"; break;
|
|
|
|
case '\\n': results += "\n"; break;
|
|
|
|
case '\\r': results += "\r"; break;
|
|
|
|
case '\\t': results += "\t"; break;
|
|
|
|
case '\\v': results += "\v"; break;
|
|
|
|
default: results += c; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return results;
|
|
|
|
}
|
2022-04-10 19:59:34 +02:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For converting a string to an array of bytes.
|
|
|
|
vector<int> StringToBytes(const string& svInput, bool bNullTerminator)
|
|
|
|
{
|
|
|
|
char* pszStringStart = const_cast<char*>(svInput.c_str());
|
|
|
|
char* pszStringEnd = pszStringStart + strlen(svInput.c_str());
|
|
|
|
vector<int> vBytes = vector<int>{ };
|
|
|
|
|
|
|
|
for (char* pszCurrentByte = pszStringStart; pszCurrentByte < pszStringEnd; ++pszCurrentByte)
|
|
|
|
{
|
|
|
|
// Dereference character and push back the byte.
|
|
|
|
vBytes.push_back(*pszCurrentByte);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bNullTerminator)
|
|
|
|
{
|
|
|
|
vBytes.push_back(0x0);
|
|
|
|
}
|
|
|
|
return vBytes;
|
|
|
|
};
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For converting a string pattern with wildcards to an array of bytes.
|
|
|
|
vector<int> PatternToBytes(const string& svInput)
|
|
|
|
{
|
|
|
|
char* pszPatternStart = const_cast<char*>(svInput.c_str());
|
|
|
|
char* pszPatternEnd = pszPatternStart + strlen(svInput.c_str());
|
|
|
|
vector<int> vBytes = vector<int>{ };
|
|
|
|
|
|
|
|
for (char* pszCurrentByte = pszPatternStart; pszCurrentByte < pszPatternEnd; ++pszCurrentByte)
|
|
|
|
{
|
|
|
|
if (*pszCurrentByte == '?')
|
|
|
|
{
|
|
|
|
++pszCurrentByte;
|
|
|
|
if (*pszCurrentByte == '?')
|
|
|
|
{
|
|
|
|
++pszCurrentByte; // Skip double wildcard.
|
|
|
|
}
|
|
|
|
vBytes.push_back(-1); // Push the byte back as invalid.
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vBytes.push_back(strtoul(pszCurrentByte, &pszCurrentByte, 16));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return vBytes;
|
|
|
|
};
|
2022-04-18 05:34:21 +02:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2022-05-10 23:32:44 +02:00
|
|
|
// For converting a integer into digits.
|
2022-05-30 01:50:21 +02:00
|
|
|
vector<int> IntToDigits(int iValue)
|
2022-04-18 05:34:21 +02:00
|
|
|
{
|
2022-04-18 16:45:26 +02:00
|
|
|
vector<int> vDigits;
|
2022-05-30 01:50:21 +02:00
|
|
|
for (; iValue > 0; iValue /= 10)
|
2022-04-18 16:45:26 +02:00
|
|
|
{
|
2022-05-30 01:50:21 +02:00
|
|
|
vDigits.push_back(iValue % 10);
|
2022-04-18 16:45:26 +02:00
|
|
|
}
|
|
|
|
std::reverse(vDigits.begin(), vDigits.end());
|
|
|
|
return vDigits;
|
2022-04-18 05:34:21 +02:00
|
|
|
}
|
2022-05-10 23:32:44 +02:00
|
|
|
|
2022-05-10 23:36:01 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For printing __m128i datatypes.
|
|
|
|
void PrintM128i8(__m128i in)
|
|
|
|
{
|
|
|
|
alignas(16) uint8_t v[16];
|
|
|
|
_mm_store_si128(reinterpret_cast<__m128i*>(v), in);
|
|
|
|
printf("v16_u8: %x %x %x %x | %x %x %x %x | %x %x %x %x | %x %x %x %x\n",
|
|
|
|
v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7],
|
|
|
|
v[8], v[9], v[10], v[11], v[12], v[13], v[14], v[15]);
|
|
|
|
}
|
|
|
|
void PrintM128i16(__m128i in)
|
|
|
|
{
|
|
|
|
alignas(16) uint16_t v[8];
|
|
|
|
_mm_store_si128(reinterpret_cast<__m128i*>(v), in);
|
2022-05-16 21:48:32 +02:00
|
|
|
printf("v8_u16: %x %x | %x %x | %x %x | %x %x\n", v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
|
2022-05-10 23:36:01 +02:00
|
|
|
}
|
|
|
|
void PrintM128i32(__m128i in)
|
|
|
|
{
|
|
|
|
alignas(16) uint32_t v[4];
|
|
|
|
_mm_store_si128(reinterpret_cast<__m128i*>(v), in);
|
2022-05-16 21:48:32 +02:00
|
|
|
printf("v4_u32: %x | %x | %x | %x\n", v[0], v[1], v[2], v[3]);
|
2022-05-10 23:36:01 +02:00
|
|
|
}
|
|
|
|
void PrintM128i64(__m128i in)
|
|
|
|
{
|
|
|
|
alignas(16) uint64_t v[2]; // uint64_t might give format-string warnings with %llx; it's just long in some ABIs
|
|
|
|
_mm_store_si128(reinterpret_cast<__m128i*>(v), in);
|
|
|
|
printf("v2_u64: %llx %llx\n", v[0], v[1]);
|
|
|
|
}
|
|
|
|
|
2022-05-10 23:32:44 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For escaping the '%' character for *rintf.
|
|
|
|
string PrintPercentageEscape(const string& svInput)
|
|
|
|
{
|
|
|
|
string results;
|
|
|
|
results.reserve(svInput.size());
|
|
|
|
|
|
|
|
for (const char c : svInput)
|
|
|
|
{
|
|
|
|
switch (c)
|
|
|
|
{
|
|
|
|
case '%': results += "%%"; break;
|
|
|
|
default: results += c; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return results;
|
|
|
|
}
|