CommonLibSSE NG
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 <intrin.h>
26 #include <iomanip>
27 #include <ios>
28 #include <istream>
29 #include <iterator>
30 #include <limits>
31 #include <locale>
32 #include <map>
33 #include <memory>
34 #include <mutex>
35 #include <new>
36 #include <numeric>
37 #include <optional>
38 #include <random>
39 #include <regex>
40 #include <set>
41 #include <source_location>
42 #include <span>
43 #include <sstream>
44 #include <stack>
45 #include <stdexcept>
46 #include <string>
47 #include <string_view>
48 #include <system_error>
49 #include <thread>
50 #include <tuple>
51 #include <type_traits>
52 #include <typeinfo>
53 #include <utility>
54 #include <variant>
55 #include <vector>
56 
57 static_assert(
58  std::is_integral_v<std::time_t> && sizeof(std::time_t) == sizeof(std::size_t),
59  "wrap std::time_t instead");
60 
61 #pragma warning(push)
62 #include <spdlog/spdlog.h>
63 #pragma warning(pop)
64 
65 #include "REX/W32/KERNEL32.h"
66 #include "REX/W32/USER32.h"
67 
68 namespace 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;
107  using pointer = char_type*;
108  using const_pointer = const char_type*;
110  using const_reference = 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 char_type value_at(size_type a_pos) const noexcept
129  {
130  assert(a_pos < N);
131  return c[a_pos];
132  }
133 
134  [[nodiscard]] consteval const_reference back() const noexcept { return (*this)[size() - 1]; }
135  [[nodiscard]] consteval const_pointer data() const noexcept { return c; }
136  [[nodiscard]] consteval bool empty() const noexcept { return this->size() == 0; }
137  [[nodiscard]] consteval const_reference front() const noexcept { return (*this)[0]; }
138  [[nodiscard]] consteval size_type length() const noexcept { return N; }
139  [[nodiscard]] consteval size_type size() const noexcept { return length(); }
140 
141  template <std::size_t POS = 0, std::size_t COUNT = npos>
142  [[nodiscard]] consteval auto substr() const noexcept
143  {
144  return string < CharT, COUNT != npos ? COUNT : N - POS > (this->data() + POS);
145  }
146 
147  char_type c[N] = {};
148  };
149 
150  template <class CharT, std::size_t N>
151  string(const CharT (&)[N]) -> string<CharT, N - 1>;
152  }
153 
154  template <class EF> //
155  requires(std::invocable<std::remove_reference_t<EF>>) //
156  class scope_exit
157  {
158  public:
159  // 1)
160  template <class Fn>
161  explicit scope_exit(Fn&& a_fn) //
162  noexcept(std::is_nothrow_constructible_v<EF, Fn> ||
163  std::is_nothrow_constructible_v<EF, Fn&>) //
164  requires(!std::is_same_v<std::remove_cvref_t<Fn>, scope_exit> &&
165  std::is_constructible_v<EF, Fn>)
166  {
167  static_assert(std::invocable<Fn>);
168 
169  if constexpr (!std::is_lvalue_reference_v<Fn> &&
170  std::is_nothrow_constructible_v<EF, Fn>) {
171  _fn.emplace(std::forward<Fn>(a_fn));
172  } else {
173  _fn.emplace(a_fn);
174  }
175  }
176 
177  // 2)
178  scope_exit(scope_exit&& a_rhs) //
179  noexcept(std::is_nothrow_move_constructible_v<EF> ||
180  std::is_nothrow_copy_constructible_v<EF>) //
181  requires(std::is_nothrow_move_constructible_v<EF> ||
182  std::is_copy_constructible_v<EF>)
183  {
184  static_assert(!(std::is_nothrow_move_constructible_v<EF> && !std::is_move_constructible_v<EF>));
185  static_assert(!(!std::is_nothrow_move_constructible_v<EF> && !std::is_copy_constructible_v<EF>));
186 
187  if (a_rhs.active()) {
188  if constexpr (std::is_nothrow_move_constructible_v<EF>) {
189  _fn.emplace(std::forward<EF>(*a_rhs._fn));
190  } else {
191  _fn.emplace(a_rhs._fn);
192  }
193  a_rhs.release();
194  }
195  }
196 
197  // 3)
198  scope_exit(const scope_exit&) = delete;
199 
200  ~scope_exit() noexcept
201  {
202  if (_fn.has_value()) {
203  (*_fn)();
204  }
205  }
206 
207  void release() noexcept { _fn.reset(); }
208 
209  private:
210  [[nodiscard]] bool active() const noexcept { return _fn.has_value(); }
211 
212  std::optional<std::remove_reference_t<EF>> _fn;
213  };
214 
215  template <class EF>
216  scope_exit(EF) -> scope_exit<EF>;
217 
218  template <
219  class Enum,
220  class Underlying = std::underlying_type_t<Enum>>
222  {
223  public:
224  using enum_type = Enum;
225  using underlying_type = Underlying;
226 
227  static_assert(std::is_enum_v<enum_type>, "enum_type must be an enum");
228  static_assert(std::is_integral_v<underlying_type>, "underlying_type must be an integral");
229 
230  constexpr enumeration() noexcept = default;
231 
232  constexpr enumeration(const enumeration&) noexcept = default;
233 
234  constexpr enumeration(enumeration&&) noexcept = default;
235 
236  template <class U2> // NOLINTNEXTLINE(google-explicit-constructor)
237  constexpr enumeration(enumeration<Enum, U2> a_rhs) noexcept :
238  _impl(static_cast<underlying_type>(a_rhs.get()))
239  {}
240 
241  template <class... Args>
242  constexpr enumeration(Args... a_values) noexcept //
243  requires(std::same_as<Args, enum_type> && ...)
244  :
245  _impl((static_cast<underlying_type>(a_values) | ...))
246  {}
247 
248  ~enumeration() noexcept = default;
249 
250  constexpr enumeration& operator=(const enumeration&) noexcept = default;
251  constexpr enumeration& operator=(enumeration&&) noexcept = default;
252 
253  template <class U2>
254  constexpr enumeration& operator=(enumeration<Enum, U2> a_rhs) noexcept
255  {
256  _impl = static_cast<underlying_type>(a_rhs.get());
257  }
258 
259  constexpr enumeration& operator=(enum_type a_value) noexcept
260  {
261  _impl = static_cast<underlying_type>(a_value);
262  return *this;
263  }
264 
265  [[nodiscard]] explicit constexpr operator bool() const noexcept { return _impl != static_cast<underlying_type>(0); }
266 
267  [[nodiscard]] constexpr enum_type operator*() const noexcept { return get(); }
268  [[nodiscard]] constexpr enum_type get() const noexcept { return static_cast<enum_type>(_impl); }
269  [[nodiscard]] constexpr underlying_type underlying() const noexcept { return _impl; }
270 
271  template <class... Args>
272  constexpr enumeration& set(Args... a_args) noexcept //
273  requires(std::same_as<Args, enum_type> && ...)
274  {
275  _impl |= (static_cast<underlying_type>(a_args) | ...);
276  return *this;
277  }
278 
279  template <class... Args>
280  constexpr enumeration& reset(Args... a_args) noexcept //
281  requires(std::same_as<Args, enum_type> && ...)
282  {
283  _impl &= ~(static_cast<underlying_type>(a_args) | ...);
284  return *this;
285  }
286 
287  template <class... Args>
288  [[nodiscard]] constexpr bool any(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>(0);
292  }
293 
294  template <class... Args>
295  [[nodiscard]] constexpr bool all(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>(a_args) | ...);
299  }
300 
301  template <class... Args>
302  [[nodiscard]] constexpr bool none(Args... a_args) const noexcept //
303  requires(std::same_as<Args, enum_type> && ...)
304  {
305  return (_impl & (static_cast<underlying_type>(a_args) | ...)) == static_cast<underlying_type>(0);
306  }
307 
308  private:
309  underlying_type _impl{ 0 };
310  };
311 
312  template <class... Args>
314  std::common_type_t<Args...>,
315  std::underlying_type_t<
316  std::common_type_t<Args...>>>;
317  }
318 }
319 
320 #define SKSE_MAKE_LOGICAL_OP(a_op, a_result) \
321  template <class E, class U1, class U2> \
322  [[nodiscard]] constexpr a_result operator a_op(enumeration<E, U1> a_lhs, enumeration<E, U2> a_rhs) noexcept \
323  { \
324  return a_lhs.get() a_op a_rhs.get(); \
325  } \
326  \
327  template <class E, class U> \
328  [[nodiscard]] constexpr a_result operator a_op(enumeration<E, U> a_lhs, E a_rhs) noexcept \
329  { \
330  return a_lhs.get() a_op a_rhs; \
331  }
332 
333 #define SKSE_MAKE_ARITHMETIC_OP(a_op) \
334  template <class E, class U> \
335  [[nodiscard]] constexpr auto operator a_op(enumeration<E, U> a_enum, U a_shift) noexcept \
336  -> enumeration<E, U> \
337  { \
338  return static_cast<E>(static_cast<U>(a_enum.get()) a_op a_shift); \
339  } \
340  \
341  template <class E, class U> \
342  constexpr auto operator a_op##=(enumeration<E, U>& a_enum, U a_shift) noexcept \
343  -> enumeration<E, U>& \
344  { \
345  return a_enum = a_enum a_op a_shift; \
346  }
347 
348 #define SKSE_MAKE_ENUMERATION_OP(a_op) \
349  template <class E, class U1, class U2> \
350  [[nodiscard]] constexpr auto operator a_op(enumeration<E, U1> a_lhs, enumeration<E, U2> a_rhs) noexcept \
351  -> enumeration<E, std::common_type_t<U1, U2>> \
352  { \
353  return static_cast<E>(static_cast<U1>(a_lhs.get()) a_op static_cast<U2>(a_rhs.get())); \
354  } \
355  \
356  template <class E, class U> \
357  [[nodiscard]] constexpr auto operator a_op(enumeration<E, U> a_lhs, E a_rhs) noexcept \
358  -> enumeration<E, U> \
359  { \
360  return static_cast<E>(static_cast<U>(a_lhs.get()) a_op static_cast<U>(a_rhs)); \
361  } \
362  \
363  template <class E, class U> \
364  [[nodiscard]] constexpr auto operator a_op(E a_lhs, enumeration<E, U> a_rhs) noexcept \
365  -> enumeration<E, U> \
366  { \
367  return static_cast<E>(static_cast<U>(a_lhs) a_op static_cast<U>(a_rhs.get())); \
368  } \
369  \
370  template <class E, class U1, class U2> \
371  constexpr auto operator a_op##=(enumeration<E, U1>& a_lhs, enumeration<E, U2> a_rhs) noexcept \
372  -> enumeration<E, U1>& \
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##=(enumeration<E, U>& a_lhs, E a_rhs) noexcept \
379  -> enumeration<E, U>& \
380  { \
381  return a_lhs = a_lhs a_op a_rhs; \
382  } \
383  \
384  template <class E, class U> \
385  constexpr auto operator a_op##=(E& a_lhs, enumeration<E, U> a_rhs) noexcept \
386  -> E& \
387  { \
388  return a_lhs = *(a_lhs a_op a_rhs); \
389  }
390 
391 #define SKSE_MAKE_INCREMENTER_OP(a_op) \
392  template <class E, class U> \
393  constexpr auto operator a_op##a_op(enumeration<E, U>& a_lhs) noexcept \
394  -> enumeration<E, U>& \
395  { \
396  return a_lhs a_op## = static_cast<E>(1); \
397  } \
398  \
399  template <class E, class U> \
400  [[nodiscard]] constexpr auto operator a_op##a_op(enumeration<E, U>& a_lhs, int) noexcept \
401  -> enumeration<E, U> \
402  { \
403  const auto tmp = a_lhs; \
404  a_op##a_op a_lhs; \
405  return tmp; \
406  }
407 
408 namespace SKSE
409 {
410  namespace stl
411  {
412  template <
413  class E,
414  class U>
415  [[nodiscard]] constexpr auto operator~(enumeration<E, U> a_enum) noexcept
417  {
418  return static_cast<E>(~static_cast<U>(a_enum.get()));
419  }
420 
422  SKSE_MAKE_LOGICAL_OP(<=>, std::strong_ordering);
423 
428 
432 
435 
438 
439  template <class T>
440  class atomic_ref :
441  public std::atomic_ref<T>
442  {
443  private:
444  using super = std::atomic_ref<T>;
445 
446  public:
447  using value_type = typename super::value_type;
448 
449  explicit atomic_ref(volatile T& a_obj) noexcept(std::is_nothrow_constructible_v<super, value_type&>) :
450  super(const_cast<value_type&>(a_obj))
451  {}
452 
453  using super::super;
454  using super::operator=;
455  };
456 
457  template <class T>
458  atomic_ref(volatile T&) -> atomic_ref<T>;
459 
460  template class atomic_ref<std::int8_t>;
461  template class atomic_ref<std::uint8_t>;
462  template class atomic_ref<std::int16_t>;
463  template class atomic_ref<std::uint16_t>;
464  template class atomic_ref<std::int32_t>;
465  template class atomic_ref<std::uint32_t>;
466  template class atomic_ref<std::int64_t>;
467  template class atomic_ref<std::uint64_t>;
468 
477 
478  template <class T>
479  struct ssizeof
480  {
481  [[nodiscard]] constexpr operator std::ptrdiff_t() const noexcept { return value; }
482 
483  [[nodiscard]] constexpr std::ptrdiff_t operator()() const noexcept { return value; }
484 
485  static constexpr auto value = static_cast<std::ptrdiff_t>(sizeof(T));
486  };
487 
488  template <class T>
489  inline constexpr auto ssizeof_v = ssizeof<T>::value;
490 
491  template <class T, class U>
492  [[nodiscard]] auto adjust_pointer(U* a_ptr, std::ptrdiff_t a_adjust) noexcept
493  {
494  auto addr = a_ptr ? reinterpret_cast<std::uintptr_t>(a_ptr) + a_adjust : 0;
495  if constexpr (std::is_const_v<U> && std::is_volatile_v<U>) {
496  return reinterpret_cast<std::add_cv_t<T>*>(addr);
497  } else if constexpr (std::is_const_v<U>) {
498  return reinterpret_cast<std::add_const_t<T>*>(addr);
499  } else if constexpr (std::is_volatile_v<U>) {
500  return reinterpret_cast<std::add_volatile_t<T>*>(addr);
501  } else {
502  return reinterpret_cast<T*>(addr);
503  }
504  }
505 
506  template <class T>
507  bool emplace_vtable(T* a_ptr)
508  {
509  auto address = T::VTABLE[0].address();
510  if (!address) {
511  return false;
512  }
513  reinterpret_cast<std::uintptr_t*>(a_ptr)[0] = address;
514  return true;
515  }
516 
517  template <class T>
518  void memzero(volatile T* a_ptr, std::size_t a_size = sizeof(T))
519  {
520  const auto begin = reinterpret_cast<volatile char*>(a_ptr);
521  constexpr char val{ 0 };
522  std::fill_n(begin, a_size, val);
523  }
524 
525  template <class... Args>
526  [[nodiscard]] inline auto pun_bits(Args... a_args) //
527  requires(std::same_as<std::remove_cv_t<Args>, bool> && ...)
528  {
529  constexpr auto ARGC = sizeof...(Args);
530 
531  std::bitset<ARGC> bits;
532  std::size_t i = 0;
533  ((bits[i++] = a_args), ...);
534 
535  if constexpr (ARGC <= std::numeric_limits<unsigned long>::digits) {
536  return bits.to_ulong();
537  } else if constexpr (ARGC <= std::numeric_limits<unsigned long long>::digits) {
538  return bits.to_ullong();
539  } else {
540  static_assert(false && sizeof...(Args));
541  }
542  }
543 
544  [[nodiscard]] inline auto utf8_to_utf16(std::string_view a_in) noexcept
545  -> std::optional<std::wstring>
546  {
547  const auto cvt = [&](wchar_t* a_dst, std::size_t a_length) {
550  0,
551  a_in.data(),
552  static_cast<int>(a_in.length()),
553  a_dst,
554  static_cast<int>(a_length));
555  };
556 
557  const auto len = cvt(nullptr, 0);
558  if (len == 0) {
559  return std::nullopt;
560  }
561 
562  std::wstring out(len, '\0');
563  if (cvt(out.data(), out.length()) == 0) {
564  return std::nullopt;
565  }
566 
567  return out;
568  }
569 
570  [[nodiscard]] inline auto utf16_to_utf8(std::wstring_view a_in) noexcept
571  -> std::optional<std::string>
572  {
573  const auto cvt = [&](char* a_dst, std::size_t a_length) {
576  0,
577  a_in.data(),
578  static_cast<int>(a_in.length()),
579  a_dst,
580  static_cast<int>(a_length),
581  nullptr,
582  nullptr);
583  };
584 
585  const auto len = cvt(nullptr, 0);
586  if (len == 0) {
587  return std::nullopt;
588  }
589 
590  std::string out(len, '\0');
591  if (cvt(out.data(), out.length()) == 0) {
592  return std::nullopt;
593  }
594 
595  return out;
596  }
597 
598  inline bool report_and_error(std::string_view a_msg, bool a_fail = true,
599  std::source_location a_loc = std::source_location::current())
600  {
601  const auto body = [&]() -> std::wstring {
602  const std::filesystem::path p = a_loc.file_name();
603  auto filename = p.lexically_normal().generic_string();
604 
605  const std::regex r{ R"((?:^|[\\\/])(?:include|src)[\\\/](.*)$)" };
606  std::smatch matches;
607  if (std::regex_search(filename, matches, r)) {
608  filename = matches[1].str();
609  }
610 
611  return utf8_to_utf16(
612  std::format(
613  "{}({}): {}"sv,
614  filename,
615  a_loc.line(),
616  a_msg))
617  .value_or(L"<character encoding error>"s);
618  }();
619 
620  const auto caption = []() {
621  std::vector<wchar_t> buf;
622  buf.reserve(REX::W32::MAX_PATH);
623  buf.resize(REX::W32::MAX_PATH / 2);
624  std::uint32_t result = 0;
625  do {
626  buf.resize(buf.size() * 2);
629  buf.data(),
630  static_cast<std::uint32_t>(buf.size()));
631  } while (result && result == buf.size() && buf.size() <= (std::numeric_limits<std::uint32_t>::max)());
632 
633  if (result && result != buf.size()) {
634  std::filesystem::path p(buf.begin(), buf.begin() + result);
635  return p.filename().native();
636  } else {
637  return L""s;
638  }
639  }();
640 
641  spdlog::log(
642  spdlog::source_loc{
643  a_loc.file_name(),
644  static_cast<int>(a_loc.line()),
645  a_loc.function_name() },
646  spdlog::level::critical,
647  a_msg);
648 
649  if (a_fail) {
650 #ifdef ENABLE_COMMONLIBSSE_TESTING
651  throw std::runtime_error(utf16_to_utf8(caption.empty() ? body.c_str() : caption.c_str())->c_str());
652 #else
653  REX::W32::MessageBoxW(nullptr, body.c_str(), (caption.empty() ? nullptr : caption.c_str()), 0);
655 #endif
656  }
657  return true;
658  }
659 
660  [[noreturn]] inline void report_and_fail(std::string_view a_msg,
661  std::source_location a_loc = std::source_location::current())
662  {
663  report_and_error(a_msg, true, a_loc);
664  }
665 
666  template <class To, class From>
667  [[nodiscard]] To unrestricted_cast(From a_from) noexcept
668  {
669  if constexpr (std::is_same_v<
670  std::remove_cv_t<From>,
671  std::remove_cv_t<To>>) {
672  return To{ a_from };
673 
674  // From != To
675  } else if constexpr (std::is_reference_v<From>) {
676  return stl::unrestricted_cast<To>(std::addressof(a_from));
677 
678  // From: NOT reference
679  } else if constexpr (std::is_reference_v<To>) {
680  return *stl::unrestricted_cast<
681  std::add_pointer_t<
682  std::remove_reference_t<To>>>(a_from);
683 
684  // To: NOT reference
685  } else if constexpr (std::is_pointer_v<From> &&
686  std::is_pointer_v<To>) {
687  return static_cast<To>(
688  const_cast<void*>(
689  static_cast<const volatile void*>(a_from)));
690  } else if constexpr ((std::is_pointer_v<From> && std::is_integral_v<To>) ||
691  (std::is_integral_v<From> && std::is_pointer_v<To>)) {
692  return reinterpret_cast<To>(a_from);
693  } else {
694  union
695  {
696  std::remove_cv_t<std::remove_reference_t<From>> from;
697  std::remove_cv_t<std::remove_reference_t<To>> to;
698  };
699 
700  from = std::forward<From>(a_from);
701  return to;
702  }
703  }
704  }
705 }
706 
707 #undef SKSE_MAKE_INCREMENTER_OP
708 #undef SKSE_MAKE_ENUMERATION_OP
709 #undef SKSE_MAKE_ARITHMETIC_OP
710 #undef SKSE_MAKE_LOGICAL_OP
711 
712 namespace RE
713 {
714  using namespace std::literals;
715  namespace stl = SKSE::stl;
716 }
717 
718 namespace REL
719 {
720  using namespace std::literals;
721  namespace stl = SKSE::stl;
722 }
723 
724 #define RELOCATION_ID(a_se, a_ae) REL::RelocationID(a_se, a_ae)
725 
726 #include "REL/REL.h"
727 
728 #include "RE/Offsets.h"
729 #include "RE/Offsets_NiRTTI.h"
730 #include "RE/Offsets_RTTI.h"
731 #include "RE/Offsets_VTABLE.h"
732 
733 #include "RE/B/BSCoreTypes.h"
734 #include "RE/S/SFTypes.h"
735 
736 #undef cdecl // Workaround for Clang.
Definition: PCH.h:442
typename super::value_type value_type
Definition: PCH.h:447
atomic_ref(volatile T &a_obj) noexcept(std::is_nothrow_constructible_v< super, value_type & >)
Definition: PCH.h:449
Definition: PCH.h:222
Underlying underlying_type
Definition: PCH.h:225
constexpr enum_type operator*() const noexcept
Definition: PCH.h:267
constexpr bool none(Args... a_args) const noexcept requires(std
Definition: PCH.h:302
constexpr enumeration(Args... a_values) noexcept requires(std
Definition: PCH.h:242
Enum enum_type
Definition: PCH.h:224
constexpr enumeration & operator=(enum_type a_value) noexcept
Definition: PCH.h:259
constexpr bool all(Args... a_args) const noexcept requires(std
Definition: PCH.h:295
~enumeration() noexcept=default
constexpr enumeration & reset(Args... a_args) noexcept requires(std
Definition: PCH.h:280
constexpr enumeration & set(Args... a_args) noexcept requires(std
Definition: PCH.h:272
constexpr underlying_type underlying() const noexcept
Definition: PCH.h:269
constexpr enumeration() noexcept=default
constexpr bool any(Args... a_args) const noexcept requires(std
Definition: PCH.h:288
constexpr enum_type get() const noexcept
Definition: PCH.h:268
Definition: ID.h:6
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:34
std::uint32_t GetModuleFileNameW(HMODULE a_module, wchar_t *a_name, std::uint32_t a_nameLen) noexcept
HANDLE GetCurrentProcess() noexcept
NiColor() max(const NiColor &a_lhs, const NiColor &a_rhs)
Definition: ColorUtil.h:71
Definition: AbsorbEffect.h:6
string(const CharT(&)[N]) -> string< CharT, N - 1 >
Definition: PCH.h:73
atomic_ref(volatile T &) -> atomic_ref< T >
T not_null
Definition: PCH.h:99
SKSE_MAKE_ENUMERATION_OP(<<)
To unrestricted_cast(From a_from) noexcept
Definition: PCH.h:667
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:518
void report_and_fail(std::string_view a_msg, std::source_location a_loc=std::source_location::current())
Definition: PCH.h:660
scope_exit(EF) -> scope_exit< EF >
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:570
bool emplace_vtable(T *a_ptr)
Definition: PCH.h:507
SKSE_MAKE_INCREMENTER_OP(+)
auto adjust_pointer(U *a_ptr, std::ptrdiff_t a_adjust) noexcept
Definition: PCH.h:492
auto utf8_to_utf16(std::string_view a_in) noexcept -> std::optional< std::wstring >
Definition: PCH.h:544
requires(std::invocable< std::remove_reference_t< EF >>) class scope_exit
Definition: PCH.h:155
bool report_and_error(std::string_view a_msg, bool a_fail=true, std::source_location a_loc=std::source_location::current())
Definition: PCH.h:598
SKSE_MAKE_LOGICAL_OP(==, bool)
basic_zstring< wchar_t > zwstring
Definition: PCH.h:78
constexpr auto operator~(enumeration< E, U > a_enum) noexcept -> enumeration< E, U >
Definition: PCH.h:415
auto pun_bits(Args... a_args) requires(std
Definition: PCH.h:526
SKSE_MAKE_ARITHMETIC_OP(<<)
basic_zstring< char > zstring
Definition: PCH.h:77
enumeration(Args...) -> enumeration< std::common_type_t< Args... >, std::underlying_type_t< std::common_type_t< Args... >>>
constexpr auto ssizeof_v
Definition: PCH.h:489
Definition: API.h:14
Definition: PCH.h:105
consteval bool empty() const noexcept
Definition: PCH.h:136
const char_type & const_reference
Definition: PCH.h:110
consteval auto substr() const noexcept
Definition: PCH.h:142
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:135
std::size_t size_type
Definition: PCH.h:111
consteval const_reference back() const noexcept
Definition: PCH.h:134
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
consteval size_type length() const noexcept
Definition: PCH.h:138
consteval char_type value_at(size_type a_pos) const noexcept
Definition: PCH.h:128
consteval size_type size() const noexcept
Definition: PCH.h:139
consteval const_reference front() const noexcept
Definition: PCH.h:137
CharT char_type
Definition: PCH.h:106
Definition: PCH.h:480
constexpr std::ptrdiff_t operator()() const noexcept
Definition: PCH.h:483