CommonLibVR
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  [[nodiscard]] inline bool contains(std::basic_string_view<value_type> a_rhs) const
165  {
166  if (a_rhs.length() > length()) {
167  return false;
168  }
169  for (size_type i = 0; i < length(); ++i) {
170  if (strncmp(&c_str()[i], a_rhs.data(), a_rhs.length()) == 0) {
171  return true;
172  }
173  }
174  return false;
175  }
176 
177  private:
178  [[nodiscard]] static inline int strncmp(const char* a_lhs, const char* a_rhs, std::size_t a_length)
179  {
180  return _strnicmp(a_lhs, a_rhs, a_length);
181  }
182 
183  [[nodiscard]] static inline int strncmp(const wchar_t* a_lhs, const wchar_t* a_rhs, std::size_t a_length)
184  {
185  return _wcsnicmp(a_lhs, a_rhs, a_length);
186  }
187 
188  inline BSFixedString* ctor(const char* a_data) { return ctor8(a_data); }
189  inline BSFixedString* ctor(const wchar_t* a_data) { return ctor16(a_data); }
190 
191  inline BSFixedString* ctor8(const char* a_data)
192  {
193  using func_t = decltype(&BSFixedString::ctor8);
194  static REL::Relocation<func_t> func{ RELOCATION_ID(67819, 69161) };
195  return func(this, a_data);
196  }
197 
198  inline BSFixedString* ctor16(const wchar_t* a_data)
199  {
200  using func_t = decltype(&BSFixedString::ctor16);
201  static REL::Relocation<func_t> func{ RELOCATION_ID(67834, 69176) };
202  return func(this, a_data);
203  }
204 
205  [[nodiscard]] inline BSStringPool::Entry* get_proxy() noexcept
206  {
207  return _data ?
208  reinterpret_cast<BSStringPool::Entry*>(const_cast<pointer>(_data)) - 1 :
209  nullptr;
210  }
211 
212  [[nodiscard]] inline const BSStringPool::Entry* get_proxy() const noexcept
213  {
214  return _data ?
215  reinterpret_cast<const BSStringPool::Entry*>(_data) - 1 :
216  nullptr;
217  }
218 
219  inline void try_acquire()
220  {
221  const auto proxy = get_proxy();
222  if (proxy) {
223  proxy->acquire();
224  }
225  }
226 
227  inline void try_release() { BSStringPool::Entry::release(_data); }
228 
229  static constexpr const value_type EMPTY[]{ 0 };
230 
231  // members
232  const_pointer _data{ nullptr }; // 0
233  };
234 
235  extern template class BSFixedString<char>;
236  extern template class BSFixedString<wchar_t>;
237  }
238 
242 
243  template <class CharT>
245  {
246  public:
247  [[nodiscard]] inline std::uint32_t operator()(const detail::BSFixedString<CharT>& a_key) const noexcept
248  {
249  return BSCRC32_<const void*>()(a_key.data());
250  }
251  };
252 }
#define RELOCATION_ID(SE, AE)
Definition: PCH.h:702
Definition: Relocation.h:210
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
bool contains(std::basic_string_view< value_type > a_rhs) const
Definition: BSFixedString.h:164
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:239
std::uint32_t operator()(const detail::BSFixedString< CharT > &a_key) const noexcept
Definition: BSFixedString.h:247
Definition: CRC.h:72