PMDK C++ bindings 1.13.0
This is the C++ bindings documentation for PMDK's libpmemobj.
Loading...
Searching...
No Matches
basic_string.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-3-Clause
2/* Copyright 2019-2021, Intel Corporation */
3
9#ifndef LIBPMEMOBJ_CPP_BASIC_STRING_HPP
10#define LIBPMEMOBJ_CPP_BASIC_STRING_HPP
11
12#include <algorithm>
13#include <iterator>
14#include <limits>
15#include <string>
16
24#include <libpmemobj++/pext.hpp>
29
30namespace pmem
31{
32
33namespace obj
34{
35
45template <typename CharT, typename Traits = std::char_traits<CharT>>
47public:
48 /* Member types */
49 using traits_type = Traits;
50 using value_type = CharT;
51 using size_type = std::size_t;
52 using difference_type = std::ptrdiff_t;
53 using reference = value_type &;
54 using const_reference = const value_type &;
55 using pointer = value_type *;
56 using const_pointer = const value_type *;
58 using const_iterator = const_pointer;
59 using reverse_iterator = std::reverse_iterator<iterator>;
60 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
63 using for_each_ptr_function =
64 std::function<void(persistent_ptr_base &)>;
65
66 /* Number of characters which can be stored using sso */
67 static constexpr size_type sso_capacity = (32 - 8) / sizeof(CharT) - 1;
68
69 /* Constructors */
71 basic_string(size_type count, CharT ch);
72 basic_string(const basic_string &other, size_type pos,
73 size_type count = npos);
74 basic_string(const std::basic_string<CharT> &other, size_type pos,
75 size_type count = npos);
76 basic_string(const CharT *s, size_type count);
77 basic_string(const CharT *s);
78 template <
79 typename InputIt,
80 typename Enable = typename std::enable_if<
82 basic_string(InputIt first, InputIt last);
83 basic_string(const basic_string &other);
84 basic_string(const std::basic_string<CharT> &other);
86 basic_string(std::initializer_list<CharT> ilist);
87 template <
88 class T,
89 typename Enable = typename std::enable_if<
90 std::is_convertible<const T &,
92 CharT, Traits>>::value &&
93 !std::is_convertible<const T &, const CharT *>::value>>
94 explicit basic_string(const T &t);
95 template <class T,
96 typename Enable = typename std::enable_if<std::is_convertible<
97 const T &,
99 basic_string(const T &t, size_type pos, size_type n);
100
101 /* Destructor */
103
104 /* Assignment operators */
105 basic_string &operator=(const basic_string &other);
106 basic_string &operator=(const std::basic_string<CharT> &other);
108 basic_string &operator=(const CharT *s);
109 basic_string &operator=(CharT ch);
110 basic_string &operator=(std::initializer_list<CharT> ilist);
111 template <
112 class T,
113 typename Enable = typename std::enable_if<
114 std::is_convertible<const T &,
116 CharT, Traits>>::value &&
117 !std::is_convertible<const T &, const CharT *>::value>>
118 basic_string &operator=(const T &t);
119
120 /* Assignment methods */
121 basic_string &assign(size_type count, CharT ch);
122 basic_string &assign(const basic_string &other);
123 basic_string &assign(const std::basic_string<CharT> &other);
124 basic_string &assign(const basic_string &other, size_type pos,
125 size_type count = npos);
126 basic_string &assign(const std::basic_string<CharT> &other,
127 size_type pos, size_type count = npos);
128 basic_string &assign(const CharT *s, size_type count);
129 basic_string &assign(const CharT *s);
130 template <typename InputIt,
131 typename Enable = typename pmem::detail::is_input_iterator<
132 InputIt>::type>
133 basic_string &assign(InputIt first, InputIt last);
135 basic_string &assign(std::initializer_list<CharT> ilist);
136
137 /* Element access */
138 reference at(size_type n);
139 const_reference at(size_type n) const;
140 const_reference const_at(size_type n) const;
141 reference operator[](size_type n);
142 const_reference operator[](size_type n) const;
143 CharT &front();
144 const CharT &front() const;
145 const CharT &cfront() const;
146 CharT &back();
147 const CharT &back() const;
148 const CharT &cback() const;
149 CharT *data();
150 const CharT *data() const noexcept;
151 const CharT *cdata() const noexcept;
152 const CharT *c_str() const noexcept;
153 void for_each_ptr(for_each_ptr_function func);
154
155 /* Range */
156 slice<pointer> range(size_type p, size_type count);
157 slice<range_snapshotting_iterator> range(size_type start, size_type n,
158 size_type snapshot_size);
159 slice<const_iterator> range(size_type start, size_type n) const;
160 slice<const_iterator> crange(size_type start, size_type n) const;
161
162 /* Iterators */
163 iterator begin();
164 const_iterator begin() const noexcept;
165 const_iterator cbegin() const noexcept;
166 iterator end();
167 const_iterator end() const noexcept;
168 const_iterator cend() const noexcept;
169 reverse_iterator rbegin();
170 const_reverse_iterator rbegin() const noexcept;
171 const_reverse_iterator crbegin() const noexcept;
172 reverse_iterator rend();
173 const_reverse_iterator rend() const noexcept;
174 const_reverse_iterator crend() const noexcept;
175
176 /* Capacity */
177 bool empty() const noexcept;
178 size_type size() const noexcept;
179 size_type length() const noexcept;
180 size_type max_size() const noexcept;
181 size_type capacity() const noexcept;
182 void resize(size_type count, CharT ch);
183 void resize(size_type n);
184 void reserve(size_type new_cap = 0);
185 void shrink_to_fit();
186 void clear();
187 void free_data();
188
189 /* Modifiers */
190 basic_string &erase(size_type index = 0, size_type count = npos);
191 iterator erase(const_iterator pos);
192 iterator erase(const_iterator first, const_iterator last);
193 /* We add following overloads to resolve erase(0) ambiguity */
194 template <typename T,
195 typename Enable = typename std::enable_if<
196 std::is_convertible<T, size_type>::value>::type>
197 basic_string &erase(T param);
198 template <typename T,
199 typename Enable = typename std::enable_if<
200 !std::is_convertible<T, size_type>::value>::type>
201 iterator erase(T param);
202 void pop_back();
203
204 basic_string &append(size_type count, CharT ch);
205 basic_string &append(const basic_string &str);
206 basic_string &append(const basic_string &str, size_type pos,
207 size_type count = npos);
208 basic_string &append(const CharT *s, size_type count);
209 basic_string &append(const CharT *s);
210 template <typename InputIt,
211 typename Enable = typename pmem::detail::is_input_iterator<
212 InputIt>::type>
213 basic_string &append(InputIt first, InputIt last);
214 basic_string &append(std::initializer_list<CharT> ilist);
215 void push_back(CharT ch);
217 basic_string &operator+=(const CharT *s);
218 basic_string &operator+=(CharT c);
219 basic_string &operator+=(std::initializer_list<CharT> ilist);
220
221 basic_string &insert(size_type index, size_type count, CharT ch);
222 basic_string &insert(size_type index, const CharT *s);
223 basic_string &insert(size_type index, const CharT *s, size_type count);
224 basic_string &insert(size_type index, const basic_string &str);
225 basic_string &insert(size_type index1, const basic_string &str,
226 size_type index2, size_type count = npos);
227 iterator insert(const_iterator pos, CharT ch);
228 iterator insert(const_iterator pos, size_type count, CharT ch);
229 template <typename InputIt,
230 typename Enable = typename pmem::detail::is_input_iterator<
231 InputIt>::type>
232 iterator insert(const_iterator pos, InputIt first, InputIt last);
233 iterator insert(const_iterator pos, std::initializer_list<CharT> ilist);
234 template <typename T,
235 typename Enable = typename std::enable_if<
236 std::is_convertible<T, size_type>::value>::type>
237 basic_string &insert(T param, size_type count, CharT ch);
238 template <typename T,
239 typename Enable = typename std::enable_if<
240 !std::is_convertible<T, size_type>::value>::type>
241 iterator insert(T param, size_type count, CharT ch);
242
243 basic_string &replace(size_type index, size_type count,
244 const basic_string &str);
245 basic_string &replace(const_iterator first, const_iterator last,
246 const basic_string &str);
247 basic_string &replace(size_type index, size_type count,
248 const basic_string &str, size_type index2,
249 size_type count2 = npos);
250 template <typename InputIt,
251 typename Enable = typename pmem::detail::is_input_iterator<
252 InputIt>::type>
253 basic_string &replace(const_iterator first, const_iterator last,
254 InputIt first2, InputIt last2);
255 basic_string &replace(const_iterator first, const_iterator last,
256 const CharT *s, size_type count2);
257 basic_string &replace(const_iterator first, const_iterator last,
258 const CharT *s);
259 basic_string &replace(size_type index, size_type count,
260 size_type count2, CharT ch);
261 basic_string &replace(const_iterator first, const_iterator last,
262 size_type count2, CharT ch);
263 basic_string &replace(size_type index, size_type count, const CharT *s,
264 size_type count2);
265 basic_string &replace(size_type index, size_type count, const CharT *s);
266 basic_string &replace(const_iterator first, const_iterator last,
267 std::initializer_list<CharT> ilist);
268
269 size_type copy(CharT *s, size_type count, size_type index = 0) const;
270
271 int compare(const basic_string &other) const;
272 int compare(const std::basic_string<CharT> &other) const;
273 int compare(size_type pos, size_type count,
274 const basic_string &other) const;
275 int compare(size_type pos, size_type count,
276 const std::basic_string<CharT> &other) const;
277 int compare(size_type pos1, size_type count1, const basic_string &other,
278 size_type pos2, size_type count2 = npos) const;
279 int compare(size_type pos1, size_type count1,
280 const std::basic_string<CharT> &other, size_type pos2,
281 size_type count2 = npos) const;
282 int compare(const CharT *s) const;
283 int compare(size_type pos, size_type count, const CharT *s) const;
284 int compare(size_type pos, size_type count1, const CharT *s,
285 size_type count2) const;
286
287 /* Search */
288 size_type find(const basic_string &str, size_type pos = 0) const
289 noexcept;
290 size_type find(const CharT *s, size_type pos, size_type count) const;
291 size_type find(const CharT *s, size_type pos = 0) const;
292 size_type find(CharT ch, size_type pos = 0) const noexcept;
293 size_type rfind(const basic_string &str, size_type pos = npos) const
294 noexcept;
295 size_type rfind(const CharT *s, size_type pos, size_type count) const;
296 size_type rfind(const CharT *s, size_type pos = npos) const;
297 size_type rfind(CharT ch, size_type pos = npos) const noexcept;
298 size_type find_first_of(const basic_string &str,
299 size_type pos = 0) const noexcept;
300 size_type find_first_of(const CharT *s, size_type pos,
301 size_type count) const;
302 size_type find_first_of(const CharT *s, size_type pos = 0) const;
303 size_type find_first_of(CharT ch, size_type pos = 0) const noexcept;
304 size_type find_first_not_of(const basic_string &str,
305 size_type pos = 0) const noexcept;
306 size_type find_first_not_of(const CharT *s, size_type pos,
307 size_type count) const;
308 size_type find_first_not_of(const CharT *s, size_type pos = 0) const;
309 size_type find_first_not_of(CharT ch, size_type pos = 0) const noexcept;
310 size_type find_last_of(const basic_string &str,
311 size_type pos = npos) const noexcept;
312 size_type find_last_of(const CharT *s, size_type pos,
313 size_type count) const;
314 size_type find_last_of(const CharT *s, size_type pos = npos) const;
315 size_type find_last_of(CharT ch, size_type pos = npos) const noexcept;
316 size_type find_last_not_of(const basic_string &str,
317 size_type pos = npos) const noexcept;
318 size_type find_last_not_of(const CharT *s, size_type pos,
319 size_type count) const;
320 size_type find_last_not_of(const CharT *s, size_type pos = npos) const;
321 size_type find_last_not_of(CharT ch, size_type pos = npos) const
322 noexcept;
323
324 void swap(basic_string &other);
325
326 operator basic_string_view<CharT, Traits>() const;
327
328 /* Special value. The exact meaning depends on the context. */
329 static const size_type npos = static_cast<size_type>(-1);
330
331private:
334
352 union {
353 struct {
354 /*
355 * EXACTLY the same type as first member in vector
356 * Holds size for sso string, bit specified by _sso_mask
357 * indicates if sso is used.
358 */
359 p<size_type> _size;
360
361 sso_type _data;
362 } sso;
363
364 struct {
365 non_sso_type _data;
366 } non_sso;
367 };
368
369 /*
370 * MSB is used because vector is known not to use entire range of
371 * size_type.
372 */
373 static constexpr size_type _sso_mask = 1ULL
374 << (std::numeric_limits<size_type>::digits - 1);
375
376 /* helper functions */
377 bool is_sso_used() const;
378 void destroy_data();
379 template <
380 typename InputIt,
381 typename Enable = typename std::enable_if<
383 size_type get_size(InputIt first, InputIt last) const;
384 size_type get_size(size_type count, value_type ch) const;
385 size_type get_size(const basic_string &other) const;
386 template <typename... Args>
387 pointer replace_content(Args &&... args);
388 template <typename... Args>
389 pointer initialize(Args &&... args);
390 void allocate(size_type capacity);
391 template <
392 typename InputIt,
393 typename Enable = typename std::enable_if<
395 pointer assign_sso_data(InputIt first, InputIt last);
396 pointer assign_sso_data(size_type count, value_type ch);
397 pointer move_data(basic_string &&other);
398 template <
399 typename InputIt,
400 typename Enable = typename std::enable_if<
402 pointer assign_large_data(InputIt first, InputIt last);
403 pointer assign_large_data(size_type count, value_type ch);
404 pool_base get_pool() const;
405 void check_pmem() const;
406 void check_tx_stage_work() const;
407 void check_pmem_tx() const;
408 void add_sso_to_tx(size_type first, size_type num) const;
409 size_type get_sso_size() const;
410 void enable_sso();
411 void disable_sso();
412 void set_sso_size(size_type new_size);
413 void sso_to_large(size_t new_capacity);
414 void large_to_sso();
415 typename basic_string<CharT, Traits>::non_sso_type &non_sso_data();
416 typename basic_string<CharT, Traits>::sso_type &sso_data();
418 non_sso_data() const;
419 const typename basic_string<CharT, Traits>::sso_type &sso_data() const;
420};
421
431template <typename CharT, typename Traits>
433{
434 check_pmem_tx();
435 sso._size = 0;
436
437 allocate(0);
438 initialize(0U, value_type('\0'));
439}
440
455template <typename CharT, typename Traits>
457{
458 check_pmem_tx();
459 sso._size = 0;
460
461 allocate(count);
462 initialize(count, ch);
463}
464
482template <typename CharT, typename Traits>
484 size_type pos, size_type count)
485{
486 check_pmem_tx();
487 sso._size = 0;
488
489 if (pos > other.size())
490 throw std::out_of_range("Index out of range.");
491
492 if (count == npos || pos + count > other.size())
493 count = other.size() - pos;
494
495 auto first = static_cast<difference_type>(pos);
496 auto last = first + static_cast<difference_type>(count);
497
498 allocate(count);
499 initialize(other.cbegin() + first, other.cbegin() + last);
500}
501
520template <typename CharT, typename Traits>
521basic_string<CharT, Traits>::basic_string(const std::basic_string<CharT> &other,
522 size_type pos, size_type count)
523 : basic_string(basic_string_view<CharT>(other), pos, count)
524{
525}
526
542template <typename CharT, typename Traits>
543basic_string<CharT, Traits>::basic_string(const CharT *s, size_type count)
544{
545 check_pmem_tx();
546 sso._size = 0;
547
548 allocate(count);
549 initialize(s, s + count);
550}
551
565template <typename CharT, typename Traits>
567{
568 check_pmem_tx();
569 sso._size = 0;
570
571 auto length = traits_type::length(s);
572
573 allocate(length);
574 initialize(s, s + length);
575}
576
593template <typename CharT, typename Traits>
594template <typename InputIt, typename Enable>
596{
597 auto len = std::distance(first, last);
598 assert(len >= 0);
599
600 check_pmem_tx();
601 sso._size = 0;
602
603 allocate(static_cast<size_type>(len));
604 initialize(first, last);
605}
606
621template <typename CharT, typename Traits>
623{
624 check_pmem_tx();
625 sso._size = 0;
626
627 allocate(other.size());
628 initialize(other.cbegin(), other.cend());
629}
630
646template <typename CharT, typename Traits>
647basic_string<CharT, Traits>::basic_string(const std::basic_string<CharT> &other)
648 : basic_string(other.cbegin(), other.cend())
649{
650}
651
666template <typename CharT, typename Traits>
668{
669 check_pmem_tx();
670 sso._size = 0;
671
672 move_data(std::move(other));
673}
674
689template <typename CharT, typename Traits>
690basic_string<CharT, Traits>::basic_string(std::initializer_list<CharT> ilist)
691{
692 check_pmem_tx();
693 sso._size = 0;
694
695 allocate(ilist.size());
696 initialize(ilist.begin(), ilist.end());
697}
698
714template <typename CharT, typename Traits>
715template <class T, typename Enable>
717{
718 check_pmem_tx();
719 sso._size = 0;
720
722
723 allocate(sv.size());
724 initialize(sv.data(), sv.data() + sv.size());
725}
726
744template <typename CharT, typename Traits>
745template <class T, typename Enable>
747 size_type n)
748{
749 check_pmem_tx();
750 sso._size = 0;
751
753
754 if (pos > sv.size())
755 throw std::out_of_range("Index out of range.");
756
757 if (n == npos || pos + n > sv.size())
758 n = sv.size() - pos;
759
760 auto first = pos;
761 auto last = first + n;
762
763 allocate(n);
764 initialize(sv.data() + first, sv.data() + last);
765}
766
770template <typename CharT, typename Traits>
772{
773 try {
774 free_data();
775 } catch (...) {
776 std::terminate();
777 }
778}
779
789template <typename CharT, typename Traits>
792{
793 return assign(other);
794}
795
806template <typename CharT, typename Traits>
808basic_string<CharT, Traits>::operator=(const std::basic_string<CharT> &other)
809{
810 return assign(other);
811}
812
822template <typename CharT, typename Traits>
825{
826 return assign(std::move(other));
827}
828
837template <typename CharT, typename Traits>
840{
841 return assign(s);
842}
843
852template <typename CharT, typename Traits>
855{
856 return assign(1, ch);
857}
858
868template <typename CharT, typename Traits>
870basic_string<CharT, Traits>::operator=(std::initializer_list<CharT> ilist)
871{
872 return assign(ilist);
873}
874
884template <typename CharT, typename Traits>
885template <class T, typename Enable>
888{
890 return assign(sv.data(), sv.size());
891}
892
903template <typename CharT, typename Traits>
905basic_string<CharT, Traits>::assign(size_type count, CharT ch)
906{
907 auto pop = get_pool();
908
909 flat_transaction::run(pop, [&] { replace_content(count, ch); });
910
911 return *this;
912}
913
923template <typename CharT, typename Traits>
926{
927 if (&other == this)
928 return *this;
929
930 auto pop = get_pool();
931
933 pop, [&] { replace_content(other.cbegin(), other.cend()); });
934
935 return *this;
936}
937
948template <typename CharT, typename Traits>
950basic_string<CharT, Traits>::assign(const std::basic_string<CharT> &other)
951{
952 return assign(other.cbegin(), other.cend());
953}
954
967template <typename CharT, typename Traits>
970 size_type count)
971{
972 if (pos > other.size())
973 throw std::out_of_range("Index out of range.");
974
975 if (count == npos || pos + count > other.size())
976 count = other.size() - pos;
977
978 auto pop = get_pool();
979 auto first = static_cast<difference_type>(pos);
980 auto last = first + static_cast<difference_type>(count);
981
982 flat_transaction::run(pop, [&] {
983 replace_content(other.cbegin() + first, other.cbegin() + last);
984 });
985
986 return *this;
987}
988
1003template <typename CharT, typename Traits>
1005basic_string<CharT, Traits>::assign(const std::basic_string<CharT> &other,
1006 size_type pos, size_type count)
1007{
1008 if (pos > other.size())
1009 throw std::out_of_range("Index out of range.");
1010
1011 if (count == npos || pos + count > other.size())
1012 count = other.size() - pos;
1013
1014 return assign(other.c_str() + pos, count);
1015}
1016
1027template <typename CharT, typename Traits>
1029basic_string<CharT, Traits>::assign(const CharT *s, size_type count)
1030{
1031 auto pop = get_pool();
1032
1033 flat_transaction::run(pop, [&] { replace_content(s, s + count); });
1034
1035 return *this;
1036}
1037
1046template <typename CharT, typename Traits>
1049{
1050 auto pop = get_pool();
1051
1052 auto length = traits_type::length(s);
1053
1054 flat_transaction::run(pop, [&] { replace_content(s, s + length); });
1055
1056 return *this;
1057}
1058
1070template <typename CharT, typename Traits>
1071template <typename InputIt, typename Enable>
1073basic_string<CharT, Traits>::assign(InputIt first, InputIt last)
1074{
1075 auto pop = get_pool();
1076
1077 flat_transaction::run(pop, [&] { replace_content(first, last); });
1078
1079 return *this;
1080}
1081
1091template <typename CharT, typename Traits>
1094{
1095 if (&other == this)
1096 return *this;
1097
1098 auto pop = get_pool();
1099
1100 flat_transaction::run(pop, [&] {
1101 destroy_data();
1102 move_data(std::move(other));
1103 });
1104
1105 return *this;
1106}
1107
1117template <typename CharT, typename Traits>
1119basic_string<CharT, Traits>::assign(std::initializer_list<CharT> ilist)
1120{
1121 return assign(ilist.begin(), ilist.end());
1122}
1123
1131template <typename CharT, typename Traits>
1132void
1134{
1135 if (!is_sso_used()) {
1136 non_sso._data.for_each_ptr(func);
1137 }
1138}
1139
1145template <typename CharT, typename Traits>
1148{
1149 return is_sso_used() ? iterator(&*sso_data().begin())
1150 : iterator(&*non_sso_data().begin());
1151}
1152
1158template <typename CharT, typename Traits>
1159typename basic_string<CharT, Traits>::const_iterator
1161{
1162 return cbegin();
1163}
1164
1170template <typename CharT, typename Traits>
1171typename basic_string<CharT, Traits>::const_iterator
1173{
1174 return is_sso_used() ? const_iterator(&*sso_data().cbegin())
1175 : const_iterator(&*non_sso_data().cbegin());
1176}
1177
1183template <typename CharT, typename Traits>
1186{
1187 return begin() + static_cast<difference_type>(size());
1188}
1189
1196template <typename CharT, typename Traits>
1197typename basic_string<CharT, Traits>::const_iterator
1199{
1200 return cbegin() + static_cast<difference_type>(size());
1201}
1202
1209template <typename CharT, typename Traits>
1210typename basic_string<CharT, Traits>::const_iterator
1212{
1213 return cbegin() + static_cast<difference_type>(size());
1214}
1215
1222template <typename CharT, typename Traits>
1223typename basic_string<CharT, Traits>::reverse_iterator
1225{
1226 return reverse_iterator(end());
1227}
1228
1235template <typename CharT, typename Traits>
1236typename basic_string<CharT, Traits>::const_reverse_iterator
1238{
1239 return crbegin();
1240}
1241
1248template <typename CharT, typename Traits>
1249typename basic_string<CharT, Traits>::const_reverse_iterator
1251{
1252 return const_reverse_iterator(cend());
1253}
1254
1261template <typename CharT, typename Traits>
1262typename basic_string<CharT, Traits>::reverse_iterator
1264{
1265 return reverse_iterator(begin());
1266}
1267
1274template <typename CharT, typename Traits>
1275typename basic_string<CharT, Traits>::const_reverse_iterator
1277{
1278 return crend();
1279}
1280
1287template <typename CharT, typename Traits>
1288typename basic_string<CharT, Traits>::const_reverse_iterator
1290{
1291 return const_reverse_iterator(cbegin());
1292}
1293
1307template <typename CharT, typename Traits>
1308typename basic_string<CharT, Traits>::reference
1310{
1311 if (n >= size())
1312 throw std::out_of_range("string::at");
1313
1314 return is_sso_used() ? sso_data()[n] : non_sso_data()[n];
1315}
1316
1327template <typename CharT, typename Traits>
1328typename basic_string<CharT, Traits>::const_reference
1330{
1331 return const_at(n);
1332}
1333
1347template <typename CharT, typename Traits>
1348typename basic_string<CharT, Traits>::const_reference
1350{
1351 if (n >= size())
1352 throw std::out_of_range("string::const_at");
1353
1354 return is_sso_used()
1355 ? static_cast<const sso_type &>(sso_data())[n]
1356 : static_cast<const non_sso_type &>(non_sso_data())[n];
1357}
1358
1370template <typename CharT, typename Traits>
1371typename basic_string<CharT, Traits>::reference
1373{
1374 return is_sso_used() ? sso_data()[n] : non_sso_data()[n];
1375}
1376
1384template <typename CharT, typename Traits>
1385typename basic_string<CharT, Traits>::const_reference
1387{
1388 return is_sso_used() ? sso_data()[n] : non_sso_data()[n];
1389}
1390
1404template <typename CharT, typename Traits>
1406basic_string<CharT, Traits>::range(size_type start, size_type n)
1407{
1408 if (start + n > size())
1409 throw std::out_of_range("basic_string::range");
1410
1411 return is_sso_used() ? sso_data().range(start, n)
1412 : non_sso_data().range(start, n);
1413}
1414
1431template <typename CharT, typename Traits>
1433basic_string<CharT, Traits>::range(size_type start, size_type n,
1434 size_type snapshot_size)
1435{
1436 if (start + n > size())
1437 throw std::out_of_range("basic_string::range");
1438
1439 if (snapshot_size > n)
1440 snapshot_size = n;
1441
1442 return is_sso_used() ? sso_data().range(start, n, snapshot_size)
1443 : non_sso_data().range(start, n, snapshot_size);
1444}
1445
1457template <typename CharT, typename Traits>
1459basic_string<CharT, Traits>::range(size_type start, size_type n) const
1460{
1461 return crange(start, n);
1462}
1463
1475template <typename CharT, typename Traits>
1477basic_string<CharT, Traits>::crange(size_type start, size_type n) const
1478{
1479 if (start + n > size())
1480 throw std::out_of_range("basic_string::range");
1481
1482 return {const_iterator(cdata() + start),
1483 const_iterator(cdata() + start + n)};
1484}
1485
1495template <typename CharT, typename Traits>
1496CharT &
1498{
1499 return (*this)[0];
1500}
1501
1507template <typename CharT, typename Traits>
1508const CharT &
1510{
1511 return cfront();
1512}
1513
1522template <typename CharT, typename Traits>
1523const CharT &
1525{
1526 return static_cast<const basic_string &>(*this)[0];
1527}
1528
1538template <typename CharT, typename Traits>
1539CharT &
1541{
1542 return (*this)[size() - 1];
1543}
1544
1550template <typename CharT, typename Traits>
1551const CharT &
1553{
1554 return cback();
1555}
1556
1565template <typename CharT, typename Traits>
1566const CharT &
1568{
1569 return static_cast<const basic_string &>(*this)[size() - 1];
1570}
1571
1575template <typename CharT, typename Traits>
1576typename basic_string<CharT, Traits>::size_type
1578{
1579 if (is_sso_used())
1580 return get_sso_size();
1581 else if (non_sso_data().size() == 0)
1582 return 0;
1583 else
1584 return non_sso_data().size() - 1;
1585}
1586
1593template <typename CharT, typename Traits>
1594CharT *
1596{
1597 return is_sso_used() ? sso_data().range(0, get_sso_size() + 1).begin()
1598 : non_sso_data().data();
1599}
1600
1619template <typename CharT, typename Traits>
1621basic_string<CharT, Traits>::erase(size_type index, size_type count)
1622{
1623 auto sz = size();
1624
1625 if (index > sz)
1626 throw std::out_of_range("Index exceeds size.");
1627
1628 count = (std::min)(count, sz - index);
1629
1630 auto pop = get_pool();
1631
1632 auto first = begin() + static_cast<difference_type>(index);
1633 auto last = first + static_cast<difference_type>(count);
1634
1635 if (is_sso_used()) {
1636 flat_transaction::run(pop, [&] {
1637 auto move_len = sz - index - count;
1638 auto new_size = sz - count;
1639
1640 if (move_len > 0) {
1641 auto range =
1642 sso_data().range(index, move_len + 1);
1643 traits_type::move(range.begin(), &*last,
1644 move_len);
1645
1646 assert(range.end() - 1 ==
1647 &sso_data()._data[index + move_len]);
1648 }
1649
1650 sso_data()[index + move_len] = value_type('\0');
1651 set_sso_size(new_size);
1652 });
1653 } else {
1654 non_sso_data().erase(first, last);
1655 }
1656
1657 return *this;
1658}
1659
1676template <typename CharT, typename Traits>
1679{
1680 return erase(pos, pos + 1);
1681}
1682
1701template <typename CharT, typename Traits>
1703basic_string<CharT, Traits>::erase(const_iterator first, const_iterator last)
1704{
1705 size_type index =
1706 static_cast<size_type>(std::distance(cbegin(), first));
1707 size_type len = static_cast<size_type>(std::distance(first, last));
1708
1709 erase(index, len);
1710
1711 return begin() + static_cast<difference_type>(index);
1712}
1713
1724template <typename CharT, typename Traits>
1725void
1727{
1728 erase(size() - 1, 1);
1729}
1730
1750template <typename CharT, typename Traits>
1752basic_string<CharT, Traits>::append(size_type count, CharT ch)
1753{
1754 auto sz = size();
1755 auto new_size = sz + count;
1756
1757 if (new_size > max_size())
1758 throw std::length_error("Size exceeds max size.");
1759
1760 if (is_sso_used()) {
1761 auto pop = get_pool();
1762
1763 flat_transaction::run(pop, [&] {
1764 if (new_size > sso_capacity) {
1765 sso_to_large(new_size);
1766
1767 non_sso_data().insert(
1768 non_sso_data().cbegin() +
1769 static_cast<difference_type>(
1770 sz),
1771 count, ch);
1772 } else {
1773 add_sso_to_tx(sz, count + 1);
1774 traits_type::assign(&sso_data()._data[sz],
1775 count, ch);
1776
1777 assert(new_size == sz + count);
1778 set_sso_size(new_size);
1779 sso_data()._data[new_size] = value_type('\0');
1780 }
1781 });
1782 } else {
1783 non_sso_data().insert(non_sso_data().cbegin() +
1784 static_cast<difference_type>(sz),
1785 count, ch);
1786 }
1787
1788 return *this;
1789}
1790
1809template <typename CharT, typename Traits>
1812{
1813 return append(str.data(), str.size());
1814}
1815
1841template <typename CharT, typename Traits>
1844 size_type count)
1845{
1846 auto sz = str.size();
1847
1848 if (pos > sz)
1849 throw std::out_of_range("Index out of range.");
1850
1851 count = (std::min)(count, sz - pos);
1852
1853 append(str.data() + pos, count);
1854
1855 return *this;
1856}
1857
1877template <typename CharT, typename Traits>
1879basic_string<CharT, Traits>::append(const CharT *s, size_type count)
1880{
1881 return append(s, s + count);
1882}
1883
1903template <typename CharT, typename Traits>
1906{
1907 return append(s, traits_type::length(s));
1908}
1909
1931template <typename CharT, typename Traits>
1932template <typename InputIt, typename Enable>
1934basic_string<CharT, Traits>::append(InputIt first, InputIt last)
1935{
1936 auto sz = size();
1937 auto count = static_cast<size_type>(std::distance(first, last));
1938 auto new_size = sz + count;
1939
1940 if (new_size > max_size())
1941 throw std::length_error("Size exceeds max size.");
1942
1943 if (is_sso_used()) {
1944 auto pop = get_pool();
1945
1946 flat_transaction::run(pop, [&] {
1947 if (new_size > sso_capacity) {
1948 /* 1) Cache C-style string in case of
1949 * self-append, because it will be destroyed
1950 * when switching from sso to large string.
1951 *
1952 * 2) We cache in std::vector instead of
1953 * std::string because of overload deduction
1954 * ambiguity on Windows
1955 */
1956 std::vector<value_type> str(first, last);
1957
1958 sso_to_large(new_size);
1959 non_sso_data().insert(
1960 non_sso_data().cbegin() +
1961 static_cast<difference_type>(
1962 sz),
1963 str.begin(), str.end());
1964 } else {
1965 add_sso_to_tx(sz, count + 1);
1966 std::copy(first, last, &sso_data()._data[sz]);
1967
1968 assert(new_size == sz + count);
1969 set_sso_size(new_size);
1970 sso_data()._data[new_size] = value_type('\0');
1971 }
1972 });
1973 } else {
1974 non_sso_data().insert(non_sso_data().cbegin() +
1975 static_cast<difference_type>(sz),
1976 first, last);
1977 }
1978
1979 return *this;
1980}
1981
2000template <typename CharT, typename Traits>
2002basic_string<CharT, Traits>::append(std::initializer_list<CharT> ilist)
2003{
2004 return append(ilist.begin(), ilist.end());
2005}
2006
2023template <typename CharT, typename Traits>
2024void
2026{
2027 append(static_cast<size_type>(1), ch);
2028}
2029
2048template <typename CharT, typename Traits>
2051{
2052 return append(str);
2053}
2054
2074template <typename CharT, typename Traits>
2077{
2078 return append(s);
2079}
2080
2097template <typename CharT, typename Traits>
2100{
2101 push_back(ch);
2102
2103 return *this;
2104}
2105
2124template <typename CharT, typename Traits>
2126basic_string<CharT, Traits>::operator+=(std::initializer_list<CharT> ilist)
2127{
2128 return append(ilist);
2129}
2130
2152template <typename CharT, typename Traits>
2154basic_string<CharT, Traits>::insert(size_type index, size_type count, CharT ch)
2155{
2156 if (index > size())
2157 throw std::out_of_range("Index out of range.");
2158
2159 auto pos = cbegin() + static_cast<difference_type>(index);
2160
2161 insert(pos, count, ch);
2162
2163 return *this;
2164}
2165
2187template <typename CharT, typename Traits>
2189basic_string<CharT, Traits>::insert(size_type index, const CharT *s)
2190{
2191 return insert(index, s, traits_type::length(s));
2192}
2193
2215template <typename CharT, typename Traits>
2217basic_string<CharT, Traits>::insert(size_type index, const CharT *s,
2218 size_type count)
2219{
2220 if (index > size())
2221 throw std::out_of_range("Index out of range.");
2222
2223 auto pos = cbegin() + static_cast<difference_type>(index);
2224
2225 insert(pos, s, s + count);
2226
2227 return *this;
2228}
2229
2250template <typename CharT, typename Traits>
2253{
2254 return insert(index, str.data(), str.size());
2255}
2256
2279template <typename CharT, typename Traits>
2282 size_type index2, size_type count)
2283{
2284 auto sz = str.size();
2285
2286 if (index1 > size() || index2 > sz)
2287 throw std::out_of_range("Index out of range.");
2288
2289 count = (std::min)(count, sz - index2);
2290
2291 return insert(index1, str.data() + index2, count);
2292}
2293
2316template <typename CharT, typename Traits>
2318basic_string<CharT, Traits>::insert(const_iterator pos, CharT ch)
2319{
2320 return insert(pos, 1, ch);
2321}
2322
2347template <typename CharT, typename Traits>
2349basic_string<CharT, Traits>::insert(const_iterator pos, size_type count,
2350 CharT ch)
2351{
2352 auto sz = size();
2353
2354 if (sz + count > max_size())
2355 throw std::length_error("Count exceeds max size.");
2356
2357 auto new_size = sz + count;
2358
2359 auto pop = get_pool();
2360
2361 auto index = static_cast<size_type>(std::distance(cbegin(), pos));
2362
2363 flat_transaction::run(pop, [&] {
2364 if (is_sso_used() && new_size <= sso_capacity) {
2365 auto len = sz - index;
2366
2367 add_sso_to_tx(index, len + count + 1);
2368
2369 traits_type::move(&sso_data()._data[index + count],
2370 &sso_data()._data[index], len);
2371 traits_type::assign(&sso_data()._data[index], count,
2372 ch);
2373
2374 assert(new_size == index + len + count);
2375 set_sso_size(new_size);
2376 sso_data()._data[new_size] = value_type('\0');
2377 } else {
2378 if (is_sso_used())
2379 sso_to_large(new_size);
2380
2381 non_sso_data().insert(
2382 non_sso_data().begin() +
2383 static_cast<difference_type>(index),
2384 count, ch);
2385 }
2386 });
2387
2388 return iterator(&data()[static_cast<difference_type>(index)]);
2389}
2390
2415template <typename CharT, typename Traits>
2416template <typename InputIt, typename Enable>
2418basic_string<CharT, Traits>::insert(const_iterator pos, InputIt first,
2419 InputIt last)
2420{
2421 auto sz = size();
2422
2423 auto count = static_cast<size_type>(std::distance(first, last));
2424
2425 if (sz + count > max_size())
2426 throw std::length_error("Count exceeds max size.");
2427
2428 auto pop = get_pool();
2429
2430 auto new_size = sz + count;
2431
2432 auto index = static_cast<size_type>(std::distance(cbegin(), pos));
2433
2434 flat_transaction::run(pop, [&] {
2435 if (is_sso_used() && new_size <= sso_capacity) {
2436 auto len = sz - index;
2437
2438 add_sso_to_tx(index, len + count + 1);
2439
2440 traits_type::move(&sso_data()._data[index + count],
2441 &sso_data()._data[index], len);
2442 std::copy(first, last, &sso_data()._data[index]);
2443
2444 assert(new_size == index + len + count);
2445 set_sso_size(new_size);
2446 sso_data()._data[new_size] = value_type('\0');
2447 } else {
2448 if (is_sso_used()) {
2449 /* 1) Cache C-style string in case of
2450 * self-insert, because it will be destroyed
2451 * when switching from sso to large string.
2452 *
2453 * 2) We cache in std::vector instead of
2454 * std::string because of overload deduction
2455 * ambiguity on Windows
2456 */
2457 std::vector<value_type> str(first, last);
2458
2459 sso_to_large(new_size);
2460 non_sso_data().insert(
2461 non_sso_data().begin() +
2462 static_cast<difference_type>(
2463 index),
2464 str.begin(), str.end());
2465 } else {
2466 non_sso_data().insert(
2467 non_sso_data().begin() +
2468 static_cast<difference_type>(
2469 index),
2470 first, last);
2471 }
2472 }
2473 });
2474
2475 return iterator(&data()[static_cast<difference_type>(index)]);
2476}
2477
2501template <typename CharT, typename Traits>
2504 std::initializer_list<CharT> ilist)
2505{
2506 return insert(pos, ilist.begin(), ilist.end());
2507}
2508
2531template <typename CharT, typename Traits>
2533basic_string<CharT, Traits>::replace(size_type index, size_type count,
2534 const basic_string &str)
2535{
2536 return replace(index, count, str.data(), str.size());
2537}
2538
2559template <typename CharT, typename Traits>
2561basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2562 const basic_string &str)
2563{
2564 return replace(first, last, str.data(), str.data() + str.size());
2565}
2566
2593template <typename CharT, typename Traits>
2595basic_string<CharT, Traits>::replace(size_type index, size_type count,
2596 const basic_string &str, size_type index2,
2597 size_type count2)
2598{
2599 auto sz = str.size();
2600
2601 if (index2 > sz)
2602 throw std::out_of_range("Index out of range.");
2603
2604 count2 = (std::min)(count2, sz - index2);
2605
2606 return replace(index, count, str.data() + index2, count2);
2607}
2608
2634template <typename CharT, typename Traits>
2635template <typename InputIt, typename Enable>
2637basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2638 InputIt first2, InputIt last2)
2639{
2640 auto sz = size();
2641 auto index = static_cast<size_type>(std::distance(cbegin(), first));
2642 auto count = static_cast<size_type>(std::distance(first, last));
2643 auto count2 = static_cast<size_type>(std::distance(first2, last2));
2644
2645 count = (std::min)(count, sz - index);
2646
2647 if (sz - count + count2 > max_size())
2648 throw std::length_error("Count exceeds max size.");
2649
2650 auto new_size = sz - count + count2;
2651
2652 auto pop = get_pool();
2653
2654 flat_transaction::run(pop, [&] {
2655 if (is_sso_used() && new_size <= sso_capacity) {
2656 add_sso_to_tx(index, new_size - index + 1);
2657
2658 assert(count2 < new_size + 1);
2659 traits_type::move(&sso_data()._data[index + count2],
2660 &sso_data()._data[index + count],
2661 sz - index - count);
2662 std::copy(first2, last2, &sso_data()._data[index]);
2663
2664 set_sso_size(new_size);
2665 sso_data()._data[new_size] = value_type('\0');
2666 } else {
2667 /* 1) Cache C-style string in case of
2668 * self-replace, because it will be destroyed
2669 * when switching from sso to large string.
2670 *
2671 * 2) We cache in std::vector instead of
2672 * std::string because of overload deduction
2673 * ambiguity on Windows
2674 */
2675 std::vector<value_type> str(first2, last2);
2676
2677 if (is_sso_used()) {
2678 sso_to_large(new_size);
2679 }
2680
2681 auto beg =
2682 begin() + static_cast<difference_type>(index);
2683 auto end = beg + static_cast<difference_type>(count);
2684 non_sso_data().erase(beg, end);
2685 non_sso_data().insert(beg, str.begin(), str.end());
2686 }
2687
2688 if (!is_sso_used() && new_size <= sso_capacity)
2689 large_to_sso();
2690 });
2691
2692 return *this;
2693}
2694
2717template <typename CharT, typename Traits>
2719basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2720 const CharT *s, size_type count2)
2721{
2722 return replace(first, last, s, s + count2);
2723}
2724
2748template <typename CharT, typename Traits>
2750basic_string<CharT, Traits>::replace(size_type index, size_type count,
2751 const CharT *s, size_type count2)
2752{
2753 if (index > size())
2754 throw std::out_of_range("Index out of range.");
2755
2756 auto first = cbegin() + static_cast<difference_type>(index);
2757 auto last = first + static_cast<difference_type>(count);
2758
2759 return replace(first, last, s, s + count2);
2760}
2761
2785template <typename CharT, typename Traits>
2787basic_string<CharT, Traits>::replace(size_type index, size_type count,
2788 const CharT *s)
2789{
2790 return replace(index, count, s, traits_type::length(s));
2791}
2792
2816template <typename CharT, typename Traits>
2818basic_string<CharT, Traits>::replace(size_type index, size_type count,
2819 size_type count2, CharT ch)
2820{
2821 if (index > size())
2822 throw std::out_of_range("Index out of range.");
2823
2824 auto first = cbegin() + static_cast<difference_type>(index);
2825 auto last = first + static_cast<difference_type>(count);
2826
2827 return replace(first, last, count2, ch);
2828}
2829
2852template <typename CharT, typename Traits>
2854basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2855 size_type count2, CharT ch)
2856{
2857 auto sz = size();
2858 auto index = static_cast<size_type>(std::distance(cbegin(), first));
2859 auto count = static_cast<size_type>(std::distance(first, last));
2860
2861 count = (std::min)(count, sz - index);
2862
2863 if (sz - count + count2 > max_size())
2864 throw std::length_error("Count exceeds max size.");
2865
2866 auto new_size = sz - count + count2;
2867
2868 auto pop = get_pool();
2869
2870 flat_transaction::run(pop, [&] {
2871 if (is_sso_used() && new_size <= sso_capacity) {
2872 add_sso_to_tx(index, new_size - index + 1);
2873
2874 assert(count2 < new_size + 1);
2875 traits_type::move(&sso_data()._data[index + count2],
2876 &sso_data()._data[index + count],
2877 sz - index - count);
2878 traits_type::assign(&sso_data()._data[index], count2,
2879 ch);
2880
2881 set_sso_size(new_size);
2882 sso_data()._data[new_size] = value_type('\0');
2883 } else {
2884 if (is_sso_used()) {
2885 sso_to_large(new_size);
2886 }
2887
2888 auto beg =
2889 begin() + static_cast<difference_type>(index);
2890 auto end = beg + static_cast<difference_type>(count);
2891 non_sso_data().erase(beg, end);
2892 non_sso_data().insert(beg, count2, ch);
2893 }
2894
2895 if (!is_sso_used() && new_size <= sso_capacity)
2896 large_to_sso();
2897 });
2898
2899 return *this;
2900}
2901
2923template <typename CharT, typename Traits>
2925basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2926 const CharT *s)
2927{
2928 return replace(first, last, s, traits_type::length(s));
2929}
2930
2953template <typename CharT, typename Traits>
2955basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2956 std::initializer_list<CharT> ilist)
2957{
2958 return replace(first, last, ilist.begin(), ilist.end());
2959}
2960
2974template <typename CharT, typename Traits>
2975typename basic_string<CharT, Traits>::size_type
2976basic_string<CharT, Traits>::copy(CharT *s, size_type count,
2977 size_type index) const
2978{
2979 auto sz = size();
2980
2981 if (index > sz)
2982 throw std::out_of_range("Index out of range.");
2983
2984 auto len = (std::min)(count, sz - index);
2985
2986 traits_type::copy(s, data() + index, len);
2987
2988 return len;
2989}
2990
3008template <typename CharT, typename Traits>
3009int
3010basic_string<CharT, Traits>::compare(size_type pos, size_type count1,
3011 const CharT *s, size_type count2) const
3012{
3013 if (pos > size())
3014 throw std::out_of_range("Index out of range.");
3015
3016 if (count1 > size() - pos)
3017 count1 = size() - pos;
3018
3019 auto ret = traits_type::compare(cdata() + pos, s,
3020 std::min<size_type>(count1, count2));
3021
3022 if (ret != 0)
3023 return ret;
3024
3025 if (count1 < count2)
3026 return -1;
3027 else if (count1 == count2)
3028 return 0;
3029 else
3030 return 1;
3031}
3032
3042template <typename CharT, typename Traits>
3043typename basic_string<CharT, Traits>::size_type
3044basic_string<CharT, Traits>::find(const basic_string &str, size_type pos) const
3045 noexcept
3046{
3047 return find(str.data(), pos, str.size());
3048}
3049
3061template <typename CharT, typename Traits>
3062typename basic_string<CharT, Traits>::size_type
3063basic_string<CharT, Traits>::find(const CharT *s, size_type pos,
3064 size_type count) const
3065{
3066 return operator basic_string_view<CharT, Traits>().find(s, pos, count);
3067}
3068
3079template <typename CharT, typename Traits>
3080typename basic_string<CharT, Traits>::size_type
3081basic_string<CharT, Traits>::find(const CharT *s, size_type pos) const
3082{
3083 return find(s, pos, traits_type::length(s));
3084}
3085
3095template <typename CharT, typename Traits>
3096typename basic_string<CharT, Traits>::size_type
3097basic_string<CharT, Traits>::find(CharT ch, size_type pos) const noexcept
3098{
3099 return find(&ch, pos, 1);
3100}
3101
3112template <typename CharT, typename Traits>
3113typename basic_string<CharT, Traits>::size_type
3114basic_string<CharT, Traits>::rfind(const basic_string &str, size_type pos) const
3115 noexcept
3116{
3117 return rfind(str.cdata(), pos, str.size());
3118}
3119
3136template <typename CharT, typename Traits>
3137typename basic_string<CharT, Traits>::size_type
3138basic_string<CharT, Traits>::rfind(const CharT *s, size_type pos,
3139 size_type count) const
3140{
3141 return operator basic_string_view<CharT, Traits>().rfind(s, pos, count);
3142}
3143
3156template <typename CharT, typename Traits>
3157typename basic_string<CharT, Traits>::size_type
3158basic_string<CharT, Traits>::rfind(const CharT *s, size_type pos) const
3159{
3160 return rfind(s, pos, traits_type::length(s));
3161}
3162
3174template <typename CharT, typename Traits>
3175typename basic_string<CharT, Traits>::size_type
3176basic_string<CharT, Traits>::rfind(CharT ch, size_type pos) const noexcept
3177{
3178 return rfind(&ch, pos, 1);
3179}
3180
3190template <typename CharT, typename Traits>
3191typename basic_string<CharT, Traits>::size_type
3193 size_type pos) const noexcept
3194{
3195 return find_first_of(str.cdata(), pos, str.size());
3196}
3197
3211template <typename CharT, typename Traits>
3212typename basic_string<CharT, Traits>::size_type
3214 size_type count) const
3215{
3216 return operator basic_string_view<CharT, Traits>().find_first_of(s, pos,
3217 count);
3218}
3219
3232template <typename CharT, typename Traits>
3233typename basic_string<CharT, Traits>::size_type
3234basic_string<CharT, Traits>::find_first_of(const CharT *s, size_type pos) const
3235{
3236 return find_first_of(s, pos, traits_type::length(s));
3237}
3238
3248template <typename CharT, typename Traits>
3249typename basic_string<CharT, Traits>::size_type
3251 noexcept
3252{
3253 return find(ch, pos);
3254}
3255
3265template <typename CharT, typename Traits>
3266typename basic_string<CharT, Traits>::size_type
3268 size_type pos) const noexcept
3269{
3270 return find_first_not_of(str.cdata(), pos, str.size());
3271}
3272
3286template <typename CharT, typename Traits>
3287typename basic_string<CharT, Traits>::size_type
3289 size_type count) const
3290{
3292 s, pos, count);
3293}
3294
3307template <typename CharT, typename Traits>
3308typename basic_string<CharT, Traits>::size_type
3310 size_type pos) const
3311{
3312 return find_first_not_of(s, pos, traits_type::length(s));
3313}
3314
3324template <typename CharT, typename Traits>
3325typename basic_string<CharT, Traits>::size_type
3327 noexcept
3328{
3329 return find_first_not_of(&ch, pos, 1);
3330}
3331
3341template <typename CharT, typename Traits>
3342typename basic_string<CharT, Traits>::size_type
3344 size_type pos) const noexcept
3345{
3346 return find_last_of(str.cdata(), pos, str.size());
3347}
3348
3362template <typename CharT, typename Traits>
3363typename basic_string<CharT, Traits>::size_type
3364basic_string<CharT, Traits>::find_last_of(const CharT *s, size_type pos,
3365 size_type count) const
3366{
3367 return operator basic_string_view<CharT, Traits>().find_last_of(s, pos,
3368 count);
3369}
3370
3383template <typename CharT, typename Traits>
3384typename basic_string<CharT, Traits>::size_type
3385basic_string<CharT, Traits>::find_last_of(const CharT *s, size_type pos) const
3386{
3387 return find_last_of(s, pos, traits_type::length(s));
3388}
3389
3399template <typename CharT, typename Traits>
3400typename basic_string<CharT, Traits>::size_type
3401basic_string<CharT, Traits>::find_last_of(CharT ch, size_type pos) const
3402 noexcept
3403{
3404 return rfind(ch, pos);
3405}
3406
3416template <typename CharT, typename Traits>
3417typename basic_string<CharT, Traits>::size_type
3419 size_type pos) const noexcept
3420{
3421 return find_last_not_of(str.cdata(), pos, str.size());
3422}
3423
3437template <typename CharT, typename Traits>
3438typename basic_string<CharT, Traits>::size_type
3440 size_type count) const
3441{
3443 s, pos, count);
3444}
3445
3458template <typename CharT, typename Traits>
3459typename basic_string<CharT, Traits>::size_type
3461 size_type pos) const
3462{
3463 return find_last_not_of(s, pos, traits_type::length(s));
3464}
3465
3475template <typename CharT, typename Traits>
3476typename basic_string<CharT, Traits>::size_type
3478 noexcept
3479{
3480 return find_last_not_of(&ch, pos, 1);
3481}
3482
3491template <typename CharT, typename Traits>
3492int
3494{
3495 return compare(0, size(), other.cdata(), other.size());
3496}
3497
3506template <typename CharT, typename Traits>
3507int
3509 const std::basic_string<CharT> &other) const
3510{
3511 return compare(0, size(), other.data(), other.size());
3512}
3513
3527template <typename CharT, typename Traits>
3528int
3529basic_string<CharT, Traits>::compare(size_type pos, size_type count,
3530 const basic_string &other) const
3531{
3532 return compare(pos, count, other.cdata(), other.size());
3533}
3534
3549template <typename CharT, typename Traits>
3550int
3552 size_type pos, size_type count,
3553 const std::basic_string<CharT> &other) const
3554{
3555 return compare(pos, count, other.data(), other.size());
3556}
3557
3576template <typename CharT, typename Traits>
3577int
3578basic_string<CharT, Traits>::compare(size_type pos1, size_type count1,
3579 const basic_string &other, size_type pos2,
3580 size_type count2) const
3581{
3582 if (pos2 > other.size())
3583 throw std::out_of_range("Index out of range.");
3584
3585 if (count2 > other.size() - pos2)
3586 count2 = other.size() - pos2;
3587
3588 return compare(pos1, count1, other.cdata() + pos2, count2);
3589}
3590
3609template <typename CharT, typename Traits>
3610int
3611basic_string<CharT, Traits>::compare(size_type pos1, size_type count1,
3612 const std::basic_string<CharT> &other,
3613 size_type pos2, size_type count2) const
3614{
3615 if (pos2 > other.size())
3616 throw std::out_of_range("Index out of range.");
3617
3618 if (count2 > other.size() - pos2)
3619 count2 = other.size() - pos2;
3620
3621 return compare(pos1, count1, other.data() + pos2, count2);
3622}
3623
3632template <typename CharT, typename Traits>
3633int
3635{
3636 return compare(0, size(), s, traits_type::length(s));
3637}
3638
3652template <typename CharT, typename Traits>
3653int
3654basic_string<CharT, Traits>::compare(size_type pos, size_type count,
3655 const CharT *s) const
3656{
3657 return compare(pos, count, s, traits_type::length(s));
3658}
3659
3663template <typename CharT, typename Traits>
3664const CharT *
3666{
3667 return is_sso_used() ? sso_data().cdata() : non_sso_data().cdata();
3668}
3669
3673template <typename CharT, typename Traits>
3674const CharT *
3676{
3677 return cdata();
3678}
3679
3683template <typename CharT, typename Traits>
3684const CharT *
3686{
3687 return cdata();
3688}
3689
3693template <typename CharT, typename Traits>
3694typename basic_string<CharT, Traits>::size_type
3696{
3697 return size();
3698}
3699
3703template <typename CharT, typename Traits>
3704typename basic_string<CharT, Traits>::size_type
3706{
3707 return PMEMOBJ_MAX_ALLOC_SIZE / sizeof(CharT) - 1;
3708}
3709
3714template <typename CharT, typename Traits>
3715typename basic_string<CharT, Traits>::size_type
3717{
3718 return is_sso_used() ? sso_capacity : non_sso_data().capacity() - 1;
3719}
3720
3740template <typename CharT, typename Traits>
3741void
3742basic_string<CharT, Traits>::resize(size_type count, CharT ch)
3743{
3744 if (count > max_size())
3745 throw std::length_error("Count exceeds max size.");
3746
3747 auto sz = size();
3748
3749 auto pop = get_pool();
3750
3751 flat_transaction::run(pop, [&] {
3752 if (count > sz) {
3753 append(count - sz, ch);
3754 } else if (is_sso_used()) {
3755 set_sso_size(count);
3756 sso_data()[count] = value_type('\0');
3757 } else {
3758 non_sso_data().resize(count + 1, ch);
3759 non_sso_data().back() = value_type('\0');
3760 }
3761 });
3762}
3763
3782template <typename CharT, typename Traits>
3783void
3785{
3786 resize(count, CharT());
3787}
3788
3809template <typename CharT, typename Traits>
3810void
3812{
3813 if (new_cap > max_size())
3814 throw std::length_error("New capacity exceeds max size.");
3815
3816 if (new_cap < capacity() || new_cap <= sso_capacity)
3817 return;
3818
3819 if (is_sso_used()) {
3820 auto pop = get_pool();
3821
3822 flat_transaction::run(pop, [&] { sso_to_large(new_cap); });
3823 } else {
3824 non_sso_data().reserve(new_cap + 1);
3825 }
3826}
3827
3841template <typename CharT, typename Traits>
3842void
3844{
3845 if (is_sso_used())
3846 return;
3847
3848 if (size() <= sso_capacity) {
3849 auto pop = get_pool();
3850
3851 flat_transaction::run(pop, [&] { large_to_sso(); });
3852 } else {
3853 non_sso_data().shrink_to_fit();
3854 }
3855}
3856
3866template <typename CharT, typename Traits>
3867void
3869{
3870 erase(begin(), end());
3871}
3872
3885template <typename CharT, typename Traits>
3886void
3888{
3889 auto pop = get_pool();
3890
3891 flat_transaction::run(pop, [&] {
3892 if (is_sso_used()) {
3893 add_sso_to_tx(0, get_sso_size() + 1);
3894 clear();
3895 /* sso.data destructor does not have to be called */
3896 } else {
3897 non_sso_data().free_data();
3898 detail::destroy<non_sso_type>(non_sso_data());
3899 enable_sso();
3900 }
3901 });
3902}
3903
3907template <typename CharT, typename Traits>
3908bool
3910{
3911 return size() == 0;
3912}
3913
3914template <typename CharT, typename Traits>
3915bool
3917{
3918 return (sso._size & _sso_mask) != 0;
3919}
3920
3921template <typename CharT, typename Traits>
3922void
3923basic_string<CharT, Traits>::destroy_data()
3924{
3925 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3926
3927 if (is_sso_used()) {
3928 add_sso_to_tx(0, get_sso_size() + 1);
3929 /* sso.data destructor does not have to be called */
3930 } else {
3931 non_sso_data().free_data();
3932 detail::destroy<non_sso_type>(non_sso_data());
3933 }
3934}
3935
3942template <typename CharT, typename Traits>
3943template <typename InputIt, typename Enable>
3944typename basic_string<CharT, Traits>::size_type
3945basic_string<CharT, Traits>::get_size(InputIt first, InputIt last) const
3946{
3947 return static_cast<size_type>(std::distance(first, last));
3948}
3949
3956template <typename CharT, typename Traits>
3957typename basic_string<CharT, Traits>::size_type
3958basic_string<CharT, Traits>::get_size(size_type count, value_type ch) const
3959{
3960 return count;
3961}
3962
3969template <typename CharT, typename Traits>
3970typename basic_string<CharT, Traits>::size_type
3972{
3973 return other.size();
3974}
3975
3982template <typename CharT, typename Traits>
3983template <typename... Args>
3984typename basic_string<CharT, Traits>::pointer
3986{
3987 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3988
3989 auto new_size = get_size(std::forward<Args>(args)...);
3990
3991 /* If non_sso.data is used and there is enough capacity */
3992 if (!is_sso_used() && new_size <= capacity())
3993 return assign_large_data(std::forward<Args>(args)...);
3994
3995 destroy_data();
3996
3997 allocate(new_size);
3998 return initialize(std::forward<Args>(args)...);
3999}
4000
4011template <typename CharT, typename Traits>
4012template <typename... Args>
4013typename basic_string<CharT, Traits>::pointer
4015{
4016 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4017
4018 if (is_sso_used()) {
4019 return assign_sso_data(std::forward<Args>(args)...);
4020 } else {
4021 return assign_large_data(std::forward<Args>(args)...);
4022 }
4023}
4024
4034template <typename CharT, typename Traits>
4035void
4037{
4038 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4039
4040 if (n <= sso_capacity) {
4041 enable_sso();
4042 } else {
4043 disable_sso();
4044 }
4045
4046 /*
4047 * array is aggregate type so it's not required to call
4048 * a constructor.
4049 */
4050 if (!is_sso_used()) {
4051 detail::conditional_add_to_tx(&non_sso_data(), 1,
4052 POBJ_XADD_NO_SNAPSHOT);
4053 detail::create<non_sso_type>(&non_sso_data());
4054 non_sso_data().reserve(n + 1);
4055 }
4056}
4057
4061template <typename CharT, typename Traits>
4062template <typename InputIt, typename Enable>
4063typename basic_string<CharT, Traits>::pointer
4065{
4066 auto size = static_cast<size_type>(std::distance(first, last));
4067
4068 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4069 assert(size <= sso_capacity);
4070
4071 add_sso_to_tx(0, size + 1);
4072 std::copy(first, last, &sso_data()._data[0]);
4073
4074 sso_data()._data[size] = value_type('\0');
4075
4076 set_sso_size(size);
4077
4078 return &sso_data()[0];
4079}
4080
4084template <typename CharT, typename Traits>
4085typename basic_string<CharT, Traits>::pointer
4087{
4088 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4089 assert(count <= sso_capacity);
4090
4091 add_sso_to_tx(0, count + 1);
4092 traits_type::assign(&sso_data()._data[0], count, ch);
4093
4094 sso_data()._data[count] = value_type('\0');
4095
4096 set_sso_size(count);
4097
4098 return &sso_data()[0];
4099}
4100
4105template <typename CharT, typename Traits>
4106template <typename InputIt, typename Enable>
4107typename basic_string<CharT, Traits>::pointer
4109{
4110 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4111
4112 auto size = static_cast<size_type>(std::distance(first, last));
4113
4114 non_sso_data().reserve(size + 1);
4115 non_sso_data().assign(first, last);
4116 non_sso_data().push_back(value_type('\0'));
4117
4118 return non_sso_data().data();
4119}
4120
4125template <typename CharT, typename Traits>
4126typename basic_string<CharT, Traits>::pointer
4128{
4129 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4130
4131 non_sso_data().reserve(count + 1);
4132 non_sso_data().assign(count, ch);
4133 non_sso_data().push_back(value_type('\0'));
4134
4135 return non_sso_data().data();
4136}
4137
4142template <typename CharT, typename Traits>
4143typename basic_string<CharT, Traits>::pointer
4145{
4146 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4147
4148 typename basic_string::pointer ptr;
4149
4150 if (other.size() <= sso_capacity) {
4151 enable_sso();
4152 ptr = assign_sso_data(other.cbegin(), other.cend());
4153 } else {
4154 disable_sso();
4155 detail::conditional_add_to_tx(&non_sso_data(), 1,
4156 POBJ_XADD_NO_SNAPSHOT);
4157 detail::create<non_sso_type>(&non_sso_data());
4158
4159 assert(!other.is_sso_used());
4160 non_sso_data() = std::move(other.non_sso_data());
4161
4162 ptr = non_sso_data().data();
4163 }
4164
4165 if (other.is_sso_used())
4166 other.initialize(0U, value_type('\0'));
4167
4168 return ptr;
4169}
4170
4174template <typename CharT, typename Traits>
4175void
4177{
4178 pool_base pb = get_pool();
4179 flat_transaction::run(pb, [&] {
4180 if (is_sso_used() && other.is_sso_used()) {
4181 sso_data().swap(other.sso_data());
4182 pmem::obj::swap(sso._size, other.sso._size);
4183 } else if (!is_sso_used() && !other.is_sso_used()) {
4184 non_sso_data().swap(other.non_sso_data());
4185 } else {
4186 basic_string *_short, *_long;
4187 if (size() > other.size()) {
4188 _short = &other;
4189 _long = this;
4190 } else {
4191 _short = this;
4192 _long = &other;
4193 }
4194
4195 std::basic_string<CharT, Traits> tmp(_short->c_str(),
4196 _short->size());
4197 *_short = *_long;
4198 *_long = tmp;
4199 }
4200 });
4201}
4202
4206template <typename CharT, typename Traits>
4208{
4209 return basic_string_view<CharT, Traits>(cdata(), length());
4210}
4211
4215template <typename CharT, typename Traits>
4218{
4219 return pmem::obj::pool_by_vptr(this);
4220}
4221
4225template <typename CharT, typename Traits>
4226void
4228{
4229 if (pmemobj_pool_by_ptr(this) == nullptr)
4230 throw pmem::pool_error("Object is not on pmem.");
4231}
4232
4236template <typename CharT, typename Traits>
4237void
4239{
4240 if (pmemobj_tx_stage() != TX_STAGE_WORK)
4242 "Call made out of transaction scope.");
4243}
4244
4249template <typename CharT, typename Traits>
4250void
4252{
4253 check_pmem();
4254 check_tx_stage_work();
4255}
4256
4260template <typename CharT, typename Traits>
4261void
4263 size_type num) const
4264{
4265 assert(idx_first + num <= sso_capacity + 1);
4266 assert(is_sso_used());
4267
4268 auto initialized_num = get_sso_size() + 1 - idx_first;
4269
4270 /* Snapshot elements in range [idx_first, sso_size + 1 (null)) */
4271 detail::conditional_add_to_tx(&sso_data()._data[0] + idx_first,
4272 (std::min)(initialized_num, num));
4273
4274 if (num > initialized_num) {
4275 /* Elements after sso_size + 1 do not have to be snapshotted */
4276 detail::conditional_add_to_tx(
4277 &sso_data()._data[0] + get_sso_size() + 1,
4278 num - initialized_num, POBJ_XADD_NO_SNAPSHOT);
4279 }
4280}
4281
4285template <typename CharT, typename Traits>
4286typename basic_string<CharT, Traits>::size_type
4288{
4289 return sso._size & ~_sso_mask;
4290}
4291
4295template <typename CharT, typename Traits>
4296void
4298{
4299 /* temporary size_type must be created to avoid undefined reference
4300 * linker error */
4301 sso._size |= (size_type)(_sso_mask);
4302}
4303
4307template <typename CharT, typename Traits>
4308void
4310{
4311 sso._size &= ~_sso_mask;
4312}
4313
4317template <typename CharT, typename Traits>
4318void
4320{
4321 sso._size = new_size | _sso_mask;
4322}
4323
4335template <typename CharT, typename Traits>
4336void
4338{
4339 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4340 assert(new_capacity > sso_capacity);
4341 assert(is_sso_used());
4342
4343 auto sz = size();
4344
4345 sso_type tmp;
4346 std::copy(cbegin(), cend(), tmp.data());
4347 tmp[sz] = value_type('\0');
4348
4349 destroy_data();
4350 allocate(new_capacity);
4351
4352 auto begin = tmp.cbegin();
4353 auto end = begin + sz;
4354
4355 initialize(begin, end);
4356
4357 assert(!is_sso_used());
4358};
4359
4369template <typename CharT, typename Traits>
4370void
4372{
4373 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4374 assert(!is_sso_used());
4375
4376 auto sz = size();
4377
4378 assert(sz <= sso_capacity);
4379
4380 sso_type tmp;
4381 std::copy(cbegin(), cbegin() + sz, tmp.data());
4382 tmp[sz] = value_type('\0');
4383
4384 destroy_data();
4385 allocate(sz);
4386
4387 auto begin = tmp.cbegin();
4388 auto end = begin + sz;
4389
4390 initialize(begin, end);
4391
4392 assert(is_sso_used());
4393};
4394
4395template <typename CharT, typename Traits>
4398{
4399 assert(!is_sso_used());
4400 return non_sso._data;
4401}
4402
4403template <typename CharT, typename Traits>
4404typename basic_string<CharT, Traits>::sso_type &
4405basic_string<CharT, Traits>::sso_data()
4406{
4407 assert(is_sso_used());
4408 return sso._data;
4409}
4410
4411template <typename CharT, typename Traits>
4412const typename basic_string<CharT, Traits>::non_sso_type &
4413basic_string<CharT, Traits>::non_sso_data() const
4414{
4415 assert(!is_sso_used());
4416 return non_sso._data;
4417}
4418
4419template <typename CharT, typename Traits>
4420const typename basic_string<CharT, Traits>::sso_type &
4421basic_string<CharT, Traits>::sso_data() const
4422{
4423 assert(is_sso_used());
4424 return sso._data;
4425}
4426
4431template <typename CharT, typename Traits>
4432template <typename T, typename Enable>
4433basic_string<CharT, Traits> &
4435{
4436 return erase(static_cast<size_type>(param));
4437}
4438
4443template <typename CharT, typename Traits>
4444template <typename T, typename Enable>
4447{
4448 return erase(static_cast<const_iterator>(param));
4449}
4450
4456template <typename CharT, typename Traits>
4457template <typename T, typename Enable>
4459basic_string<CharT, Traits>::insert(T param, size_type count, CharT ch)
4460{
4461 return insert(static_cast<size_type>(param), count, ch);
4462}
4463
4469template <typename CharT, typename Traits>
4470template <typename T, typename Enable>
4472basic_string<CharT, Traits>::insert(T param, size_type count, CharT ch)
4473{
4474 return insert(static_cast<const_iterator>(param), count, ch);
4475}
4476
4480template <class CharT, class Traits>
4481bool
4483 const basic_string<CharT, Traits> &rhs)
4484{
4485 return lhs.compare(rhs) == 0;
4486}
4487
4491template <class CharT, class Traits>
4492bool
4494 const basic_string<CharT, Traits> &rhs)
4495{
4496 return lhs.compare(rhs) != 0;
4497}
4498
4502template <class CharT, class Traits>
4503bool
4505 const basic_string<CharT, Traits> &rhs)
4506{
4507 return lhs.compare(rhs) < 0;
4508}
4509
4513template <class CharT, class Traits>
4514bool
4516 const basic_string<CharT, Traits> &rhs)
4517{
4518 return lhs.compare(rhs) <= 0;
4519}
4520
4524template <class CharT, class Traits>
4525bool
4527 const basic_string<CharT, Traits> &rhs)
4528{
4529 return lhs.compare(rhs) > 0;
4530}
4531
4535template <class CharT, class Traits>
4536bool
4538 const basic_string<CharT, Traits> &rhs)
4539{
4540 return lhs.compare(rhs) >= 0;
4541}
4542
4546template <class CharT, class Traits>
4547bool
4548operator==(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4549{
4550 return rhs.compare(lhs) == 0;
4551}
4552
4556template <class CharT, class Traits>
4557bool
4558operator!=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4559{
4560 return rhs.compare(lhs) != 0;
4561}
4562
4566template <class CharT, class Traits>
4567bool
4568operator<(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4569{
4570 return rhs.compare(lhs) > 0;
4571}
4572
4576template <class CharT, class Traits>
4577bool
4578operator<=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4579{
4580 return rhs.compare(lhs) >= 0;
4581}
4582
4586template <class CharT, class Traits>
4587bool
4588operator>(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4589{
4590 return rhs.compare(lhs) < 0;
4591}
4592
4596template <class CharT, class Traits>
4597bool
4598operator>=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4599{
4600 return rhs.compare(lhs) <= 0;
4601}
4602
4606template <class CharT, class Traits>
4607bool
4608operator==(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4609{
4610 return lhs.compare(rhs) == 0;
4611}
4612
4616template <class CharT, class Traits>
4617bool
4618operator!=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4619{
4620 return lhs.compare(rhs) != 0;
4621}
4622
4626template <class CharT, class Traits>
4627bool
4628operator<(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4629{
4630 return lhs.compare(rhs) < 0;
4631}
4632
4636template <class CharT, class Traits>
4637bool
4638operator<=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4639{
4640 return lhs.compare(rhs) <= 0;
4641}
4642
4646template <class CharT, class Traits>
4647bool
4648operator>(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4649{
4650 return lhs.compare(rhs) > 0;
4651}
4652
4656template <class CharT, class Traits>
4657bool
4658operator>=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4659{
4660 return lhs.compare(rhs) >= 0;
4661}
4662
4666template <class CharT, class Traits>
4667bool
4668operator==(const std::basic_string<CharT, Traits> &lhs,
4669 const basic_string<CharT, Traits> &rhs)
4670{
4671 return rhs.compare(lhs) == 0;
4672}
4673
4677template <class CharT, class Traits>
4678bool
4679operator!=(const std::basic_string<CharT, Traits> &lhs,
4680 const basic_string<CharT, Traits> &rhs)
4681{
4682 return rhs.compare(lhs) != 0;
4683}
4684
4688template <class CharT, class Traits>
4689bool
4690operator<(const std::basic_string<CharT, Traits> &lhs,
4691 const basic_string<CharT, Traits> &rhs)
4692{
4693 return rhs.compare(lhs) > 0;
4694}
4695
4699template <class CharT, class Traits>
4700bool
4701operator<=(const std::basic_string<CharT, Traits> &lhs,
4702 const basic_string<CharT, Traits> &rhs)
4703{
4704 return rhs.compare(lhs) >= 0;
4705}
4706
4710template <class CharT, class Traits>
4711bool
4712operator>(const std::basic_string<CharT, Traits> &lhs,
4713 const basic_string<CharT, Traits> &rhs)
4714{
4715 return rhs.compare(lhs) < 0;
4716}
4717
4721template <class CharT, class Traits>
4722bool
4723operator>=(const std::basic_string<CharT, Traits> &lhs,
4724 const basic_string<CharT, Traits> &rhs)
4725{
4726 return rhs.compare(lhs) <= 0;
4727}
4728
4732template <class CharT, class Traits>
4733bool
4735 const std::basic_string<CharT, Traits> &rhs)
4736{
4737 return lhs.compare(rhs) == 0;
4738}
4739
4743template <class CharT, class Traits>
4744bool
4746 const std::basic_string<CharT, Traits> &rhs)
4747{
4748 return lhs.compare(rhs) != 0;
4749}
4750
4754template <class CharT, class Traits>
4755bool
4757 const std::basic_string<CharT, Traits> &rhs)
4758{
4759 return lhs.compare(rhs) < 0;
4760}
4761
4765template <class CharT, class Traits>
4766bool
4768 const std::basic_string<CharT, Traits> &rhs)
4769{
4770 return lhs.compare(rhs) <= 0;
4771}
4772
4776template <class CharT, class Traits>
4777bool
4779 const std::basic_string<CharT, Traits> &rhs)
4780{
4781 return lhs.compare(rhs) > 0;
4782}
4783
4787template <class CharT, class Traits>
4788bool
4790 const std::basic_string<CharT, Traits> &rhs)
4791{
4792 return lhs.compare(rhs) >= 0;
4793}
4794
4798template <class CharT, class Traits>
4799void
4801{
4802 return lhs.swap(rhs);
4803}
4804
4805} /* namespace obj */
4806
4807} /* namespace pmem */
4808
4809#endif /* LIBPMEMOBJ_CPP_BASIC_STRING_HPP */
Array container with std::array compatible interface.
Our partial std::string_view implementation.
Definition: string_view.hpp:46
constexpr size_type size() const noexcept
Returns count of characters stored in this pmem::obj::string_view data.
Definition: string_view.hpp:334
size_type find_first_not_of(basic_string_view str, size_type pos=0) const noexcept
Finds the first character equal to none of the characters in str.
Definition: string_view.hpp:712
size_type find_last_not_of(basic_string_view str, size_type pos=npos) const noexcept
Finds the last character equal to none of the characters in str.
Definition: string_view.hpp:887
size_type find_last_of(basic_string_view str, size_type pos=npos) const noexcept
Finds the last character equal to any of the characters in str.
Definition: string_view.hpp:797
size_type rfind(basic_string_view str, size_type pos=npos) const noexcept
Finds the last substring equal to str.
Definition: string_view.hpp:546
size_type find_first_of(basic_string_view str, size_type pos=0) const noexcept
Finds the first character equal to any of the characters in str.
Definition: string_view.hpp:631
constexpr const CharT * data() const noexcept
Returns pointer to data stored in this pmem::obj::string_view.
Definition: string_view.hpp:296
pmem::obj::string - persistent container with std::basic_string compatible interface.
Definition: basic_string.hpp:46
void for_each_ptr(for_each_ptr_function func)
Iterates over all internal pointers and executes a callback function on each of them.
Definition: basic_string.hpp:1133
void resize(size_type count, CharT ch)
Resize the string to count characters transactionally.
Definition: basic_string.hpp:3742
void clear()
Remove all characters from the string transactionally.
Definition: basic_string.hpp:3868
void check_tx_stage_work() const
Definition: basic_string.hpp:4238
pointer move_data(basic_string &&other)
Move initialize for basic_string.
Definition: basic_string.hpp:4144
reverse_iterator rbegin()
Return a reverse iterator to the beginning.
Definition: basic_string.hpp:1224
size_type find_first_not_of(const basic_string &str, size_type pos=0) const noexcept
Finds the first character equal to none of the characters in str.
Definition: basic_string.hpp:3267
slice< pointer > range(size_type p, size_type count)
Returns slice and snapshots requested range.
Definition: basic_string.hpp:1406
const_iterator cbegin() const noexcept
Return const iterator to the beginning.
Definition: basic_string.hpp:1172
iterator begin()
Return an iterator to the beginning.
Definition: basic_string.hpp:1147
bool empty() const noexcept
Definition: basic_string.hpp:3909
basic_string & erase(size_type index=0, size_type count=npos)
Remove characters from string starting at index transactionally.
Definition: basic_string.hpp:1621
void large_to_sso()
Resize large string to sso string of size() size.
Definition: basic_string.hpp:4371
const_reverse_iterator crbegin() const noexcept
Return a const reverse iterator to the beginning.
Definition: basic_string.hpp:1250
void shrink_to_fit()
Remove unused capacity transactionally.
Definition: basic_string.hpp:3843
reference at(size_type n)
Access element at specific index with bounds checking and snapshot it if there is an active transacti...
Definition: basic_string.hpp:1309
void enable_sso()
Enable sso string.
Definition: basic_string.hpp:4297
basic_string & append(size_type count, CharT ch)
Append count copies of character ch to the string transactionally.
Definition: basic_string.hpp:1752
void push_back(CharT ch)
Append character ch at the end of the string transactionally.
Definition: basic_string.hpp:2025
pool_base get_pool() const
Return pool_base instance and assert that object is on pmem.
Definition: basic_string.hpp:4217
void swap(basic_string &other)
Swap the content of persistent strings.
Definition: basic_string.hpp:4176
void pop_back()
Remove the last character from the string transactionally.
Definition: basic_string.hpp:1726
iterator end()
Return an iterator to past the end.
Definition: basic_string.hpp:1185
void set_sso_size(size_type new_size)
Set size for sso.
Definition: basic_string.hpp:4319
size_type length() const noexcept
Definition: basic_string.hpp:3695
size_type copy(CharT *s, size_type count, size_type index=0) const
Copy [index, index + count) substring of *this to C-style string.
Definition: basic_string.hpp:2976
pointer assign_sso_data(InputIt first, InputIt last)
Initialize sso data.
Definition: basic_string.hpp:4064
CharT * data()
Definition: basic_string.hpp:1595
size_type size() const noexcept
Definition: basic_string.hpp:1577
basic_string & insert(size_type index, size_type count, CharT ch)
Insert count copies of ch character at index transactionally.
Definition: basic_string.hpp:2154
int compare(const basic_string &other) const
Compares this string to other.
Definition: basic_string.hpp:3493
size_type get_size(InputIt first, InputIt last) const
Overload of generic get_size method used to calculate size based on provided parameters.
Definition: basic_string.hpp:3945
void add_sso_to_tx(size_type first, size_type num) const
Snapshot sso data.
Definition: basic_string.hpp:4262
reference operator[](size_type n)
Access element at specific index and snapshot it if there is an active transaction.
Definition: basic_string.hpp:1372
void reserve(size_type new_cap=0)
Increase the capacity of the string to new_cap transactionally.
Definition: basic_string.hpp:3811
void allocate(size_type capacity)
Allocate storage for container of n elements.
Definition: basic_string.hpp:4036
reverse_iterator rend()
Return a reverse iterator to the end.
Definition: basic_string.hpp:1263
basic_string & replace(size_type index, size_type count, const basic_string &str)
Replace range [index, index + count) with the content of str string transactionally.
Definition: basic_string.hpp:2533
pointer replace_content(Args &&... args)
Generic function which replace_content current content based on provided parameters.
Definition: basic_string.hpp:3985
basic_string & assign(size_type count, CharT ch)
Replace the contents with count copies of character ch transactionally.
Definition: basic_string.hpp:905
void free_data()
Clears the content of a string and frees all allocated persistent memory for data transactionally.
Definition: basic_string.hpp:3887
const_iterator cend() const noexcept
Return const iterator to past the end.
Definition: basic_string.hpp:1211
size_type get_sso_size() const
Return size of sso string.
Definition: basic_string.hpp:4287
size_type find_last_of(const basic_string &str, size_type pos=npos) const noexcept
Finds the last character equal to any of the characters in str.
Definition: basic_string.hpp:3343
basic_string()
Default constructor.
Definition: basic_string.hpp:432
size_type rfind(const basic_string &str, size_type pos=npos) const noexcept
Finds the last substring equal to str.
Definition: basic_string.hpp:3114
const CharT & cfront() const
Access first element.
Definition: basic_string.hpp:1524
void check_pmem_tx() const
Definition: basic_string.hpp:4251
const CharT * cdata() const noexcept
Definition: basic_string.hpp:3665
~basic_string()
Destructor.
Definition: basic_string.hpp:771
basic_string & operator+=(const basic_string &str)
Append string str transactionally.
Definition: basic_string.hpp:2050
pointer assign_large_data(InputIt first, InputIt last)
Initialize non_sso.data - call constructor of non_sso.data.
Definition: basic_string.hpp:4108
pointer initialize(Args &&... args)
Generic function which initializes memory based on provided parameters - forwards parameters to initi...
Definition: basic_string.hpp:4014
const CharT & cback() const
Access last element.
Definition: basic_string.hpp:1567
size_type max_size() const noexcept
Definition: basic_string.hpp:3705
void sso_to_large(size_t new_capacity)
Resize sso string to large string.
Definition: basic_string.hpp:4337
size_type find_first_of(const basic_string &str, size_type pos=0) const noexcept
Finds the first character equal to any of the characters in str.
Definition: basic_string.hpp:3192
size_type find_last_not_of(const basic_string &str, size_type pos=npos) const noexcept
Finds the last character equal to none of the characters in str.
Definition: basic_string.hpp:3418
void disable_sso()
Disable sso string.
Definition: basic_string.hpp:4309
CharT & back()
Access last element and snapshot it if there is an active transaction.
Definition: basic_string.hpp:1540
const_reverse_iterator crend() const noexcept
Return a const reverse iterator to the end.
Definition: basic_string.hpp:1289
CharT & front()
Access first element and snapshot it if there is an active transaction.
Definition: basic_string.hpp:1497
size_type find(const basic_string &str, size_type pos=0) const noexcept
Finds the first substring equal str.
Definition: basic_string.hpp:3044
const_reference const_at(size_type n) const
Access element at specific index with bounds checking.
Definition: basic_string.hpp:1349
const CharT * c_str() const noexcept
Definition: basic_string.hpp:3685
void check_pmem() const
Definition: basic_string.hpp:4227
size_type capacity() const noexcept
Definition: basic_string.hpp:3716
slice< const_iterator > crange(size_type start, size_type n) const
Returns const slice.
Definition: basic_string.hpp:1477
basic_string & operator=(const basic_string &other)
Copy assignment operator.
Definition: basic_string.hpp:791
static void run(obj::pool_base &pool, std::function< void()> tx, Locks &... locks)
Execute a closure-like transaction and lock locks.
Definition: transaction.hpp:823
Resides on pmem class.
Definition: p.hpp:35
Persistent_ptr base (non-template) class.
Definition: persistent_ptr_base.hpp:42
The non-template pool base class.
Definition: pool.hpp:50
pmem::obj::slice - provides interface to access sequence of objects.
Definition: slice.hpp:50
Custom pool error class.
Definition: pexceptions.hpp:45
Custom transaction error class.
Definition: pexceptions.hpp:176
Commonly used functionality.
Iterators for contiguous persistent containers.
Common iterator traits.
Functions for destroying arrays.
bool operator<=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less or equal operator.
Definition: array.hpp:779
pmem::obj::array< T, N >::const_iterator cend(const pmem::obj::array< T, N > &a)
Non-member cend.
Definition: array.hpp:799
pmem::obj::array< T, N >::iterator end(pmem::obj::array< T, N > &a)
Non-member end.
Definition: array.hpp:849
bool operator<(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less than operator.
Definition: array.hpp:748
bool operator>=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater or equal operator.
Definition: array.hpp:769
bool operator!=(const allocator< T, P, Tr > &lhs, const OtherAllocator &rhs)
Determines if memory from another allocator can be deallocated from this one.
Definition: allocator.hpp:536
pmem::obj::array< T, N >::const_reverse_iterator crbegin(const pmem::obj::array< T, N > &a)
Non-member crbegin.
Definition: array.hpp:809
pmem::obj::array< T, N >::const_reverse_iterator crend(const pmem::obj::array< T, N > &a)
Non-member crend.
Definition: array.hpp:819
pool_base pool_by_vptr(const T *that)
Retrieve pool handle for the given pointer.
Definition: utils.hpp:32
bool operator==(standard_alloc_policy< T > const &, standard_alloc_policy< T2 > const &)
Determines if memory from another allocator can be deallocated from this one.
Definition: allocator.hpp:420
bool operator>(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater than operator.
Definition: array.hpp:759
pmem::obj::array< T, N >::const_iterator cbegin(const pmem::obj::array< T, N > &a)
Non-member cbegin.
Definition: array.hpp:789
pmem::obj::array< T, N >::iterator begin(pmem::obj::array< T, N > &a)
Non-member begin.
Definition: array.hpp:829
void swap(pmem::obj::array< T, N > &lhs, pmem::obj::array< T, N > &rhs)
Non-member swap function.
Definition: array.hpp:909
Persistent memory namespace.
Definition: allocation_flag.hpp:15
Persistent smart pointer.
Convenience extensions for the resides on pmem property template.
Interface to access sequence of objects.
Our partial std::string_view implementation.
Default non-const iterator which adds element to a transaction on every access.
Definition: contiguous_iterator.hpp:331
Type trait to determine if a given parameter type satisfies requirements of InputIterator.
Definition: iterator_traits.hpp:47
Non-const iterator which adds elements to a transaction in a bulk.
Definition: contiguous_iterator.hpp:192
T * data()
Returns raw pointer to the underlying data and adds entire array to a transaction.
Definition: array.hpp:274
const_iterator cbegin() const noexcept
Returns const iterator to the beginning.
Definition: array.hpp:336
C++ pmemobj transactions.
Libpmemobj C++ utils.
Vector container with std::vector compatible interface.