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