43#include <source_location>
50#include <system_error>
60 std::is_integral_v<std::time_t> &&
sizeof(std::time_t) ==
sizeof(std::size_t),
61 "wrap std::time_t instead");
69#include <binary_io/file_stream.hpp>
70#include <spdlog/spdlog.h>
75 using namespace std::literals;
79 template <
class CharT>
88 class = std::enable_if_t<
89 std::is_pointer_v<T>>>
95 class = std::enable_if_t<
96 std::is_pointer_v<T>>>
102 class = std::enable_if_t<
103 std::is_pointer_v<T>>>
108 template <
class CharT, std::
size_t N>
118 static constexpr auto npos =
static_cast<std::size_t
>(-1);
135 [[nodiscard]]
consteval bool empty() const noexcept {
return this->
size() == 0; }
140 template <std::
size_t POS = 0, std::
size_t COUNT = npos>
141 [[nodiscard]]
consteval auto substr() const noexcept
143 return string < CharT, COUNT !=
npos ? COUNT : N - POS > (this->
data() + POS);
149 template <
class CharT, std::
size_t N>
150 string(
const CharT (&)[N]) ->
string<CharT, N - 1>;
154 requires(std::invocable<std::remove_reference_t<EF>>)
class scope_exit
159 explicit scope_exit(Fn&& a_fn)
noexcept(std::is_nothrow_constructible_v<EF, Fn> ||
160 std::is_nothrow_constructible_v<EF, Fn&>)
161 requires(!std::is_same_v<std::remove_cvref_t<Fn>,
scope_exit> &&
162 std::is_constructible_v<EF, Fn>)
164 static_assert(std::invocable<Fn>);
166 if constexpr (!std::is_lvalue_reference_v<Fn> &&
167 std::is_nothrow_constructible_v<EF, Fn>) {
168 _fn.emplace(std::forward<Fn>(a_fn));
176 std::is_nothrow_copy_constructible_v<EF>)
177 requires(std::is_nothrow_move_constructible_v<EF> ||
178 std::is_copy_constructible_v<EF>)
180 static_assert(!(std::is_nothrow_move_constructible_v<EF> && !std::is_move_constructible_v<EF>));
181 static_assert(!(!std::is_nothrow_move_constructible_v<EF> && !std::is_copy_constructible_v<EF>));
183 if (a_rhs.active()) {
184 if constexpr (std::is_nothrow_move_constructible_v<EF>) {
185 _fn.emplace(std::forward<EF>(*a_rhs._fn));
187 _fn.emplace(a_rhs._fn);
198 if (_fn.has_value()) {
206 [[nodiscard]]
bool active() const noexcept {
return _fn.has_value(); }
208 std::optional<std::remove_reference_t<EF>> _fn;
217 class U = std::underlying_type_t<E>>
227 using super::operator=;
228 using super::operator*;
231 template <
class... Args>
233 std::common_type_t<Args...>,
234 std::underlying_type_t<
235 std::common_type_t<Args...>>>;
245 public std::atomic_ref<T>
248 using super = std::atomic_ref<T>;
253 explicit atomic_ref(
volatile T& a_obj)
noexcept(std::is_nothrow_constructible_v<super, value_type&>) :
258 using super::operator=;
285 [[nodiscard]]
constexpr operator std::ptrdiff_t() const noexcept {
return value; }
287 [[nodiscard]]
constexpr std::ptrdiff_t
operator()() const noexcept {
return value; }
289 static constexpr auto value =
static_cast<std::ptrdiff_t
>(
sizeof(T));
295 template <
class T,
class U>
298 auto addr = a_ptr ?
reinterpret_cast<std::uintptr_t
>(a_ptr) + a_adjust : 0;
299 if constexpr (std::is_const_v<U> && std::is_volatile_v<U>) {
300 return reinterpret_cast<std::add_cv_t<T>*
>(addr);
301 }
else if constexpr (std::is_const_v<U>) {
302 return reinterpret_cast<std::add_const_t<T>*
>(addr);
303 }
else if constexpr (std::is_volatile_v<U>) {
304 return reinterpret_cast<std::add_volatile_t<T>*
>(addr);
306 return reinterpret_cast<T*
>(addr);
313 reinterpret_cast<std::uintptr_t*
>(a_ptr)[0] = T::VTABLE[0].address();
317 void memzero(
volatile T* a_ptr, std::size_t a_size =
sizeof(T))
319 const auto begin =
reinterpret_cast<volatile char*
>(a_ptr);
320 constexpr char val{ 0 };
321 std::fill_n(begin, a_size, val);
324 template <
class... Args>
326 requires(std::same_as<std::remove_cv_t<Args>,
bool>&&...)
328 constexpr auto ARGC =
sizeof...(Args);
330 std::bitset<ARGC> bits;
332 ((bits[i++] = a_args), ...);
334 if constexpr (ARGC <= std::numeric_limits<unsigned long>::digits) {
335 return bits.to_ulong();
336 }
else if constexpr (ARGC <= std::numeric_limits<unsigned long long>::digits) {
337 return bits.to_ullong();
339 static_assert(
false &&
sizeof...(Args));
344 -> std::optional<std::wstring>
346 const auto cvt = [&](
wchar_t* a_dst, std::size_t a_length) {
351 static_cast<int>(a_in.length()),
353 static_cast<int>(a_length));
356 const auto len = cvt(
nullptr, 0);
361 std::wstring out(len,
'\0');
362 if (cvt(out.data(), out.length()) == 0) {
370 -> std::optional<std::string>
372 const auto cvt = [&](
char* a_dst, std::size_t a_length) {
377 static_cast<int>(a_in.length()),
379 static_cast<int>(a_length),
384 const auto len = cvt(
nullptr, 0);
389 std::string out(len,
'\0');
390 if (cvt(out.data(), out.length()) == 0) {
397 [[noreturn]]
inline void report_and_fail(std::string_view a_msg, std::source_location a_loc = std::source_location::current())
399 const auto body = [&]() {
400 const std::filesystem::path p = a_loc.file_name();
401 auto filename = p.lexically_normal().generic_string();
403 const std::regex r{ R
"((?:^|[\\\/])(?:include|src)[\\\/](.*)$)" };
405 if (std::regex_search(filename, matches, r)) {
406 filename = matches[1].str();
415 .value_or(L
"<character encoding error>"s);
418 const auto caption = []() {
419 std::vector<wchar_t> buf;
422 std::uint32_t result = 0;
424 buf.resize(buf.size() * 2);
428 static_cast<std::uint32_t
>(buf.size()));
429 }
while (result && result == buf.size() && buf.size() <= std::numeric_limits<std::uint32_t>::max());
431 if (result && result != buf.size()) {
432 std::filesystem::path p(buf.begin(), buf.begin() + result);
433 return p.filename().native();
442 static_cast<int>(a_loc.line()),
443 a_loc.function_name() },
444 spdlog::level::critical,
450 template <
class To,
class From>
453 if constexpr (std::is_same_v<
454 std::remove_cv_t<From>,
455 std::remove_cv_t<To>>) {
459 }
else if constexpr (std::is_reference_v<From>) {
460 return stl::unrestricted_cast<To>(std::addressof(a_from));
463 }
else if constexpr (std::is_reference_v<To>) {
466 std::remove_reference_t<To>>>(a_from);
469 }
else if constexpr (std::is_pointer_v<From> &&
470 std::is_pointer_v<To>) {
471 return static_cast<To
>(
473 static_cast<const volatile void*
>(a_from)));
474 }
else if constexpr ((std::is_pointer_v<From> && std::is_integral_v<To>) ||
475 (std::is_integral_v<From> && std::is_pointer_v<To>)) {
476 return reinterpret_cast<To
>(a_from);
480 std::remove_cv_t<std::remove_reference_t<From>> from;
481 std::remove_cv_t<std::remove_reference_t<To>> to;
484 from = std::forward<From>(a_from);
493 using namespace std::literals;
499 using namespace std::literals;
503#ifdef SKYRIM_SUPPORT_AE
504# define RELOCATION_ID(SE, AE) REL::ID(AE)
506# define RELOCATION_ID(SE, AE) REL::ID(SE)
513# define KEEP_FOR_RE() \
517# define KEEP_FOR_RE()
typename super::value_type value_type
Definition PCH.h:251
atomic_ref(volatile T &a_obj) noexcept(std::is_nothrow_constructible_v< super, value_type & >)
Definition PCH.h:253
U underlying_type
Definition PCH.h:224
E enum_type
Definition PCH.h:223
scope_exit(Fn &&a_fn) noexcept(std::is_nothrow_constructible_v< EF, Fn >||std::is_nothrow_constructible_v< EF, Fn & >)
Definition PCH.h:159
scope_exit(const scope_exit &)=delete
scope_exit(scope_exit &&a_rhs) noexcept(std::is_nothrow_move_constructible_v< EF >||std::is_nothrow_copy_constructible_v< EF >)
Definition PCH.h:175
~scope_exit() noexcept
Definition PCH.h:196
void release() noexcept
Definition PCH.h:203
std::int32_t WideCharToMultiByte(std::uint32_t a_codePage, std::uint32_t a_flags, const wchar_t *a_src, std::int32_t a_srcLen, char *a_dst, std::int32_t a_dstLen, const char *a_default, std::int32_t *a_defaultLen)
bool TerminateProcess(HANDLE a_process, std::uint32_t a_exitCode) noexcept
constexpr auto CP_UTF8
Definition KERNEL32.h:12
std::int32_t MessageBoxW(HWND a_wnd, const wchar_t *a_text, const wchar_t *a_caption, std::uint32_t a_type) noexcept
HMODULE GetCurrentModule() noexcept
std::int32_t MultiByteToWideChar(std::uint32_t a_codePage, std::uint32_t a_flags, const char *a_src, std::int32_t a_srcLen, wchar_t *a_dst, std::int32_t a_dstLen) noexcept
constexpr auto MAX_PATH
Definition BASE.h:35
std::uint32_t GetModuleFileNameW(HMODULE a_module, wchar_t *a_name, std::uint32_t a_nameLen) noexcept
HANDLE GetCurrentProcess() noexcept
Definition AbsorbEffect.h:6
T not_null
Definition PCH.h:104
To unrestricted_cast(From a_from) noexcept
Definition PCH.h:451
std::basic_string_view< CharT > basic_zstring
Definition PCH.h:80
void memzero(volatile T *a_ptr, std::size_t a_size=sizeof(T))
Definition PCH.h:317
void report_and_fail(std::string_view a_msg, std::source_location a_loc=std::source_location::current())
Definition PCH.h:397
T owner
Definition PCH.h:90
T observer
Definition PCH.h:97
auto utf16_to_utf8(std::wstring_view a_in) noexcept -> std::optional< std::string >
Definition PCH.h:369
auto pun_bits(Args... a_args)
Definition PCH.h:325
void emplace_vtable(T *a_ptr)
Definition PCH.h:311
auto adjust_pointer(U *a_ptr, std::ptrdiff_t a_adjust) noexcept
Definition PCH.h:296
auto utf8_to_utf16(std::string_view a_in) noexcept -> std::optional< std::wstring >
Definition PCH.h:343
basic_zstring< wchar_t > zwstring
Definition PCH.h:83
basic_zstring< char > zstring
Definition PCH.h:82
constexpr auto ssizeof_v
Definition PCH.h:293
consteval bool empty() const noexcept
Definition PCH.h:135
const char_type & const_reference
Definition PCH.h:115
consteval auto substr() const noexcept
Definition PCH.h:141
consteval const_reference operator[](size_type a_pos) const noexcept
Definition PCH.h:127
const char_type * const_pointer
Definition PCH.h:113
consteval const_pointer data() const noexcept
Definition PCH.h:134
std::size_t size_type
Definition PCH.h:116
char_type c[N]
Definition PCH.h:146
consteval const_reference back() const noexcept
Definition PCH.h:133
consteval string(const_pointer a_string) noexcept
Definition PCH.h:120
char_type & reference
Definition PCH.h:114
char_type * pointer
Definition PCH.h:112
static constexpr auto npos
Definition PCH.h:118
consteval size_type length() const noexcept
Definition PCH.h:137
consteval size_type size() const noexcept
Definition PCH.h:138
consteval const_reference front() const noexcept
Definition PCH.h:136
CharT char_type
Definition PCH.h:111
constexpr std::ptrdiff_t operator()() const noexcept
Definition PCH.h:287