#pragma once #ifdef _WIN64 constexpr bool x64 = true; #else constexpr bool x64 = false; #endif template struct ArrayImpl { using Type = std::tuple[]; }; template struct ArrayImpl { using Type = T[]; }; template using Array = typename ArrayImpl::Type; template using Functor = std::integral_constant, F>; // shouldn't need remove_reference_t but MSVC is bugged struct PermissivePointer { template operator T *() { return (T *)p; } void *p; }; template > 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 h; }; template class Synchronized { public: template Synchronized(Args &&...args) : contents(std::forward(args)...) {} struct Locker { T *operator->() { return &contents; } std::unique_lock lock; T &contents; }; Locker Acquire() { return {std::unique_lock(m), contents}; } Locker operator->() { return Acquire(); } T Copy() { return Acquire().contents; } private: T contents; M m; }; template 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)); } inline struct // should be inline but MSVC (linker) is bugged { inline static BYTE DUMMY[100]; template operator T *() { static_assert(sizeof(T) < sizeof(DUMMY)); return (T *)DUMMY; } } DUMMY; inline auto Swallow = [](auto &&...) {}; template std::optional> Copy(T *ptr) { if (ptr) return *ptr; return {}; } inline std::optional getModuleFilename(DWORD processId, HMODULE module = NULL) { std::vector buffer(MAX_PATH); if (AutoHandle<> process = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, processId)) if (GetModuleFileNameExW(process, module, buffer.data(), MAX_PATH)) return buffer.data(); return {}; } inline std::optional getModuleFilename(HMODULE module = NULL) { std::vector buffer(MAX_PATH); if (GetModuleFileNameW(module, buffer.data(), MAX_PATH)) return buffer.data(); return {}; } template struct SafeFptr { T ptr; uintptr_t errorvalue; SafeFptr(T _ptr, uintptr_t v = {NULL}) : ptr(_ptr), errorvalue(v) {} template std::invoke_result_t operator()(Args... args) { if (!ptr) return (std::invoke_result_t)(errorvalue); return ptr(std::forward(args)...); } }; namespace simplehash { enum : UINT64 { djb2_hash0 = 5381 }; inline UINT64 djb2(const UINT8 *str, UINT64 hash = djb2_hash0) { UINT8 c; while ((c = *str++)) hash = ((hash << 5) + hash) + c; // hash * 33 + c return hash; } inline UINT64 djb2_n2(const unsigned char *str, size_t len, UINT64 hash = djb2_hash0) { while (len--) hash = ((hash << 5) + hash) + (*str++); // hash * 33 + c return hash; } inline UINT64 hashByteArraySTD(const std::string &b, UINT64 h = djb2_hash0) { return djb2_n2((const unsigned char *)b.c_str(), b.size(), h); } inline UINT64 hashCharArray(const void *lp) { return djb2(reinterpret_cast(lp)); } }