CommonLibVR
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 <format>
24 #include <fstream>
25 #include <functional>
26 #include <intrin.h>
27 #include <iomanip>
28 #include <ios>
29 #include <istream>
30 #include <iterator>
31 #include <limits>
32 #include <locale>
33 #include <map>
34 #include <memory>
35 #include <mutex>
36 #include <new>
37 #include <numeric>
38 #include <optional>
39 #include <random>
40 #include <regex>
41 #include <set>
42 #include <source_location>
43 #include <span>
44 #include <sstream>
45 #include <stack>
46 #include <stdexcept>
47 #include <string>
48 #include <string_view>
49 #include <system_error>
50 #include <thread>
51 #include <tuple>
52 #include <type_traits>
53 #include <typeinfo>
54 #include <utility>
55 #include <variant>
56 #include <vector>
57 
58 static_assert(
59  std::is_integral_v<std::time_t> && sizeof(std::time_t) == sizeof(std::size_t),
60  "wrap std::time_t instead");
61 
62 #pragma warning(push)
63 #include <binary_io/file_stream.hpp>
64 #include <spdlog/spdlog.h>
65 #pragma warning(pop)
66 
67 #include "REX/W32/KERNEL32.h"
68 #include "REX/W32/USER32.h"
69 
70 namespace SKSE
71 {
72  using namespace std::literals;
73 
74  namespace stl
75  {
76  template <class CharT>
77  using basic_zstring = std::basic_string_view<CharT>;
78 
81 
82  // owning pointer
83  template <
84  class T,
85  class = std::enable_if_t<
86  std::is_pointer_v<T>>>
87  using owner = T;
88 
89  // non-owning pointer
90  template <
91  class T,
92  class = std::enable_if_t<
93  std::is_pointer_v<T>>>
94  using observer = T;
95 
96  // non-null pointer
97  template <
98  class T,
99  class = std::enable_if_t<
100  std::is_pointer_v<T>>>
101  using not_null = T;
102 
103  namespace nttp
104  {
105  template <class CharT, std::size_t N>
106  struct string
107  {
108  using char_type = CharT;
109  using pointer = char_type*;
110  using const_pointer = const char_type*;
112  using const_reference = const char_type&;
113  using size_type = std::size_t;
114 
115  static constexpr auto npos = static_cast<std::size_t>(-1);
116 
117  consteval string(const_pointer a_string) noexcept
118  {
119  for (size_type i = 0; i < N; ++i) {
120  c[i] = a_string[i];
121  }
122  }
123 
124  [[nodiscard]] consteval const_reference operator[](size_type a_pos) const noexcept
125  {
126  assert(a_pos < N);
127  return c[a_pos];
128  }
129 
130  [[nodiscard]] consteval const_reference back() const noexcept { return (*this)[size() - 1]; }
131  [[nodiscard]] consteval const_pointer data() const noexcept { return c; }
132  [[nodiscard]] consteval bool empty() const noexcept { return this->size() == 0; }
133  [[nodiscard]] consteval const_reference front() const noexcept { return (*this)[0]; }
134  [[nodiscard]] consteval size_type length() const noexcept { return N; }
135  [[nodiscard]] consteval size_type size() const noexcept { return length(); }
136 
137  template <std::size_t POS = 0, std::size_t COUNT = npos>
138  [[nodiscard]] consteval auto substr() const noexcept
139  {
140  return string < CharT, COUNT != npos ? COUNT : N - POS > (this->data() + POS);
141  }
142 
143  char_type c[N] = {};
144  };
145 
146  template <class CharT, std::size_t N>
147  string(const CharT (&)[N]) -> string<CharT, N - 1>;
148  }
149 
150  template <class EF> //
151  requires(std::invocable<std::remove_reference_t<EF>>) //
152  class scope_exit
153  {
154  public:
155  // 1)
156  template <class Fn>
157  explicit scope_exit(Fn&& a_fn) //
158  noexcept(std::is_nothrow_constructible_v<EF, Fn> ||
159  std::is_nothrow_constructible_v<EF, Fn&>) //
160  requires(!std::is_same_v<std::remove_cvref_t<Fn>, scope_exit> &&
161  std::is_constructible_v<EF, Fn>)
162  {
163  static_assert(std::invocable<Fn>);
164 
165  if constexpr (!std::is_lvalue_reference_v<Fn> &&
166  std::is_nothrow_constructible_v<EF, Fn>) {
167  _fn.emplace(std::forward<Fn>(a_fn));
168  } else {
169  _fn.emplace(a_fn);
170  }
171  }
172 
173  // 2)
174  scope_exit(scope_exit&& a_rhs) //
175  noexcept(std::is_nothrow_move_constructible_v<EF> ||
176  std::is_nothrow_copy_constructible_v<EF>) //
177  requires(std::is_nothrow_move_constructible_v<EF> ||
178  std::is_copy_constructible_v<EF>)
179  {
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>));
182 
183  if (a_rhs.active()) {
184  if constexpr (std::is_nothrow_move_constructible_v<EF>) {
185  _fn.emplace(std::forward<EF>(*a_rhs._fn));
186  } else {
187  _fn.emplace(a_rhs._fn);
188  }
189  a_rhs.release();
190  }
191  }
192 
193  // 3)
194  scope_exit(const scope_exit&) = delete;
195 
196  ~scope_exit() noexcept
197  {
198  if (_fn.has_value()) {
199  (*_fn)();
200  }
201  }
202 
203  void release() noexcept { _fn.reset(); }
204 
205  private:
206  [[nodiscard]] bool active() const noexcept { return _fn.has_value(); }
207 
208  std::optional<std::remove_reference_t<EF>> _fn;
209  };
210 
211  template <class EF>
212  scope_exit(EF) -> scope_exit<EF>;
213 
214  template <
215  class Enum,
216  class Underlying = std::underlying_type_t<Enum>>
218  {
219  public:
220  using enum_type = Enum;
221  using underlying_type = Underlying;
222 
223  static_assert(std::is_enum_v<enum_type>, "enum_type must be an enum");
224  static_assert(std::is_integral_v<underlying_type>, "underlying_type must be an integral");
225 
226  constexpr enumeration() noexcept = default;
227 
228  constexpr enumeration(const enumeration&) noexcept = default;
229 
230  constexpr enumeration(enumeration&&) noexcept = default;
231 
232  template <class U2> // NOLINTNEXTLINE(google-explicit-constructor)
233  constexpr enumeration(enumeration<Enum, U2> a_rhs) noexcept :
234  _impl(static_cast<underlying_type>(a_rhs.get()))
235  {}
236 
237  template <class... Args>
238  constexpr enumeration(Args... a_values) noexcept //
239  requires(std::same_as<Args, enum_type>&&...) :
240  _impl((static_cast<underlying_type>(a_values) | ...))
241  {}
242 
243  ~enumeration() noexcept = default;
244 
245  constexpr enumeration& operator=(const enumeration&) noexcept = default;
246  constexpr enumeration& operator=(enumeration&&) noexcept = default;
247 
248  template <class U2>
249  constexpr enumeration& operator=(enumeration<Enum, U2> a_rhs) noexcept
250  {
251  _impl = static_cast<underlying_type>(a_rhs.get());
252  }
253 
254  constexpr enumeration& operator=(enum_type a_value) noexcept
255  {
256  _impl = static_cast<underlying_type>(a_value);
257  return *this;
258  }
259 
260  [[nodiscard]] explicit constexpr operator bool() const noexcept { return _impl != static_cast<underlying_type>(0); }
261 
262  [[nodiscard]] constexpr enum_type operator*() const noexcept { return get(); }
263  [[nodiscard]] constexpr enum_type get() const noexcept { return static_cast<enum_type>(_impl); }
264  [[nodiscard]] constexpr underlying_type underlying() const noexcept { return _impl; }
265 
266  template <class... Args>
267  constexpr enumeration& set(Args... a_args) noexcept //
268  requires(std::same_as<Args, enum_type>&&...)
269  {
270  _impl |= (static_cast<underlying_type>(a_args) | ...);
271  return *this;
272  }
273 
274  template <class... Args>
275  constexpr enumeration& reset(Args... a_args) noexcept //
276  requires(std::same_as<Args, enum_type>&&...)
277  {
278  _impl &= ~(static_cast<underlying_type>(a_args) | ...);
279  return *this;
280  }
281 
282  template <class... Args>
283  [[nodiscard]] constexpr bool any(Args... a_args) const noexcept //
284  requires(std::same_as<Args, enum_type>&&...)
285  {
286  return (_impl & (static_cast<underlying_type>(a_args) | ...)) != static_cast<underlying_type>(0);
287  }
288 
289  template <class... Args>
290  [[nodiscard]] constexpr bool all(Args... a_args) const noexcept //
291  requires(std::same_as<Args, enum_type>&&...)
292  {
293  return (_impl & (static_cast<underlying_type>(a_args) | ...)) == (static_cast<underlying_type>(a_args) | ...);
294  }
295 
296  template <class... Args>
297  [[nodiscard]] constexpr bool none(Args... a_args) const noexcept //
298  requires(std::same_as<Args, enum_type>&&...)
299  {
300  return (_impl & (static_cast<underlying_type>(a_args) | ...)) == static_cast<underlying_type>(0);
301  }
302 
303  private:
304  underlying_type _impl{ 0 };
305  };
306 
307  template <class... Args>
309  std::common_type_t<Args...>,
310  std::underlying_type_t<
311  std::common_type_t<Args...>>>;
312  }
313 }
314 
315 #define SKSE_MAKE_LOGICAL_OP(a_op, a_result) \
316  template <class E, class U1, class U2> \
317  [[nodiscard]] constexpr a_result operator a_op(enumeration<E, U1> a_lhs, enumeration<E, U2> a_rhs) noexcept \
318  { \
319  return a_lhs.get() a_op a_rhs.get(); \
320  } \
321  \
322  template <class E, class U> \
323  [[nodiscard]] constexpr a_result operator a_op(enumeration<E, U> a_lhs, E a_rhs) noexcept \
324  { \
325  return a_lhs.get() a_op a_rhs; \
326  }
327 
328 #define SKSE_MAKE_ARITHMETIC_OP(a_op) \
329  template <class E, class U> \
330  [[nodiscard]] constexpr auto operator a_op(enumeration<E, U> a_enum, U a_shift) noexcept \
331  ->enumeration<E, U> \
332  { \
333  return static_cast<E>(static_cast<U>(a_enum.get()) a_op a_shift); \
334  } \
335  \
336  template <class E, class U> \
337  constexpr auto operator a_op##=(enumeration<E, U>& a_enum, U a_shift) noexcept \
338  ->enumeration<E, U>& \
339  { \
340  return a_enum = a_enum a_op a_shift; \
341  }
342 
343 #define SKSE_MAKE_ENUMERATION_OP(a_op) \
344  template <class E, class U1, class U2> \
345  [[nodiscard]] constexpr auto operator a_op(enumeration<E, U1> a_lhs, enumeration<E, U2> a_rhs) noexcept \
346  ->enumeration<E, std::common_type_t<U1, U2>> \
347  { \
348  return static_cast<E>(static_cast<U1>(a_lhs.get()) a_op static_cast<U2>(a_rhs.get())); \
349  } \
350  \
351  template <class E, class U> \
352  [[nodiscard]] constexpr auto operator a_op(enumeration<E, U> a_lhs, E a_rhs) noexcept \
353  ->enumeration<E, U> \
354  { \
355  return static_cast<E>(static_cast<U>(a_lhs.get()) a_op static_cast<U>(a_rhs)); \
356  } \
357  \
358  template <class E, class U> \
359  [[nodiscard]] constexpr auto operator a_op(E a_lhs, enumeration<E, U> a_rhs) noexcept \
360  ->enumeration<E, U> \
361  { \
362  return static_cast<E>(static_cast<U>(a_lhs) a_op static_cast<U>(a_rhs.get())); \
363  } \
364  \
365  template <class E, class U1, class U2> \
366  constexpr auto operator a_op##=(enumeration<E, U1>& a_lhs, enumeration<E, U2> a_rhs) noexcept \
367  ->enumeration<E, U1>& \
368  { \
369  return a_lhs = a_lhs a_op a_rhs; \
370  } \
371  \
372  template <class E, class U> \
373  constexpr auto operator a_op##=(enumeration<E, U>& a_lhs, E a_rhs) noexcept \
374  ->enumeration<E, U>& \
375  { \
376  return a_lhs = a_lhs a_op a_rhs; \
377  } \
378  \
379  template <class E, class U> \
380  constexpr auto operator a_op##=(E& a_lhs, enumeration<E, U> a_rhs) noexcept \
381  ->E& \
382  { \
383  return a_lhs = *(a_lhs a_op a_rhs); \
384  }
385 
386 #define SKSE_MAKE_INCREMENTER_OP(a_op) \
387  template <class E, class U> \
388  constexpr auto operator a_op##a_op(enumeration<E, U>& a_lhs) noexcept \
389  ->enumeration<E, U>& \
390  { \
391  return a_lhs a_op## = static_cast<E>(1); \
392  } \
393  \
394  template <class E, class U> \
395  [[nodiscard]] constexpr auto operator a_op##a_op(enumeration<E, U>& a_lhs, int) noexcept \
396  ->enumeration<E, U> \
397  { \
398  const auto tmp = a_lhs; \
399  a_op##a_op a_lhs; \
400  return tmp; \
401  }
402 
403 namespace SKSE
404 {
405  namespace stl
406  {
407  template <
408  class E,
409  class U>
410  [[nodiscard]] constexpr auto operator~(enumeration<E, U> a_enum) noexcept
412  {
413  return static_cast<E>(~static_cast<U>(a_enum.get()));
414  }
415 
417  SKSE_MAKE_LOGICAL_OP(<=>, std::strong_ordering);
418 
423 
427 
430 
433 
434  template <class T>
435  class atomic_ref :
436  public std::atomic_ref<T>
437  {
438  private:
439  using super = std::atomic_ref<T>;
440 
441  public:
442  using value_type = typename super::value_type;
443 
444  explicit atomic_ref(volatile T& a_obj) noexcept(std::is_nothrow_constructible_v<super, value_type&>) :
445  super(const_cast<value_type&>(a_obj))
446  {}
447 
448  using super::super;
449  using super::operator=;
450  };
451 
452  template <class T>
453  atomic_ref(volatile T&) -> atomic_ref<T>;
454 
455  template class atomic_ref<std::int8_t>;
456  template class atomic_ref<std::uint8_t>;
457  template class atomic_ref<std::int16_t>;
458  template class atomic_ref<std::uint16_t>;
459  template class atomic_ref<std::int32_t>;
460  template class atomic_ref<std::uint32_t>;
461  template class atomic_ref<std::int64_t>;
462  template class atomic_ref<std::uint64_t>;
463 
472 
473  template <class T>
474  struct ssizeof
475  {
476  [[nodiscard]] constexpr operator std::ptrdiff_t() const noexcept { return value; }
477 
478  [[nodiscard]] constexpr std::ptrdiff_t operator()() const noexcept { return value; }
479 
480  static constexpr auto value = static_cast<std::ptrdiff_t>(sizeof(T));
481  };
482 
483  template <class T>
484  inline constexpr auto ssizeof_v = ssizeof<T>::value;
485 
486  template <class T, class U>
487  [[nodiscard]] auto adjust_pointer(U* a_ptr, std::ptrdiff_t a_adjust) noexcept
488  {
489  auto addr = a_ptr ? reinterpret_cast<std::uintptr_t>(a_ptr) + a_adjust : 0;
490  if constexpr (std::is_const_v<U> && std::is_volatile_v<U>) {
491  return reinterpret_cast<std::add_cv_t<T>*>(addr);
492  } else if constexpr (std::is_const_v<U>) {
493  return reinterpret_cast<std::add_const_t<T>*>(addr);
494  } else if constexpr (std::is_volatile_v<U>) {
495  return reinterpret_cast<std::add_volatile_t<T>*>(addr);
496  } else {
497  return reinterpret_cast<T*>(addr);
498  }
499  }
500 
501  template <class T>
502  void emplace_vtable(T* a_ptr)
503  {
504  reinterpret_cast<std::uintptr_t*>(a_ptr)[0] = T::VTABLE[0].address();
505  }
506 
507  template <class T>
508  void memzero(volatile T* a_ptr, std::size_t a_size = sizeof(T))
509  {
510  const auto begin = reinterpret_cast<volatile char*>(a_ptr);
511  constexpr char val{ 0 };
512  std::fill_n(begin, a_size, val);
513  }
514 
515  template <class... Args>
516  [[nodiscard]] inline auto pun_bits(Args... a_args) //
517  requires(std::same_as<std::remove_cv_t<Args>, bool>&&...)
518  {
519  constexpr auto ARGC = sizeof...(Args);
520 
521  std::bitset<ARGC> bits;
522  std::size_t i = 0;
523  ((bits[i++] = a_args), ...);
524 
525  if constexpr (ARGC <= std::numeric_limits<unsigned long>::digits) {
526  return bits.to_ulong();
527  } else if constexpr (ARGC <= std::numeric_limits<unsigned long long>::digits) {
528  return bits.to_ullong();
529  } else {
530  static_assert(false && sizeof...(Args));
531  }
532  }
533 
534  [[nodiscard]] inline auto utf8_to_utf16(std::string_view a_in) noexcept
535  -> std::optional<std::wstring>
536  {
537  const auto cvt = [&](wchar_t* a_dst, std::size_t a_length) {
540  0,
541  a_in.data(),
542  static_cast<int>(a_in.length()),
543  a_dst,
544  static_cast<int>(a_length));
545  };
546 
547  const auto len = cvt(nullptr, 0);
548  if (len == 0) {
549  return std::nullopt;
550  }
551 
552  std::wstring out(len, '\0');
553  if (cvt(out.data(), out.length()) == 0) {
554  return std::nullopt;
555  }
556 
557  return out;
558  }
559 
560  [[nodiscard]] inline auto utf16_to_utf8(std::wstring_view a_in) noexcept
561  -> std::optional<std::string>
562  {
563  const auto cvt = [&](char* a_dst, std::size_t a_length) {
566  0,
567  a_in.data(),
568  static_cast<int>(a_in.length()),
569  a_dst,
570  static_cast<int>(a_length),
571  nullptr,
572  nullptr);
573  };
574 
575  const auto len = cvt(nullptr, 0);
576  if (len == 0) {
577  return std::nullopt;
578  }
579 
580  std::string out(len, '\0');
581  if (cvt(out.data(), out.length()) == 0) {
582  return std::nullopt;
583  }
584 
585  return out;
586  }
587 
588  [[noreturn]] inline void report_and_fail(std::string_view a_msg, std::source_location a_loc = std::source_location::current())
589  {
590  const auto body = [&]() {
591  const std::filesystem::path p = a_loc.file_name();
592  auto filename = p.lexically_normal().generic_string();
593 
594  const std::regex r{ R"((?:^|[\\\/])(?:include|src)[\\\/](.*)$)" };
595  std::smatch matches;
596  if (std::regex_search(filename, matches, r)) {
597  filename = matches[1].str();
598  }
599 
600  return utf8_to_utf16(
601  std::format(
602  "{}({}): {}"sv,
603  filename,
604  a_loc.line(),
605  a_msg))
606  .value_or(L"<character encoding error>"s);
607  }();
608 
609  const auto caption = []() {
610  std::vector<wchar_t> buf;
611  buf.reserve(REX::W32::MAX_PATH);
612  buf.resize(REX::W32::MAX_PATH / 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  REX::W32::MessageBoxW(nullptr, body.c_str(), (caption.empty() ? nullptr : caption.c_str()), 0);
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>) {
655  return *stl::unrestricted_cast<
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 
687 namespace RE
688 {
689  using namespace std::literals;
690  namespace stl = SKSE::stl;
691 }
692 
693 namespace REL
694 {
695  using namespace std::literals;
696  namespace stl = SKSE::stl;
697 }
698 
699 #ifdef SKYRIM_SUPPORT_AE
700 # define RELOCATION_ID(SE, AE) REL::ID(AE)
701 #else
702 # define RELOCATION_ID(SE, AE) REL::ID(SE)
703 #endif
704 
705 #include "REL/REL.h"
706 
707 #ifdef _DEBUG
708 // Generates a concrete function to force the class to be included in the PDB when loading types from PDB for IDA/Ghidra
709 # define KEEP_FOR_RE() \
710  void REdebug(){};
711 #else
712 // Generates a concrete function to help with RE, does nothing on release builds
713 # define KEEP_FOR_RE()
714 #endif
715 
716 #include "RE/B/BSCoreTypes.h"
717 #include "RE/Offsets_VTABLE.h"
718 #include "RE/S/SFTypes.h"
719 
720 #ifndef SKYRIMVR
721 # include "RE/Offsets.h"
722 # include "RE/Offsets_NiRTTI.h"
723 # include "RE/Offsets_RTTI.h"
724 # include "RE/C/CreationClubMenu.h"
725 #else
726 # include "RE/Offsets_VR.h"
727 # include "RE/Offsets_VR_NiRTTI.h"
728 # include "RE/Offsets_VR_RTTI.h"
729 #endif
Definition: PCH.h:437
typename super::value_type value_type
Definition: PCH.h:442
atomic_ref(volatile T &a_obj) noexcept(std::is_nothrow_constructible_v< super, value_type & >)
Definition: PCH.h:444
Definition: PCH.h:218
Underlying underlying_type
Definition: PCH.h:221
constexpr enum_type operator*() const noexcept
Definition: PCH.h:262
constexpr bool none(Args... a_args) const noexcept requires(std
Definition: PCH.h:297
constexpr enumeration(Args... a_values) noexcept requires(std
Definition: PCH.h:238
Enum enum_type
Definition: PCH.h:220
constexpr enumeration & operator=(enum_type a_value) noexcept
Definition: PCH.h:254
constexpr bool all(Args... a_args) const noexcept requires(std
Definition: PCH.h:290
~enumeration() noexcept=default
constexpr enumeration & reset(Args... a_args) noexcept requires(std
Definition: PCH.h:275
constexpr enumeration & set(Args... a_args) noexcept requires(std
Definition: PCH.h:267
constexpr underlying_type underlying() const noexcept
Definition: PCH.h:264
constexpr enumeration() noexcept=default
constexpr bool any(Args... a_args) const noexcept requires(std
Definition: PCH.h:283
constexpr enum_type get() const noexcept
Definition: PCH.h:263
Definition: ID.h:9
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:75
atomic_ref(volatile T &) -> atomic_ref< T >
T not_null
Definition: PCH.h:101
SKSE_MAKE_ENUMERATION_OP(<<)
To unrestricted_cast(From a_from) noexcept
Definition: PCH.h:642
std::basic_string_view< CharT > basic_zstring
Definition: PCH.h:77
void memzero(volatile T *a_ptr, std::size_t a_size=sizeof(T))
Definition: PCH.h:508
void report_and_fail(std::string_view a_msg, std::source_location a_loc=std::source_location::current())
Definition: PCH.h:588
scope_exit(EF) -> scope_exit< EF >
T owner
Definition: PCH.h:87
T observer
Definition: PCH.h:94
auto utf16_to_utf8(std::wstring_view a_in) noexcept -> std::optional< std::string >
Definition: PCH.h:560
void emplace_vtable(T *a_ptr)
Definition: PCH.h:502
SKSE_MAKE_INCREMENTER_OP(+)
auto adjust_pointer(U *a_ptr, std::ptrdiff_t a_adjust) noexcept
Definition: PCH.h:487
auto utf8_to_utf16(std::string_view a_in) noexcept -> std::optional< std::wstring >
Definition: PCH.h:534
requires(std::invocable< std::remove_reference_t< EF >>) class scope_exit
Definition: PCH.h:151
SKSE_MAKE_LOGICAL_OP(==, bool)
basic_zstring< wchar_t > zwstring
Definition: PCH.h:80
constexpr auto operator~(enumeration< E, U > a_enum) noexcept -> enumeration< E, U >
Definition: PCH.h:410
auto pun_bits(Args... a_args) requires(std
Definition: PCH.h:516
SKSE_MAKE_ARITHMETIC_OP(<<)
basic_zstring< char > zstring
Definition: PCH.h:79
enumeration(Args...) -> enumeration< std::common_type_t< Args... >, std::underlying_type_t< std::common_type_t< Args... >>>
constexpr auto ssizeof_v
Definition: PCH.h:484
Definition: API.h:14
Definition: PCH.h:107
consteval bool empty() const noexcept
Definition: PCH.h:132
const char_type & const_reference
Definition: PCH.h:112
consteval auto substr() const noexcept
Definition: PCH.h:138
consteval const_reference operator[](size_type a_pos) const noexcept
Definition: PCH.h:124
const char_type * const_pointer
Definition: PCH.h:110
consteval const_pointer data() const noexcept
Definition: PCH.h:131
std::size_t size_type
Definition: PCH.h:113
consteval const_reference back() const noexcept
Definition: PCH.h:130
consteval string(const_pointer a_string) noexcept
Definition: PCH.h:117
char_type & reference
Definition: PCH.h:111
char_type * pointer
Definition: PCH.h:109
consteval size_type length() const noexcept
Definition: PCH.h:134
consteval size_type size() const noexcept
Definition: PCH.h:135
consteval const_reference front() const noexcept
Definition: PCH.h:133
CharT char_type
Definition: PCH.h:108
Definition: PCH.h:475
constexpr std::ptrdiff_t operator()() const noexcept
Definition: PCH.h:478