CommonLibSSE (powerof3)
BSFixedString.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "RE/B/BSStringPool.h"
4 #include "RE/C/CRC.h"
5 
6 namespace RE
7 {
8  namespace detail
9  {
10  template <class CharT>
12  {
13  public:
14  using size_type = std::uint32_t;
15  using value_type = CharT;
16  using pointer = value_type*;
17  using const_pointer = const value_type*;
19  using const_reference = const value_type&;
20 
21  constexpr BSFixedString() noexcept = default;
22 
23  inline BSFixedString(const BSFixedString& a_rhs) :
24  _data(a_rhs._data)
25  {
26  try_acquire();
27  }
28 
29  inline BSFixedString(BSFixedString&& a_rhs) :
30  _data(a_rhs._data)
31  {
32  a_rhs._data = nullptr;
33  }
34 
35  inline BSFixedString(const_pointer a_string)
36  {
37  if (a_string) {
38  ctor(a_string);
39  }
40  }
41 
42  template <
43  class T,
44  std::enable_if_t<
45  std::conjunction_v<
46  std::is_convertible<const T&, std::basic_string_view<value_type>>,
47  std::negation<
48  std::is_convertible<const T&, const_pointer>>>,
49  int> = 0>
50  inline BSFixedString(const T& a_string)
51  {
52  const auto view = static_cast<std::basic_string_view<value_type>>(a_string);
53  if (!view.empty()) {
54  ctor(view.data());
55  }
56  }
57 
58  inline ~BSFixedString() { try_release(); }
59 
60  inline BSFixedString& operator=(const BSFixedString& a_rhs)
61  {
62  if (this != std::addressof(a_rhs)) {
63  try_release();
64  _data = a_rhs._data;
65  try_acquire();
66  }
67  return *this;
68  }
69 
71  {
72  if (this != std::addressof(a_rhs)) {
73  try_release();
74  _data = a_rhs._data;
75  a_rhs._data = nullptr;
76  }
77  return *this;
78  }
79 
81  {
82  try_release();
83  if (a_string) {
84  ctor(a_string);
85  }
86  return *this;
87  }
88 
89  template <
90  class T,
91  std::enable_if_t<
92  std::conjunction_v<
93  std::is_convertible<const T&, std::basic_string_view<value_type>>,
94  std::negation<
95  std::is_convertible<const T&, const_pointer>>>,
96  int> = 0>
97  inline BSFixedString& operator=(const T& a_string)
98  {
99  const auto view = static_cast<std::basic_string_view<value_type>>(a_string);
100  try_release();
101  if (!view.empty()) {
102  ctor(view.data());
103  }
104  return *this;
105  }
106 
107  [[nodiscard]] inline const_reference operator[](size_type a_pos) const noexcept
108  {
109  assert(a_pos < size());
110  return _data[a_pos];
111  }
112 
113  [[nodiscard]] inline const_reference front() const noexcept { return _data[0]; }
114  [[nodiscard]] inline const_reference back() const noexcept { return _data[size() - 1]; }
115 
116  [[nodiscard]] inline const_pointer data() const noexcept
117  {
118  const auto proxy = get_proxy();
119  const auto cstr = proxy ? proxy->template data<value_type>() : nullptr;
120  return cstr ? cstr : EMPTY;
121  }
122 
123  [[nodiscard]] inline const_pointer c_str() const noexcept { return data(); }
124 
125  [[nodiscard]] constexpr operator std::basic_string_view<value_type>() const { return { c_str(), length() }; }
126 
127  [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
128 
129  [[nodiscard]] constexpr size_type size() const noexcept
130  {
131  const auto proxy = get_proxy();
132  return proxy ? proxy->size() : 0;
133  }
134 
135  [[nodiscard]] constexpr size_type length() const noexcept { return size(); }
136 
137  [[nodiscard]] inline friend bool operator==(const BSFixedString& a_lhs, const BSFixedString& a_rhs) noexcept
138  {
139  return a_lhs._data == a_rhs._data || a_lhs.empty() && a_rhs.empty();
140  }
141 
142  [[nodiscard]] inline friend bool operator!=(const BSFixedString& a_lhs, const BSFixedString& a_rhs) noexcept { return !(a_lhs == a_rhs); }
143 
144  [[nodiscard]] inline friend bool operator==(const BSFixedString& a_lhs, std::basic_string_view<value_type> a_rhs)
145  {
146  if (a_lhs.empty() && a_rhs.empty()) {
147  return true;
148  } else if (const auto length = a_lhs.length(); length != a_rhs.length()) {
149  return false;
150  } else {
151  return strncmp(a_lhs.c_str(), a_rhs.data(), length) == 0;
152  }
153  }
154 
155  [[nodiscard]] inline friend bool operator!=(const BSFixedString& a_lhs, std::basic_string_view<value_type> a_rhs) { return !(a_lhs == a_rhs); }
156  [[nodiscard]] inline friend bool operator==(std::basic_string_view<value_type> a_lhs, const BSFixedString& a_rhs) { return a_rhs == a_lhs; }
157  [[nodiscard]] inline friend bool operator!=(std::basic_string_view<value_type> a_lhs, const BSFixedString& a_rhs) { return !(a_lhs == a_rhs); }
158 
159  [[nodiscard]] inline friend bool operator==(const BSFixedString& a_lhs, const_pointer a_rhs) { return a_lhs == std::basic_string_view<value_type>(a_rhs ? a_rhs : EMPTY); }
160  [[nodiscard]] inline friend bool operator!=(const BSFixedString& a_lhs, const_pointer a_rhs) { return !(a_lhs == a_rhs); }
161  [[nodiscard]] inline friend bool operator==(const_pointer a_lhs, const BSFixedString& a_rhs) { return a_rhs == a_lhs; }
162  [[nodiscard]] inline friend bool operator!=(const_pointer a_lhs, const BSFixedString& a_rhs) { return !(a_lhs == a_rhs); }
163 
164  private:
165  [[nodiscard]] static inline int strncmp(const char* a_lhs, const char* a_rhs, std::size_t a_length)
166  {
167  return _strnicmp(a_lhs, a_rhs, a_length);
168  }
169 
170  [[nodiscard]] static inline int strncmp(const wchar_t* a_lhs, const wchar_t* a_rhs, std::size_t a_length)
171  {
172  return _wcsnicmp(a_lhs, a_rhs, a_length);
173  }
174 
175  inline BSFixedString* ctor(const char* a_data) { return ctor8(a_data); }
176  inline BSFixedString* ctor(const wchar_t* a_data) { return ctor16(a_data); }
177 
178  inline BSFixedString* ctor8(const char* a_data)
179  {
180  using func_t = decltype(&BSFixedString::ctor8);
181  REL::Relocation<func_t> func{ REL::ID(69161) };
182  return func(this, a_data);
183  }
184 
185  inline BSFixedString* ctor16(const wchar_t* a_data)
186  {
187  using func_t = decltype(&BSFixedString::ctor16);
188  REL::Relocation<func_t> func{ REL::ID(69176) };
189  return func(this, a_data);
190  }
191 
192  [[nodiscard]] inline BSStringPool::Entry* get_proxy() noexcept
193  {
194  return _data ?
195  reinterpret_cast<BSStringPool::Entry*>(const_cast<pointer>(_data)) - 1 :
196  nullptr;
197  }
198 
199  [[nodiscard]] inline const BSStringPool::Entry* get_proxy() const noexcept
200  {
201  return _data ?
202  reinterpret_cast<const BSStringPool::Entry*>(_data) - 1 :
203  nullptr;
204  }
205 
206  inline void try_acquire()
207  {
208  const auto proxy = get_proxy();
209  if (proxy) {
210  proxy->acquire();
211  }
212  }
213 
214  inline void try_release() { BSStringPool::Entry::release(_data); }
215 
216  static constexpr const value_type EMPTY[]{ 0 };
217 
218  // members
219  const_pointer _data{ nullptr }; // 0
220  };
221 
222  extern template class BSFixedString<char>;
223  extern template class BSFixedString<wchar_t>;
224  }
225 
229 
230  template <class CharT>
232  {
233  public:
234  [[nodiscard]] inline std::uint32_t operator()(const detail::BSFixedString<CharT>& a_key) const noexcept
235  {
236  return BSCRC32_<const void*>()(a_key.data());
237  }
238  };
239 }
Definition: Relocation.h:841
Definition: Relocation.h:867
static void release(const char *&a_entry)
Definition: BSStringPool.h:23
Definition: BSFixedString.h:12
constexpr size_type length() const noexcept
Definition: BSFixedString.h:135
friend bool operator==(std::basic_string_view< value_type > a_lhs, const BSFixedString &a_rhs)
Definition: BSFixedString.h:156
value_type & reference
Definition: BSFixedString.h:18
constexpr BSFixedString() noexcept=default
CharT value_type
Definition: BSFixedString.h:15
BSFixedString(BSFixedString &&a_rhs)
Definition: BSFixedString.h:29
friend bool operator!=(const BSFixedString &a_lhs, std::basic_string_view< value_type > a_rhs)
Definition: BSFixedString.h:155
const_reference front() const noexcept
Definition: BSFixedString.h:113
friend bool operator!=(const BSFixedString &a_lhs, const BSFixedString &a_rhs) noexcept
Definition: BSFixedString.h:142
BSFixedString(const_pointer a_string)
Definition: BSFixedString.h:35
friend bool operator!=(std::basic_string_view< value_type > a_lhs, const BSFixedString &a_rhs)
Definition: BSFixedString.h:157
value_type * pointer
Definition: BSFixedString.h:16
BSFixedString(const T &a_string)
Definition: BSFixedString.h:50
friend bool operator==(const BSFixedString &a_lhs, const BSFixedString &a_rhs) noexcept
Definition: BSFixedString.h:137
friend bool operator==(const BSFixedString &a_lhs, const_pointer a_rhs)
Definition: BSFixedString.h:159
friend bool operator==(const_pointer a_lhs, const BSFixedString &a_rhs)
Definition: BSFixedString.h:161
friend bool operator!=(const_pointer a_lhs, const BSFixedString &a_rhs)
Definition: BSFixedString.h:162
const_reference back() const noexcept
Definition: BSFixedString.h:114
const_pointer c_str() const noexcept
Definition: BSFixedString.h:123
BSFixedString & operator=(const_pointer a_string)
Definition: BSFixedString.h:80
const value_type & const_reference
Definition: BSFixedString.h:19
~BSFixedString()
Definition: BSFixedString.h:58
friend bool operator==(const BSFixedString &a_lhs, std::basic_string_view< value_type > a_rhs)
Definition: BSFixedString.h:144
const_reference operator[](size_type a_pos) const noexcept
Definition: BSFixedString.h:107
const_pointer data() const noexcept
Definition: BSFixedString.h:116
const value_type * const_pointer
Definition: BSFixedString.h:17
BSFixedString & operator=(BSFixedString &&a_rhs)
Definition: BSFixedString.h:70
constexpr bool empty() const noexcept
Definition: BSFixedString.h:127
friend bool operator!=(const BSFixedString &a_lhs, const_pointer a_rhs)
Definition: BSFixedString.h:160
constexpr size_type size() const noexcept
Definition: BSFixedString.h:129
std::uint32_t size_type
Definition: BSFixedString.h:14
BSFixedString & operator=(const T &a_string)
Definition: BSFixedString.h:97
BSFixedString & operator=(const BSFixedString &a_rhs)
Definition: BSFixedString.h:60
Definition: AbsorbEffect.h:6
detail::BSFixedString< char > BSFixedString
Definition: BSFixedString.h:226
std::uint32_t operator()(const detail::BSFixedString< CharT > &a_key) const noexcept
Definition: BSFixedString.h:234
Definition: CRC.h:72