MOS Source Code
Loading...
Searching...
No Matches
string.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2#pragma once
3
4#include <cstddef>
6#include <mos/string_view.hpp>
7#include <mos_stdlib.hpp>
8#include <mos_string.hpp>
9
10namespace mos
11{
12 constexpr size_t short_string_capacity = 16;
13
14 template<typename Char, typename TAllocator = mos::default_allocator<Char>>
16 {
17 bool _is_long = false;
18 size_t _length;
19
20 union
21 {
22 struct _long_buffer
23 {
24 Char *_buffer;
25 size_t _capacity;
27
28 struct _short_buffer
29 {
33
34 public:
35 static constexpr auto npos = size_t(-1);
36
37 public:
38 basic_string(std::nullptr_t) = delete;
39
41
42 basic_string(const Char *buffer)
43 {
45 }
46
47 explicit basic_string(const Char *buffer, size_t size)
48 {
50 }
51
52 template<class StringViewLike>
53 explicit basic_string(const StringViewLike &view)
54 {
55 _init(view.data(), view.size());
56 }
57
58 basic_string(size_t size, Char c = 0)
59 {
60 _init(&c, size);
61 }
62
64 {
65 _init(other.data(), other.size());
66 }
67
69 {
70 _length = other._length;
71 _is_long = other._is_long;
72 if (_is_long)
73 {
74 _data._long._capacity = other._data._long._capacity;
75 _data._long._buffer = other._data._long._buffer;
76 other._data._long._buffer = nullptr; // detach
77 }
78 else
79 {
80 for (size_t i = 0; i < short_string_capacity; i++)
81 _data._short._buffer[i] = other._data._short._buffer[i];
82 }
83 }
84
86 {
87 if (_is_long && _data._long._buffer)
88 TAllocator::free(_data._long._buffer);
89 }
90
92 {
93 if (buffer == nullptr)
95 this->~basic_string();
96 this->_length = generic_strlen(buffer);
97 this->_is_long = this->_length >= short_string_capacity;
98 if (this->_is_long)
99 {
100 this->_data._long._capacity = this->_length + 1;
101 this->_data._long._buffer = (Char *) TAllocator::allocate(sizeof(Char) * this->_data._long._capacity);
102 memcpy(this->_data._long._buffer, buffer, sizeof(Char) * this->_length);
103 this->_data._long._buffer[this->_length] = 0;
104 }
105 else
106 {
107 for (size_t i = 0; i < short_string_capacity; i++)
108 this->_data._short._buffer[i] = buffer[i];
109 }
110 return *this;
111 }
112
114 {
115 this->~basic_string();
116 this->_length = view.size();
117 this->_is_long = this->_length >= short_string_capacity;
118 if (this->_is_long)
119 {
120 this->_data._long._capacity = this->_length + 1;
121 this->_data._long._buffer = (Char *) TAllocator::allocate(sizeof(Char) * this->_data._long._capacity);
122 memcpy(this->_data._long._buffer, view.data(), sizeof(Char) * this->_length);
123 this->_data._long._buffer[this->_length] = 0;
124 }
125 else
126 {
127 for (size_t i = 0; i < short_string_capacity; i++)
128 this->_data._short._buffer[i] = view.data()[i];
129 }
130 return *this;
131 }
132
134 {
135 this->~basic_string();
136 this->_length = other._length;
137 this->_is_long = other._is_long;
138 if (this->_is_long)
139 {
140 this->_data._long._capacity = other._data._long._capacity;
141 this->_data._long._buffer = other._data._long._buffer;
142 other._data._long._buffer = nullptr; // detach
143 }
144 else
145 {
146 for (size_t i = 0; i < short_string_capacity; i++)
147 this->_data._short._buffer[i] = other._data._short._buffer[i];
148 }
149 return *this;
150 }
151
153 {
154 _init(other.data(), other.size());
155 return *this;
156 }
157
159 {
160 return basic_string(lhs) + rhs;
161 }
162
163 void resize(size_t new_length)
164 {
165 if (new_length == _length)
166 return;
167 if (new_length < short_string_capacity)
169 else
171 _length = new_length;
172 }
173
174 bool begins_with(Char c) const
175 {
176 if (_length == 0)
177 return false;
178 return _data._short._buffer[0] == c;
179 }
180
181 bool begins_with(const basic_string_view<Char> &prefix) const
182 {
183 if (prefix.size() > _length)
184 return false;
185 return generic_strncmp(data(), prefix.data(), prefix.size()) == 0;
186 }
187
188 bool ends_with(Char c) const
189 {
190 if (_length == 0)
191 return false;
192 return _data._short._buffer[_length - 1] == c;
193 }
194
195 bool ends_with(const basic_string_view<Char> &suffix) const
196 {
197 if (suffix.size() > _length)
198 return false;
199 return generic_strncmp(data() + _length - suffix.size(), suffix.data(), suffix.size()) == 0;
200 }
201
202 void clear()
203 {
204 if (_is_long)
205 {
206 TAllocator::free(_data._long._buffer);
207 _data._long._buffer = nullptr;
208 _is_long = false;
209 }
210 _length = 0;
211 }
212
214 {
215 auto copy = *this;
216 return copy += other;
217 }
218
220 {
221 return operator+(basic_string_view(&c, 1));
222 }
223
224 void push_back(Char c)
225 {
226 operator+=(c);
227 }
228
230 {
231 const auto new_length = _length + other.size();
232 if (new_length < short_string_capacity)
233 {
234 memcpy(_data._short._buffer + _length, other.data(), sizeof(Char) * other.size());
235 _data._short._buffer[new_length] = 0;
236 _length = new_length;
237 }
238 else
239 {
240 _convert_to_long(new_length);
241 memcpy(_data._long._buffer + _length, other.data(), sizeof(Char) * other.size());
242 _data._long._buffer[new_length] = 0;
243 _length = new_length;
244 }
245
246 return *this;
247 }
248
250 {
251 return operator+=(basic_string_view(&c, 1));
252 }
253
254 const Char *data() const
255 {
256 return _is_long ? _data._long._buffer : _data._short._buffer;
257 }
258
259 const Char *c_str() const
260 {
261 return data();
262 }
263
264 Char &operator[](size_t index)
265 {
266 return _is_long ? _data._long._buffer[index] : _data._short._buffer[index];
267 }
268
269 const Char &operator[](size_t index) const
270 {
271 return _is_long ? _data._long._buffer[index] : _data._short._buffer[index];
272 }
273
274 size_t size() const
275 {
276 return _length;
277 }
278
279 bool empty() const
280 {
281 return _length == 0;
282 }
283
284 ssize_t copy(Char *buffer, size_t size, size_t pos = 0) const
285 {
286 if (pos > _length)
287 return -1;
288 if (pos + size > _length)
289 size = _length - pos;
290 memcpy(buffer, data() + pos, sizeof(Char) * size);
291 return size;
292 }
293
295 {
296 return empty() ? other : *this;
297 }
298
299 Char *begin()
300 {
301 return _is_long ? &_data._long._buffer[0] : &_data._short._buffer[0];
302 }
303 const Char *begin() const
304 {
305 return _is_long ? &_data._long._buffer[0] : &_data._short._buffer[0];
306 }
307
308 Char *end()
309 {
310 return _is_long ? &_data._long._buffer[_length] : &_data._short._buffer[_length];
311 }
312 const Char *end() const
313 {
314 return _is_long ? &_data._long._buffer[_length] : &_data._short._buffer[_length];
315 }
316
317 bool operator==(const basic_string &other) const
318 {
319 return _do_compare(other.data(), other.size()) == 0;
320 }
321
322 bool operator==(const char *rhs) const
323 {
324 return _do_compare(rhs, generic_strlen(rhs)) == 0;
325 }
326
327 operator basic_string_view<Char>() const
328 {
330 }
331
332 bool operator==(std::nullptr_t) const = delete;
333
334 private:
335 void _init(const Char *buffer, size_t size)
336 {
337 if (buffer == nullptr)
339 _length = size;
341 {
342 for (size_t i = 0; i < _length; i++)
343 _data._short._buffer[i] = buffer[i];
344 _data._short._buffer[_length] = 0;
345 _is_long = false;
346 }
347 else
348 {
349 _data._long._capacity = sizeof(Char) * _length + 1;
350 _data._long._buffer = (Char *) TAllocator::allocate(_data._long._capacity);
351 memcpy(_data._long._buffer, buffer, sizeof(Char) * size);
352 _data._long._buffer[size] = 0;
353 _is_long = true;
354 }
355 }
356 int _do_compare(const Char *other, const size_t other_size) const
357 {
358 if (_length != other_size)
359 return _length < other_size ? -1 : 1;
360
361 return generic_strncmp(data(), other, _length);
362 }
363
364 void _convert_to_long(size_t new_length = 0)
365 {
366 if (_is_long)
367 return;
368
369 const auto new_capacity = sizeof(Char) * std::max(new_length, _length) + 1; //_length + 1 for null terminator
370 const auto new_buffer = (Char *) TAllocator::allocate(new_capacity);
371 memcpy(new_buffer, _data._short._buffer, std::min(short_string_capacity, _length) * sizeof(Char));
372 new_buffer[_length] = 0;
373
374 _data._long._buffer = new_buffer;
375 _data._long._capacity = new_capacity;
376 _is_long = true;
377 }
378
380 {
381 if (!_is_long)
382 return;
383
384 const auto buffer = _data._long._buffer;
385 const auto capacity = _data._long._capacity;
386
387 memcpy(_data._short._buffer, buffer, std::min(short_string_capacity, _length) * sizeof(Char));
388 _data._short._buffer[_length] = 0;
389
390 TAllocator::free(buffer);
391 _is_long = false;
392 }
393 };
394
396
397 // convert a pointer to a string
398 mos::string to_string(const void *value);
399} // namespace mos
const CharT * data() const
bool ends_with(const basic_string_view< Char > &suffix) const
Definition string.hpp:195
basic_string operator+(Char c) const
Definition string.hpp:219
basic_string & operator=(basic_string &&other)
Definition string.hpp:133
const Char * end() const
Definition string.hpp:312
basic_string & operator=(const Char *buffer)
Definition string.hpp:91
bool operator==(const basic_string &other) const
Definition string.hpp:317
const Char * begin() const
Definition string.hpp:303
bool begins_with(Char c) const
Definition string.hpp:174
size_t size() const
Definition string.hpp:274
basic_string & operator=(const basic_string &other)
Definition string.hpp:152
const Char * c_str() const
Definition string.hpp:259
basic_string(const Char *buffer)
Definition string.hpp:42
basic_string operator+(const basic_string &other) const
Definition string.hpp:213
int _do_compare(const Char *other, const size_t other_size) const
Definition string.hpp:356
Char & operator[](size_t index)
Definition string.hpp:264
basic_string & operator+=(const basic_string_view< Char > &other)
Definition string.hpp:229
bool empty() const
Definition string.hpp:279
basic_string_view< Char > value_or(basic_string_view< Char > other) const
Definition string.hpp:294
union mos::basic_string::@316261373317277370236264047140336051253031235271 _data
void _init(const Char *buffer, size_t size)
Definition string.hpp:335
void push_back(Char c)
Definition string.hpp:224
struct mos::basic_string::@316261373317277370236264047140336051253031235271::_long_buffer _long
struct mos::basic_string::@316261373317277370236264047140336051253031235271::_short_buffer _short
static constexpr auto npos
Definition string.hpp:35
void _convert_to_short()
Definition string.hpp:379
basic_string & operator+=(Char c)
Definition string.hpp:249
basic_string(basic_string &&other)
Definition string.hpp:68
basic_string(const basic_string &other)
Definition string.hpp:63
void _convert_to_long(size_t new_length=0)
Definition string.hpp:364
const Char & operator[](size_t index) const
Definition string.hpp:269
basic_string(std::nullptr_t)=delete
basic_string & operator=(const mos::basic_string_view< Char > &view)
Definition string.hpp:113
bool begins_with(const basic_string_view< Char > &prefix) const
Definition string.hpp:181
bool operator==(const char *rhs) const
Definition string.hpp:322
basic_string(const Char *buffer, size_t size)
Definition string.hpp:47
basic_string(const StringViewLike &view)
Definition string.hpp:53
bool operator==(std::nullptr_t) const =delete
friend basic_string operator+(const basic_string_view< Char > &lhs, const basic_string &rhs)
Definition string.hpp:158
void resize(size_t new_length)
Definition string.hpp:163
basic_string(size_t size, Char c=0)
Definition string.hpp:58
const Char * data() const
Definition string.hpp:254
bool ends_with(Char c) const
Definition string.hpp:188
ssize_t copy(char *buffer, size_t size, size_t pos=0) const
Definition string.hpp:284
mos::string to_string(const void *value)
Definition string.cpp:9
constexpr auto generic_strncmp(const CharT *a, const CharT *b, size_t n)
mos::basic_string< char > string
Definition string.hpp:395
void __raise_null_pointer_exception()
constexpr size_t short_string_capacity
Definition string.hpp:12
constexpr auto generic_strlen(const CharT *c)
static void * memcpy(void *s1, const void *s2, size_t n)
Definition pb_syshdr.h:90
uint32_t size_t
Definition pb_syshdr.h:42
#define false
Definition pb_syshdr.h:58
static char buffer[2048]
signed long ssize_t
Definition types.h:79