fennec
Loading...
Searching...
No Matches
cstring.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_CSTRING_H
20#define FENNEC_STRING_CSTRING_H
21
22#include <fennec/string/detail/_ctype.h>
23#include <fennec/memory/detail/_string.h>
24
25#include <fennec/lang/assert.h>
26
27#include <fennec/math/common.h>
28#include <fennec/memory/bytes.h>
29
30namespace fennec
31{
32
33// TODO: Document
34
35using ::isalnum;
36using ::isalpha;
37using ::islower;
38using ::isupper;
39using ::isdigit;
40using ::isxdigit;
41using ::iscntrl;
42using ::isgraph;
43using ::isspace;
44using ::isblank;
45using ::isprint;
46using ::ispunct;
47
48using ::tolower;
49using ::toupper;
50
51
52struct string_view {
53 const char* str;
54 size_t len;
55};
56
63struct cstring
64{
65public:
66 static constexpr size_t npos = -1;
67 using char_t = char;
68
69// Constructors ========================================================================================================
70
73 constexpr cstring()
74 : _str(nullptr), _size(0), _const(true) {
75 }
76
79 constexpr cstring(nullptr_t)
80 : _str(nullptr), _size(0), _const(true) {
81 }
82
87 constexpr cstring(char* str, size_t n)
88 : _str(str)
89 , _size(n - 1)
90 , _const(false) {
91 if constexpr(not is_constant_evaluated()) {
92 assert(_str[n - 1] == '\0', "Invalid NTBS.");
93 }
94 }
95
100 template<size_t n>
101 constexpr cstring(char(&str)[n])
102 : _str(str)
103 , _size(n - 1)
104 , _const(false) {
105 if constexpr(not is_constant_evaluated()) {
106 assert(_str[n - 1] == '\0', "Invalid NTBS.");
107 }
108 }
109
114 constexpr cstring(const char* str, size_t n)
115 : _cstr(str)
116 , _size(n - 1)
117 , _const(true) {
118 if constexpr(not is_constant_evaluated()) {
119 assert(_str[n - 1] == '\0', "Invalid NTBS.");
120 }
121 }
122
127 template<size_t n>
128 constexpr cstring(const char(&str)[n])
129 : _cstr(str)
130 , _size(n - 1)
131 , _const(true) {
132 if constexpr(not is_constant_evaluated()) {
133 assert(_str[n - 1] == '\0', "Invalid NTBS.");
134 }
135 }
136
140 constexpr cstring(cstring&& str) noexcept
141 : _cstr(str._cstr)
142 , _size(str._size)
143 , _const(str._const) {
144 str._cstr = nullptr;
145 str._size = 0;
146 str._const = true;
147 }
148
149 // TODO: Document
150 constexpr cstring(const cstring&) = delete;
151 constexpr ~cstring() = default;
152
153 constexpr cstring& operator=(nullptr_t) {
154 _str = nullptr, _size = 0, _const = true;
155 return *this;
156 }
157
158 // TODO: Document
159 template<size_t n>
160 constexpr cstring& operator=(char(&str)[n]) {
161 assert(_str[n - 1] == '\0', "Invalid NTBS.");
162 _str = str, _size = n - 1, _const = false;
163 return *this;
164 }
165
166 // TODO: Document
167 template<size_t n>
168 constexpr cstring& operator=(const char(&str)[n]) {
169 assert(str[n - 1] == '\0', "Invalid NTBS.");
170 _cstr = str; _size = n - 1; _const = true;
171 return *this;
172 }
173
174 // TODO: Document
175 constexpr cstring& operator=(cstring&& str) noexcept {
176 _cstr = str._cstr; str._cstr = nullptr;
177 _size = str._size; str._size = 0;
178 _const = str._const; str._const = true;
179 return *this;
180 }
181
182
183// Properties ==========================================================================================================
184
187 constexpr size_t size() const {
188 return _size;
189 }
190
193 constexpr size_t capacity() const {
194 return _size + 1;
195 }
196
197 constexpr bool empty() const {
198 return _cstr == nullptr || _size == 0;
199 }
200
201
202// Access ==============================================================================================================
203
208 constexpr char& operator[](size_t i) {
209 assertd(not _const, "Attempted to Access Const-Qualified Memory as Non-Const");
210 assertd(i < size(), "Array Out of Bounds");
211 return _str[i];
212 }
213
218 constexpr char operator[](size_t i) const {
219 assertd(i < size(), "Array Out of Bounds");
220 return _cstr[i];
221 }
222
226 constexpr char* data() {
227 return _str;
228 }
229
233 constexpr const char* data() const {
234 return _cstr;
235 }
236
239 constexpr operator const char*() const {
240 return _cstr;
241 }
242
243
244// Examination =========================================================================================================
245
248 constexpr size_t length() const {
249 return find('\0');
250 }
251
259 constexpr int compare(const cstring& str, size_t i = 0, size_t n = npos) const {
260 if (i >= _size) {
261 return -1;
262 }
263
264 n = min(n, max(_size, str._size) + 1);
265 return ::strncmp(_cstr + i, str, n);
266 }
267
272 template<size_t n>
273 constexpr bool operator==(const char (&str)[n]) const {
274 return compare(cstring(str)) == 0;
275 }
276
281 constexpr bool operator==(const cstring& str) const {
282 return compare(str) == 0;
283 }
284
290 constexpr size_t find(char c, size_t i = 0) const {
291 if (i >= _size) { // bounds check
292 return _size;
293 }
294
295 const char* loc = ::strchr(_cstr + i, c); // get location using strchr
296 return loc ? loc - _cstr : _size; // return size if not found
297 }
298
304 constexpr size_t find(const cstring& str, size_t i = 0) const {
305 if (i + str._size > _size) { // bounds check
306 return _size;
307 }
308
309 const char* loc = ::strstr(_cstr + i, str); // get location using strstr
310 return loc ? loc - _cstr : _size; // return size if not found
311 }
312
318 constexpr size_t rfind(char c, size_t i = npos) const {
319 if (_size == 0) {
320 return _size;
321 }
322
323 i = min(i, _size - 1); // clamp i to bounds
324 do {
325 if (_cstr[i] == c) return i; // loop backwards looking for c
326 } while (i--);
327 return _size; // base case
328 }
329
335 constexpr size_t rfind(const cstring& str, size_t i = npos) const {
336 if (_size == 0) {
337 return _size;
338 }
339
340 const char first = str[0];
341 i = min(i, _size - str._size);
342 do {
343 if(_cstr[i] == first) {
344 if (compare(str, i, str._size - 1) == 0) {
345 return i;
346 }
347 } // loop backwards looking for str
348 } while (i--);
349 return _size; // base case
350 }
351
352private:
353 union { // hack to allow both const qualified and non-const strings
354 char* _str;
355 const char* _cstr;
356 };
357 size_t _size;
358 bool _const;
359};
360
361template<>
362struct hash<cstring> : hash<byte_array> {
363 constexpr size_t operator()(const cstring& str) const {
364 return hash<byte_array>::operator()(byte_array(str, str.size()));
365 }
366};
367
368}
369
370#endif // FENNEC_STRING_CSTRING_H
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 struct wraps c-style strings.
Definition cstring.h:64
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 cstring.h:304
constexpr cstring(char *str, size_t n)
Buffer Constructor, wraps the provided C-Style string.
Definition cstring.h:87
constexpr cstring(const char *str, size_t n)
Const Buffer Constructor, wraps the provided C-Style string.
Definition cstring.h:114
constexpr size_t capacity() const
Definition cstring.h:193
constexpr size_t find(char c, size_t i=0) const
Finds the index of the first occurrence of c in the string.
Definition cstring.h:290
constexpr int compare(const cstring &str, size_t i=0, size_t n=npos) const
String Comparison.
Definition cstring.h:259
constexpr cstring(const char(&str)[n])
Buffer Constructor, wraps the provided C-Style string.
Definition cstring.h:128
constexpr cstring(char(&str)[n])
Buffer Constructor, wraps the provided C-Style string.
Definition cstring.h:101
constexpr cstring()
Default Constructor, initializes with nullptr.
Definition cstring.h:73
constexpr size_t size() const
Definition cstring.h:187
constexpr cstring(nullptr_t)
Default Constructor, initializes with nullptr.
Definition cstring.h:79
constexpr char & operator[](size_t i)
Array Access Operator.
Definition cstring.h:208
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 cstring.h:335
constexpr char operator[](size_t i) const
Const-Array Access Operator.
Definition cstring.h:218
constexpr bool operator==(const cstring &str) const
String Equality.
Definition cstring.h:281
constexpr size_t length() const
Definition cstring.h:248
constexpr cstring(cstring &&str) noexcept
Move Constructor.
Definition cstring.h:140
constexpr bool operator==(const char(&str)[n]) const
String Equality.
Definition cstring.h:273
constexpr size_t rfind(char c, size_t i=npos) const
Finds the index of the last occurrence of c in the string.
Definition cstring.h:318
constexpr char * data()
Data Access.
Definition cstring.h:226
constexpr const char * data() const
Data Access.
Definition cstring.h:233
decltype(nullptr) nullptr_t
Null Pointer Type.
Definition types.h:245