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