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>
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 basic_string(std::nullptr_t) = delete;
36
38
39 basic_string(const Char *buffer)
40 {
42 }
43
44 explicit basic_string(const Char *buffer, size_t size)
45 {
47 }
48
49 template<class StringViewLike>
50 explicit basic_string(const StringViewLike &view)
51 {
52 _init(view.data(), view.size());
53 }
54
55 basic_string(size_t size, Char c = 0)
56 {
57 _init(&c, size);
58 }
59
61 {
62 _init(other.data(), other.size());
63 }
64
66 {
67 _length = other._length;
68 _is_long = other._is_long;
69 if (_is_long)
70 {
71 _data._long._capacity = other._data._long._capacity;
72 _data._long._buffer = other._data._long._buffer;
73 other._data._long._buffer = nullptr; // detach
74 }
75 else
76 {
77 for (size_t i = 0; i < short_string_capacity; i++)
78 _data._short._buffer[i] = other._data._short._buffer[i];
79 }
80 }
81
83 {
84 if (_is_long && _data._long._buffer)
85 TAllocator::free(_data._long._buffer);
86 }
87
89 {
90 this->~basic_string();
91 this->_length = generic_strlen(buffer);
92 this->_is_long = this->_length >= short_string_capacity;
93 if (this->_is_long)
94 {
95 this->_data._long._capacity = this->_length + 1;
96 this->_data._long._buffer = (Char *) TAllocator::allocate(sizeof(Char) * this->_data._long._capacity);
97 memcpy(this->_data._long._buffer, buffer, sizeof(Char) * this->_length);
98 this->_data._long._buffer[this->_length] = 0;
99 }
100 else
101 {
102 for (size_t i = 0; i < short_string_capacity; i++)
103 this->_data._short._buffer[i] = buffer[i];
104 }
105 return *this;
106 }
107
109 {
110 this->~basic_string();
111 this->_length = view.size();
112 this->_is_long = this->_length >= short_string_capacity;
113 if (this->_is_long)
114 {
115 this->_data._long._capacity = this->_length + 1;
116 this->_data._long._buffer = (Char *) TAllocator::allocate(sizeof(Char) * this->_data._long._capacity);
117 memcpy(this->_data._long._buffer, view.data(), sizeof(Char) * this->_length);
118 this->_data._long._buffer[this->_length] = 0;
119 }
120 else
121 {
122 for (size_t i = 0; i < short_string_capacity; i++)
123 this->_data._short._buffer[i] = view.data()[i];
124 }
125 return *this;
126 }
127
129 {
130 this->~basic_string();
131 this->_length = other._length;
132 this->_is_long = other._is_long;
133 if (this->_is_long)
134 {
135 this->_data._long._capacity = other._data._long._capacity;
136 this->_data._long._buffer = other._data._long._buffer;
137 other._data._long._buffer = nullptr; // detach
138 }
139 else
140 {
141 for (size_t i = 0; i < short_string_capacity; i++)
142 this->_data._short._buffer[i] = other._data._short._buffer[i];
143 }
144 return *this;
145 }
146
148 {
149 _init(other.data(), other.size());
150 return *this;
151 }
152
154 {
155 return basic_string(lhs) + rhs;
156 }
157
158 void resize(size_t new_length)
159 {
160 if (new_length == _length)
161 return;
162 if (new_length < short_string_capacity)
164 else
166 _length = new_length;
167 }
168
170 {
171 auto copy = *this;
172 return copy += other;
173 }
174
176 {
177 return operator+(basic_string_view(&c, 1));
178 }
179
180 void push_back(Char c)
181 {
182 operator+=(c);
183 }
184
186 {
187 const auto new_length = _length + other.size();
188 if (new_length < short_string_capacity)
189 {
190 memcpy(_data._short._buffer + _length, other.data(), sizeof(Char) * other.size());
191 _data._short._buffer[new_length] = 0;
192 _length = new_length;
193 }
194 else
195 {
196 _convert_to_long(new_length);
197 memcpy(_data._long._buffer + _length, other.data(), sizeof(Char) * other.size());
198 _data._long._buffer[new_length] = 0;
199 _length = new_length;
200 }
201
202 return *this;
203 }
204
206 {
207 return operator+=(basic_string_view(&c, 1));
208 }
209
210 const Char *data() const
211 {
212 return _is_long ? _data._long._buffer : _data._short._buffer;
213 }
214
215 const Char *c_str() const
216 {
217 return data();
218 }
219
220 Char &operator[](size_t index)
221 {
222 return _is_long ? _data._long._buffer[index] : _data._short._buffer[index];
223 }
224
225 const Char &operator[](size_t index) const
226 {
227 return _is_long ? _data._long._buffer[index] : _data._short._buffer[index];
228 }
229
230 size_t size() const
231 {
232 return _length;
233 }
234
235 bool empty() const
236 {
237 return _length == 0;
238 }
239
240 Char *begin()
241 {
242 return _is_long ? &_data._long._buffer[0] : &_data._short._buffer[0];
243 }
244
245 const Char *begin() const
246 {
247 return _is_long ? &_data._long._buffer[0] : &_data._short._buffer[0];
248 }
249
250 Char *end()
251 {
252 return _is_long ? &_data._long._buffer[_length] : &_data._short._buffer[_length];
253 }
254
255 const Char *end() const
256 {
257 return _is_long ? &_data._long._buffer[_length] : &_data._short._buffer[_length];
258 }
259
260 bool operator==(const basic_string &other) const
261 {
262 return _do_compare(other.data(), other.size()) == 0;
263 }
264
265 bool operator==(const char *rhs) const
266 {
267 return _do_compare(rhs, generic_strlen(rhs)) == 0;
268 }
269
270 operator basic_string_view<Char>() const
271 {
273 }
274
275 bool operator==(std::nullptr_t) const = delete;
276
277 private:
278 void _init(const Char *buffer, size_t size)
279 {
280 _length = size;
282 {
283 for (size_t i = 0; i < _length; i++)
284 _data._short._buffer[i] = buffer[i];
285 _data._short._buffer[_length] = 0;
286 _is_long = false;
287 }
288 else
289 {
290 _data._long._capacity = sizeof(Char) * _length + 1;
291 _data._long._buffer = (Char *) TAllocator::allocate(_data._long._capacity);
292 memcpy(_data._long._buffer, buffer, sizeof(Char) * size);
293 _data._long._buffer[size] = 0;
294 _is_long = true;
295 }
296 }
297 int _do_compare(const Char *other, const size_t other_size) const
298 {
299 if (_length != other_size)
300 return _length < other_size ? -1 : 1;
301
302 return generic_strncmp(data(), other, _length);
303 }
304
305 void _convert_to_long(size_t new_length = 0)
306 {
307 if (_is_long)
308 return;
309
310 const auto new_capacity = sizeof(Char) * std::max(new_length, _length) + 1; //_length + 1 for null terminator
311 const auto new_buffer = (Char *) TAllocator::allocate(new_capacity);
312 memcpy(new_buffer, _data._short._buffer, std::min(short_string_capacity, _length) * sizeof(Char));
313 new_buffer[_length] = 0;
314
315 _data._long._buffer = new_buffer;
316 _data._long._capacity = new_capacity;
317 _is_long = true;
318 }
319
321 {
322 if (!_is_long)
323 return;
324
325 const auto buffer = _data._long._buffer;
326 const auto capacity = _data._long._capacity;
327
328 memcpy(_data._short._buffer, buffer, std::min(short_string_capacity, _length) * sizeof(Char));
329 _data._short._buffer[_length] = 0;
330
331 TAllocator::free(buffer);
332 _is_long = false;
333 }
334 };
335
337} // namespace mos
const CharT * data() const
basic_string operator+(Char c) const
Definition string.hpp:175
basic_string & operator=(basic_string &&other)
Definition string.hpp:128
const Char * end() const
Definition string.hpp:255
basic_string & operator=(const Char *buffer)
Definition string.hpp:88
bool operator==(const basic_string &other) const
Definition string.hpp:260
const Char * begin() const
Definition string.hpp:245
basic_string & operator=(const basic_string &other)
Definition string.hpp:147
const Char * c_str() const
Definition string.hpp:215
basic_string(const Char *buffer)
Definition string.hpp:39
basic_string operator+(const basic_string &other) const
Definition string.hpp:169
int _do_compare(const Char *other, const size_t other_size) const
Definition string.hpp:297
Char & operator[](size_t index)
Definition string.hpp:220
basic_string & operator+=(const basic_string_view< Char > &other)
Definition string.hpp:185
bool empty() const
Definition string.hpp:235
union mos::basic_string::@316261373317277370236264047140336051253031235271 _data
void _init(const Char *buffer, size_t size)
Definition string.hpp:278
void push_back(Char c)
Definition string.hpp:180
struct mos::basic_string::@316261373317277370236264047140336051253031235271::_long_buffer _long
struct mos::basic_string::@316261373317277370236264047140336051253031235271::_short_buffer _short
void _convert_to_short()
Definition string.hpp:320
basic_string & operator+=(Char c)
Definition string.hpp:205
basic_string(basic_string &&other)
Definition string.hpp:65
basic_string(const basic_string &other)
Definition string.hpp:60
void _convert_to_long(size_t new_length=0)
Definition string.hpp:305
const Char & operator[](size_t index) const
Definition string.hpp:225
basic_string(std::nullptr_t)=delete
basic_string & operator=(const mos::basic_string_view< Char > &view)
Definition string.hpp:108
bool operator==(const char *rhs) const
Definition string.hpp:265
basic_string(const Char *buffer, size_t size)
Definition string.hpp:44
basic_string(const StringViewLike &view)
Definition string.hpp:50
bool operator==(std::nullptr_t) const =delete
friend basic_string operator+(const basic_string_view< Char > &lhs, const basic_string &rhs)
Definition string.hpp:153
void resize(size_t new_length)
Definition string.hpp:158
basic_string(size_t size, Char c=0)
Definition string.hpp:55
const Char * data() const
Definition string.hpp:210
mos::basic_string< char, mos::default_allocator > string
Definition string.hpp:336
constexpr auto generic_strncmp(const CharT *a, const CharT *b, size_t n)
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
#define false
Definition pb_syshdr.h:58
static char buffer[2048]