fennec
Loading...
Searching...
No Matches
string.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_STRING_H
20#define FENNEC_STRING_STRING_H
21
22#include <fennec/string/cstring.h>
23
26
27#include <fennec/math/common.h>
28
29namespace fennec
30{
31
32// Forward def
33template<typename AllocT = allocator<char>> struct _string;
34
35// Alias for default allocator
36using string = _string<>;
37
42template<typename AllocT>
43struct _string
44{
45public:
46 static constexpr size_t npos = -1;
47 using char_t = char;
49
50
51// Constructors ========================================================================================================
52
55 constexpr _string()
56 : _str() {
57 }
58
65 constexpr _string(size_t n, char c = '\0')
66 : _str(n + 1) {
67 fennec::memset(_str, c, n);
68 }
69
70 constexpr _string(const alloc_t& alloc)
71 : _str(alloc) {
72 }
73
74 constexpr _string(size_t n, char c, const alloc_t& alloc)
75 : _str(n + 1, alloc) {
76 fennec::memset(_str, c, n);
77 }
78
79 constexpr _string(const cstring& cstr)
80 : _str(cstr, cstr.size() + 1) {
81 }
82
90 template<size_t n>
91 explicit constexpr _string(const char (&str)[n])
92 : _str(str[n - 1] != '\0' ? n + 1 : n) {
93 fennec::memcpy(_str, str, n);
94 if (str[n - 1] != '\0') {
95 _str[n] = '\0';
96 }
97 }
98
103 constexpr _string(const char* buf, size_t n)
104 : _str(buf[n - 1] != '\0' ? n + 1 : n) {
105 fennec::memcpy(_str, buf, n);
106 if (buf[n - 1] != '\0') {
107 _str[n] = '\0';
108 }
109 }
110
111 constexpr _string(const string_view& view)
112 : _string(view.str, view.len) {
113 }
114
118 constexpr _string(const _string& str) = default;
119
123 constexpr _string(_string&& str) noexcept = default;
124
127 constexpr ~_string() = default;
128
129// Assignment ==========================================================================================================
130
131 constexpr _string& operator=(const cstring& cstr) {
132 _str.callocate(cstr.capacity());
133 fennec::memcpy(_str, cstr, cstr.capacity());
134 return *this;
135 }
136
137 constexpr _string& operator=(const _string& str) {
138 _str = str._str;
139 return *this;
140 }
141 constexpr _string& operator=(_string&& str) noexcept {
142 _str = fennec::move(str._str);
143 return *this;
144 }
145
146// Properties ==========================================================================================================
147
150 constexpr size_t size() const {
151 return _str.capacity() > 0 ? _str.capacity() - 1 : 0;
152 }
153
156 constexpr size_t capacity() const {
157 return _str.capacity();
158 }
159
160 constexpr bool empty() const {
161 return size() == 0;
162 }
163
164// Access ==============================================================================================================
165
170 constexpr char& operator[](size_t i) {
171 return _str[i];
172 }
173
178 constexpr const char& operator[](size_t i) const {
179 return _str[i];
180 }
181
182 constexpr char* data() {
183 return _str;
184 }
185
186 constexpr const char* data() const {
187 return _str;
188 }
189
190 constexpr const char* cstr() const {
191 return _str;
192 }
193
194// Examination =========================================================================================================
195
198 constexpr size_t length() const {
199 return find('\0');
200 }
201
207 constexpr int compare(const cstring& str, size_t i = 0, size_t n = npos) const {
208 if (i >= size()) { // bounds check
209 return -1;
210 }
211 n = fennec::min(n, fennec::max(size(), str.size()) + 1);
212
213 return ::strncmp(_str + i, str, n);
214 }
215
221 constexpr int compare(const string& str, size_t i = 0, size_t n = npos) const {
222 if (i >= size()) { // bounds check
223 return -1;
224 }
225 n = min(n, max(size(), str.size()) + 1);
226
227 return ::strncmp(_str + i, str.data(), n);
228 }
229
230 constexpr bool operator==(const cstring& str) const {
231 return compare(str) == 0;
232 }
233
234 constexpr bool operator==(const _string& str) const {
235 return compare(str) == 0;
236 }
237
243 constexpr bool contains(char c, size_t i = 0) const {
244 return find(c, i) != size();
245 }
246
251 constexpr size_t find(char c, size_t i = 0) const {
252 if (i >= size()) { // bounds check
253 return size();
254 }
255
256 const char* loc = ::strchr(_str + i, c); // get location using strchr
257 return loc ? loc - _str : size(); // return size if not found
258 }
259
264 constexpr size_t find(const string& str, size_t i = 0) const { // bounds check
265 if (i >= size()) { // bounds check
266 return size();
267 }
268
269 const char* loc = ::strstr(_str, str._str);
270 return loc ? loc - _str : size();
271 }
272
277 constexpr size_t find(const cstring& str, size_t i = 0) const {
278 if (i + str.size() > size()) { // bounds check
279 return size();
280 }
281
282 const char* loc = ::strstr(_str + i, str); // get location using strstr
283 return loc ? loc - _str : size(); // return size if not found
284 }
285
291 constexpr size_t rfind(char c, size_t i = npos) const {
292 if (size() == 0) {
293 return size();
294 }
295 i = min(i, size() - 1); // clamp i to bounds
296 do {
297 if (_str[i] == c) { // loop backwards looking for c
298 return i;
299 }
300 } while (i--);
301 return size(); // base case
302 }
303
309 constexpr size_t rfind(const cstring& str, size_t i = npos) const {
310 if (size() == 0) {
311 return size();
312 }
313 const char first = str[0];
314 i = min(i, size() - str.size());
315 do {
316 if(_str[i] == first) {
317 if (compare(str, i) == 0) {
318 return i;
319 }
320 }
321 } while (i--);
322 return size(); // base case
323 }
324
330 constexpr size_t rfind(const string& str, size_t i = npos) const {
331 if (size() == 0) {
332 return size();
333 }
334 const char first = str[0];
335 i = min(i, size() - str.size());
336 do {
337 if(_str[i] == first) {
338 if (compare(str, i) == 0) { // loop backwards looking for str
339 return i;
340 }
341 }
342 } while (i--);
343 return size(); // base case
344 }
345
351 constexpr _string substring(size_t i, size_t n = npos) const {
352 if (i >= size() || n == 0) {
353 return _string("");
354 }
355 n = fennec::min(n, size() - i);
356 _string res;
357 res._str.callocate(n + 1);
358 fennec::memcpy(res.data(), _str + i, n);
359 return res;
360 }
361
362
363
364// Modifiers ===========================================================================================================
365
366 constexpr void resize(size_t n) {
367 _str.creallocate(n + 1);
368 _str[size()] = '\0';
369 }
370
371 constexpr _string operator+(char c) const {
372 if (_str == nullptr) {
373 return _string(1, c);
374 }
375 _string res;
376 res._str.callocate(capacity() + 1);
377 fennec::memcpy(res.data(), _str, size());
378 res[size()] = c;
379 return res;
380 }
381
382 friend constexpr _string operator+(char c, const _string& str) {
383 _string res(1, c);
384 return res += str;
385 }
386
387 constexpr _string operator+(const cstring& cstr) const {
388 if (_str == nullptr) {
389 return _string(cstr);
390 }
391 _string res;
392 res._str.callocate(size() + cstr.size() + 1);
393 fennec::memcpy(res.data(), _str, size());
394 fennec::memcpy(res.data() + size(), cstr, cstr.size());
395 return res;
396 }
397
398 constexpr _string operator+(const _string& str) const {
399 if (_str == nullptr) {
400 return _string(str);
401 }
402 if (str.data() == nullptr) {
403 return _string(*this);
404 }
405 _string res;
406 res._str.callocate(size() + str.size() + 1);
407 fennec::memcpy(res.data(), _str, size());
408 fennec::memcpy(res.data() + size(), str.data(), str.size());
409 return res;
410 }
411
412 constexpr _string& operator+=(char c) {
413 if (_str == nullptr) {
414 _str.callocate(2);
415 _str[0] = c;
416 return *this;
417 }
418 _str.creallocate(capacity() + 1);
419 _str[size() - 1] = c;
420 return *this;
421 }
422
423 constexpr _string& operator+=(const cstring& cstr) {
424 if (_str == nullptr) {
425 return *this = cstr;
426 }
427 size_t middle = size();
428 _str.creallocate(middle + cstr.size() + 1);
429 fennec::memcpy(_str + middle, cstr, cstr.size());
430 return *this;
431 }
432
433 constexpr _string& operator+=(const _string& str) {
434 if (_str == nullptr) {
435 return *this = str;
436 }
437 if (str.data() == nullptr) {
438 return *this;
439 }
440 size_t middle = size();
441 _str.creallocate(middle + str.size() + 1);
442 fennec::memcpy(_str + middle, str.data(), str.size());
443 return *this;
444 }
445
446
447// Iteration ===========================================================================================================
448
449 constexpr char* begin() {
450 return _str.data();
451 }
452
453 constexpr const char* begin() const {
454 return _str.data();
455 }
456
457 constexpr char* end() {
458 return _str.data() + _str.capacity();
459 }
460
461 constexpr const char* end() const {
462 return _str.data() + _str.capacity();
463 }
464
465
466private:
467 alloc_t _str;
468};
469
470template<>
471struct hash<string> : hash<byte_array> {
472 constexpr size_t operator()(const string& str) const {
473 return hash<byte_array>::operator()(byte_array(str.data(), str.size()));
474 }
475};
476
477}
478
479
480#endif // FENNEC_STRING_STRING_H
This header contains structures and classes related to allocating blocks of memory.
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 char & operator[](size_t i)
Array Access Operator.
Definition string.h:170
constexpr size_t find(const cstring &str, size_t i=0) const
Finds the index of the first occurrence of str in the string.
Definition string.h:277
constexpr size_t find(const string &str, size_t i=0) const
Finds the index of the first occurrence of str in the string.
Definition string.h:264
constexpr _string(const _string &str)=default
String Copy Constructor.
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 string.h:330
constexpr bool contains(char c, size_t i=0) const
Check if the string contains a character.
Definition string.h:243
constexpr _string(const char(&str)[n])
Buffer Constructor, wraps the provided C-Style string, appending a null-terminator if not present.
Definition string.h:91
constexpr _string(_string &&str) noexcept=default
String Move Constructor.
constexpr const char & operator[](size_t i) const
Const-Array Access Operator.
Definition string.h:178
constexpr _string()
Default Constructor, initializes empty string.
Definition string.h:55
constexpr size_t rfind(char c, size_t i=npos) const
Finds the index of the last occurrence of c in the string.
Definition string.h:291
constexpr _string(size_t n, char c='\0')
Sized Constructor, initializes a null-terminated string of size n with ‘'c’...`.
Definition string.h:65
constexpr size_t length() const
Definition string.h:198
constexpr ~_string()=default
Destructor, cleans up underlying allocation.
constexpr size_t size() const
Definition string.h:150
constexpr _string substring(size_t i, size_t n=npos) const
Retrieve a substring of a string.
Definition string.h:351
constexpr size_t capacity() const
Definition string.h:156
constexpr size_t find(char c, size_t i=0) const
Finds the index of the first occurrence of c in the string.
Definition string.h:251
constexpr _string(const char *buf, size_t n)
Buffer Constructor, wraps the provided C-Style string, appending a null-terminator if not present.
Definition string.h:103
constexpr size_t rfind(const cstring &str, size_t i=npos) const
Finds the index of the last occurrence of str in the string.
Definition string.h:309
constexpr int compare(const string &str, size_t i=0, size_t n=npos) const
String Comparison.
Definition string.h:221
constexpr int compare(const cstring &str, size_t i=0, size_t n=npos) const
String Comparison.
Definition string.h:207
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 value_t * data()
Getter for the real pointer to the allocated block of memory.
Definition allocator.h:624
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 cstring.h:64
constexpr size_t capacity() const
Definition cstring.h:193
constexpr size_t size() const
Definition cstring.h:187