fennec
Loading...
Searching...
No Matches
wstring.h
1// =====================================================================================================================
2// fennec, a free and open source game engine
3// Copyright © 2025 Medusa Slockbower
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <https://www.gnu.org/licenses/>.
17// =====================================================================================================================
18
19#ifndef FENNEC_STRING_WSTRING_H
20#define FENNEC_STRING_WSTRING_H
21
22#include <fennec/string/detail/_ctype.h>
23#include <fennec/string/wcstring.h>
24
25#include <fennec/lang/assert.h>
26
29
30#include <fennec/math/common.h>
31
32namespace fennec
33{
34
35// Forward def
36template<typename AllocT = allocator<wchar_t>> struct _wstring;
37
38// Alias for default allocator
39using wstring = _wstring<>;
40
45template<typename AllocT>
47{
48public:
49 static constexpr size_t npos = -1;
50 using char_t = wchar_t;
52
53
54// Constructors ========================================================================================================
55
58 constexpr _wstring()
59 : _str() {
60 }
61
68 constexpr _wstring(size_t n, wchar_t c = '\0')
69 : _str(n + 1) {
70 fennec::wmemset(_str, c, n);
71 }
72
73 constexpr _wstring(const alloc_t& alloc)
74 : _str(alloc) {
75 }
76
77 constexpr _wstring(size_t n, wchar_t c, const alloc_t& alloc)
78 : _str(n + 1, alloc) {
79 fennec::wmemset(_str, c, n);
80 }
81
82 constexpr _wstring(const wcstring& cstr)
83 : _str(cstr, cstr.size() + 1) {
84 }
85
90 template<size_t n>
91 explicit constexpr _wstring(const wchar_t (&str)[n])
92 : _str(str[n - 1] != '\0' ? n + 1 : n) {
93 fennec::wmemcpy(_str, str, n);
94 if (str[n - 1] != '\0') {
95 _str[n] = '\0';
96 }
97 }
98
103 constexpr _wstring(const wchar_t* buf, size_t n)
104 : _str(buf[n - 1] != '\0' ? n + 1 : n) {
105 fennec::wmemcpy(_str, buf, n);
106 if (buf[n - 1] != '\0') {
107 _str[n] = '\0';
108 }
109 }
110
114 constexpr _wstring(const _wstring& str) = default;
115
119 constexpr _wstring(_wstring&& str) noexcept = default;
120
123 constexpr ~_wstring() = default;
124
125// Assignment ==========================================================================================================
126
127 constexpr _wstring& operator=(const wcstring& cstr) {
128 _str.callocate(cstr.capacity());
129 fennec::wmemcpy(_str, cstr, cstr.capacity());
130 return *this;
131 }
132
133 constexpr _wstring& operator=(const _wstring& str) = default;
134 constexpr _wstring& operator=(_wstring&& str) noexcept = default;
135
136// Properties ==========================================================================================================
137
140 constexpr size_t size() const {
141 return _str.capacity() > 0 ? _str.capacity() - 1 : 0;
142 }
143
146 constexpr size_t capacity() const {
147 return _str.capacity();
148 }
149
150 constexpr bool empty() const {
151 return size() == 0;
152 }
153
154// Access ==============================================================================================================
155
160 constexpr wchar_t& operator[](size_t i) {
161 return _str[i];
162 }
163
168 constexpr const wchar_t& operator[](size_t i) const {
169 return _str[i];
170 }
171
172 constexpr wchar_t* data() {
173 return _str;
174 }
175
176 constexpr const wchar_t* data() const {
177 return _str;
178 }
179
180 constexpr const wchar_t* cstr() const {
181 return _str;
182 }
183
184// Examination =========================================================================================================
185
188 constexpr size_t length() const {
189 return find('\0');
190 }
191
197 constexpr int compare(const wcstring& str, size_t i = 0, size_t n = npos) const {
198 if (i >= size()) { // bounds check
199 return -1;
200 }
201 n = fennec::min(n, fennec::max(_str, str.size()) + 1);
202
203 return ::wcsncmp(_str + i, str, n);
204 }
205
211 constexpr int compare(const _wstring& str, size_t i = 0, size_t n = npos) const {
212 if (i >= size()) { // bounds check
213 return -1;
214 }
215 n = min(n, max(size(), str.size()) + 1);
216
217 return ::wcsncmp(_str + i, str.data(), n);
218 }
219
220 constexpr bool operator==(const wcstring& str) const {
221 return compare(str) == 0;
222 }
223
224 constexpr bool operator==(const _wstring& str) const {
225 return compare(str) == 0;
226 }
227
233 constexpr bool contains(char c, size_t i = 0) const {
234 return find(c, i) != size();
235 }
236
241 constexpr size_t find(wchar_t c, size_t i = 0) const {
242 if (i >= size()) { // bounds check
243 return size();
244 }
245
246 const wchar_t* loc = ::wcschr(_str + i, c); // get location using strchr
247 return loc ? loc - _str : size(); // return size if not found
248 }
249
254 constexpr size_t find(const _wstring& str, size_t i = 0) const { // bounds check
255 if (i >= size()) { // bounds check
256 return size();
257 }
258
259 const wchar_t* loc = ::wcsstr(_str, str);
260 return loc ? loc - _str : size();
261 }
262
267 constexpr size_t find(const wcstring& str, size_t i = 0) const {
268 if (i + str.size() > size()) { // bounds check
269 return size();
270 }
271
272 const wchar_t* loc = ::wcsstr(_str + i, str); // get location using strstr
273 return loc ? loc - _str : size(); // return size if not found
274 }
275
281 constexpr size_t rfind(wchar_t c, size_t i = npos) const {
282 if (size() == 0) {
283 return size();
284 }
285 i = min(i, size() - 1); // clamp i to bounds
286 do {
287 if (_str[i] == c) { // loop backwards looking for c
288 return i;
289 }
290 } while (i--);
291 return size(); // base case
292 }
293
299 constexpr size_t rfind(const wcstring& str, size_t i = npos) const {
300 if (size() == 0) {
301 return size();
302 }
303 const wchar_t first = str[0];
304 i = min(i, size() - str.size());
305 do {
306 if(_str[i] == first) {
307 if (compare(str, i) == 0) {
308 return i;
309 }
310 }
311 } while (i--);
312 return size(); // base case
313 }
314
320 constexpr size_t rfind(const string& str, size_t i = npos) const {
321 if (size() == 0) {
322 return size();
323 }
324 const wchar_t first = str[0];
325 i = min(i, size() - str.size());
326 do {
327 if(_str[i] == first) {
328 if (compare(str, i) == 0) { // loop backwards looking for str
329 return i;
330 }
331 }
332 } while (i--);
333 return size(); // base case
334 }
335
341 constexpr _wstring substring(size_t i, size_t n = npos) const {
342 if (i >= size()) {
343 return _wstring("");
344 }
345 n = fennec::min(n, size() - i);
346 _wstring res;
347 res._str.callocate(n + 1);
348 fennec::wmemcpy(res.data(), _str + i, n);
349 return res;
350 }
351
352
353
354// Modifiers ===========================================================================================================
355
356 constexpr void resize(size_t n) {
357 _str.creallocate(n + 1);
358 _str[size()] = '\0';
359 }
360
361 constexpr _wstring operator+(wchar_t c) const {
362 if (_str == nullptr) {
363 return _wstring(1, c);
364 }
365 _wstring res;
366 res._str.callocate(capacity() + 1);
367 fennec::wmemcpy(res.data(), _str, size());
368 res[size()] = c;
369 return res;
370 }
371
372 friend constexpr _wstring operator+(wchar_t c, const _wstring& str) {
373 _wstring res(1, c);
374 return res += str;
375 }
376
377 constexpr _wstring operator+(const wcstring& cstr) const {
378 if (_str == nullptr) {
379 return _wstring(cstr);
380 }
381 _wstring res;
382 res._str.callocate(size() + cstr.size() + 1);
383 fennec::wmemcpy(res.data(), _str, size());
384 fennec::wmemcpy(res.data() + size(), cstr, cstr.size());
385 return res;
386 }
387
388 constexpr _wstring operator+(const _wstring& str) const {
389 if (_str == nullptr) {
390 return _wstring(str);
391 }
392 if (str.data() == nullptr) {
393 return _wstring(*this);
394 }
395 _wstring res;
396 res._str.callocate(size() + str.size() + 1);
397 fennec::wmemcpy(res.data(), _str, size());
398 fennec::wmemcpy(res.data() + size(), str.data(), str.size());
399 return res;
400 }
401
402 constexpr _wstring& operator+=(wchar_t c) {
403 if (_str == nullptr) {
404 _str.callocate(2);
405 _str[0] = c;
406 return *this;
407 }
408 _str.creallocate(capacity() + 1);
409 _str[size() - 1] = c;
410 return *this;
411 }
412
413 constexpr _wstring& operator+=(const wcstring& cstr) {
414 if (_str == nullptr) {
415 return *this = cstr;
416 }
417 size_t middle = size();
418 _str.creallocate(middle + cstr.size() + 1);
419 fennec::wmemcpy(_str + middle, cstr, cstr.size());
420 return *this;
421 }
422
423 constexpr _wstring& operator+=(const _wstring& str) {
424 if (_str == nullptr) {
425 return *this = str;
426 }
427 if (str.data() == nullptr) {
428 return *this;
429 }
430 size_t middle = size();
431 _str.creallocate(middle + str.size() + 1);
432 fennec::wmemcpy(_str + middle, str.data(), str.size());
433 return *this;
434 }
435
436
437private:
438 alloc_t _str;
439};
440
441template<>
442struct hash<wstring> : hash<byte_array> {
443 constexpr size_t operator()(const string& str) const {
444 return hash<byte_array>::operator()(byte_array(str.data(), str.size()));
445 }
446};
447
448}
449
450
451#endif // FENNEC_STRING_WSTRING_H
This header contains structures and classes related to allocating blocks of memory.
Assertions
Common
constexpr genType min(genType x, genType y)
Returns if otherwise it returns .
Definition common.h:688
constexpr genType max(genType x, genType y)
Returns if , otherwise it returns .
Definition common.h:705
This header contains functions related to analyzing, modifying or copying buffers interpreted as byte...
constexpr size_t size() const
Definition string.h:150
Struct for wrapping c-style strings.
Definition wstring.h:47
constexpr _wstring(const _wstring &str)=default
String Copy Constructor.
constexpr _wstring substring(size_t i, size_t n=npos) const
Retrieve a substring of a string.
Definition wstring.h:341
constexpr size_t find(wchar_t c, size_t i=0) const
Finds the index of the first occurrence of c in the string.
Definition wstring.h:241
constexpr size_t find(const wcstring &str, size_t i=0) const
Finds the index of the first occurrence of str in the string.
Definition wstring.h:267
constexpr int compare(const _wstring &str, size_t i=0, size_t n=npos) const
String Comparison.
Definition wstring.h:211
constexpr ~_wstring()=default
Destructor, cleans up underlying allocation.
constexpr bool contains(char c, size_t i=0) const
Check if the string contains a character.
Definition wstring.h:233
constexpr const wchar_t & operator[](size_t i) const
Const-Array Access Operator.
Definition wstring.h:168
constexpr _wstring(const wchar_t(&str)[n])
Buffer Constructor, wraps the provided C-Style string, appending a null-terminator if not present.
Definition wstring.h:91
constexpr wchar_t & operator[](size_t i)
Array Access Operator.
Definition wstring.h:160
constexpr size_t find(const _wstring &str, size_t i=0) const
Finds the index of the first occurrence of str in the string.
Definition wstring.h:254
constexpr size_t length() const
Definition wstring.h:188
constexpr _wstring(_wstring &&str) noexcept=default
String Move Constructor.
constexpr _wstring(size_t n, wchar_t c='\0')
Sized Constructor, initializes a null-terminated string of size n with ‘'c’...`.
Definition wstring.h:68
constexpr size_t size() const
Definition wstring.h:140
constexpr size_t capacity() const
Definition wstring.h:146
constexpr size_t rfind(const wcstring &str, size_t i=npos) const
Finds the index of the last occurrence of str in the string.
Definition wstring.h:299
constexpr size_t rfind(const string &str, size_t i=npos) const
Finds the index of the last occurrence of str in the string.
Definition wstring.h:320
constexpr _wstring(const wchar_t *buf, size_t n)
Buffer Constructor, wraps the provided C-Style string, appending a null-terminator if not present.
Definition wstring.h:103
constexpr _wstring()
Default Constructor, initializes empty string.
Definition wstring.h:58
constexpr int compare(const wcstring &str, size_t i=0, size_t n=npos) const
String Comparison.
Definition wstring.h:197
constexpr size_t rfind(wchar_t c, size_t i=npos) const
Finds the index of the last occurrence of c in the string.
Definition wstring.h:281
constexpr void callocate(size_t n, align_t align=zero< align_t >()) noexcept
Allocate a block of memory for the allocation. If there is already an allocated block of memory,...
Definition allocator.h:498
constexpr size_t capacity() const
Getter for the number of elements n of type T that the allocation can hold.
Definition allocator.h:617
constexpr void creallocate(size_t n, align_t align=zero< align_t >()) noexcept
Reallocate the block with a new size. Contents are copied to the new allocation.
Definition allocator.h:541
This struct wraps c-style strings.
Definition wcstring.h:60
constexpr size_t capacity() const
Definition wcstring.h:179
constexpr size_t size() const
Definition wcstring.h:175