Line data Source code
1 : /**
2 : Copyright (c) 2017-2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #ifndef STAPPLER_CORE_MEMORY_SPMEMSTRING_H_
25 : #define STAPPLER_CORE_MEMORY_SPMEMSTRING_H_
26 :
27 : #include "SPMemStorageMem.h"
28 :
29 : namespace STAPPLER_VERSIONIZED stappler::memory {
30 :
31 : struct char_pointer_test;
32 : template<typename T> struct is_char_pointer {};
33 : template<> struct is_char_pointer<const char *> { using Type = char_pointer_test*; };
34 : template<> struct is_char_pointer<char *> { using Type = char_pointer_test; };
35 : template<> struct is_char_pointer<const char16_t *> { using Type = char_pointer_test; };
36 : template<> struct is_char_pointer<char16_t *> { using Type = char_pointer_test; };
37 : template<> struct is_char_pointer<const char32_t *> { using Type = char_pointer_test; };
38 : template<> struct is_char_pointer<char32_t *> { using Type = char_pointer_test; };
39 :
40 : template <typename CharType, typename InputIterator, bool IsIntegral>
41 : struct __basic_string_fill;
42 :
43 : template <typename CharType>
44 : class basic_string : public AllocPool {
45 : public:
46 : using allocator_type = Allocator<CharType>;
47 :
48 : using pointer = CharType *;
49 : using const_pointer = const CharType *;
50 : using reference = CharType &;
51 : using const_reference = const CharType &;
52 :
53 : using traits_type = std::char_traits<CharType>;
54 :
55 : using size_type = size_t;
56 : using charT = CharType;
57 : using value_type = CharType;
58 : using mem_type = storage_mem<CharType, size_t(1)>;
59 : using self = basic_string<CharType>;
60 :
61 : using iterator = typename mem_type::iterator;
62 : using const_iterator = typename mem_type::const_iterator;
63 : using reverse_iterator = typename mem_type::reverse_iterator;
64 : using const_reverse_iterator = typename mem_type::const_reverse_iterator;
65 :
66 : static const size_type npos;
67 :
68 2989531 : basic_string() noexcept : _mem() { }
69 48550 : explicit basic_string (const allocator_type& alloc) noexcept : _mem(alloc) { }
70 :
71 9439396 : basic_string (const self& str) noexcept : _mem(str._mem) { }
72 : basic_string (const self& str, const allocator_type& alloc) noexcept : _mem(str._mem, alloc) { }
73 :
74 125 : basic_string (const self& str, size_type pos, size_type len = npos, const allocator_type& alloc = allocator_type()) noexcept
75 125 : : _mem(str._mem, pos, len, alloc) { }
76 :
77 108841 : basic_string(const charT* s, const allocator_type& alloc = allocator_type()) noexcept
78 108841 : : _mem(s, (s?traits_type::length(s):0), alloc) { }
79 :
80 4406065 : basic_string (const charT* s, size_type n, const allocator_type& alloc = allocator_type()) noexcept
81 4406065 : : _mem(s, n, alloc) { }
82 :
83 25 : basic_string (size_type n, charT c, const allocator_type& alloc = allocator_type()) noexcept : _mem(alloc) {
84 25 : _mem.fill(n, c);
85 25 : }
86 :
87 : template <class InputIterator>
88 : basic_string (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()) noexcept;
89 :
90 25 : basic_string (InitializerList<charT> il, const allocator_type& alloc = allocator_type()) noexcept : _mem(alloc) {
91 25 : _mem.reserve(il.size());
92 200 : for (auto it = il.begin(); it != il.end(); it ++) {
93 175 : _mem.emplace_back_unsafe(*it);
94 : }
95 25 : }
96 :
97 8146151 : basic_string (basic_string&& str) noexcept : _mem(std::move(str._mem)) { }
98 : basic_string (basic_string&& str, const allocator_type& alloc) noexcept : _mem(std::move(str._mem), alloc) { }
99 :
100 5300 : basic_string& operator=( const basic_string& str ) noexcept {
101 5300 : _mem = str._mem;
102 5300 : return *this;
103 : }
104 :
105 14020 : basic_string& operator=( basic_string&& str ) noexcept {
106 14020 : _mem = std::move(str._mem);
107 14020 : return *this;
108 : }
109 :
110 1075 : basic_string& operator=( const charT* s ) noexcept {
111 1075 : _mem.assign(s, traits_type::length(s));
112 1075 : return *this;
113 : }
114 :
115 : basic_string& operator=( charT ch ) noexcept {
116 : _mem.assign(&ch, 1);
117 : return *this;
118 : }
119 :
120 : basic_string& operator=( InitializerList<charT> ilist ) noexcept {
121 : _mem.clear();
122 : _mem.reserve(ilist.size());
123 : for (auto &it : ilist) {
124 : _mem.emplace_back_unsafe(it);
125 : }
126 : return *this;
127 : }
128 :
129 175 : allocator_type get_allocator() const noexcept { return _mem.get_allocator(); }
130 :
131 152525 : iterator begin() noexcept { return _mem.begin(); }
132 164650 : iterator end() noexcept { return _mem.end(); }
133 :
134 8118325 : const_iterator begin() const noexcept { return _mem.begin(); }
135 8118300 : const_iterator end() const noexcept { return _mem.end(); }
136 :
137 200 : const_iterator cbegin() const noexcept { return _mem.cbegin(); }
138 75 : const_iterator cend() const noexcept { return _mem.cend(); }
139 :
140 50 : reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
141 25 : reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
142 :
143 : const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
144 : const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
145 :
146 50 : const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); }
147 50 : const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); }
148 :
149 42081667 : size_type size() const noexcept { return _mem.size(); }
150 30750 : size_type length() const noexcept { return _mem.size(); }
151 625 : size_type capacity() const noexcept { return _mem.capacity(); }
152 :
153 242902 : void reserve (size_type n = 0) { _mem.reserve(n); }
154 :
155 314319 : void resize (size_type n) { _mem.resize(n); }
156 25 : void resize (size_type n, charT c) { _mem.resize(n, c); }
157 :
158 11100 : void clear() { _mem.clear(); }
159 90019 : bool empty() const noexcept { return _mem.empty(); }
160 :
161 25 : void shrink_to_fit() noexcept { _mem.shrink_to_fit(); }
162 :
163 29125 : reference operator[] (size_type pos) noexcept { return _mem.at(pos); }
164 125 : const_reference operator[] (size_type pos) const noexcept { return _mem.at(pos); }
165 :
166 3100 : reference at (size_type pos) noexcept { return _mem.at(pos); }
167 : const_reference at (size_type pos) const noexcept { return _mem.at(pos); }
168 :
169 22075 : charT& back() noexcept { return _mem.back(); }
170 25 : const charT& back() const noexcept { return _mem.back(); }
171 :
172 25 : charT& front() noexcept { return _mem.front(); }
173 2100 : const charT& front() const noexcept { return _mem.front(); }
174 :
175 19675 : basic_string& append (const basic_string& str) {
176 19675 : _mem.insert_back(str._mem);
177 19675 : return *this;
178 : }
179 25 : basic_string& append (const basic_string& str, size_type subpos, size_type sublen = npos) {
180 25 : _mem.insert_back(str._mem, subpos, sublen);
181 25 : return *this;
182 : }
183 15725 : basic_string& append (const charT* s) {
184 15725 : _mem.insert_back(s, traits_type::length(s));
185 15725 : return *this;
186 : }
187 494101925 : basic_string& append (const charT* s, size_type n) {
188 494101925 : _mem.insert_back(s, n);
189 494101925 : return *this;
190 : }
191 50 : basic_string& append (size_type n, charT c) {
192 50 : _mem.resize(_mem.size() + n, c);
193 50 : return *this;
194 : }
195 : template <class InputIterator>
196 25 : basic_string& append (InputIterator first, InputIterator last) {
197 25 : auto diff = std::distance(first, last);
198 25 : _mem.reserve(_mem.size() + diff, true);
199 225 : for (auto it = first; it != last; ++ it) {
200 225 : if (*it != value_type(0)) {
201 200 : _mem.emplace_back_unsafe(*it);
202 : } else {
203 25 : break;
204 : }
205 : }
206 25 : return *this;
207 : }
208 50 : basic_string& append (InitializerList<charT> il) {
209 50 : _mem.reserve(il.size() + _mem.size(), true);
210 375 : for (auto it = il.begin(); it != il.end(); it ++) {
211 325 : _mem.emplace_back_unsafe(*it);
212 : }
213 50 : return *this;
214 : }
215 :
216 25 : basic_string& operator+= (const basic_string& str) { return append(str); }
217 50 : basic_string& operator+= (const charT* s) { return append(s); }
218 50 : basic_string& operator+= (charT c) { _mem.emplace_back(c); return *this; }
219 25 : basic_string& operator+= (InitializerList<charT> il) { return append(il); }
220 :
221 1925 : basic_string& assign (const basic_string& str) {
222 1925 : _mem.assign(str._mem);
223 1925 : return *this;
224 : }
225 25 : basic_string& assign (const basic_string& str, size_type subpos, size_type sublen = npos) {
226 25 : _mem.assign(str._mem, subpos, sublen);
227 25 : return *this;
228 : }
229 25 : basic_string& assign (const charT* s) {
230 25 : _mem.assign(s, traits_type::length(s));
231 25 : return *this;
232 : }
233 5506650 : basic_string& assign (const charT* s, size_type n) {
234 5506650 : _mem.assign(s, n);
235 5506650 : return *this;
236 : }
237 25 : basic_string& assign (size_type n, charT c) {
238 25 : _mem.fill(n, c);
239 25 : return *this;
240 : }
241 :
242 : template <class InputIterator>
243 : basic_string& assign (InputIterator first, InputIterator last) {
244 : _mem.clear();
245 : auto diff = last - first;
246 : _mem.reserve(diff);
247 : for (auto it = first; it != last; it ++) {
248 : _mem.emplace_back_unsafe(*it);
249 : }
250 : return *this;
251 : }
252 :
253 25 : basic_string& assign (InitializerList<charT> il) {
254 25 : _mem.clear();
255 25 : _mem.reserve(il.size());
256 200 : for (auto it = il.begin(); it != il.end(); it ++) {
257 175 : _mem.emplace_back_unsafe(*it);
258 : }
259 25 : return *this;
260 : }
261 25 : basic_string& assign (basic_string&& str) noexcept {
262 25 : _mem = std::move(str._mem);
263 25 : return *this;
264 : }
265 :
266 2046814 : void push_back(CharType c) noexcept {
267 2046814 : _mem.emplace_back(c);
268 2046814 : }
269 :
270 663575 : void emplace_back(CharType c) noexcept {
271 663575 : _mem.emplace_back(c);
272 663575 : }
273 :
274 1375 : void pop_back() noexcept {
275 1375 : _mem.pop_back();
276 1375 : }
277 :
278 25 : basic_string& insert (size_type pos, const basic_string& str) {
279 25 : _mem.insert(pos, str._mem);
280 25 : return *this;
281 : }
282 25 : basic_string& insert (size_type pos, const basic_string& str, size_type subpos, size_type sublen = npos) {
283 25 : _mem.insert(pos, str._mem, subpos, sublen);
284 25 : return *this;
285 : }
286 :
287 150 : basic_string& insert (size_type pos, const charT* s) {
288 150 : _mem.insert(pos, s, traits_type::length(s));
289 150 : return *this;
290 : }
291 :
292 : basic_string& insert (size_type pos, const charT* s, size_type n) {
293 : _mem.insert(pos, s, n);
294 : return *this;
295 : }
296 :
297 25 : basic_string& insert (size_type pos, size_type n, charT c) {
298 25 : _mem.insert(pos, n, c);
299 25 : return *this;
300 : }
301 25 : iterator insert (const_iterator p, size_type n, charT c) {
302 25 : return _mem.insert(p, n, c);
303 : }
304 :
305 25 : iterator insert (const_iterator p, charT c) {
306 25 : return _mem.insert(p, 1, c);
307 : }
308 :
309 : template< class InputIt >
310 11125 : iterator insert( const_iterator pos, InputIt first, InputIt last ) {
311 11125 : return _mem.insert(pos, first, last);
312 : }
313 :
314 25 : iterator insert( const_iterator pos, std::initializer_list<charT> init ) {
315 25 : return _mem.insert(pos, init.begin(), init.end());
316 : }
317 :
318 50 : basic_string& erase (size_type pos = 0, size_type len = npos) {
319 50 : _mem.erase(pos, len);
320 50 : return *this;
321 : }
322 :
323 25 : iterator erase (const_iterator p) {
324 25 : return _mem.erase(p);
325 : }
326 :
327 : iterator erase (const_iterator first, const_iterator last) {
328 : return _mem.erase(first, last);
329 : }
330 :
331 : basic_string& replace (size_type pos, size_type len, const basic_string& str) {
332 : _mem.replace(pos, len, str._mem);
333 : return *this;
334 : }
335 : basic_string& replace (const_iterator i1, const_iterator i2, const basic_string& str) {
336 : _mem.replace(i1 - _mem.data(), i2 - i1, str._mem);
337 : return *this;
338 : }
339 :
340 : basic_string& replace (size_type pos, size_type len, const basic_string& str,
341 : size_type subpos, size_type sublen = npos) {
342 : _mem.replace(pos, len, str._mem, subpos, sublen);
343 : return *this;
344 : }
345 :
346 25 : basic_string& replace (size_type pos, size_type len, const charT* s) {
347 25 : _mem.replace(pos, len, s, traits_type::length(s));
348 25 : return *this;
349 : }
350 : basic_string& replace (const_iterator i1, const_iterator i2, const charT* s) {
351 : _mem.replace(i1 - _mem.data(), i2 - i1, s, traits_type::length(s));
352 : return *this;
353 : }
354 :
355 : basic_string& replace (size_type pos, size_type len, const charT* s, size_type n) {
356 : _mem.replace(pos, len, s, n);
357 : return *this;
358 : }
359 : basic_string& replace (const_iterator i1, const_iterator i2, const charT* s, size_type n) {
360 : _mem.replace(i1 - _mem.data(), i2 - i1, s, n);
361 : return *this;
362 : }
363 :
364 : basic_string& replace (size_type pos, size_type len, size_type n, charT c) {
365 : _mem.replace(pos, len, n, c);
366 : return *this;
367 : }
368 25 : basic_string& replace (const_iterator i1, const_iterator i2, size_type n, charT c) {
369 25 : _mem.replace(i1 - _mem.data(), i2 - i1, n, c);
370 25 : return *this;
371 : }
372 :
373 : template< class InputIt >
374 : basic_string& replace( const_iterator first, const_iterator last, InputIt first2, InputIt last2 ) {
375 : _mem.replace(first, last, first2, last2);
376 : return *this;
377 : }
378 :
379 : basic_string& replace( const_iterator first, const_iterator last, InitializerList<charT> init ) {
380 : _mem.replace(first, last, init.begin(), init.end());
381 : return *this;
382 : }
383 :
384 125 : const charT* c_str() const noexcept { return _mem.data(); }
385 41898791 : const charT* data() const noexcept { return _mem.data(); }
386 200485 : charT* data() noexcept { return _mem.data(); }
387 :
388 25 : size_type copy (charT* s, size_type len, size_type pos = 0) const {
389 25 : len = std::min(len, _mem.size() - pos);
390 25 : memcpy(s, _mem.data() + pos, len * sizeof(charT));
391 25 : return len;
392 : }
393 :
394 100 : basic_string substr (size_type pos = 0, size_type len = npos) const {
395 100 : return basic_string(*this, pos, len);
396 : }
397 :
398 :
399 : size_type find(const charT* __s, size_type __pos, size_type __n) const;
400 : size_type find(charT __c, size_type __pos = 0) const;
401 : size_type rfind(const charT* __s, size_type __pos, size_type __n) const;
402 : size_type rfind(charT __c, size_type __pos = npos) const;
403 : size_type find_first_of(const charT* __s, size_type __pos, size_type __n) const;
404 : size_type find_last_of(const charT* __s, size_type __pos, size_type __n) const;
405 : size_type find_first_not_of(const charT* __s, size_type __pos, size_type __n) const;
406 : size_type find_first_not_of(charT __c, size_type __pos = 0) const;
407 : size_type find_last_not_of(const charT* __s, size_type __pos, size_type __n) const;
408 : size_type find_last_not_of(charT __c, size_type __pos = npos) const;
409 :
410 : size_type find(const basic_string& __str, size_type __pos = 0) const {
411 : return this->find(__str.data(), __pos, __str.size());
412 : }
413 :
414 0 : size_type find(const charT* __s, size_type __pos = 0) const {
415 0 : return this->find(__s, __pos, traits_type::length(__s));
416 : }
417 :
418 : size_type rfind(const basic_string& __str, size_type __pos = npos) const {
419 : return this->rfind(__str.data(), __pos, __str.size());
420 : }
421 :
422 : size_type rfind(const charT* __s, size_type __pos = npos) const {
423 : return this->rfind(__s, __pos, traits_type::length(__s));
424 : }
425 :
426 : size_type find_first_of(const basic_string& __str, size_type __pos = 0) const {
427 : return this->find_first_of(__str.data(), __pos, __str.size());
428 : }
429 :
430 : size_type find_first_of(const charT* __s, size_type __pos = 0) const {
431 : return this->find_first_of(__s, __pos, traits_type::length(__s));
432 : }
433 :
434 75 : size_type find_first_of(charT __c, size_type __pos = 0) const {
435 75 : return this->find(__c, __pos);
436 : }
437 :
438 : size_type find_last_of(const basic_string& __str, size_type __pos = npos) const {
439 : return this->find_last_of(__str.data(), __pos, __str.size());
440 : }
441 :
442 : size_type find_last_of(const charT* __s, size_type __pos = npos) const {
443 : return this->find_last_of(__s, __pos, traits_type::length(__s));
444 : }
445 :
446 200 : size_type find_last_of(charT __c, size_type __pos = npos) const {
447 200 : return this->rfind(__c, __pos);
448 : }
449 :
450 : size_type find_first_not_of(const basic_string& __str, size_type __pos = 0) const {
451 : return this->find_first_not_of(__str.data(), __pos, __str.size());
452 : }
453 :
454 : size_type find_first_not_of(const charT* __s, size_type __pos = 0) const {
455 : return this->find_first_not_of(__s, __pos, traits_type::length(__s));
456 : }
457 :
458 : size_type find_last_not_of(const basic_string& __str, size_type __pos = npos) const {
459 : return this->find_last_not_of(__str.data(), __pos, __str.size());
460 : }
461 :
462 : size_type find_last_not_of(const charT* __s, size_type __pos = npos) const {
463 : return this->find_last_not_of(__s, __pos, traits_type::length(__s));
464 : }
465 :
466 15498721 : int compare (const basic_string& str) const noexcept {
467 15498721 : size_type lhs_sz = size();
468 15498707 : size_type rhs_sz = str.size();
469 15498708 : return compare(data(), lhs_sz, str.data(), rhs_sz);
470 : }
471 :
472 : int compare (size_type pos, size_type len, const basic_string& str) const {
473 : size_type lhs_sz = min(size() - pos, len);
474 : size_type rhs_sz = str.size();
475 : return compare(data() + pos, lhs_sz, str.data(), rhs_sz);
476 : }
477 : int compare (size_type pos, size_type len, const basic_string& str,
478 : size_type subpos, size_type sublen = npos) const {
479 : size_type lhs_sz = min(size() - pos, len);
480 : size_type rhs_sz = min(str.size() - subpos, sublen);
481 : return compare(data() + pos, lhs_sz, str.data() + subpos, rhs_sz);
482 : }
483 :
484 459952 : int compare (const charT* s) const {
485 459952 : size_type lhs_sz = size();
486 459953 : size_type rhs_sz = traits_type::length(s);
487 459952 : return compare(data(), lhs_sz, s, rhs_sz);
488 : }
489 0 : int compare (size_type pos, size_type len, const charT* s) const {
490 0 : size_type lhs_sz = min(size() - pos, len);
491 0 : size_type rhs_sz = traits_type::length(s);
492 0 : return compare(data() + pos, lhs_sz, s, rhs_sz);
493 : }
494 :
495 : int compare (size_type pos, size_type len, const charT* s, size_type n) const {
496 : size_type lhs_sz = min(size() - pos, len);
497 : size_type rhs_sz = n;
498 : return compare(data() + pos, lhs_sz, s, rhs_sz);
499 : }
500 :
501 : public: /* APR extensions */
502 :
503 : /* Weak strings - strings, that do not own their memory
504 : * It's behave like normal strings, and copy it's data into
505 : * new allocated memory block on first mutate call
506 : *
507 : * Weak string usually used with const qualifier.
508 : * Weak strings do not require any dynamic memory for creation
509 : *
510 : * Weak strings designed as bridge between APR C-like API (const char *)
511 : * and Stappler/Serenity C++-like api (const String &)
512 : */
513 25 : static const basic_string make_weak(const CharType *str, const allocator_type& alloc = allocator_type()) {
514 25 : basic_string ret(alloc);
515 25 : if (str) {
516 25 : ret.assign_weak(str, traits_type::length(str));
517 : }
518 25 : return ret;
519 0 : }
520 :
521 48525 : static const basic_string make_weak(const CharType *str, size_type l, const allocator_type& alloc = allocator_type()) {
522 48525 : basic_string ret(alloc);
523 48524 : if (str) {
524 48524 : ret.assign_weak(str, l);
525 : }
526 48524 : return ret;
527 0 : }
528 :
529 61822 : basic_string& assign_weak(const CharType *str, size_type l) {
530 61822 : _mem.assign_weak(str, l);
531 61818 : return *this;
532 : }
533 :
534 : basic_string& assign_weak(const CharType *str) {
535 : _mem.assign_weak(str, traits_type::length(str));
536 : return *this;
537 : }
538 :
539 : bool is_weak() const noexcept {
540 : return _mem.is_weak();
541 : }
542 :
543 : template<int N>
544 : basic_string(const charT (&s)[N], const allocator_type& alloc = allocator_type())
545 : : _mem(alloc) {
546 : _mem.assign_weak(s, N);
547 : }
548 :
549 : template<int N>
550 : basic_string(charT (&s)[N], const allocator_type& alloc = allocator_type())
551 : : _mem(alloc) {
552 : _mem.assign_weak(s, N);
553 : }
554 :
555 :
556 : /* Wrap function used to assign preallocated c-string to apr::string
557 : * string will use provided memory for mutate operations, and return it to manager when destroyed
558 : */
559 :
560 : static basic_string wrap(CharType *str, const allocator_type& alloc = allocator_type()) {
561 : basic_string ret(alloc);
562 : ret.assign_wrap(str, traits_type::length(str));
563 : return ret;
564 : }
565 :
566 : static basic_string wrap(CharType *str, size_type l, const allocator_type& alloc = allocator_type()) {
567 : basic_string ret(alloc);
568 : ret.assign_wrap(str, l);
569 : return ret;
570 : }
571 :
572 : static basic_string wrap(CharType *str, size_type l, size_type nalloc, const allocator_type& alloc = allocator_type()) {
573 : basic_string ret(alloc);
574 : ret.assign_wrap(str, l, nalloc);
575 : return ret;
576 : }
577 :
578 : basic_string& assign_wrap(CharType *str, size_type l) {
579 : _mem.assign_mem(str, l, l + 1);
580 : return *this;
581 : }
582 :
583 : basic_string& assign_wrap(CharType *str, size_type l, size_type nalloc) {
584 : _mem.assign_mem(str, l, nalloc);
585 : return *this;
586 : }
587 :
588 : // Extract should be used to capture string memory for non-STL-like container, e.g. apr::table.
589 : CharType *extract() {
590 : return _mem.extract();
591 : }
592 :
593 : protected:
594 15958657 : static int compare(const charT* s1, size_type len1, const charT* s2, size_type len2) {
595 15958657 : int result = (s1 && s2) ? traits_type::compare(s1, s2, min(len1, len2)) : 0;
596 15958670 : if (result != 0)
597 15513306 : return result;
598 445364 : if (len1 < len2)
599 23472 : return -1;
600 421892 : if (len1 > len2)
601 4900 : return 1;
602 416992 : return 0;
603 : }
604 :
605 : template <typename C, typename I, bool B>
606 : friend struct __basic_string_fill;
607 :
608 : mem_type _mem;
609 : };
610 :
611 : template <typename CharType, typename InputIterator>
612 : struct __basic_string_fill<CharType, InputIterator, true> {
613 25 : static void fill(basic_string<CharType> &str, InputIterator first, InputIterator last) noexcept {
614 25 : str._mem.fill(size_t(first), CharType(last));
615 25 : }
616 : };
617 :
618 : template <typename CharType, typename InputIterator>
619 : struct __basic_string_fill<CharType, InputIterator, false> {
620 25 : static void fill(basic_string<CharType> &str, InputIterator first, InputIterator last) noexcept {
621 25 : auto size = std::distance(first, last);
622 25 : str.reserve(size);
623 375 : for (auto it = first; it != last; it ++) {
624 350 : str._mem.emplace_back_unsafe(*it);
625 : }
626 25 : }
627 : };
628 :
629 : template< class CharT >
630 : template <class InputIterator>
631 50 : basic_string<CharT>::basic_string (InputIterator first, InputIterator last, const allocator_type& alloc) noexcept : _mem(alloc) {
632 50 : __basic_string_fill<CharT, InputIterator, std::is_integral<InputIterator>::value>::fill(*this, first, last);
633 50 : }
634 :
635 : template< class CharT > basic_string<CharT>
636 : operator+( const basic_string<CharT>& lhs, const basic_string<CharT>& rhs ) {
637 : basic_string<CharT> ret;
638 : ret.reserve(lhs.size() + rhs.size());
639 : ret.assign(lhs);
640 : ret.append(rhs);
641 : return ret;
642 : }
643 :
644 : template< class CharT > basic_string<CharT>
645 : operator+( const CharT* lhs, const basic_string<CharT> & rhs ) {
646 : basic_string<CharT> ret;
647 : ret.reserve(std::char_traits<CharT>::length(lhs) + rhs.size());
648 : ret.assign(lhs);
649 : ret.append(rhs);
650 : return ret;
651 : }
652 :
653 : template< class CharT > basic_string<CharT>
654 : operator+( CharT lhs, const basic_string<CharT>& rhs ) {
655 : basic_string<CharT> ret;
656 : ret.reserve(rhs.size() + 1);
657 : ret.assign(1, lhs);
658 : ret.append(rhs);
659 : return ret;
660 : }
661 :
662 : template< class CharT > basic_string<CharT>
663 1900 : operator+( const basic_string<CharT>& lhs, const CharT* rhs ) {
664 1900 : basic_string<CharT> ret;
665 1900 : ret.reserve(lhs.size() + std::char_traits<CharT>::length(rhs));
666 1900 : ret.assign(lhs);
667 1900 : ret.append(rhs);
668 1900 : return ret;
669 0 : }
670 :
671 : template< class CharT > basic_string<CharT>
672 : operator+( const basic_string<CharT>& lhs, CharT rhs ) {
673 : basic_string<CharT> ret;
674 : ret.reserve(rhs.size() + 1);
675 : ret.assign(lhs);
676 : ret.append(1, rhs);
677 : return ret;
678 : }
679 :
680 : template< class CharT > basic_string<CharT>
681 : operator+( basic_string<CharT>&& lhs, const basic_string<CharT>& rhs ) {
682 : return std::move(lhs.append(rhs));
683 : }
684 :
685 : template< class CharT > basic_string<CharT>
686 : operator+( const basic_string<CharT>& lhs, basic_string<CharT>&& rhs ) {
687 : return std::move(rhs.insert(0, lhs));
688 : }
689 :
690 : template< class CharT > basic_string<CharT>
691 5400 : operator+( basic_string<CharT>&& lhs, basic_string<CharT>&& rhs ) {
692 5400 : return std::move(lhs.append(rhs));
693 : }
694 :
695 : template< class CharT > basic_string<CharT>
696 125 : operator+(const CharT* lhs, basic_string<CharT>&& rhs ) {
697 125 : return std::move(rhs.insert(0, lhs));
698 : }
699 :
700 : template< class CharT > basic_string<CharT>
701 : operator+( CharT lhs, basic_string<CharT>&& rhs ) {
702 : return std::move(rhs.insert(0, 1, lhs));
703 : }
704 :
705 : template< class CharT > basic_string<CharT>
706 25 : operator+( basic_string<CharT>&& lhs, const CharT* rhs ) {
707 25 : return std::move(lhs.append(rhs));
708 : }
709 :
710 : template< class CharT > basic_string<CharT>
711 : operator+( basic_string<CharT>&& lhs, CharT rhs ) {
712 : return std::move(lhs.append(1, rhs));
713 : }
714 :
715 9650 : template< class CharT > bool operator== ( const basic_string<CharT>& lhs, const basic_string<CharT>& rhs ) {
716 9650 : return lhs.compare(rhs) == 0;
717 : }
718 :
719 1279 : template< class CharT > bool operator!= ( const basic_string<CharT>& lhs, const basic_string<CharT>& rhs ) {
720 1279 : return lhs.compare(rhs) != 0;
721 : }
722 :
723 15487770 : template< class CharT > bool operator< ( const basic_string<CharT>& lhs, const basic_string<CharT>& rhs ) {
724 15487770 : return lhs.compare(rhs) < 0;
725 : }
726 :
727 : template< class CharT > bool operator<= ( const basic_string<CharT>& lhs, const basic_string<CharT>& rhs ) {
728 : return lhs.compare(rhs) <= 0;
729 : }
730 :
731 : template< class CharT > bool operator> ( const basic_string<CharT>& lhs, const basic_string<CharT>& rhs ) {
732 : return lhs.compare(rhs) > 0;
733 : }
734 :
735 : template< class CharT > bool operator>= ( const basic_string<CharT>& lhs, const basic_string<CharT>& rhs ) {
736 : return lhs.compare(rhs) >= 0;
737 : }
738 :
739 258097 : template< class CharT > bool operator== ( const basic_string<CharT>& lhs, const CharT* rhs ) {
740 258097 : return lhs.compare(rhs) == 0;
741 : }
742 :
743 2400 : template< class CharT > bool operator!= ( const basic_string<CharT>& lhs, const CharT* rhs ) {
744 2400 : return lhs.compare(rhs) != 0;
745 : }
746 :
747 66766 : template< class CharT > bool operator<( const basic_string<CharT>& lhs, const CharT* rhs ) {
748 66766 : return lhs.compare(rhs) < 0;
749 : }
750 :
751 : template< class CharT > bool operator<= ( const basic_string<CharT>& lhs, const CharT* rhs ) {
752 : return lhs.compare(rhs) <= 0;
753 : }
754 :
755 : template< class CharT > bool operator>( const basic_string<CharT>& lhs, const CharT* rhs ) {
756 : return lhs.compare(rhs) > 0;
757 : }
758 :
759 : template< class CharT > bool operator>=( const basic_string<CharT>& lhs, const CharT* rhs ) {
760 : return lhs.compare(rhs) >= 0;
761 : }
762 :
763 :
764 475 : template< class CharT > bool operator== ( const CharT* lhs, const basic_string<CharT>& rhs ) {
765 475 : return rhs.compare(lhs) == 0;
766 : }
767 :
768 : template< class CharT > bool operator!= ( const CharT* lhs, const basic_string<CharT>& rhs ) {
769 : return rhs.compare(lhs) != 0;
770 : }
771 :
772 132216 : template< class CharT > bool operator< ( const CharT* lhs, const basic_string<CharT>& rhs ) {
773 132216 : return rhs.compare(lhs) > 0;
774 : }
775 :
776 : template< class CharT > bool operator<= ( const CharT* lhs, const basic_string<CharT>& rhs ) {
777 : return rhs.compare(lhs) >= 0;
778 : }
779 :
780 : template< class CharT > bool operator>( const CharT* lhs, const basic_string<CharT>& rhs ) {
781 : return rhs.compare(lhs) < 0;
782 : }
783 :
784 : template< class CharT > bool operator>=( const CharT* lhs, const basic_string<CharT>& rhs ) {
785 : return rhs.compare(lhs) <= 0;
786 : }
787 :
788 : template<typename _CharT> typename basic_string<_CharT>::size_type
789 0 : basic_string<_CharT>:: find(const charT* __s, size_type __pos, size_type __n) const {
790 0 : const size_type __size = this->size();
791 0 : const _CharT* __data = _mem.data();
792 :
793 0 : if (__n == 0) {
794 0 : return __pos <= __size ? __pos : npos;
795 0 : } else if (__n <= __size) {
796 0 : for (; __pos <= __size - __n; ++__pos)
797 0 : if (traits_type::eq(__data[__pos], __s[0])
798 0 : && traits_type::compare(__data + __pos + 1,
799 : __s + 1, __n - 1) == 0)
800 0 : return __pos;
801 : }
802 0 : return npos;
803 : }
804 :
805 : template<typename _CharT> typename basic_string<_CharT>::size_type
806 100 : basic_string<_CharT>::find(charT __c, size_type __pos) const {
807 100 : size_type __ret = npos;
808 100 : const size_type __size = this->size();
809 100 : if (__pos < __size) {
810 100 : const _CharT* __data = _mem.data();
811 100 : const size_type __n = __size - __pos;
812 100 : const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
813 100 : if (__p)
814 100 : __ret = __p - __data;
815 : }
816 100 : return __ret;
817 : }
818 :
819 : template<typename _CharT> typename basic_string<_CharT>::size_type
820 : basic_string<_CharT>::rfind(const charT* __s, size_type __pos, size_type __n) const {
821 : const size_type __size = this->size();
822 : if (__n <= __size) {
823 : __pos = min(size_type(__size - __n), __pos);
824 : const _CharT* __data = _mem.data();
825 : do {
826 : if (traits_type::compare(__data + __pos, __s, __n) == 0)
827 : return __pos;
828 : }
829 : while (__pos-- > 0);
830 : }
831 : return npos;
832 : }
833 :
834 : template<typename _CharT> typename basic_string<_CharT>::size_type
835 200 : basic_string<_CharT>::rfind(charT __c, size_type __pos) const {
836 200 : size_type __size = this->size();
837 200 : if (__size) {
838 200 : if (--__size > __pos)
839 0 : __size = __pos;
840 2350 : for (++__size; __size-- > 0; )
841 2300 : if (traits_type::eq(_mem.data()[__size], __c))
842 150 : return __size;
843 : }
844 50 : return npos;
845 : }
846 :
847 : template<typename _CharT> typename basic_string<_CharT>::size_type
848 : basic_string<_CharT>::find_first_of(const charT* __s, size_type __pos, size_type __n) const {
849 : for (; __n && __pos < this->size(); ++__pos) {
850 : const _CharT* __p = traits_type::find(__s, __n, _mem.data()[__pos]);
851 : if (__p)
852 : return __pos;
853 : }
854 : return npos;
855 : }
856 :
857 : template<typename _CharT> typename basic_string<_CharT>::size_type
858 : basic_string<_CharT>:: find_last_of(const charT* __s, size_type __pos, size_type __n) const {
859 : size_type __size = this->size();
860 : if (__size && __n) {
861 : if (--__size > __pos)
862 : __size = __pos;
863 : do {
864 : if (traits_type::find(__s, __n, _mem.data()[__size]))
865 : return __size;
866 : } while (__size-- != 0);
867 : }
868 : return npos;
869 : }
870 :
871 : template<typename _CharT> typename basic_string<_CharT>::size_type
872 : basic_string<_CharT>::find_first_not_of(const charT* __s, size_type __pos, size_type __n) const {
873 : for (; __pos < this->size(); ++__pos)
874 : if (!traits_type::find(__s, __n, _mem.data()[__pos]))
875 : return __pos;
876 : return npos;
877 : }
878 :
879 : template<typename _CharT> typename basic_string<_CharT>::size_type
880 : basic_string<_CharT>::find_first_not_of(charT __c, size_type __pos) const {
881 : for (; __pos < this->size(); ++__pos)
882 : if (!traits_type::eq(_mem.data()[__pos], __c))
883 : return __pos;
884 : return npos;
885 : }
886 :
887 : template<typename _CharT> typename basic_string<_CharT>::size_type
888 : basic_string<_CharT>:: find_last_not_of(const charT* __s, size_type __pos, size_type __n) const {
889 : size_type __size = this->size();
890 : if (__size) {
891 : if (--__size > __pos)
892 : __size = __pos;
893 : do {
894 : if (!traits_type::find(__s, __n, _mem.data()[__size]))
895 : return __size;
896 : } while (__size--);
897 : }
898 : return npos;
899 : }
900 :
901 : template<typename _CharT> typename basic_string<_CharT>::size_type
902 : basic_string<_CharT>::find_last_not_of(charT __c, size_type __pos) const {
903 : size_type __size = this->size();
904 : if (__size) {
905 : if (--__size > __pos)
906 : __size = __pos;
907 : do {
908 : if (!traits_type::eq(_mem.data()[__size], __c))
909 : return __size;
910 : } while (__size--);
911 : }
912 : return npos;
913 : }
914 :
915 : template<typename CharType> inline std::basic_ostream<CharType> &
916 54325 : operator << (std::basic_ostream<CharType> & os, const basic_string<CharType> & str) {
917 54325 : return os.write(str.data(), str.size());
918 : }
919 :
920 : template<typename CharType> const typename basic_string<CharType>::size_type
921 : basic_string<CharType>::npos = maxOf<typename basic_string<CharType>::size_type>();
922 :
923 : using string = basic_string<char>;
924 : using u16string = basic_string<char16_t>;
925 : using u32string = basic_string<char32_t>;
926 :
927 : using weak_string = const string;
928 :
929 : }
930 :
931 : namespace STAPPLER_VERSIONIZED stappler {
932 :
933 13274 : inline stappler::memory::basic_string<char> operator"" _weak ( const char* str, size_t len) {
934 13274 : stappler::memory::basic_string<char> ret;
935 13274 : if (str) {
936 13274 : ret.assign_weak(str, len);
937 : }
938 13270 : return ret;
939 0 : }
940 :
941 : }
942 :
943 : namespace std {
944 :
945 : template<>
946 : struct hash<STAPPLER_VERSIONIZED_NAMESPACE::memory::basic_string<char>> {
947 175 : size_t operator() (const STAPPLER_VERSIONIZED_NAMESPACE::memory::basic_string<char> & s) const noexcept {
948 : if (sizeof(size_t) == 8) {
949 175 : return STAPPLER_VERSIONIZED_NAMESPACE::hash::hash64(s.data(), s.size());
950 : } else {
951 : return STAPPLER_VERSIONIZED_NAMESPACE::hash::hash32(s.data(), s.size());
952 : }
953 : }
954 : };
955 :
956 : template<>
957 : struct hash<STAPPLER_VERSIONIZED_NAMESPACE::memory::basic_string<char16_t>> {
958 : size_t operator() (const STAPPLER_VERSIONIZED_NAMESPACE::memory::basic_string<char16_t> & s) const noexcept {
959 : if (sizeof(size_t) == 8) {
960 : return STAPPLER_VERSIONIZED_NAMESPACE::hash::hash64((char *)s.data(), s.size() * sizeof(char16_t));
961 : } else {
962 : return STAPPLER_VERSIONIZED_NAMESPACE::hash::hash32((char *)s.data(), s.size() * sizeof(char16_t));
963 : }
964 : }
965 : };
966 :
967 : }
968 :
969 : #endif /* STAPPLER_CORE_MEMORY_SPMEMSTRING_H_ */
|