CommonLibSSE (powerof3)
Loading...
Searching...
No Matches
PCH.h
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <array>
5#include <bit>
6#include <bitset>
7#include <cassert>
8#include <cmath>
9#include <concepts>
10#include <cstdarg>
11#include <cstddef>
12#include <cstdint>
13#include <cstdio>
14#include <cstdlib>
15#include <cstring>
16#include <ctime>
17#include <cwchar>
18#include <cwctype>
19#include <exception>
20#include <execution>
21#include <filesystem>
22#include <format>
23#include <fstream>
24#include <functional>
25#include <iomanip>
26#include <ios>
27#include <istream>
28#include <iterator>
29#include <limits>
30#include <locale>
31#include <map>
32#include <memory>
33#include <mutex>
34#include <new>
35#include <numeric>
36#include <optional>
37#include <random>
38#include <regex>
39#include <set>
40#include <source_location>
41#include <span>
42#include <sstream>
43#include <stack>
44#include <stdexcept>
45#include <string>
46#include <string_view>
47#include <system_error>
48#include <thread>
49#include <tuple>
50#include <type_traits>
51#include <typeinfo>
52#include <utility>
53#include <variant>
54#include <vector>
55
56static_assert(
57 std::is_integral_v<std::time_t> && sizeof(std::time_t) == sizeof(std::size_t),
58 "wrap std::time_t instead");
59
60#pragma warning(push)
61#include <binary_io/file_stream.hpp>
62#include <boost/stl_interfaces/iterator_interface.hpp>
63#include <fmt/format.h>
64#include <spdlog/spdlog.h>
65#pragma warning(pop)
66
67#include "SKSE/Impl/WinAPI.h"
68
69namespace SKSE
70{
71 using namespace std::literals;
72
73 namespace stl
74 {
75 template <class CharT>
76 using basic_zstring = std::basic_string_view<CharT>;
77
80
81 // owning pointer
82 template <
83 class T,
84 class = std::enable_if_t<
85 std::is_pointer_v<T>>>
86 using owner = T;
87
88 // non-owning pointer
89 template <
90 class T,
91 class = std::enable_if_t<
92 std::is_pointer_v<T>>>
93 using observer = T;
94
95 // non-null pointer
96 template <
97 class T,
98 class = std::enable_if_t<
99 std::is_pointer_v<T>>>
100 using not_null = T;
101
102 namespace nttp
103 {
104 template <class CharT, std::size_t N>
105 struct string
106 {
107 using char_type = CharT;
109 using const_pointer = const char_type*;
112 using size_type = std::size_t;
113
114 static constexpr auto npos = static_cast<std::size_t>(-1);
115
116 consteval string(const_pointer a_string) noexcept
117 {
118 for (size_type i = 0; i < N; ++i) {
119 c[i] = a_string[i];
120 }
121 }
122
123 [[nodiscard]] consteval const_reference operator[](size_type a_pos) const noexcept
124 {
125 assert(a_pos < N);
126 return c[a_pos];
127 }
128
129 [[nodiscard]] consteval const_reference back() const noexcept { return (*this)[size() - 1]; }
130 [[nodiscard]] consteval const_pointer data() const noexcept { return c; }
131 [[nodiscard]] consteval bool empty() const noexcept { return this->size() == 0; }
132 [[nodiscard]] consteval const_reference front() const noexcept { return (*this)[0]; }
133 [[nodiscard]] consteval size_type length() const noexcept { return N; }
134 [[nodiscard]] consteval size_type size() const noexcept { return length(); }
135
136 template <std::size_t POS = 0, std::size_t COUNT = npos>
137 [[nodiscard]] consteval auto substr() const noexcept
138 {
139 return string < CharT, COUNT != npos ? COUNT : N - POS > (this->data() + POS);
140 }
141
142 char_type c[N] = {};
143 };
144
145 template <class CharT, std::size_t N>
146 string(const CharT (&)[N]) -> string<CharT, N - 1>;
147 }
148
149 template <class EF> //
150 requires(std::invocable<std::remove_reference_t<EF>>) //
152 {
153 public:
154 // 1)
155 template <class Fn>
156 explicit scope_exit(Fn&& a_fn) //
157 noexcept(std::is_nothrow_constructible_v<EF, Fn> ||
158 std::is_nothrow_constructible_v<EF, Fn&>) //
159 requires(!std::is_same_v<std::remove_cvref_t<Fn>, scope_exit> &&
160 std::is_constructible_v<EF, Fn>)
161 {
162 static_assert(std::invocable<Fn>);
163
164 if constexpr (!std::is_lvalue_reference_v<Fn> &&
165 std::is_nothrow_constructible_v<EF, Fn>) {
166 _fn.emplace(std::forward<Fn>(a_fn));
167 } else {
168 _fn.emplace(a_fn);
169 }
170 }
171
172 // 2)
174 noexcept(std::is_nothrow_move_constructible_v<EF> ||
175 std::is_nothrow_copy_constructible_v<EF>) //
176 requires(std::is_nothrow_move_constructible_v<EF> ||
177 std::is_copy_constructible_v<EF>)
178 {
179 static_assert(!(std::is_nothrow_move_constructible_v<EF> && !std::is_move_constructible_v<EF>));
180 static_assert(!(!std::is_nothrow_move_constructible_v<EF> && !std::is_copy_constructible_v<EF>));
181
182 if (a_rhs.active()) {
183 if constexpr (std::is_nothrow_move_constructible_v<EF>) {
184 _fn.emplace(std::forward<EF>(*a_rhs._fn));
185 } else {
186 _fn.emplace(a_rhs._fn);
187 }
188 a_rhs.release();
189 }
190 }
191
192 // 3)
193 scope_exit(const scope_exit&) = delete;
194
195 ~scope_exit() noexcept
196 {
197 if (_fn.has_value()) {
198 (*_fn)();
199 }
200 }
201
202 void release() noexcept { _fn.reset(); }
203
204 private:
205 [[nodiscard]] bool active() const noexcept { return _fn.has_value(); }
206
207 std::optional<std::remove_reference_t<EF>> _fn;
208 };
209
210 template <class EF>
212
213 template <
214 class Enum,
215 class Underlying = std::underlying_type_t<Enum>>
217 {
218 public:
219 using enum_type = Enum;
220 using underlying_type = Underlying;
221
222 static_assert(std::is_enum_v<enum_type>, "enum_type must be an enum");
223 static_assert(std::is_integral_v<underlying_type>, "underlying_type must be an integral");
224
225 constexpr enumeration() noexcept = default;
226
227 constexpr enumeration(const enumeration&) noexcept = default;
228
229 constexpr enumeration(enumeration&&) noexcept = default;
230
231 template <class U2> // NOLINTNEXTLINE(google-explicit-constructor)
232 constexpr enumeration(enumeration<Enum, U2> a_rhs) noexcept :
233 _impl(static_cast<underlying_type>(a_rhs.get()))
234 {}
235
236 template <class... Args>
237 constexpr enumeration(Args... a_values) noexcept //
238 requires(std::same_as<Args, enum_type>&&...) :
239 _impl((static_cast<underlying_type>(a_values) | ...))
240 {}
241
242 ~enumeration() noexcept = default;
243
244 constexpr enumeration& operator=(const enumeration&) noexcept = default;
245 constexpr enumeration& operator=(enumeration&&) noexcept = default;
246
247 template <class U2>
248 constexpr enumeration& operator=(enumeration<Enum, U2> a_rhs) noexcept
249 {
250 _impl = static_cast<underlying_type>(a_rhs.get());
251 }
252
253 constexpr enumeration& operator=(enum_type a_value) noexcept
254 {
255 _impl = static_cast<underlying_type>(a_value);
256 return *this;
257 }
258
259 [[nodiscard]] explicit constexpr operator bool() const noexcept { return _impl != static_cast<underlying_type>(0); }
260
261 [[nodiscard]] constexpr enum_type operator*() const noexcept { return get(); }
262 [[nodiscard]] constexpr enum_type get() const noexcept { return static_cast<enum_type>(_impl); }
263 [[nodiscard]] constexpr underlying_type underlying() const noexcept { return _impl; }
264
265 template <class... Args>
266 constexpr enumeration& set(Args... a_args) noexcept //
267 requires(std::same_as<Args, enum_type>&&...)
268 {
269 _impl |= (static_cast<underlying_type>(a_args) | ...);
270 return *this;
271 }
272
273 template <class... Args>
274 constexpr enumeration& reset(Args... a_args) noexcept //
275 requires(std::same_as<Args, enum_type>&&...)
276 {
277 _impl &= ~(static_cast<underlying_type>(a_args) | ...);
278 return *this;
279 }
280
281 template <class... Args>
282 [[nodiscard]] constexpr bool any(Args... a_args) const noexcept //
283 requires(std::same_as<Args, enum_type>&&...)
284 {
285 return (_impl & (static_cast<underlying_type>(a_args) | ...)) != static_cast<underlying_type>(0);
286 }
287
288 template <class... Args>
289 [[nodiscard]] constexpr bool all(Args... a_args) const noexcept //
290 requires(std::same_as<Args, enum_type>&&...)
291 {
292 return (_impl & (static_cast<underlying_type>(a_args) | ...)) == (static_cast<underlying_type>(a_args) | ...);
293 }
294
295 template <class... Args>
296 [[nodiscard]] constexpr bool none(Args... a_args) const noexcept //
297 requires(std::same_as<Args, enum_type>&&...)
298 {
299 return (_impl & (static_cast<underlying_type>(a_args) | ...)) == static_cast<underlying_type>(0);
300 }
301
302 private :
303 underlying_type _impl{ 0 };
304 };
305
306 template <class... Args>
308 std::common_type_t<Args...>,
309 std::underlying_type_t<
310 std::common_type_t<Args...>>>;
311 }
312}
313
314#define SKSE_MAKE_LOGICAL_OP(a_op, a_result) \
315 template <class E, class U1, class U2> \
316 [[nodiscard]] constexpr a_result operator a_op(enumeration<E, U1> a_lhs, enumeration<E, U2> a_rhs) noexcept \
317 { \
318 return a_lhs.get() a_op a_rhs.get(); \
319 } \
320 \
321 template <class E, class U> \
322 [[nodiscard]] constexpr a_result operator a_op(enumeration<E, U> a_lhs, E a_rhs) noexcept \
323 { \
324 return a_lhs.get() a_op a_rhs; \
325 }
326
327#define SKSE_MAKE_ARITHMETIC_OP(a_op) \
328 template <class E, class U> \
329 [[nodiscard]] constexpr auto operator a_op(enumeration<E, U> a_enum, U a_shift) noexcept \
330 ->enumeration<E, U> \
331 { \
332 return static_cast<E>(static_cast<U>(a_enum.get()) a_op a_shift); \
333 } \
334 \
335 template <class E, class U> \
336 constexpr auto operator a_op##=(enumeration<E, U>& a_enum, U a_shift) noexcept \
337 ->enumeration<E, U>& \
338 { \
339 return a_enum = a_enum a_op a_shift; \
340 }
341
342#define SKSE_MAKE_ENUMERATION_OP(a_op) \
343 template <class E, class U1, class U2> \
344 [[nodiscard]] constexpr auto operator a_op(enumeration<E, U1> a_lhs, enumeration<E, U2> a_rhs) noexcept \
345 ->enumeration<E, std::common_type_t<U1, U2>> \
346 { \
347 return static_cast<E>(static_cast<U1>(a_lhs.get()) a_op static_cast<U2>(a_rhs.get())); \
348 } \
349 \
350 template <class E, class U> \
351 [[nodiscard]] constexpr auto operator a_op(enumeration<E, U> a_lhs, E a_rhs) noexcept \
352 ->enumeration<E, U> \
353 { \
354 return static_cast<E>(static_cast<U>(a_lhs.get()) a_op static_cast<U>(a_rhs)); \
355 } \
356 \
357 template <class E, class U> \
358 [[nodiscard]] constexpr auto operator a_op(E a_lhs, enumeration<E, U> a_rhs) noexcept \
359 ->enumeration<E, U> \
360 { \
361 return static_cast<E>(static_cast<U>(a_lhs) a_op static_cast<U>(a_rhs.get())); \
362 } \
363 \
364 template <class E, class U1, class U2> \
365 constexpr auto operator a_op##=(enumeration<E, U1>& a_lhs, enumeration<E, U2> a_rhs) noexcept \
366 ->enumeration<E, U1>& \
367 { \
368 return a_lhs = a_lhs a_op a_rhs; \
369 } \
370 \
371 template <class E, class U> \
372 constexpr auto operator a_op##=(enumeration<E, U>& a_lhs, E a_rhs) noexcept \
373 ->enumeration<E, U>& \
374 { \
375 return a_lhs = a_lhs a_op a_rhs; \
376 } \
377 \
378 template <class E, class U> \
379 constexpr auto operator a_op##=(E& a_lhs, enumeration<E, U> a_rhs) noexcept \
380 ->E& \
381 { \
382 return a_lhs = *(a_lhs a_op a_rhs); \
383 }
384
385#define SKSE_MAKE_INCREMENTER_OP(a_op) \
386 template <class E, class U> \
387 constexpr auto operator a_op##a_op(enumeration<E, U>& a_lhs) noexcept \
388 ->enumeration<E, U>& \
389 { \
390 return a_lhs a_op## = static_cast<E>(1); \
391 } \
392 \
393 template <class E, class U> \
394 [[nodiscard]] constexpr auto operator a_op##a_op(enumeration<E, U>& a_lhs, int) noexcept \
395 ->enumeration<E, U> \
396 { \
397 const auto tmp = a_lhs; \
398 a_op##a_op a_lhs; \
399 return tmp; \
400 }
401
402namespace SKSE
403{
404 namespace stl
405 {
406 template <
407 class E,
408 class U>
409 [[nodiscard]] constexpr auto operator~(enumeration<E, U> a_enum) noexcept
411 {
412 return static_cast<E>(~static_cast<U>(a_enum.get()));
413 }
414
416 SKSE_MAKE_LOGICAL_OP(<=>, std::strong_ordering);
417
422
426
429
432
433 template <class T>
435 public std::atomic_ref<T>
436 {
437 private:
438 using super = std::atomic_ref<T>;
439
440 public:
441 using value_type = typename super::value_type;
442
443 explicit atomic_ref(volatile T& a_obj) noexcept(std::is_nothrow_constructible_v<super, value_type&>) :
444 super(const_cast<value_type&>(a_obj))
445 {}
446
447 using super::super;
448 using super::operator=;
449 };
450
451 template <class T>
452 atomic_ref(volatile T&) -> atomic_ref<T>;
453
454 template class atomic_ref<std::int8_t>;
455 template class atomic_ref<std::uint8_t>;
456 template class atomic_ref<std::int16_t>;
457 template class atomic_ref<std::uint16_t>;
458 template class atomic_ref<std::int32_t>;
459 template class atomic_ref<std::uint32_t>;
460 template class atomic_ref<std::int64_t>;
461 template class atomic_ref<std::uint64_t>;
462
471
472 template <class T>
473 struct ssizeof
474 {
475 [[nodiscard]] constexpr operator std::ptrdiff_t() const noexcept { return value; }
476
477 [[nodiscard]] constexpr std::ptrdiff_t operator()() const noexcept { return value; }
478
479 static constexpr auto value = static_cast<std::ptrdiff_t>(sizeof(T));
480 };
481
482 template <class T>
483 inline constexpr auto ssizeof_v = ssizeof<T>::value;
484
485 template <class T, class U>
486 [[nodiscard]] auto adjust_pointer(U* a_ptr, std::ptrdiff_t a_adjust) noexcept
487 {
488 auto addr = a_ptr ? reinterpret_cast<std::uintptr_t>(a_ptr) + a_adjust : 0;
489 if constexpr (std::is_const_v<U> && std::is_volatile_v<U>) {
490 return reinterpret_cast<std::add_cv_t<T>*>(addr);
491 } else if constexpr (std::is_const_v<U>) {
492 return reinterpret_cast<std::add_const_t<T>*>(addr);
493 } else if constexpr (std::is_volatile_v<U>) {
494 return reinterpret_cast<std::add_volatile_t<T>*>(addr);
495 } else {
496 return reinterpret_cast<T*>(addr);
497 }
498 }
499
500 template <class T>
501 void emplace_vtable(T* a_ptr)
502 {
503 reinterpret_cast<std::uintptr_t*>(a_ptr)[0] = T::VTABLE[0].address();
504 }
505
506 template <class T>
507 void memzero(volatile T* a_ptr, std::size_t a_size = sizeof(T))
508 {
509 const auto begin = reinterpret_cast<volatile char*>(a_ptr);
510 constexpr char val{ 0 };
511 std::fill_n(begin, a_size, val);
512 }
513
514 template <class... Args>
515 [[nodiscard]] inline auto pun_bits(Args... a_args) //
516 requires(std::same_as<std::remove_cv_t<Args>, bool>&&...)
517 {
518 constexpr auto ARGC = sizeof...(Args);
519
520 std::bitset<ARGC> bits;
521 std::size_t i = 0;
522 ((bits[i++] = a_args), ...);
523
524 if constexpr (ARGC <= std::numeric_limits<unsigned long>::digits) {
525 return bits.to_ulong();
526 } else if constexpr (ARGC <= std::numeric_limits<unsigned long long>::digits) {
527 return bits.to_ullong();
528 } else {
529 static_assert(false && sizeof...(Args));
530 }
531 }
532
533 [[nodiscard]] inline auto utf8_to_utf16(std::string_view a_in) noexcept
534 -> std::optional<std::wstring>
535 {
536 const auto cvt = [&](wchar_t* a_dst, std::size_t a_length) {
539 0,
540 a_in.data(),
541 static_cast<int>(a_in.length()),
542 a_dst,
543 static_cast<int>(a_length));
544 };
545
546 const auto len = cvt(nullptr, 0);
547 if (len == 0) {
548 return std::nullopt;
549 }
550
551 std::wstring out(len, '\0');
552 if (cvt(out.data(), out.length()) == 0) {
553 return std::nullopt;
554 }
555
556 return out;
557 }
558
559 [[nodiscard]] inline auto utf16_to_utf8(std::wstring_view a_in) noexcept
560 -> std::optional<std::string>
561 {
562 const auto cvt = [&](char* a_dst, std::size_t a_length) {
565 0,
566 a_in.data(),
567 static_cast<int>(a_in.length()),
568 a_dst,
569 static_cast<int>(a_length),
570 nullptr,
571 nullptr);
572 };
573
574 const auto len = cvt(nullptr, 0);
575 if (len == 0) {
576 return std::nullopt;
577 }
578
579 std::string out(len, '\0');
580 if (cvt(out.data(), out.length()) == 0) {
581 return std::nullopt;
582 }
583
584 return out;
585 }
586
587 [[noreturn]] inline void report_and_fail(std::string_view a_msg, std::source_location a_loc = std::source_location::current())
588 {
589 const auto body = [&]() {
590 const std::filesystem::path p = a_loc.file_name();
591 auto filename = p.lexically_normal().generic_string();
592
593 const std::regex r{ R"((?:^|[\\\/])(?:include|src)[\\\/](.*)$)" };
594 std::smatch matches;
595 if (std::regex_search(filename, matches, r)) {
596 filename = matches[1].str();
597 }
598
599 return utf8_to_utf16(
600 fmt::format(
601 "{}({}): {}"sv,
602 filename,
603 a_loc.line(),
604 a_msg))
605 .value_or(L"<character encoding error>"s);
606 }();
607
608 const auto caption = []() {
609 const auto maxPath = WinAPI::GetMaxPath();
610 std::vector<wchar_t> buf;
611 buf.reserve(maxPath);
612 buf.resize(maxPath / 2);
613 std::uint32_t result = 0;
614 do {
615 buf.resize(buf.size() * 2);
618 buf.data(),
619 static_cast<std::uint32_t>(buf.size()));
620 } while (result && result == buf.size() && buf.size() <= std::numeric_limits<std::uint32_t>::max());
621
622 if (result && result != buf.size()) {
623 std::filesystem::path p(buf.begin(), buf.begin() + result);
624 return p.filename().native();
625 } else {
626 return L""s;
627 }
628 }();
629
630 spdlog::log(
631 spdlog::source_loc{
632 a_loc.file_name(),
633 static_cast<int>(a_loc.line()),
634 a_loc.function_name() },
635 spdlog::level::critical,
636 a_msg);
637 WinAPI::MessageBox(nullptr, body.c_str(), (caption.empty() ? nullptr : caption.c_str()), 0);
639 }
640
641 template <class Enum>
642 [[nodiscard]] constexpr auto to_underlying(Enum a_val) noexcept //
643 requires(std::is_enum_v<Enum>)
644 {
645 return static_cast<std::underlying_type_t<Enum>>(a_val);
646 }
647
648 template <class To, class From>
649 [[nodiscard]] To unrestricted_cast(From a_from) noexcept
650 {
651 if constexpr (std::is_same_v<
652 std::remove_cv_t<From>,
653 std::remove_cv_t<To>>) {
654 return To{ a_from };
655
656 // From != To
657 } else if constexpr (std::is_reference_v<From>) {
658 return stl::unrestricted_cast<To>(std::addressof(a_from));
659
660 // From: NOT reference
661 } else if constexpr (std::is_reference_v<To>) {
663 std::add_pointer_t<
664 std::remove_reference_t<To>>>(a_from);
665
666 // To: NOT reference
667 } else if constexpr (std::is_pointer_v<From> &&
668 std::is_pointer_v<To>) {
669 return static_cast<To>(
670 const_cast<void*>(
671 static_cast<const volatile void*>(a_from)));
672 } else if constexpr ((std::is_pointer_v<From> && std::is_integral_v<To>) ||
673 (std::is_integral_v<From> && std::is_pointer_v<To>)) {
674 return reinterpret_cast<To>(a_from);
675 } else {
676 union
677 {
678 std::remove_cv_t<std::remove_reference_t<From>> from;
679 std::remove_cv_t<std::remove_reference_t<To>> to;
680 };
681
682 from = std::forward<From>(a_from);
683 return to;
684 }
685 }
686 }
687}
688
689#undef SKSE_MAKE_INCREMENTER_OP
690#undef SKSE_MAKE_ENUMERATION_OP
691#undef SKSE_MAKE_ARITHMETIC_OP
692#undef SKSE_MAKE_LOGICAL_OP
693
694namespace RE
695{
696 using namespace std::literals;
697 namespace stl = SKSE::stl;
698 namespace WinAPI = SKSE::WinAPI;
699}
700
701namespace REL
702{
703 using namespace std::literals;
704 namespace stl = SKSE::stl;
705 namespace WinAPI = SKSE::WinAPI;
706}
707
708#ifdef SKYRIM_SUPPORT_AE
709# define RELOCATION_ID(SE, AE) REL::ID(AE)
710#else
711# define RELOCATION_ID(SE, AE) REL::ID(SE)
712#endif
713
714#include "REL/Relocation.h"
715
716#include "RE/Offsets.h"
717#include "RE/Offsets_NiRTTI.h"
718#include "RE/Offsets_RTTI.h"
719#include "RE/Offsets_VTABLE.h"
720
721#include "RE/B/BSCoreTypes.h"
722#include "RE/S/SFTypes.h"
#define SKSE_MAKE_ARITHMETIC_OP(a_op)
Definition: PCH.h:327
#define SKSE_MAKE_ENUMERATION_OP(a_op)
Definition: PCH.h:342
#define SKSE_MAKE_INCREMENTER_OP(a_op)
Definition: PCH.h:385
#define SKSE_MAKE_LOGICAL_OP(a_op, a_result)
Definition: PCH.h:314
Definition: PCH.h:436
typename super::value_type value_type
Definition: PCH.h:441
atomic_ref(volatile T &a_obj) noexcept(std::is_nothrow_constructible_v< super, value_type & >)
Definition: PCH.h:443
Definition: PCH.h:217
constexpr bool all(Args... a_args) const noexcept
Definition: PCH.h:289
constexpr enumeration & reset(Args... a_args) noexcept
Definition: PCH.h:274
Underlying underlying_type
Definition: PCH.h:220
constexpr enumeration(Args... a_values) noexcept
Definition: PCH.h:237
constexpr enum_type operator*() const noexcept
Definition: PCH.h:261
constexpr enumeration & set(Args... a_args) noexcept
Definition: PCH.h:266
constexpr bool any(Args... a_args) const noexcept
Definition: PCH.h:282
constexpr bool none(Args... a_args) const noexcept
Definition: PCH.h:296
Enum enum_type
Definition: PCH.h:219
constexpr enumeration & operator=(enum_type a_value) noexcept
Definition: PCH.h:253
~enumeration() noexcept=default
constexpr underlying_type underlying() const noexcept
Definition: PCH.h:263
constexpr enumeration() noexcept=default
constexpr enum_type get() const noexcept
Definition: PCH.h:262
Definition: PCH.h:152
scope_exit(Fn &&a_fn) noexcept(std::is_nothrow_constructible_v< EF, Fn >||std::is_nothrow_constructible_v< EF, Fn & >)
Definition: PCH.h:156
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:173
~scope_exit() noexcept
Definition: PCH.h:195
void release() noexcept
Definition: PCH.h:202
Definition: AbsorbEffect.h:6
Definition: Relocation.h:60
Definition: WinAPI.h:4
void * GetCurrentProcess() noexcept
std::size_t GetMaxPath() noexcept
std::uint32_t GetModuleFileName(void *a_module, char *a_filename, std::uint32_t a_size) noexcept
void * GetCurrentModule() noexcept
int MultiByteToWideChar(unsigned int a_codePage, std::uint32_t a_flags, const char *a_multiByteStr, int a_multiByte, wchar_t *a_wideCharStr, int a_wideChar)
std::int32_t MessageBox(void *a_wnd, const char *a_text, const char *a_caption, unsigned int a_type) noexcept
constexpr auto CP_UTF8
Definition: WinAPI.h:5
int WideCharToMultiByte(unsigned int a_codePage, std::uint32_t a_flags, const wchar_t *a_wideCharStr, int a_wideChar, char *a_multiByteStr, int a_multiByte, const char *a_defaultChar, int *a_usedDefaultChar)
void TerminateProcess(void *a_process, unsigned int a_exitCode) noexcept
Definition: PCH.h:74
T not_null
Definition: PCH.h:100
constexpr auto to_underlying(Enum a_val) noexcept
Definition: PCH.h:642
To unrestricted_cast(From a_from) noexcept
Definition: PCH.h:649
std::basic_string_view< CharT > basic_zstring
Definition: PCH.h:76
void memzero(volatile T *a_ptr, std::size_t a_size=sizeof(T))
Definition: PCH.h:507
void report_and_fail(std::string_view a_msg, std::source_location a_loc=std::source_location::current())
Definition: PCH.h:587
T owner
Definition: PCH.h:86
T observer
Definition: PCH.h:93
auto utf16_to_utf8(std::wstring_view a_in) noexcept -> std::optional< std::string >
Definition: PCH.h:559
auto pun_bits(Args... a_args)
Definition: PCH.h:515
void emplace_vtable(T *a_ptr)
Definition: PCH.h:501
auto adjust_pointer(U *a_ptr, std::ptrdiff_t a_adjust) noexcept
Definition: PCH.h:486
auto utf8_to_utf16(std::string_view a_in) noexcept -> std::optional< std::wstring >
Definition: PCH.h:533
basic_zstring< wchar_t > zwstring
Definition: PCH.h:79
constexpr auto operator~(enumeration< E, U > a_enum) noexcept -> enumeration< E, U >
Definition: PCH.h:409
basic_zstring< char > zstring
Definition: PCH.h:78
constexpr auto ssizeof_v
Definition: PCH.h:483
Definition: API.h:14
Definition: PCH.h:106
consteval bool empty() const noexcept
Definition: PCH.h:131
const char_type & const_reference
Definition: PCH.h:111
consteval auto substr() const noexcept
Definition: PCH.h:137
consteval const_reference operator[](size_type a_pos) const noexcept
Definition: PCH.h:123
const char_type * const_pointer
Definition: PCH.h:109
consteval const_pointer data() const noexcept
Definition: PCH.h:130
std::size_t size_type
Definition: PCH.h:112
char_type c[N]
Definition: PCH.h:142
consteval const_reference back() const noexcept
Definition: PCH.h:129
consteval string(const_pointer a_string) noexcept
Definition: PCH.h:116
char_type & reference
Definition: PCH.h:110
char_type * pointer
Definition: PCH.h:108
static constexpr auto npos
Definition: PCH.h:114
consteval size_type length() const noexcept
Definition: PCH.h:133
consteval size_type size() const noexcept
Definition: PCH.h:134
consteval const_reference front() const noexcept
Definition: PCH.h:132
CharT char_type
Definition: PCH.h:107
Definition: PCH.h:474
constexpr std::ptrdiff_t operator()() const noexcept
Definition: PCH.h:477