2018-08-22 12:24:55 -04:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#define WIN32_LEAN_AND_MEAN
|
|
|
|
#include <Windows.h>
|
2021-06-05 02:58:53 -06:00
|
|
|
#include <concrt.h>
|
2018-08-22 12:24:55 -04:00
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
2019-06-04 15:21:04 -04:00
|
|
|
#include <deque>
|
2019-02-09 00:30:38 -05:00
|
|
|
#include <array>
|
2018-08-22 12:24:55 -04:00
|
|
|
#include <unordered_map>
|
2018-11-04 21:19:00 -05:00
|
|
|
#include <unordered_set>
|
2018-08-22 12:24:55 -04:00
|
|
|
#include <functional>
|
2018-10-31 01:20:44 -04:00
|
|
|
#include <algorithm>
|
2018-11-04 21:19:00 -05:00
|
|
|
#include <regex>
|
2018-10-31 01:20:44 -04:00
|
|
|
#include <memory>
|
2018-10-10 07:03:15 -04:00
|
|
|
#include <optional>
|
2018-08-22 12:24:55 -04:00
|
|
|
#include <thread>
|
2018-08-23 11:53:23 -04:00
|
|
|
#include <mutex>
|
2019-02-09 00:30:38 -05:00
|
|
|
#include <atomic>
|
2020-02-16 17:58:09 -07:00
|
|
|
#include <filesystem>
|
2018-09-20 21:59:07 -04:00
|
|
|
#include <cstdint>
|
2018-12-26 23:56:42 -05:00
|
|
|
#include <cassert>
|
2019-02-18 23:12:12 -05:00
|
|
|
|
2019-05-31 14:48:07 -04:00
|
|
|
#ifdef _WIN64
|
|
|
|
constexpr bool x64 = true;
|
|
|
|
#else
|
|
|
|
constexpr bool x64 = false;
|
|
|
|
#endif
|
|
|
|
|
2020-12-14 06:26:01 -07:00
|
|
|
template <typename T, typename... Xs> struct ArrayImpl { using Type = std::tuple<T, Xs...>[]; };
|
|
|
|
template <typename T> struct ArrayImpl<T> { using Type = T[]; };
|
|
|
|
template <typename... Ts> using Array = typename ArrayImpl<Ts...>::Type;
|
2019-02-18 23:12:12 -05:00
|
|
|
|
2020-12-14 06:26:01 -07:00
|
|
|
template <auto F> using Functor = std::integral_constant<std::remove_reference_t<decltype(F)>, F>; // shouldn't need remove_reference_t but MSVC is bugged
|
2019-08-07 05:18:04 -04:00
|
|
|
|
|
|
|
struct PermissivePointer
|
|
|
|
{
|
2020-12-14 06:26:01 -07:00
|
|
|
template <typename T> operator T*() { return (T*)p; }
|
2019-08-07 05:18:04 -04:00
|
|
|
void* p;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename HandleCloser = Functor<CloseHandle>>
|
|
|
|
class AutoHandle
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
AutoHandle(HANDLE h) : h(h) {}
|
|
|
|
operator HANDLE() { return h.get(); }
|
|
|
|
PHANDLE operator&() { static_assert(sizeof(*this) == sizeof(HANDLE)); assert(!h); return (PHANDLE)this; }
|
|
|
|
operator bool() { return h.get() != NULL && h.get() != INVALID_HANDLE_VALUE; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
struct HandleCleaner { void operator()(void* h) { if (h != INVALID_HANDLE_VALUE) HandleCloser()(PermissivePointer{ h }); } };
|
|
|
|
std::unique_ptr<void, HandleCleaner> h;
|
|
|
|
};
|
|
|
|
|
2019-06-10 01:49:11 -04:00
|
|
|
template<typename T, typename M = std::mutex>
|
2019-06-04 23:12:45 -04:00
|
|
|
class Synchronized
|
2019-02-18 23:12:12 -05:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
template <typename... Args>
|
2019-06-04 23:12:45 -04:00
|
|
|
Synchronized(Args&&... args) : contents(std::forward<Args>(args)...) {}
|
|
|
|
|
|
|
|
struct Locker
|
2019-02-18 23:12:12 -05:00
|
|
|
{
|
2019-06-10 01:49:11 -04:00
|
|
|
T* operator->() { return &contents; }
|
2019-06-04 23:12:45 -04:00
|
|
|
std::unique_lock<M> lock;
|
2019-06-10 01:49:11 -04:00
|
|
|
T& contents;
|
2019-06-04 23:12:45 -04:00
|
|
|
};
|
|
|
|
|
2019-06-10 01:49:11 -04:00
|
|
|
Locker Acquire() { return { std::unique_lock(m), contents }; }
|
2019-06-04 23:12:45 -04:00
|
|
|
Locker operator->() { return Acquire(); }
|
2020-12-14 06:26:01 -07:00
|
|
|
T Copy() { return Acquire().contents; }
|
2020-03-29 20:55:12 -06:00
|
|
|
|
2019-02-18 23:12:12 -05:00
|
|
|
private:
|
2019-06-10 01:49:11 -04:00
|
|
|
T contents;
|
|
|
|
M m;
|
2019-02-18 23:12:12 -05:00
|
|
|
};
|
|
|
|
|
2021-11-13 15:49:07 -07:00
|
|
|
template <typename F>
|
|
|
|
void SpawnThread(const F& f) // works in DllMain unlike std thread
|
|
|
|
{
|
|
|
|
F* copy = new F(f);
|
|
|
|
CloseHandle(CreateThread(nullptr, 0, [](void* copy)
|
|
|
|
{
|
|
|
|
(*(F*)copy)();
|
|
|
|
delete (F*)copy;
|
|
|
|
return 0UL;
|
|
|
|
}, copy, 0, nullptr));
|
|
|
|
}
|
|
|
|
|
2020-12-14 06:26:01 -07:00
|
|
|
static struct // should be inline but MSVC (linker) is bugged
|
2019-06-03 17:58:30 -04:00
|
|
|
{
|
2020-12-14 06:26:01 -07:00
|
|
|
inline static BYTE DUMMY[100];
|
|
|
|
template <typename T> operator T*() { static_assert(sizeof(T) < sizeof(DUMMY)); return (T*)DUMMY; }
|
2019-06-03 17:58:30 -04:00
|
|
|
} DUMMY;
|
|
|
|
|
2021-01-15 06:07:23 -07:00
|
|
|
inline auto Swallow = [](auto&&...) {};
|
|
|
|
|
2020-12-14 06:26:01 -07:00
|
|
|
template <typename T> std::optional<std::remove_cv_t<T>> Copy(T* ptr) { if (ptr) return *ptr; return {}; }
|
2019-06-13 04:01:29 -04:00
|
|
|
|
2020-12-14 06:26:01 -07:00
|
|
|
template <typename T> inline auto FormatArg(T arg) { return arg; }
|
|
|
|
template <typename C> inline auto FormatArg(const std::basic_string<C>& arg) { return arg.c_str(); }
|
2019-06-13 04:01:29 -04:00
|
|
|
|
2019-06-01 13:59:37 -04:00
|
|
|
#pragma warning(push)
|
|
|
|
#pragma warning(disable: 4996)
|
|
|
|
template <typename... Args>
|
2019-06-29 15:43:26 +05:30
|
|
|
inline std::string FormatString(const char* format, const Args&... args)
|
2019-06-01 13:59:37 -04:00
|
|
|
{
|
2019-06-13 04:01:29 -04:00
|
|
|
std::string buffer(snprintf(nullptr, 0, format, FormatArg(args)...), '\0');
|
|
|
|
sprintf(buffer.data(), format, FormatArg(args)...);
|
2019-06-01 13:59:37 -04:00
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename... Args>
|
2019-06-29 15:43:26 +05:30
|
|
|
inline std::wstring FormatString(const wchar_t* format, const Args&... args)
|
2019-06-01 13:59:37 -04:00
|
|
|
{
|
2019-06-13 04:01:29 -04:00
|
|
|
std::wstring buffer(_snwprintf(nullptr, 0, format, FormatArg(args)...), L'\0');
|
|
|
|
_swprintf(buffer.data(), format, FormatArg(args)...);
|
2019-06-01 13:59:37 -04:00
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
#pragma warning(pop)
|
|
|
|
|
2020-02-28 00:34:34 -07:00
|
|
|
inline std::optional<std::wstring> StringToWideString(const std::string& text, UINT encoding)
|
|
|
|
{
|
|
|
|
std::vector<wchar_t> buffer(text.size() + 1);
|
|
|
|
if (int length = MultiByteToWideChar(encoding, 0, text.c_str(), text.size() + 1, buffer.data(), buffer.size()))
|
|
|
|
return std::wstring(buffer.data(), length - 1);
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
inline std::wstring StringToWideString(const std::string& text)
|
|
|
|
{
|
|
|
|
std::vector<wchar_t> buffer(text.size() + 1);
|
|
|
|
MultiByteToWideChar(CP_UTF8, 0, text.c_str(), -1, buffer.data(), buffer.size());
|
|
|
|
return buffer.data();
|
|
|
|
}
|
|
|
|
|
|
|
|
inline std::string WideStringToString(const std::wstring& text)
|
|
|
|
{
|
|
|
|
std::vector<char> buffer((text.size() + 1) * 4);
|
|
|
|
WideCharToMultiByte(CP_UTF8, 0, text.c_str(), -1, buffer.data(), buffer.size(), nullptr, nullptr);
|
|
|
|
return buffer.data();
|
|
|
|
}
|
|
|
|
|
2020-02-11 23:34:03 -07:00
|
|
|
template <typename... Args>
|
|
|
|
inline void TEXTRACTOR_MESSAGE(const wchar_t* format, const Args&... args) { MessageBoxW(NULL, FormatString(format, args...).c_str(), L"Textractor", MB_OK); }
|
2019-09-10 18:53:55 -04:00
|
|
|
|
2020-09-09 14:54:15 -06:00
|
|
|
template <typename... Args>
|
2021-11-13 15:49:07 -07:00
|
|
|
inline void TEXTRACTOR_DEBUG(const wchar_t* format, const Args&... args) { SpawnThread([=] { TEXTRACTOR_MESSAGE(format, args...); }); }
|
2020-09-09 14:54:15 -06:00
|
|
|
|
2021-01-15 06:07:23 -07:00
|
|
|
void Localize();
|
2020-11-02 06:27:21 -07:00
|
|
|
|
2019-02-18 23:12:12 -05:00
|
|
|
#ifdef _DEBUG
|
2021-03-13 00:51:36 -07:00
|
|
|
#define TEST(...) static auto _ = CreateThread(nullptr, 0, [](auto) { __VA_ARGS__; return 0UL; }, NULL, 0, nullptr)
|
2019-02-18 23:12:12 -05:00
|
|
|
#else
|
|
|
|
#define TEST(...)
|
|
|
|
#endif
|