spicetools/util/utils.h

291 lines
7.9 KiB
C++

#pragma once
#include <locale>
#include <string>
#include <vector>
#include <windows.h>
#include "logging.h"
#include "circular_buffer.h"
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define CLAMP(x, lower, upper) (MIN(upper, MAX(x, lower)))
#define ARRAY_SETB(A, k) ((A)[((k) / 8)] |= (1 << ((k) % 8)))
#define ARRAY_CLRB(A, k) ((A)[((k) / 8)] &= ~(1 << ((k) % 8)))
#define ARRAY_TSTB(A, k) ((A)[((k) / 8)] & (1 << ((k) % 8)))
#ifndef RtlOffsetToPointer
#define RtlOffsetToPointer(B, O) ((PCHAR) (((PCHAR) (B)) + ((ULONG_PTR) (O))))
#endif
static const char HEX_LOOKUP_UPPERCASE[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
const char *inet_ntop(short af, const void *src, char *dst, DWORD size);
static inline bool string_begins_with(const std::string &s, const std::string &prefix) {
return s.compare(0, prefix.size(), prefix) == 0;
}
static inline bool string_begins_with(const std::wstring &s, const std::wstring &prefix) {
return s.compare(0, prefix.size(), prefix) == 0;
}
static inline bool string_ends_with(const char *s, const char *suffix) {
if (!s || !suffix) {
return false;
}
auto len1 = strlen(s);
auto len2 = strlen(suffix);
if (len2 > len1) {
return false;
}
return strncmp(s + len1 - len2, suffix, len2) == 0;
}
static inline bool string_ends_with(const wchar_t *s, const wchar_t *suffix) {
if (!s || !suffix) {
return false;
}
auto len1 = wcslen(s);
auto len2 = wcslen(suffix);
if (len2 > len1) {
return false;
}
return wcsncmp(s + len1 - len2, suffix, len2) == 0;
}
template<class Container>
static inline void strsplit(const std::string &str, Container &cont, char delim = ' ')
{
std::istringstream ss(str);
std::string token;
while (std::getline(ss, token, delim)) {
cont.push_back(token);
}
}
static inline void strreplace(std::string &s, const std::string &search, const std::string &replace) {
size_t pos = 0;
while ((pos = s.find(search, pos)) != std::string::npos) {
s.replace(pos, search.length(), replace);
pos += replace.length();
}
}
static inline std::string strtrim(const std::string& input) {
std::string output = input;
// trim spaces
output.erase(0, output.find_first_not_of("\t\n\v\f\r "));
output.erase(output.find_last_not_of("\t\n\v\f\r ") + 1);
return output;
}
static inline std::string strtolower(const std::string& input) {
std::string output = strtrim(input);
// replace with lower case
std::transform(
output.begin(), output.end(), output.begin(),
[](unsigned char c){ return std::tolower(c); });
return output;
}
static inline int _hex2bin_helper(char input) {
if (input >= '0' && input <= '9') {
return input - '0';
}
if (input >= 'A' && input <= 'F') {
return input - 'A' + 10;
}
if (input >= 'a' && input <= 'f') {
return input - 'a' + 10;
}
return -1;
}
static inline bool hex2bin(const char *src, uint8_t *target) {
while (*src) {
if (!src[1]) {
return false;
}
auto first = _hex2bin_helper(*src) * 16;
auto second = _hex2bin_helper(src[1]);
if (first < 0 || second < 0) {
return false;
}
*(target++) = first + second;
src += 2;
}
return true;
}
template<typename T>
static inline std::string bin2hex(T data) {
std::string str;
str.reserve(sizeof(T) * 2);
for (size_t i = 0; i < sizeof(T); i++) {
auto ch = ((uint8_t *) &data)[i];
str.push_back(HEX_LOOKUP_UPPERCASE[(ch & 0xF0) >> 4]);
str.push_back(HEX_LOOKUP_UPPERCASE[ch & 0x0F]);
}
return str;
}
template<typename T>
static inline std::string bin2hex(T *data, size_t size) {
std::string str;
str.reserve(size * 2);
auto bytes = reinterpret_cast<const uint8_t *>(data);
for (size_t i = 0; i < size; i++) {
const auto ch = bytes[i];
str.push_back(HEX_LOOKUP_UPPERCASE[(ch & 0xF0) >> 4]);
str.push_back(HEX_LOOKUP_UPPERCASE[ch & 0x0F]);
}
return str;
}
template<typename T>
static inline std::string bin2hex(const std::vector<T> &data) {
std::string str;
str.reserve(data.size() * 2);
for (const auto ch : data) {
str.push_back(HEX_LOOKUP_UPPERCASE[(ch & 0xF0) >> 4]);
str.push_back(HEX_LOOKUP_UPPERCASE[ch & 0x0F]);
}
return str;
}
template<typename T>
static inline std::string bin2hex(const circular_buffer<T> &data) {
std::string str;
str.reserve(data.size() * 2);
for (size_t i = 0; i < data.size(); i++) {
const auto ch = data.peek(i);
str.push_back(HEX_LOOKUP_UPPERCASE[(ch & 0xF0) >> 4]);
str.push_back(HEX_LOOKUP_UPPERCASE[ch & 0x0F]);
}
return str;
}
static inline bool file_exists(const std::string &name) {
auto dwAttrib = GetFileAttributes(name.c_str());
return dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY);
}
static inline std::string get_window_title(HWND hWnd) {
char wnd_title[256] { 0 };
GetWindowTextA(hWnd, wnd_title, sizeof(wnd_title));
return std::string(wnd_title);
}
static inline std::string GetActiveWindowTitle() {
return get_window_title(GetForegroundWindow());
}
BOOL CALLBACK _find_window_begins_with_cb(HWND wnd, LPARAM lParam);
static inline std::vector<HWND> find_windows_beginning_with(const std::string &title) {
// get all windows
DWORD dwThreadID = GetCurrentThreadId();
HDESK hDesktop = GetThreadDesktop(dwThreadID);
std::vector<HWND> windows;
EnumDesktopWindows(hDesktop, _find_window_begins_with_cb, reinterpret_cast<LPARAM>(&windows));
// check window titles
windows.erase(
std::remove_if(
windows.begin(),
windows.end(),
[title](HWND hWnd) {
return !string_begins_with(get_window_title(hWnd), title);
}
),
windows.end()
);
// return found windows
return windows;
}
static inline HWND FindWindowBeginsWith(std::string title) {
// get all windows
DWORD dwThreadID = GetCurrentThreadId();
HDESK hDesktop = GetThreadDesktop(dwThreadID);
std::vector<HWND> windows;
EnumDesktopWindows(hDesktop, _find_window_begins_with_cb, reinterpret_cast<LPARAM>(&windows));
// check window titles
char wnd_title[256];
for (HWND hWnd : windows) {
GetWindowText(hWnd, wnd_title, sizeof(wnd_title));
if (string_begins_with(std::string(wnd_title), title)) {
return hWnd;
}
}
// nothing found
return nullptr;
}
static inline std::string get_last_error_string() {
// get error
DWORD error = GetLastError();
if (error == 0) {
return std::string();
}
// get error string
LPSTR messageBuffer = nullptr;
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr,
error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&messageBuffer,
0,
nullptr);
// return as string
std::string message(messageBuffer, size);
LocalFree(messageBuffer);
return message;
}
std::wstring s2ws(const std::string &str);
std::string ws2s(const std::wstring &wstr);
static inline std::string guid2s(const GUID guid) {
return fmt::format("{{{:08X}-{:04X}-{:04X}-{:02X}{:02X}-{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}}}",
guid.Data1, guid.Data2, guid.Data3,
guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
}
bool acquire_shutdown_privs();
void generate_ea_card(char card[17]);