CommonLibSSE (Parapets fork)
Loading...
Searching...
No Matches
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
6namespace 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;
17 using const_pointer = 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
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
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{ Offset::BSFixedString::Ctor8 };
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{ Offset::BSFixedString::Ctor16 };
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}
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
BSFixedString & operator=(BSFixedString &&a_rhs)
Definition: BSFixedString.h:70
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
BSFixedString & operator=(const_pointer a_string)
Definition: BSFixedString.h:80
const_reference back() const noexcept
Definition: BSFixedString.h:114
const_pointer c_str() const noexcept
Definition: BSFixedString.h:123
const value_type & const_reference
Definition: BSFixedString.h:19
BSFixedString & operator=(const T &a_string)
Definition: BSFixedString.h:97
~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
constexpr bool empty() const noexcept
Definition: BSFixedString.h:127
BSFixedString & operator=(const BSFixedString &a_rhs)
Definition: BSFixedString.h:60
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
Definition: Relocation.h:858
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