PMDK C++ bindings  1.13.0-git107.g7e59f08f
This is the C++ bindings documentation for PMDK's libpmemobj.
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>
25 #include <libpmemobj++/slice.hpp>
28 #include <libpmemobj++/utils.hpp>
29 
30 namespace pmem
31 {
32 
33 namespace obj
34 {
35 
47 template <typename CharT, typename Traits = std::char_traits<CharT>>
48 class basic_string {
49 public:
50  /* Member types */
51  using traits_type = Traits;
52  using value_type = CharT;
53  using size_type = std::size_t;
54  using difference_type = std::ptrdiff_t;
55  using reference = value_type &;
56  using const_reference = const value_type &;
57  using pointer = value_type *;
58  using const_pointer = const value_type *;
60  using const_iterator = const_pointer;
61  using reverse_iterator = std::reverse_iterator<iterator>;
62  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
65  using for_each_ptr_function =
66  std::function<void(persistent_ptr_base &)>;
67 
68  /* Number of characters which can be stored using sso */
69  static constexpr size_type sso_capacity = (32 - 8) / sizeof(CharT) - 1;
70 
71  /* Constructors */
72  basic_string();
73  basic_string(size_type count, CharT ch);
74  basic_string(const basic_string &other, size_type pos,
75  size_type count = npos);
76  basic_string(const std::basic_string<CharT> &other, size_type pos,
77  size_type count = npos);
78  basic_string(const CharT *s, size_type count);
79  basic_string(const CharT *s);
80  template <
81  typename InputIt,
82  typename Enable = typename std::enable_if<
84  basic_string(InputIt first, InputIt last);
85  basic_string(const basic_string &other);
86  basic_string(const std::basic_string<CharT> &other);
87  basic_string(basic_string &&other);
88  basic_string(std::initializer_list<CharT> ilist);
89  template <
90  class T,
91  typename Enable = typename std::enable_if<
92  std::is_convertible<const T &,
94  CharT, Traits>>::value &&
95  !std::is_convertible<const T &, const CharT *>::value>>
96  explicit basic_string(const T &t);
97  template <class T,
98  typename Enable = typename std::enable_if<std::is_convertible<
99  const T &,
101  basic_string(const T &t, size_type pos, size_type n);
102 
103  /* Destructor */
104  ~basic_string();
105 
106  /* Assignment operators */
107  basic_string &operator=(const basic_string &other);
108  basic_string &operator=(const std::basic_string<CharT> &other);
110  basic_string &operator=(const CharT *s);
111  basic_string &operator=(CharT ch);
112  basic_string &operator=(std::initializer_list<CharT> ilist);
113  template <
114  class T,
115  typename Enable = typename std::enable_if<
116  std::is_convertible<const T &,
118  CharT, Traits>>::value &&
119  !std::is_convertible<const T &, const CharT *>::value>>
120  basic_string &operator=(const T &t);
121 
122  /* Assignment methods */
123  basic_string &assign(size_type count, CharT ch);
124  basic_string &assign(const basic_string &other);
125  basic_string &assign(const std::basic_string<CharT> &other);
126  basic_string &assign(const basic_string &other, size_type pos,
127  size_type count = npos);
128  basic_string &assign(const std::basic_string<CharT> &other,
129  size_type pos, size_type count = npos);
130  basic_string &assign(const CharT *s, size_type count);
131  basic_string &assign(const CharT *s);
132  template <typename InputIt,
133  typename Enable = typename pmem::detail::is_input_iterator<
134  InputIt>::type>
135  basic_string &assign(InputIt first, InputIt last);
136  basic_string &assign(basic_string &&other);
137  basic_string &assign(std::initializer_list<CharT> ilist);
138 
139  /* Element access */
140  reference at(size_type n);
141  const_reference at(size_type n) const;
142  const_reference const_at(size_type n) const;
143  reference operator[](size_type n);
144  const_reference operator[](size_type n) const;
145  CharT &front();
146  const CharT &front() const;
147  const CharT &cfront() const;
148  CharT &back();
149  const CharT &back() const;
150  const CharT &cback() const;
151  CharT *data();
152  const CharT *data() const noexcept;
153  const CharT *cdata() const noexcept;
154  const CharT *c_str() const noexcept;
155  void for_each_ptr(for_each_ptr_function func);
156 
157  /* Range */
158  slice<pointer> range(size_type p, size_type count);
159  slice<range_snapshotting_iterator> range(size_type start, size_type n,
160  size_type snapshot_size);
161  slice<const_iterator> range(size_type start, size_type n) const;
162  slice<const_iterator> crange(size_type start, size_type n) const;
163 
164  /* Iterators */
165  iterator begin();
166  const_iterator begin() const noexcept;
167  const_iterator cbegin() const noexcept;
168  iterator end();
169  const_iterator end() const noexcept;
170  const_iterator cend() const noexcept;
171  reverse_iterator rbegin();
172  const_reverse_iterator rbegin() const noexcept;
173  const_reverse_iterator crbegin() const noexcept;
174  reverse_iterator rend();
175  const_reverse_iterator rend() const noexcept;
176  const_reverse_iterator crend() const noexcept;
177 
178  /* Capacity */
179  bool empty() const noexcept;
180  size_type size() const noexcept;
181  size_type length() const noexcept;
182  size_type max_size() const noexcept;
183  size_type capacity() const noexcept;
184  void resize(size_type count, CharT ch);
185  void resize(size_type n);
186  void reserve(size_type new_cap = 0);
187  void shrink_to_fit();
188  void clear();
189  void free_data();
190 
191  /* Modifiers */
192  basic_string &erase(size_type index = 0, size_type count = npos);
193  iterator erase(const_iterator pos);
194  iterator erase(const_iterator first, const_iterator last);
195  /* We add following overloads to resolve erase(0) ambiguity */
196  template <typename T,
197  typename Enable = typename std::enable_if<
198  std::is_convertible<T, size_type>::value>::type>
199  basic_string &erase(T param);
200  template <typename T,
201  typename Enable = typename std::enable_if<
202  !std::is_convertible<T, size_type>::value>::type>
203  iterator erase(T param);
204  void pop_back();
205 
206  basic_string &append(size_type count, CharT ch);
207  basic_string &append(const basic_string &str);
208  basic_string &append(const basic_string &str, size_type pos,
209  size_type count = npos);
210  basic_string &append(const CharT *s, size_type count);
211  basic_string &append(const CharT *s);
212  template <typename InputIt,
213  typename Enable = typename pmem::detail::is_input_iterator<
214  InputIt>::type>
215  basic_string &append(InputIt first, InputIt last);
216  basic_string &append(std::initializer_list<CharT> ilist);
217  void push_back(CharT ch);
218  basic_string &operator+=(const basic_string &str);
219  basic_string &operator+=(const CharT *s);
220  basic_string &operator+=(CharT c);
221  basic_string &operator+=(std::initializer_list<CharT> ilist);
222 
223  basic_string &insert(size_type index, size_type count, CharT ch);
224  basic_string &insert(size_type index, const CharT *s);
225  basic_string &insert(size_type index, const CharT *s, size_type count);
226  basic_string &insert(size_type index, const basic_string &str);
227  basic_string &insert(size_type index1, const basic_string &str,
228  size_type index2, size_type count = npos);
229  iterator insert(const_iterator pos, CharT ch);
230  iterator insert(const_iterator pos, size_type count, CharT ch);
231  template <typename InputIt,
232  typename Enable = typename pmem::detail::is_input_iterator<
233  InputIt>::type>
234  iterator insert(const_iterator pos, InputIt first, InputIt last);
235  iterator insert(const_iterator pos, std::initializer_list<CharT> ilist);
236  template <typename T,
237  typename Enable = typename std::enable_if<
238  std::is_convertible<T, size_type>::value>::type>
239  basic_string &insert(T param, size_type count, CharT ch);
240  template <typename T,
241  typename Enable = typename std::enable_if<
242  !std::is_convertible<T, size_type>::value>::type>
243  iterator insert(T param, size_type count, CharT ch);
244 
245  basic_string &replace(size_type index, size_type count,
246  const basic_string &str);
247  basic_string &replace(const_iterator first, const_iterator last,
248  const basic_string &str);
249  basic_string &replace(size_type index, size_type count,
250  const basic_string &str, size_type index2,
251  size_type count2 = npos);
252  template <typename InputIt,
253  typename Enable = typename pmem::detail::is_input_iterator<
254  InputIt>::type>
255  basic_string &replace(const_iterator first, const_iterator last,
256  InputIt first2, InputIt last2);
257  basic_string &replace(const_iterator first, const_iterator last,
258  const CharT *s, size_type count2);
259  basic_string &replace(const_iterator first, const_iterator last,
260  const CharT *s);
261  basic_string &replace(size_type index, size_type count,
262  size_type count2, CharT ch);
263  basic_string &replace(const_iterator first, const_iterator last,
264  size_type count2, CharT ch);
265  basic_string &replace(size_type index, size_type count, const CharT *s,
266  size_type count2);
267  basic_string &replace(size_type index, size_type count, const CharT *s);
268  basic_string &replace(const_iterator first, const_iterator last,
269  std::initializer_list<CharT> ilist);
270 
271  size_type copy(CharT *s, size_type count, size_type index = 0) const;
272 
273  int compare(const basic_string &other) const;
274  int compare(const std::basic_string<CharT> &other) const;
275  int compare(size_type pos, size_type count,
276  const basic_string &other) const;
277  int compare(size_type pos, size_type count,
278  const std::basic_string<CharT> &other) const;
279  int compare(size_type pos1, size_type count1, const basic_string &other,
280  size_type pos2, size_type count2 = npos) const;
281  int compare(size_type pos1, size_type count1,
282  const std::basic_string<CharT> &other, size_type pos2,
283  size_type count2 = npos) const;
284  int compare(const CharT *s) const;
285  int compare(size_type pos, size_type count, const CharT *s) const;
286  int compare(size_type pos, size_type count1, const CharT *s,
287  size_type count2) const;
288 
289  /* Search */
290  size_type find(const basic_string &str, size_type pos = 0) const
291  noexcept;
292  size_type find(const CharT *s, size_type pos, size_type count) const;
293  size_type find(const CharT *s, size_type pos = 0) const;
294  size_type find(CharT ch, size_type pos = 0) const noexcept;
295  size_type rfind(const basic_string &str, size_type pos = npos) const
296  noexcept;
297  size_type rfind(const CharT *s, size_type pos, size_type count) const;
298  size_type rfind(const CharT *s, size_type pos = npos) const;
299  size_type rfind(CharT ch, size_type pos = npos) const noexcept;
300  size_type find_first_of(const basic_string &str,
301  size_type pos = 0) const noexcept;
302  size_type find_first_of(const CharT *s, size_type pos,
303  size_type count) const;
304  size_type find_first_of(const CharT *s, size_type pos = 0) const;
305  size_type find_first_of(CharT ch, size_type pos = 0) const noexcept;
306  size_type find_first_not_of(const basic_string &str,
307  size_type pos = 0) const noexcept;
308  size_type find_first_not_of(const CharT *s, size_type pos,
309  size_type count) const;
310  size_type find_first_not_of(const CharT *s, size_type pos = 0) const;
311  size_type find_first_not_of(CharT ch, size_type pos = 0) const noexcept;
312  size_type find_last_of(const basic_string &str,
313  size_type pos = npos) const noexcept;
314  size_type find_last_of(const CharT *s, size_type pos,
315  size_type count) const;
316  size_type find_last_of(const CharT *s, size_type pos = npos) const;
317  size_type find_last_of(CharT ch, size_type pos = npos) const noexcept;
318  size_type find_last_not_of(const basic_string &str,
319  size_type pos = npos) const noexcept;
320  size_type find_last_not_of(const CharT *s, size_type pos,
321  size_type count) const;
322  size_type find_last_not_of(const CharT *s, size_type pos = npos) const;
323  size_type find_last_not_of(CharT ch, size_type pos = npos) const
324  noexcept;
325 
326  void swap(basic_string &other);
327 
328  operator basic_string_view<CharT, Traits>() const;
329 
330  /* Special value. The exact meaning depends on the context. */
331  static const size_type npos = static_cast<size_type>(-1);
332 
333 private:
336 
354  union {
355  struct {
356  /*
357  * EXACTLY the same type as first member in vector
358  * Holds size for sso string, bit specified by _sso_mask
359  * indicates if sso is used.
360  */
361  p<size_type> _size;
362 
363  sso_type _data;
364  } sso;
365 
366  struct {
367  non_sso_type _data;
368  } non_sso;
369  };
370 
371  /*
372  * MSB is used because vector is known not to use entire range of
373  * size_type.
374  */
375  static constexpr size_type _sso_mask = 1ULL
376  << (std::numeric_limits<size_type>::digits - 1);
377 
378  /* helper functions */
379  bool is_sso_used() const;
380  void destroy_data();
381  template <
382  typename InputIt,
383  typename Enable = typename std::enable_if<
385  size_type get_size(InputIt first, InputIt last) const;
386  size_type get_size(size_type count, value_type ch) const;
387  size_type get_size(const basic_string &other) const;
388  template <typename... Args>
389  pointer replace_content(Args &&... args);
390  template <typename... Args>
391  pointer initialize(Args &&... args);
392  void allocate(size_type capacity);
393  template <
394  typename InputIt,
395  typename Enable = typename std::enable_if<
397  pointer assign_sso_data(InputIt first, InputIt last);
398  pointer assign_sso_data(size_type count, value_type ch);
399  pointer move_data(basic_string &&other);
400  template <
401  typename InputIt,
402  typename Enable = typename std::enable_if<
404  pointer assign_large_data(InputIt first, InputIt last);
405  pointer assign_large_data(size_type count, value_type ch);
406  pool_base get_pool() const;
407  void check_pmem() const;
408  void check_tx_stage_work() const;
409  void check_pmem_tx() const;
410  void add_sso_to_tx(size_type first, size_type num) const;
411  size_type get_sso_size() const;
412  void enable_sso();
413  void disable_sso();
414  void set_sso_size(size_type new_size);
415  void sso_to_large(size_t new_capacity);
416  void large_to_sso();
417  typename basic_string<CharT, Traits>::non_sso_type &non_sso_data();
418  typename basic_string<CharT, Traits>::sso_type &sso_data();
420  non_sso_data() const;
421  const typename basic_string<CharT, Traits>::sso_type &sso_data() const;
422 };
423 
433 template <typename CharT, typename Traits>
435 {
436  check_pmem_tx();
437  sso._size = 0;
438 
439  allocate(0);
440  initialize(0U, value_type('\0'));
441 }
442 
457 template <typename CharT, typename Traits>
459 {
460  check_pmem_tx();
461  sso._size = 0;
462 
463  allocate(count);
464  initialize(count, ch);
465 }
466 
484 template <typename CharT, typename Traits>
486  size_type pos, size_type count)
487 {
488  check_pmem_tx();
489  sso._size = 0;
490 
491  if (pos > other.size())
492  throw std::out_of_range("Index out of range.");
493 
494  if (count == npos || pos + count > other.size())
495  count = other.size() - pos;
496 
497  auto first = static_cast<difference_type>(pos);
498  auto last = first + static_cast<difference_type>(count);
499 
500  allocate(count);
501  initialize(other.cbegin() + first, other.cbegin() + last);
502 }
503 
522 template <typename CharT, typename Traits>
523 basic_string<CharT, Traits>::basic_string(const std::basic_string<CharT> &other,
524  size_type pos, size_type count)
525  : basic_string(basic_string_view<CharT>(other), pos, count)
526 {
527 }
528 
544 template <typename CharT, typename Traits>
545 basic_string<CharT, Traits>::basic_string(const CharT *s, size_type count)
546 {
547  check_pmem_tx();
548  sso._size = 0;
549 
550  allocate(count);
551  initialize(s, s + count);
552 }
553 
567 template <typename CharT, typename Traits>
569 {
570  check_pmem_tx();
571  sso._size = 0;
572 
573  auto length = traits_type::length(s);
574 
575  allocate(length);
576  initialize(s, s + length);
577 }
578 
595 template <typename CharT, typename Traits>
596 template <typename InputIt, typename Enable>
597 basic_string<CharT, Traits>::basic_string(InputIt first, InputIt last)
598 {
599  auto len = std::distance(first, last);
600  assert(len >= 0);
601 
602  check_pmem_tx();
603  sso._size = 0;
604 
605  allocate(static_cast<size_type>(len));
606  initialize(first, last);
607 }
608 
623 template <typename CharT, typename Traits>
625 {
626  check_pmem_tx();
627  sso._size = 0;
628 
629  allocate(other.size());
630  initialize(other.cbegin(), other.cend());
631 }
632 
648 template <typename CharT, typename Traits>
649 basic_string<CharT, Traits>::basic_string(const std::basic_string<CharT> &other)
650  : basic_string(other.cbegin(), other.cend())
651 {
652 }
653 
668 template <typename CharT, typename Traits>
670 {
671  check_pmem_tx();
672  sso._size = 0;
673 
674  move_data(std::move(other));
675 }
676 
691 template <typename CharT, typename Traits>
692 basic_string<CharT, Traits>::basic_string(std::initializer_list<CharT> ilist)
693 {
694  check_pmem_tx();
695  sso._size = 0;
696 
697  allocate(ilist.size());
698  initialize(ilist.begin(), ilist.end());
699 }
700 
716 template <typename CharT, typename Traits>
717 template <class T, typename Enable>
719 {
720  check_pmem_tx();
721  sso._size = 0;
722 
724 
725  allocate(sv.size());
726  initialize(sv.data(), sv.data() + sv.size());
727 }
728 
746 template <typename CharT, typename Traits>
747 template <class T, typename Enable>
749  size_type n)
750 {
751  check_pmem_tx();
752  sso._size = 0;
753 
755 
756  if (pos > sv.size())
757  throw std::out_of_range("Index out of range.");
758 
759  if (n == npos || pos + n > sv.size())
760  n = sv.size() - pos;
761 
762  auto first = pos;
763  auto last = first + n;
764 
765  allocate(n);
766  initialize(sv.data() + first, sv.data() + last);
767 }
768 
772 template <typename CharT, typename Traits>
774 {
775  try {
776  free_data();
777  } catch (...) {
778  std::terminate();
779  }
780 }
781 
791 template <typename CharT, typename Traits>
794 {
795  return assign(other);
796 }
797 
808 template <typename CharT, typename Traits>
810 basic_string<CharT, Traits>::operator=(const std::basic_string<CharT> &other)
811 {
812  return assign(other);
813 }
814 
824 template <typename CharT, typename Traits>
827 {
828  return assign(std::move(other));
829 }
830 
839 template <typename CharT, typename Traits>
842 {
843  return assign(s);
844 }
845 
854 template <typename CharT, typename Traits>
857 {
858  return assign(1, ch);
859 }
860 
870 template <typename CharT, typename Traits>
872 basic_string<CharT, Traits>::operator=(std::initializer_list<CharT> ilist)
873 {
874  return assign(ilist);
875 }
876 
886 template <typename CharT, typename Traits>
887 template <class T, typename Enable>
890 {
892  return assign(sv.data(), sv.size());
893 }
894 
905 template <typename CharT, typename Traits>
907 basic_string<CharT, Traits>::assign(size_type count, CharT ch)
908 {
909  auto pop = get_pool();
910 
911  flat_transaction::run(pop, [&] { replace_content(count, ch); });
912 
913  return *this;
914 }
915 
925 template <typename CharT, typename Traits>
928 {
929  if (&other == this)
930  return *this;
931 
932  auto pop = get_pool();
933 
935  pop, [&] { replace_content(other.cbegin(), other.cend()); });
936 
937  return *this;
938 }
939 
950 template <typename CharT, typename Traits>
952 basic_string<CharT, Traits>::assign(const std::basic_string<CharT> &other)
953 {
954  return assign(other.cbegin(), other.cend());
955 }
956 
969 template <typename CharT, typename Traits>
972  size_type count)
973 {
974  if (pos > other.size())
975  throw std::out_of_range("Index out of range.");
976 
977  if (count == npos || pos + count > other.size())
978  count = other.size() - pos;
979 
980  auto pop = get_pool();
981  auto first = static_cast<difference_type>(pos);
982  auto last = first + static_cast<difference_type>(count);
983 
984  flat_transaction::run(pop, [&] {
985  replace_content(other.cbegin() + first, other.cbegin() + last);
986  });
987 
988  return *this;
989 }
990 
1005 template <typename CharT, typename Traits>
1007 basic_string<CharT, Traits>::assign(const std::basic_string<CharT> &other,
1008  size_type pos, size_type count)
1009 {
1010  if (pos > other.size())
1011  throw std::out_of_range("Index out of range.");
1012 
1013  if (count == npos || pos + count > other.size())
1014  count = other.size() - pos;
1015 
1016  return assign(other.c_str() + pos, count);
1017 }
1018 
1029 template <typename CharT, typename Traits>
1031 basic_string<CharT, Traits>::assign(const CharT *s, size_type count)
1032 {
1033  auto pop = get_pool();
1034 
1035  flat_transaction::run(pop, [&] { replace_content(s, s + count); });
1036 
1037  return *this;
1038 }
1039 
1048 template <typename CharT, typename Traits>
1051 {
1052  auto pop = get_pool();
1053 
1054  auto length = traits_type::length(s);
1055 
1056  flat_transaction::run(pop, [&] { replace_content(s, s + length); });
1057 
1058  return *this;
1059 }
1060 
1072 template <typename CharT, typename Traits>
1073 template <typename InputIt, typename Enable>
1075 basic_string<CharT, Traits>::assign(InputIt first, InputIt last)
1076 {
1077  auto pop = get_pool();
1078 
1079  flat_transaction::run(pop, [&] { replace_content(first, last); });
1080 
1081  return *this;
1082 }
1083 
1093 template <typename CharT, typename Traits>
1096 {
1097  if (&other == this)
1098  return *this;
1099 
1100  auto pop = get_pool();
1101 
1102  flat_transaction::run(pop, [&] {
1103  destroy_data();
1104  move_data(std::move(other));
1105  });
1106 
1107  return *this;
1108 }
1109 
1119 template <typename CharT, typename Traits>
1121 basic_string<CharT, Traits>::assign(std::initializer_list<CharT> ilist)
1122 {
1123  return assign(ilist.begin(), ilist.end());
1124 }
1125 
1133 template <typename CharT, typename Traits>
1134 void
1136 {
1137  if (!is_sso_used()) {
1138  non_sso._data.for_each_ptr(func);
1139  }
1140 }
1141 
1147 template <typename CharT, typename Traits>
1150 {
1151  return is_sso_used() ? iterator(&*sso_data().begin())
1152  : iterator(&*non_sso_data().begin());
1153 }
1154 
1160 template <typename CharT, typename Traits>
1161 typename basic_string<CharT, Traits>::const_iterator
1163 {
1164  return cbegin();
1165 }
1166 
1172 template <typename CharT, typename Traits>
1173 typename basic_string<CharT, Traits>::const_iterator
1175 {
1176  return is_sso_used() ? const_iterator(&*sso_data().cbegin())
1177  : const_iterator(&*non_sso_data().cbegin());
1178 }
1179 
1185 template <typename CharT, typename Traits>
1188 {
1189  return begin() + static_cast<difference_type>(size());
1190 }
1191 
1198 template <typename CharT, typename Traits>
1199 typename basic_string<CharT, Traits>::const_iterator
1201 {
1202  return cbegin() + static_cast<difference_type>(size());
1203 }
1204 
1211 template <typename CharT, typename Traits>
1212 typename basic_string<CharT, Traits>::const_iterator
1214 {
1215  return cbegin() + static_cast<difference_type>(size());
1216 }
1217 
1224 template <typename CharT, typename Traits>
1225 typename basic_string<CharT, Traits>::reverse_iterator
1227 {
1228  return reverse_iterator(end());
1229 }
1230 
1237 template <typename CharT, typename Traits>
1238 typename basic_string<CharT, Traits>::const_reverse_iterator
1240 {
1241  return crbegin();
1242 }
1243 
1250 template <typename CharT, typename Traits>
1251 typename basic_string<CharT, Traits>::const_reverse_iterator
1253 {
1254  return const_reverse_iterator(cend());
1255 }
1256 
1263 template <typename CharT, typename Traits>
1264 typename basic_string<CharT, Traits>::reverse_iterator
1266 {
1267  return reverse_iterator(begin());
1268 }
1269 
1276 template <typename CharT, typename Traits>
1277 typename basic_string<CharT, Traits>::const_reverse_iterator
1279 {
1280  return crend();
1281 }
1282 
1289 template <typename CharT, typename Traits>
1290 typename basic_string<CharT, Traits>::const_reverse_iterator
1292 {
1293  return const_reverse_iterator(cbegin());
1294 }
1295 
1309 template <typename CharT, typename Traits>
1310 typename basic_string<CharT, Traits>::reference
1312 {
1313  if (n >= size())
1314  throw std::out_of_range("string::at");
1315 
1316  return is_sso_used() ? sso_data()[n] : non_sso_data()[n];
1317 }
1318 
1329 template <typename CharT, typename Traits>
1330 typename basic_string<CharT, Traits>::const_reference
1332 {
1333  return const_at(n);
1334 }
1335 
1349 template <typename CharT, typename Traits>
1350 typename basic_string<CharT, Traits>::const_reference
1352 {
1353  if (n >= size())
1354  throw std::out_of_range("string::const_at");
1355 
1356  return is_sso_used()
1357  ? static_cast<const sso_type &>(sso_data())[n]
1358  : static_cast<const non_sso_type &>(non_sso_data())[n];
1359 }
1360 
1372 template <typename CharT, typename Traits>
1373 typename basic_string<CharT, Traits>::reference
1375 {
1376  return is_sso_used() ? sso_data()[n] : non_sso_data()[n];
1377 }
1378 
1386 template <typename CharT, typename Traits>
1387 typename basic_string<CharT, Traits>::const_reference
1389 {
1390  return is_sso_used() ? sso_data()[n] : non_sso_data()[n];
1391 }
1392 
1406 template <typename CharT, typename Traits>
1408 basic_string<CharT, Traits>::range(size_type start, size_type n)
1409 {
1410  if (start + n > size())
1411  throw std::out_of_range("basic_string::range");
1412 
1413  return is_sso_used() ? sso_data().range(start, n)
1414  : non_sso_data().range(start, n);
1415 }
1416 
1433 template <typename CharT, typename Traits>
1435 basic_string<CharT, Traits>::range(size_type start, size_type n,
1436  size_type snapshot_size)
1437 {
1438  if (start + n > size())
1439  throw std::out_of_range("basic_string::range");
1440 
1441  if (snapshot_size > n)
1442  snapshot_size = n;
1443 
1444  return is_sso_used() ? sso_data().range(start, n, snapshot_size)
1445  : non_sso_data().range(start, n, snapshot_size);
1446 }
1447 
1459 template <typename CharT, typename Traits>
1461 basic_string<CharT, Traits>::range(size_type start, size_type n) const
1462 {
1463  return crange(start, n);
1464 }
1465 
1477 template <typename CharT, typename Traits>
1479 basic_string<CharT, Traits>::crange(size_type start, size_type n) const
1480 {
1481  if (start + n > size())
1482  throw std::out_of_range("basic_string::range");
1483 
1484  return {const_iterator(cdata() + start),
1485  const_iterator(cdata() + start + n)};
1486 }
1487 
1497 template <typename CharT, typename Traits>
1498 CharT &
1500 {
1501  return (*this)[0];
1502 }
1503 
1509 template <typename CharT, typename Traits>
1510 const CharT &
1512 {
1513  return cfront();
1514 }
1515 
1524 template <typename CharT, typename Traits>
1525 const CharT &
1527 {
1528  return static_cast<const basic_string &>(*this)[0];
1529 }
1530 
1540 template <typename CharT, typename Traits>
1541 CharT &
1543 {
1544  return (*this)[size() - 1];
1545 }
1546 
1552 template <typename CharT, typename Traits>
1553 const CharT &
1555 {
1556  return cback();
1557 }
1558 
1567 template <typename CharT, typename Traits>
1568 const CharT &
1570 {
1571  return static_cast<const basic_string &>(*this)[size() - 1];
1572 }
1573 
1577 template <typename CharT, typename Traits>
1578 typename basic_string<CharT, Traits>::size_type
1580 {
1581  if (is_sso_used())
1582  return get_sso_size();
1583  else if (non_sso_data().size() == 0)
1584  return 0;
1585  else
1586  return non_sso_data().size() - 1;
1587 }
1588 
1595 template <typename CharT, typename Traits>
1596 CharT *
1598 {
1599  return is_sso_used() ? sso_data().range(0, get_sso_size() + 1).begin()
1600  : non_sso_data().data();
1601 }
1602 
1621 template <typename CharT, typename Traits>
1623 basic_string<CharT, Traits>::erase(size_type index, size_type count)
1624 {
1625  auto sz = size();
1626 
1627  if (index > sz)
1628  throw std::out_of_range("Index exceeds size.");
1629 
1630  count = (std::min)(count, sz - index);
1631 
1632  auto pop = get_pool();
1633 
1634  auto first = begin() + static_cast<difference_type>(index);
1635  auto last = first + static_cast<difference_type>(count);
1636 
1637  if (is_sso_used()) {
1638  flat_transaction::run(pop, [&] {
1639  auto move_len = sz - index - count;
1640  auto new_size = sz - count;
1641 
1642  if (move_len > 0) {
1643  auto range =
1644  sso_data().range(index, move_len + 1);
1645  traits_type::move(range.begin(), &*last,
1646  move_len);
1647 
1648  assert(range.end() - 1 ==
1649  &sso_data()._data[index + move_len]);
1650  }
1651 
1652  sso_data()[index + move_len] = value_type('\0');
1653  set_sso_size(new_size);
1654  });
1655  } else {
1656  non_sso_data().erase(first, last);
1657  }
1658 
1659  return *this;
1660 }
1661 
1678 template <typename CharT, typename Traits>
1681 {
1682  return erase(pos, pos + 1);
1683 }
1684 
1703 template <typename CharT, typename Traits>
1705 basic_string<CharT, Traits>::erase(const_iterator first, const_iterator last)
1706 {
1707  size_type index =
1708  static_cast<size_type>(std::distance(cbegin(), first));
1709  size_type len = static_cast<size_type>(std::distance(first, last));
1710 
1711  erase(index, len);
1712 
1713  return begin() + static_cast<difference_type>(index);
1714 }
1715 
1726 template <typename CharT, typename Traits>
1727 void
1729 {
1730  erase(size() - 1, 1);
1731 }
1732 
1752 template <typename CharT, typename Traits>
1754 basic_string<CharT, Traits>::append(size_type count, CharT ch)
1755 {
1756  auto sz = size();
1757  auto new_size = sz + count;
1758 
1759  if (new_size > max_size())
1760  throw std::length_error("Size exceeds max size.");
1761 
1762  if (is_sso_used()) {
1763  auto pop = get_pool();
1764 
1765  flat_transaction::run(pop, [&] {
1766  if (new_size > sso_capacity) {
1767  sso_to_large(new_size);
1768 
1769  non_sso_data().insert(
1770  non_sso_data().cbegin() +
1771  static_cast<difference_type>(
1772  sz),
1773  count, ch);
1774  } else {
1775  add_sso_to_tx(sz, count + 1);
1776  traits_type::assign(&sso_data()._data[sz],
1777  count, ch);
1778 
1779  assert(new_size == sz + count);
1780  set_sso_size(new_size);
1781  sso_data()._data[new_size] = value_type('\0');
1782  }
1783  });
1784  } else {
1785  non_sso_data().insert(non_sso_data().cbegin() +
1786  static_cast<difference_type>(sz),
1787  count, ch);
1788  }
1789 
1790  return *this;
1791 }
1792 
1811 template <typename CharT, typename Traits>
1814 {
1815  return append(str.data(), str.size());
1816 }
1817 
1843 template <typename CharT, typename Traits>
1846  size_type count)
1847 {
1848  auto sz = str.size();
1849 
1850  if (pos > sz)
1851  throw std::out_of_range("Index out of range.");
1852 
1853  count = (std::min)(count, sz - pos);
1854 
1855  append(str.data() + pos, count);
1856 
1857  return *this;
1858 }
1859 
1879 template <typename CharT, typename Traits>
1881 basic_string<CharT, Traits>::append(const CharT *s, size_type count)
1882 {
1883  return append(s, s + count);
1884 }
1885 
1905 template <typename CharT, typename Traits>
1908 {
1909  return append(s, traits_type::length(s));
1910 }
1911 
1933 template <typename CharT, typename Traits>
1934 template <typename InputIt, typename Enable>
1936 basic_string<CharT, Traits>::append(InputIt first, InputIt last)
1937 {
1938  auto sz = size();
1939  auto count = static_cast<size_type>(std::distance(first, last));
1940  auto new_size = sz + count;
1941 
1942  if (new_size > max_size())
1943  throw std::length_error("Size exceeds max size.");
1944 
1945  if (is_sso_used()) {
1946  auto pop = get_pool();
1947 
1948  flat_transaction::run(pop, [&] {
1949  if (new_size > sso_capacity) {
1950  /* 1) Cache C-style string in case of
1951  * self-append, because it will be destroyed
1952  * when switching from sso to large string.
1953  *
1954  * 2) We cache in std::vector instead of
1955  * std::string because of overload deduction
1956  * ambiguity on Windows
1957  */
1958  std::vector<value_type> str(first, last);
1959 
1960  sso_to_large(new_size);
1961  non_sso_data().insert(
1962  non_sso_data().cbegin() +
1963  static_cast<difference_type>(
1964  sz),
1965  str.begin(), str.end());
1966  } else {
1967  add_sso_to_tx(sz, count + 1);
1968  std::copy(first, last, &sso_data()._data[sz]);
1969 
1970  assert(new_size == sz + count);
1971  set_sso_size(new_size);
1972  sso_data()._data[new_size] = value_type('\0');
1973  }
1974  });
1975  } else {
1976  non_sso_data().insert(non_sso_data().cbegin() +
1977  static_cast<difference_type>(sz),
1978  first, last);
1979  }
1980 
1981  return *this;
1982 }
1983 
2002 template <typename CharT, typename Traits>
2004 basic_string<CharT, Traits>::append(std::initializer_list<CharT> ilist)
2005 {
2006  return append(ilist.begin(), ilist.end());
2007 }
2008 
2025 template <typename CharT, typename Traits>
2026 void
2028 {
2029  append(static_cast<size_type>(1), ch);
2030 }
2031 
2050 template <typename CharT, typename Traits>
2053 {
2054  return append(str);
2055 }
2056 
2076 template <typename CharT, typename Traits>
2079 {
2080  return append(s);
2081 }
2082 
2099 template <typename CharT, typename Traits>
2102 {
2103  push_back(ch);
2104 
2105  return *this;
2106 }
2107 
2126 template <typename CharT, typename Traits>
2128 basic_string<CharT, Traits>::operator+=(std::initializer_list<CharT> ilist)
2129 {
2130  return append(ilist);
2131 }
2132 
2154 template <typename CharT, typename Traits>
2156 basic_string<CharT, Traits>::insert(size_type index, size_type count, CharT ch)
2157 {
2158  if (index > size())
2159  throw std::out_of_range("Index out of range.");
2160 
2161  auto pos = cbegin() + static_cast<difference_type>(index);
2162 
2163  insert(pos, count, ch);
2164 
2165  return *this;
2166 }
2167 
2189 template <typename CharT, typename Traits>
2191 basic_string<CharT, Traits>::insert(size_type index, const CharT *s)
2192 {
2193  return insert(index, s, traits_type::length(s));
2194 }
2195 
2217 template <typename CharT, typename Traits>
2219 basic_string<CharT, Traits>::insert(size_type index, const CharT *s,
2220  size_type count)
2221 {
2222  if (index > size())
2223  throw std::out_of_range("Index out of range.");
2224 
2225  auto pos = cbegin() + static_cast<difference_type>(index);
2226 
2227  insert(pos, s, s + count);
2228 
2229  return *this;
2230 }
2231 
2252 template <typename CharT, typename Traits>
2255 {
2256  return insert(index, str.data(), str.size());
2257 }
2258 
2281 template <typename CharT, typename Traits>
2284  size_type index2, size_type count)
2285 {
2286  auto sz = str.size();
2287 
2288  if (index1 > size() || index2 > sz)
2289  throw std::out_of_range("Index out of range.");
2290 
2291  count = (std::min)(count, sz - index2);
2292 
2293  return insert(index1, str.data() + index2, count);
2294 }
2295 
2318 template <typename CharT, typename Traits>
2320 basic_string<CharT, Traits>::insert(const_iterator pos, CharT ch)
2321 {
2322  return insert(pos, 1, ch);
2323 }
2324 
2349 template <typename CharT, typename Traits>
2351 basic_string<CharT, Traits>::insert(const_iterator pos, size_type count,
2352  CharT ch)
2353 {
2354  auto sz = size();
2355 
2356  if (sz + count > max_size())
2357  throw std::length_error("Count exceeds max size.");
2358 
2359  auto new_size = sz + count;
2360 
2361  auto pop = get_pool();
2362 
2363  auto index = static_cast<size_type>(std::distance(cbegin(), pos));
2364 
2365  flat_transaction::run(pop, [&] {
2366  if (is_sso_used() && new_size <= sso_capacity) {
2367  auto len = sz - index;
2368 
2369  add_sso_to_tx(index, len + count + 1);
2370 
2371  traits_type::move(&sso_data()._data[index + count],
2372  &sso_data()._data[index], len);
2373  traits_type::assign(&sso_data()._data[index], count,
2374  ch);
2375 
2376  assert(new_size == index + len + count);
2377  set_sso_size(new_size);
2378  sso_data()._data[new_size] = value_type('\0');
2379  } else {
2380  if (is_sso_used())
2381  sso_to_large(new_size);
2382 
2383  non_sso_data().insert(
2384  non_sso_data().begin() +
2385  static_cast<difference_type>(index),
2386  count, ch);
2387  }
2388  });
2389 
2390  return iterator(&data()[static_cast<difference_type>(index)]);
2391 }
2392 
2417 template <typename CharT, typename Traits>
2418 template <typename InputIt, typename Enable>
2420 basic_string<CharT, Traits>::insert(const_iterator pos, InputIt first,
2421  InputIt last)
2422 {
2423  auto sz = size();
2424 
2425  auto count = static_cast<size_type>(std::distance(first, last));
2426 
2427  if (sz + count > max_size())
2428  throw std::length_error("Count exceeds max size.");
2429 
2430  auto pop = get_pool();
2431 
2432  auto new_size = sz + count;
2433 
2434  auto index = static_cast<size_type>(std::distance(cbegin(), pos));
2435 
2436  flat_transaction::run(pop, [&] {
2437  if (is_sso_used() && new_size <= sso_capacity) {
2438  auto len = sz - index;
2439 
2440  add_sso_to_tx(index, len + count + 1);
2441 
2442  traits_type::move(&sso_data()._data[index + count],
2443  &sso_data()._data[index], len);
2444  std::copy(first, last, &sso_data()._data[index]);
2445 
2446  assert(new_size == index + len + count);
2447  set_sso_size(new_size);
2448  sso_data()._data[new_size] = value_type('\0');
2449  } else {
2450  if (is_sso_used()) {
2451  /* 1) Cache C-style string in case of
2452  * self-insert, because it will be destroyed
2453  * when switching from sso to large string.
2454  *
2455  * 2) We cache in std::vector instead of
2456  * std::string because of overload deduction
2457  * ambiguity on Windows
2458  */
2459  std::vector<value_type> str(first, last);
2460 
2461  sso_to_large(new_size);
2462  non_sso_data().insert(
2463  non_sso_data().begin() +
2464  static_cast<difference_type>(
2465  index),
2466  str.begin(), str.end());
2467  } else {
2468  non_sso_data().insert(
2469  non_sso_data().begin() +
2470  static_cast<difference_type>(
2471  index),
2472  first, last);
2473  }
2474  }
2475  });
2476 
2477  return iterator(&data()[static_cast<difference_type>(index)]);
2478 }
2479 
2503 template <typename CharT, typename Traits>
2506  std::initializer_list<CharT> ilist)
2507 {
2508  return insert(pos, ilist.begin(), ilist.end());
2509 }
2510 
2533 template <typename CharT, typename Traits>
2535 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2536  const basic_string &str)
2537 {
2538  return replace(index, count, str.data(), str.size());
2539 }
2540 
2561 template <typename CharT, typename Traits>
2563 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2564  const basic_string &str)
2565 {
2566  return replace(first, last, str.data(), str.data() + str.size());
2567 }
2568 
2595 template <typename CharT, typename Traits>
2597 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2598  const basic_string &str, size_type index2,
2599  size_type count2)
2600 {
2601  auto sz = str.size();
2602 
2603  if (index2 > sz)
2604  throw std::out_of_range("Index out of range.");
2605 
2606  count2 = (std::min)(count2, sz - index2);
2607 
2608  return replace(index, count, str.data() + index2, count2);
2609 }
2610 
2636 template <typename CharT, typename Traits>
2637 template <typename InputIt, typename Enable>
2639 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2640  InputIt first2, InputIt last2)
2641 {
2642  auto sz = size();
2643  auto index = static_cast<size_type>(std::distance(cbegin(), first));
2644  auto count = static_cast<size_type>(std::distance(first, last));
2645  auto count2 = static_cast<size_type>(std::distance(first2, last2));
2646 
2647  count = (std::min)(count, sz - index);
2648 
2649  if (sz - count + count2 > max_size())
2650  throw std::length_error("Count exceeds max size.");
2651 
2652  auto new_size = sz - count + count2;
2653 
2654  auto pop = get_pool();
2655 
2656  flat_transaction::run(pop, [&] {
2657  if (is_sso_used() && new_size <= sso_capacity) {
2658  add_sso_to_tx(index, new_size - index + 1);
2659 
2660  assert(count2 < new_size + 1);
2661  traits_type::move(&sso_data()._data[index + count2],
2662  &sso_data()._data[index + count],
2663  sz - index - count);
2664  std::copy(first2, last2, &sso_data()._data[index]);
2665 
2666  set_sso_size(new_size);
2667  sso_data()._data[new_size] = value_type('\0');
2668  } else {
2669  /* 1) Cache C-style string in case of
2670  * self-replace, because it will be destroyed
2671  * when switching from sso to large string.
2672  *
2673  * 2) We cache in std::vector instead of
2674  * std::string because of overload deduction
2675  * ambiguity on Windows
2676  */
2677  std::vector<value_type> str(first2, last2);
2678 
2679  if (is_sso_used()) {
2680  sso_to_large(new_size);
2681  }
2682 
2683  auto beg =
2684  begin() + static_cast<difference_type>(index);
2685  auto end = beg + static_cast<difference_type>(count);
2686  non_sso_data().erase(beg, end);
2687  non_sso_data().insert(beg, str.begin(), str.end());
2688  }
2689 
2690  if (!is_sso_used() && new_size <= sso_capacity)
2691  large_to_sso();
2692  });
2693 
2694  return *this;
2695 }
2696 
2719 template <typename CharT, typename Traits>
2721 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2722  const CharT *s, size_type count2)
2723 {
2724  return replace(first, last, s, s + count2);
2725 }
2726 
2750 template <typename CharT, typename Traits>
2752 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2753  const CharT *s, size_type count2)
2754 {
2755  if (index > size())
2756  throw std::out_of_range("Index out of range.");
2757 
2758  auto first = cbegin() + static_cast<difference_type>(index);
2759  auto last = first + static_cast<difference_type>(count);
2760 
2761  return replace(first, last, s, s + count2);
2762 }
2763 
2787 template <typename CharT, typename Traits>
2789 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2790  const CharT *s)
2791 {
2792  return replace(index, count, s, traits_type::length(s));
2793 }
2794 
2818 template <typename CharT, typename Traits>
2820 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2821  size_type count2, CharT ch)
2822 {
2823  if (index > size())
2824  throw std::out_of_range("Index out of range.");
2825 
2826  auto first = cbegin() + static_cast<difference_type>(index);
2827  auto last = first + static_cast<difference_type>(count);
2828 
2829  return replace(first, last, count2, ch);
2830 }
2831 
2854 template <typename CharT, typename Traits>
2856 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2857  size_type count2, CharT ch)
2858 {
2859  auto sz = size();
2860  auto index = static_cast<size_type>(std::distance(cbegin(), first));
2861  auto count = static_cast<size_type>(std::distance(first, last));
2862 
2863  count = (std::min)(count, sz - index);
2864 
2865  if (sz - count + count2 > max_size())
2866  throw std::length_error("Count exceeds max size.");
2867 
2868  auto new_size = sz - count + count2;
2869 
2870  auto pop = get_pool();
2871 
2872  flat_transaction::run(pop, [&] {
2873  if (is_sso_used() && new_size <= sso_capacity) {
2874  add_sso_to_tx(index, new_size - index + 1);
2875 
2876  assert(count2 < new_size + 1);
2877  traits_type::move(&sso_data()._data[index + count2],
2878  &sso_data()._data[index + count],
2879  sz - index - count);
2880  traits_type::assign(&sso_data()._data[index], count2,
2881  ch);
2882 
2883  set_sso_size(new_size);
2884  sso_data()._data[new_size] = value_type('\0');
2885  } else {
2886  if (is_sso_used()) {
2887  sso_to_large(new_size);
2888  }
2889 
2890  auto beg =
2891  begin() + static_cast<difference_type>(index);
2892  auto end = beg + static_cast<difference_type>(count);
2893  non_sso_data().erase(beg, end);
2894  non_sso_data().insert(beg, count2, ch);
2895  }
2896 
2897  if (!is_sso_used() && new_size <= sso_capacity)
2898  large_to_sso();
2899  });
2900 
2901  return *this;
2902 }
2903 
2925 template <typename CharT, typename Traits>
2927 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2928  const CharT *s)
2929 {
2930  return replace(first, last, s, traits_type::length(s));
2931 }
2932 
2955 template <typename CharT, typename Traits>
2957 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2958  std::initializer_list<CharT> ilist)
2959 {
2960  return replace(first, last, ilist.begin(), ilist.end());
2961 }
2962 
2976 template <typename CharT, typename Traits>
2977 typename basic_string<CharT, Traits>::size_type
2978 basic_string<CharT, Traits>::copy(CharT *s, size_type count,
2979  size_type index) const
2980 {
2981  auto sz = size();
2982 
2983  if (index > sz)
2984  throw std::out_of_range("Index out of range.");
2985 
2986  auto len = (std::min)(count, sz - index);
2987 
2988  traits_type::copy(s, data() + index, len);
2989 
2990  return len;
2991 }
2992 
3010 template <typename CharT, typename Traits>
3011 int
3012 basic_string<CharT, Traits>::compare(size_type pos, size_type count1,
3013  const CharT *s, size_type count2) const
3014 {
3015  if (pos > size())
3016  throw std::out_of_range("Index out of range.");
3017 
3018  if (count1 > size() - pos)
3019  count1 = size() - pos;
3020 
3021  auto ret = traits_type::compare(cdata() + pos, s,
3022  std::min<size_type>(count1, count2));
3023 
3024  if (ret != 0)
3025  return ret;
3026 
3027  if (count1 < count2)
3028  return -1;
3029  else if (count1 == count2)
3030  return 0;
3031  else
3032  return 1;
3033 }
3034 
3044 template <typename CharT, typename Traits>
3045 typename basic_string<CharT, Traits>::size_type
3046 basic_string<CharT, Traits>::find(const basic_string &str, size_type pos) const
3047  noexcept
3048 {
3049  return find(str.data(), pos, str.size());
3050 }
3051 
3063 template <typename CharT, typename Traits>
3064 typename basic_string<CharT, Traits>::size_type
3065 basic_string<CharT, Traits>::find(const CharT *s, size_type pos,
3066  size_type count) const
3067 {
3068  return operator basic_string_view<CharT, Traits>().find(s, pos, count);
3069 }
3070 
3081 template <typename CharT, typename Traits>
3082 typename basic_string<CharT, Traits>::size_type
3083 basic_string<CharT, Traits>::find(const CharT *s, size_type pos) const
3084 {
3085  return find(s, pos, traits_type::length(s));
3086 }
3087 
3097 template <typename CharT, typename Traits>
3098 typename basic_string<CharT, Traits>::size_type
3099 basic_string<CharT, Traits>::find(CharT ch, size_type pos) const noexcept
3100 {
3101  return find(&ch, pos, 1);
3102 }
3103 
3114 template <typename CharT, typename Traits>
3115 typename basic_string<CharT, Traits>::size_type
3116 basic_string<CharT, Traits>::rfind(const basic_string &str, size_type pos) const
3117  noexcept
3118 {
3119  return rfind(str.cdata(), pos, str.size());
3120 }
3121 
3138 template <typename CharT, typename Traits>
3139 typename basic_string<CharT, Traits>::size_type
3140 basic_string<CharT, Traits>::rfind(const CharT *s, size_type pos,
3141  size_type count) const
3142 {
3143  return operator basic_string_view<CharT, Traits>().rfind(s, pos, count);
3144 }
3145 
3158 template <typename CharT, typename Traits>
3159 typename basic_string<CharT, Traits>::size_type
3160 basic_string<CharT, Traits>::rfind(const CharT *s, size_type pos) const
3161 {
3162  return rfind(s, pos, traits_type::length(s));
3163 }
3164 
3176 template <typename CharT, typename Traits>
3177 typename basic_string<CharT, Traits>::size_type
3178 basic_string<CharT, Traits>::rfind(CharT ch, size_type pos) const noexcept
3179 {
3180  return rfind(&ch, pos, 1);
3181 }
3182 
3192 template <typename CharT, typename Traits>
3193 typename basic_string<CharT, Traits>::size_type
3195  size_type pos) const noexcept
3196 {
3197  return find_first_of(str.cdata(), pos, str.size());
3198 }
3199 
3213 template <typename CharT, typename Traits>
3214 typename basic_string<CharT, Traits>::size_type
3215 basic_string<CharT, Traits>::find_first_of(const CharT *s, size_type pos,
3216  size_type count) const
3217 {
3218  return operator basic_string_view<CharT, Traits>().find_first_of(s, pos,
3219  count);
3220 }
3221 
3234 template <typename CharT, typename Traits>
3235 typename basic_string<CharT, Traits>::size_type
3236 basic_string<CharT, Traits>::find_first_of(const CharT *s, size_type pos) const
3237 {
3238  return find_first_of(s, pos, traits_type::length(s));
3239 }
3240 
3250 template <typename CharT, typename Traits>
3251 typename basic_string<CharT, Traits>::size_type
3252 basic_string<CharT, Traits>::find_first_of(CharT ch, size_type pos) const
3253  noexcept
3254 {
3255  return find(ch, pos);
3256 }
3257 
3267 template <typename CharT, typename Traits>
3268 typename basic_string<CharT, Traits>::size_type
3270  size_type pos) const noexcept
3271 {
3272  return find_first_not_of(str.cdata(), pos, str.size());
3273 }
3274 
3288 template <typename CharT, typename Traits>
3289 typename basic_string<CharT, Traits>::size_type
3291  size_type count) const
3292 {
3294  s, pos, count);
3295 }
3296 
3309 template <typename CharT, typename Traits>
3310 typename basic_string<CharT, Traits>::size_type
3312  size_type pos) const
3313 {
3314  return find_first_not_of(s, pos, traits_type::length(s));
3315 }
3316 
3326 template <typename CharT, typename Traits>
3327 typename basic_string<CharT, Traits>::size_type
3329  noexcept
3330 {
3331  return find_first_not_of(&ch, pos, 1);
3332 }
3333 
3343 template <typename CharT, typename Traits>
3344 typename basic_string<CharT, Traits>::size_type
3346  size_type pos) const noexcept
3347 {
3348  return find_last_of(str.cdata(), pos, str.size());
3349 }
3350 
3364 template <typename CharT, typename Traits>
3365 typename basic_string<CharT, Traits>::size_type
3366 basic_string<CharT, Traits>::find_last_of(const CharT *s, size_type pos,
3367  size_type count) const
3368 {
3369  return operator basic_string_view<CharT, Traits>().find_last_of(s, pos,
3370  count);
3371 }
3372 
3385 template <typename CharT, typename Traits>
3386 typename basic_string<CharT, Traits>::size_type
3387 basic_string<CharT, Traits>::find_last_of(const CharT *s, size_type pos) const
3388 {
3389  return find_last_of(s, pos, traits_type::length(s));
3390 }
3391 
3401 template <typename CharT, typename Traits>
3402 typename basic_string<CharT, Traits>::size_type
3403 basic_string<CharT, Traits>::find_last_of(CharT ch, size_type pos) const
3404  noexcept
3405 {
3406  return rfind(ch, pos);
3407 }
3408 
3418 template <typename CharT, typename Traits>
3419 typename basic_string<CharT, Traits>::size_type
3421  size_type pos) const noexcept
3422 {
3423  return find_last_not_of(str.cdata(), pos, str.size());
3424 }
3425 
3439 template <typename CharT, typename Traits>
3440 typename basic_string<CharT, Traits>::size_type
3442  size_type count) const
3443 {
3445  s, pos, count);
3446 }
3447 
3460 template <typename CharT, typename Traits>
3461 typename basic_string<CharT, Traits>::size_type
3463  size_type pos) const
3464 {
3465  return find_last_not_of(s, pos, traits_type::length(s));
3466 }
3467 
3477 template <typename CharT, typename Traits>
3478 typename basic_string<CharT, Traits>::size_type
3480  noexcept
3481 {
3482  return find_last_not_of(&ch, pos, 1);
3483 }
3484 
3493 template <typename CharT, typename Traits>
3494 int
3496 {
3497  return compare(0, size(), other.cdata(), other.size());
3498 }
3499 
3508 template <typename CharT, typename Traits>
3509 int
3511  const std::basic_string<CharT> &other) const
3512 {
3513  return compare(0, size(), other.data(), other.size());
3514 }
3515 
3529 template <typename CharT, typename Traits>
3530 int
3531 basic_string<CharT, Traits>::compare(size_type pos, size_type count,
3532  const basic_string &other) const
3533 {
3534  return compare(pos, count, other.cdata(), other.size());
3535 }
3536 
3551 template <typename CharT, typename Traits>
3552 int
3554  size_type pos, size_type count,
3555  const std::basic_string<CharT> &other) const
3556 {
3557  return compare(pos, count, other.data(), other.size());
3558 }
3559 
3578 template <typename CharT, typename Traits>
3579 int
3580 basic_string<CharT, Traits>::compare(size_type pos1, size_type count1,
3581  const basic_string &other, size_type pos2,
3582  size_type count2) const
3583 {
3584  if (pos2 > other.size())
3585  throw std::out_of_range("Index out of range.");
3586 
3587  if (count2 > other.size() - pos2)
3588  count2 = other.size() - pos2;
3589 
3590  return compare(pos1, count1, other.cdata() + pos2, count2);
3591 }
3592 
3611 template <typename CharT, typename Traits>
3612 int
3613 basic_string<CharT, Traits>::compare(size_type pos1, size_type count1,
3614  const std::basic_string<CharT> &other,
3615  size_type pos2, size_type count2) const
3616 {
3617  if (pos2 > other.size())
3618  throw std::out_of_range("Index out of range.");
3619 
3620  if (count2 > other.size() - pos2)
3621  count2 = other.size() - pos2;
3622 
3623  return compare(pos1, count1, other.data() + pos2, count2);
3624 }
3625 
3634 template <typename CharT, typename Traits>
3635 int
3637 {
3638  return compare(0, size(), s, traits_type::length(s));
3639 }
3640 
3654 template <typename CharT, typename Traits>
3655 int
3656 basic_string<CharT, Traits>::compare(size_type pos, size_type count,
3657  const CharT *s) const
3658 {
3659  return compare(pos, count, s, traits_type::length(s));
3660 }
3661 
3665 template <typename CharT, typename Traits>
3666 const CharT *
3668 {
3669  return is_sso_used() ? sso_data().cdata() : non_sso_data().cdata();
3670 }
3671 
3675 template <typename CharT, typename Traits>
3676 const CharT *
3678 {
3679  return cdata();
3680 }
3681 
3685 template <typename CharT, typename Traits>
3686 const CharT *
3688 {
3689  return cdata();
3690 }
3691 
3695 template <typename CharT, typename Traits>
3696 typename basic_string<CharT, Traits>::size_type
3698 {
3699  return size();
3700 }
3701 
3705 template <typename CharT, typename Traits>
3706 typename basic_string<CharT, Traits>::size_type
3708 {
3709  return PMEMOBJ_MAX_ALLOC_SIZE / sizeof(CharT) - 1;
3710 }
3711 
3716 template <typename CharT, typename Traits>
3717 typename basic_string<CharT, Traits>::size_type
3719 {
3720  return is_sso_used() ? sso_capacity : non_sso_data().capacity() - 1;
3721 }
3722 
3742 template <typename CharT, typename Traits>
3743 void
3744 basic_string<CharT, Traits>::resize(size_type count, CharT ch)
3745 {
3746  if (count > max_size())
3747  throw std::length_error("Count exceeds max size.");
3748 
3749  auto sz = size();
3750 
3751  auto pop = get_pool();
3752 
3753  flat_transaction::run(pop, [&] {
3754  if (count > sz) {
3755  append(count - sz, ch);
3756  } else if (is_sso_used()) {
3757  set_sso_size(count);
3758  sso_data()[count] = value_type('\0');
3759  } else {
3760  non_sso_data().resize(count + 1, ch);
3761  non_sso_data().back() = value_type('\0');
3762  }
3763  });
3764 }
3765 
3784 template <typename CharT, typename Traits>
3785 void
3787 {
3788  resize(count, CharT());
3789 }
3790 
3811 template <typename CharT, typename Traits>
3812 void
3814 {
3815  if (new_cap > max_size())
3816  throw std::length_error("New capacity exceeds max size.");
3817 
3818  if (new_cap < capacity() || new_cap <= sso_capacity)
3819  return;
3820 
3821  if (is_sso_used()) {
3822  auto pop = get_pool();
3823 
3824  flat_transaction::run(pop, [&] { sso_to_large(new_cap); });
3825  } else {
3826  non_sso_data().reserve(new_cap + 1);
3827  }
3828 }
3829 
3843 template <typename CharT, typename Traits>
3844 void
3846 {
3847  if (is_sso_used())
3848  return;
3849 
3850  if (size() <= sso_capacity) {
3851  auto pop = get_pool();
3852 
3853  flat_transaction::run(pop, [&] { large_to_sso(); });
3854  } else {
3855  non_sso_data().shrink_to_fit();
3856  }
3857 }
3858 
3868 template <typename CharT, typename Traits>
3869 void
3871 {
3872  erase(begin(), end());
3873 }
3874 
3887 template <typename CharT, typename Traits>
3888 void
3890 {
3891  auto pop = get_pool();
3892 
3893  flat_transaction::run(pop, [&] {
3894  if (is_sso_used()) {
3895  add_sso_to_tx(0, get_sso_size() + 1);
3896  clear();
3897  /* sso.data destructor does not have to be called */
3898  } else {
3899  non_sso_data().free_data();
3900  detail::destroy<non_sso_type>(non_sso_data());
3901  enable_sso();
3902  }
3903  });
3904 }
3905 
3909 template <typename CharT, typename Traits>
3910 bool
3912 {
3913  return size() == 0;
3914 }
3915 
3916 template <typename CharT, typename Traits>
3917 bool
3919 {
3920  return (sso._size & _sso_mask) != 0;
3921 }
3922 
3923 template <typename CharT, typename Traits>
3924 void
3925 basic_string<CharT, Traits>::destroy_data()
3926 {
3927  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3928 
3929  if (is_sso_used()) {
3930  add_sso_to_tx(0, get_sso_size() + 1);
3931  /* sso.data destructor does not have to be called */
3932  } else {
3933  non_sso_data().free_data();
3934  detail::destroy<non_sso_type>(non_sso_data());
3935  }
3936 }
3937 
3944 template <typename CharT, typename Traits>
3945 template <typename InputIt, typename Enable>
3946 typename basic_string<CharT, Traits>::size_type
3947 basic_string<CharT, Traits>::get_size(InputIt first, InputIt last) const
3948 {
3949  return static_cast<size_type>(std::distance(first, last));
3950 }
3951 
3958 template <typename CharT, typename Traits>
3959 typename basic_string<CharT, Traits>::size_type
3960 basic_string<CharT, Traits>::get_size(size_type count, value_type ch) const
3961 {
3962  return count;
3963 }
3964 
3971 template <typename CharT, typename Traits>
3972 typename basic_string<CharT, Traits>::size_type
3973 basic_string<CharT, Traits>::get_size(const basic_string &other) const
3974 {
3975  return other.size();
3976 }
3977 
3984 template <typename CharT, typename Traits>
3985 template <typename... Args>
3986 typename basic_string<CharT, Traits>::pointer
3987 basic_string<CharT, Traits>::replace_content(Args &&... args)
3988 {
3989  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3990 
3991  auto new_size = get_size(std::forward<Args>(args)...);
3992 
3993  /* If non_sso.data is used and there is enough capacity */
3994  if (!is_sso_used() && new_size <= capacity())
3995  return assign_large_data(std::forward<Args>(args)...);
3996 
3997  destroy_data();
3998 
3999  allocate(new_size);
4000  return initialize(std::forward<Args>(args)...);
4001 }
4002 
4013 template <typename CharT, typename Traits>
4014 template <typename... Args>
4015 typename basic_string<CharT, Traits>::pointer
4016 basic_string<CharT, Traits>::initialize(Args &&... args)
4017 {
4018  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4019 
4020  if (is_sso_used()) {
4021  return assign_sso_data(std::forward<Args>(args)...);
4022  } else {
4023  return assign_large_data(std::forward<Args>(args)...);
4024  }
4025 }
4026 
4036 template <typename CharT, typename Traits>
4037 void
4038 basic_string<CharT, Traits>::allocate(size_type n)
4039 {
4040  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4041 
4042  if (n <= sso_capacity) {
4043  enable_sso();
4044  } else {
4045  disable_sso();
4046  }
4047 
4048  /*
4049  * array is aggregate type so it's not required to call
4050  * a constructor.
4051  */
4052  if (!is_sso_used()) {
4053  detail::conditional_add_to_tx(&non_sso_data(), 1,
4054  POBJ_XADD_NO_SNAPSHOT);
4055  detail::create<non_sso_type>(&non_sso_data());
4056  non_sso_data().reserve(n + 1);
4057  }
4058 }
4059 
4063 template <typename CharT, typename Traits>
4064 template <typename InputIt, typename Enable>
4065 typename basic_string<CharT, Traits>::pointer
4066 basic_string<CharT, Traits>::assign_sso_data(InputIt first, InputIt last)
4067 {
4068  auto size = static_cast<size_type>(std::distance(first, last));
4069 
4070  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4071  assert(size <= sso_capacity);
4072 
4073  add_sso_to_tx(0, size + 1);
4074  std::copy(first, last, &sso_data()._data[0]);
4075 
4076  sso_data()._data[size] = value_type('\0');
4077 
4078  set_sso_size(size);
4079 
4080  return &sso_data()[0];
4081 }
4082 
4086 template <typename CharT, typename Traits>
4087 typename basic_string<CharT, Traits>::pointer
4088 basic_string<CharT, Traits>::assign_sso_data(size_type count, value_type ch)
4089 {
4090  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4091  assert(count <= sso_capacity);
4092 
4093  add_sso_to_tx(0, count + 1);
4094  traits_type::assign(&sso_data()._data[0], count, ch);
4095 
4096  sso_data()._data[count] = value_type('\0');
4097 
4098  set_sso_size(count);
4099 
4100  return &sso_data()[0];
4101 }
4102 
4107 template <typename CharT, typename Traits>
4108 template <typename InputIt, typename Enable>
4109 typename basic_string<CharT, Traits>::pointer
4110 basic_string<CharT, Traits>::assign_large_data(InputIt first, InputIt last)
4111 {
4112  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4113 
4114  auto size = static_cast<size_type>(std::distance(first, last));
4115 
4116  non_sso_data().reserve(size + 1);
4117  non_sso_data().assign(first, last);
4118  non_sso_data().push_back(value_type('\0'));
4119 
4120  return non_sso_data().data();
4121 }
4122 
4127 template <typename CharT, typename Traits>
4128 typename basic_string<CharT, Traits>::pointer
4129 basic_string<CharT, Traits>::assign_large_data(size_type count, value_type ch)
4130 {
4131  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4132 
4133  non_sso_data().reserve(count + 1);
4134  non_sso_data().assign(count, ch);
4135  non_sso_data().push_back(value_type('\0'));
4136 
4137  return non_sso_data().data();
4138 }
4139 
4144 template <typename CharT, typename Traits>
4145 typename basic_string<CharT, Traits>::pointer
4146 basic_string<CharT, Traits>::move_data(basic_string &&other)
4147 {
4148  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4149 
4150  typename basic_string::pointer ptr;
4151 
4152  if (other.size() <= sso_capacity) {
4153  enable_sso();
4154  ptr = assign_sso_data(other.cbegin(), other.cend());
4155  } else {
4156  disable_sso();
4157  detail::conditional_add_to_tx(&non_sso_data(), 1,
4158  POBJ_XADD_NO_SNAPSHOT);
4159  detail::create<non_sso_type>(&non_sso_data());
4160 
4161  assert(!other.is_sso_used());
4162  non_sso_data() = std::move(other.non_sso_data());
4163 
4164  ptr = non_sso_data().data();
4165  }
4166 
4167  if (other.is_sso_used())
4168  other.initialize(0U, value_type('\0'));
4169 
4170  return ptr;
4171 }
4172 
4176 template <typename CharT, typename Traits>
4177 void
4179 {
4180  pool_base pb = get_pool();
4181  flat_transaction::run(pb, [&] {
4182  if (is_sso_used() && other.is_sso_used()) {
4183  sso_data().swap(other.sso_data());
4184  pmem::obj::swap(sso._size, other.sso._size);
4185  } else if (!is_sso_used() && !other.is_sso_used()) {
4186  non_sso_data().swap(other.non_sso_data());
4187  } else {
4188  basic_string *_short, *_long;
4189  if (size() > other.size()) {
4190  _short = &other;
4191  _long = this;
4192  } else {
4193  _short = this;
4194  _long = &other;
4195  }
4196 
4197  std::basic_string<CharT, Traits> tmp(_short->c_str(),
4198  _short->size());
4199  *_short = *_long;
4200  *_long = tmp;
4201  }
4202  });
4203 }
4204 
4208 template <typename CharT, typename Traits>
4210 {
4211  return basic_string_view<CharT, Traits>(cdata(), length());
4212 }
4213 
4217 template <typename CharT, typename Traits>
4218 pool_base
4220 {
4221  return pmem::obj::pool_by_vptr(this);
4222 }
4223 
4227 template <typename CharT, typename Traits>
4228 void
4229 basic_string<CharT, Traits>::check_pmem() const
4230 {
4231  if (pmemobj_pool_by_ptr(this) == nullptr)
4232  throw pmem::pool_error("Object is not on pmem.");
4233 }
4234 
4238 template <typename CharT, typename Traits>
4239 void
4240 basic_string<CharT, Traits>::check_tx_stage_work() const
4241 {
4242  if (pmemobj_tx_stage() != TX_STAGE_WORK)
4244  "Call made out of transaction scope.");
4245 }
4246 
4251 template <typename CharT, typename Traits>
4252 void
4253 basic_string<CharT, Traits>::check_pmem_tx() const
4254 {
4255  check_pmem();
4256  check_tx_stage_work();
4257 }
4258 
4262 template <typename CharT, typename Traits>
4263 void
4264 basic_string<CharT, Traits>::add_sso_to_tx(size_type idx_first,
4265  size_type num) const
4266 {
4267  assert(idx_first + num <= sso_capacity + 1);
4268  assert(is_sso_used());
4269 
4270  auto initialized_num = get_sso_size() + 1 - idx_first;
4271 
4272  /* Snapshot elements in range [idx_first, sso_size + 1 (null)) */
4273  detail::conditional_add_to_tx(&sso_data()._data[0] + idx_first,
4274  (std::min)(initialized_num, num));
4275 
4276  if (num > initialized_num) {
4277  /* Elements after sso_size + 1 do not have to be snapshotted */
4279  &sso_data()._data[0] + get_sso_size() + 1,
4280  num - initialized_num, POBJ_XADD_NO_SNAPSHOT);
4281  }
4282 }
4283 
4287 template <typename CharT, typename Traits>
4288 typename basic_string<CharT, Traits>::size_type
4289 basic_string<CharT, Traits>::get_sso_size() const
4290 {
4291  return sso._size & ~_sso_mask;
4292 }
4293 
4297 template <typename CharT, typename Traits>
4298 void
4299 basic_string<CharT, Traits>::enable_sso()
4300 {
4301  /* temporary size_type must be created to avoid undefined reference
4302  * linker error */
4303  sso._size |= (size_type)(_sso_mask);
4304 }
4305 
4309 template <typename CharT, typename Traits>
4310 void
4311 basic_string<CharT, Traits>::disable_sso()
4312 {
4313  sso._size &= ~_sso_mask;
4314 }
4315 
4319 template <typename CharT, typename Traits>
4320 void
4321 basic_string<CharT, Traits>::set_sso_size(size_type new_size)
4322 {
4323  sso._size = new_size | _sso_mask;
4324 }
4325 
4337 template <typename CharT, typename Traits>
4338 void
4339 basic_string<CharT, Traits>::sso_to_large(size_t new_capacity)
4340 {
4341  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4342  assert(new_capacity > sso_capacity);
4343  assert(is_sso_used());
4344 
4345  auto sz = size();
4346 
4347  sso_type tmp;
4348  std::copy(cbegin(), cend(), tmp.data());
4349  tmp[sz] = value_type('\0');
4350 
4351  destroy_data();
4352  allocate(new_capacity);
4353 
4354  auto begin = tmp.cbegin();
4355  auto end = begin + sz;
4356 
4357  initialize(begin, end);
4358 
4359  assert(!is_sso_used());
4360 };
4361 
4371 template <typename CharT, typename Traits>
4372 void
4373 basic_string<CharT, Traits>::large_to_sso()
4374 {
4375  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4376  assert(!is_sso_used());
4377 
4378  auto sz = size();
4379 
4380  assert(sz <= sso_capacity);
4381 
4382  sso_type tmp;
4383  std::copy(cbegin(), cbegin() + sz, tmp.data());
4384  tmp[sz] = value_type('\0');
4385 
4386  destroy_data();
4387  allocate(sz);
4388 
4389  auto begin = tmp.cbegin();
4390  auto end = begin + sz;
4391 
4392  initialize(begin, end);
4393 
4394  assert(is_sso_used());
4395 };
4396 
4397 template <typename CharT, typename Traits>
4398 typename basic_string<CharT, Traits>::non_sso_type &
4399 basic_string<CharT, Traits>::non_sso_data()
4400 {
4401  assert(!is_sso_used());
4402  return non_sso._data;
4403 }
4404 
4405 template <typename CharT, typename Traits>
4406 typename basic_string<CharT, Traits>::sso_type &
4407 basic_string<CharT, Traits>::sso_data()
4408 {
4409  assert(is_sso_used());
4410  return sso._data;
4411 }
4412 
4413 template <typename CharT, typename Traits>
4414 const typename basic_string<CharT, Traits>::non_sso_type &
4415 basic_string<CharT, Traits>::non_sso_data() const
4416 {
4417  assert(!is_sso_used());
4418  return non_sso._data;
4419 }
4420 
4421 template <typename CharT, typename Traits>
4422 const typename basic_string<CharT, Traits>::sso_type &
4423 basic_string<CharT, Traits>::sso_data() const
4424 {
4425  assert(is_sso_used());
4426  return sso._data;
4427 }
4428 
4433 template <typename CharT, typename Traits>
4434 template <typename T, typename Enable>
4435 basic_string<CharT, Traits> &
4437 {
4438  return erase(static_cast<size_type>(param));
4439 }
4440 
4445 template <typename CharT, typename Traits>
4446 template <typename T, typename Enable>
4449 {
4450  return erase(static_cast<const_iterator>(param));
4451 }
4452 
4458 template <typename CharT, typename Traits>
4459 template <typename T, typename Enable>
4461 basic_string<CharT, Traits>::insert(T param, size_type count, CharT ch)
4462 {
4463  return insert(static_cast<size_type>(param), count, ch);
4464 }
4465 
4471 template <typename CharT, typename Traits>
4472 template <typename T, typename Enable>
4474 basic_string<CharT, Traits>::insert(T param, size_type count, CharT ch)
4475 {
4476  return insert(static_cast<const_iterator>(param), count, ch);
4477 }
4478 
4483 template <class CharT, class Traits>
4484 bool
4486  const basic_string<CharT, Traits> &rhs)
4487 {
4488  return lhs.compare(rhs) == 0;
4489 }
4490 
4495 template <class CharT, class Traits>
4496 bool
4498  const basic_string<CharT, Traits> &rhs)
4499 {
4500  return lhs.compare(rhs) != 0;
4501 }
4502 
4507 template <class CharT, class Traits>
4508 bool
4509 operator<(const basic_string<CharT, Traits> &lhs,
4510  const basic_string<CharT, Traits> &rhs)
4511 {
4512  return lhs.compare(rhs) < 0;
4513 }
4514 
4519 template <class CharT, class Traits>
4520 bool
4521 operator<=(const basic_string<CharT, Traits> &lhs,
4522  const basic_string<CharT, Traits> &rhs)
4523 {
4524  return lhs.compare(rhs) <= 0;
4525 }
4526 
4531 template <class CharT, class Traits>
4532 bool
4534  const basic_string<CharT, Traits> &rhs)
4535 {
4536  return lhs.compare(rhs) > 0;
4537 }
4538 
4543 template <class CharT, class Traits>
4544 bool
4546  const basic_string<CharT, Traits> &rhs)
4547 {
4548  return lhs.compare(rhs) >= 0;
4549 }
4550 
4555 template <class CharT, class Traits>
4556 bool
4557 operator==(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4558 {
4559  return rhs.compare(lhs) == 0;
4560 }
4561 
4566 template <class CharT, class Traits>
4567 bool
4568 operator!=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4569 {
4570  return rhs.compare(lhs) != 0;
4571 }
4572 
4577 template <class CharT, class Traits>
4578 bool
4579 operator<(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4580 {
4581  return rhs.compare(lhs) > 0;
4582 }
4583 
4588 template <class CharT, class Traits>
4589 bool
4590 operator<=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4591 {
4592  return rhs.compare(lhs) >= 0;
4593 }
4594 
4599 template <class CharT, class Traits>
4600 bool
4601 operator>(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4602 {
4603  return rhs.compare(lhs) < 0;
4604 }
4605 
4610 template <class CharT, class Traits>
4611 bool
4612 operator>=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4613 {
4614  return rhs.compare(lhs) <= 0;
4615 }
4616 
4621 template <class CharT, class Traits>
4622 bool
4623 operator==(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4624 {
4625  return lhs.compare(rhs) == 0;
4626 }
4627 
4632 template <class CharT, class Traits>
4633 bool
4634 operator!=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4635 {
4636  return lhs.compare(rhs) != 0;
4637 }
4638 
4643 template <class CharT, class Traits>
4644 bool
4645 operator<(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4646 {
4647  return lhs.compare(rhs) < 0;
4648 }
4649 
4654 template <class CharT, class Traits>
4655 bool
4656 operator<=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4657 {
4658  return lhs.compare(rhs) <= 0;
4659 }
4660 
4665 template <class CharT, class Traits>
4666 bool
4667 operator>(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4668 {
4669  return lhs.compare(rhs) > 0;
4670 }
4671 
4676 template <class CharT, class Traits>
4677 bool
4678 operator>=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4679 {
4680  return lhs.compare(rhs) >= 0;
4681 }
4682 
4687 template <class CharT, class Traits>
4688 bool
4689 operator==(const std::basic_string<CharT, Traits> &lhs,
4690  const basic_string<CharT, Traits> &rhs)
4691 {
4692  return rhs.compare(lhs) == 0;
4693 }
4694 
4699 template <class CharT, class Traits>
4700 bool
4701 operator!=(const std::basic_string<CharT, Traits> &lhs,
4702  const basic_string<CharT, Traits> &rhs)
4703 {
4704  return rhs.compare(lhs) != 0;
4705 }
4706 
4711 template <class CharT, class Traits>
4712 bool
4713 operator<(const std::basic_string<CharT, Traits> &lhs,
4714  const basic_string<CharT, Traits> &rhs)
4715 {
4716  return rhs.compare(lhs) > 0;
4717 }
4718 
4723 template <class CharT, class Traits>
4724 bool
4725 operator<=(const std::basic_string<CharT, Traits> &lhs,
4726  const basic_string<CharT, Traits> &rhs)
4727 {
4728  return rhs.compare(lhs) >= 0;
4729 }
4730 
4735 template <class CharT, class Traits>
4736 bool
4737 operator>(const std::basic_string<CharT, Traits> &lhs,
4738  const basic_string<CharT, Traits> &rhs)
4739 {
4740  return rhs.compare(lhs) < 0;
4741 }
4742 
4747 template <class CharT, class Traits>
4748 bool
4749 operator>=(const std::basic_string<CharT, Traits> &lhs,
4750  const basic_string<CharT, Traits> &rhs)
4751 {
4752  return rhs.compare(lhs) <= 0;
4753 }
4754 
4759 template <class CharT, class Traits>
4760 bool
4762  const std::basic_string<CharT, Traits> &rhs)
4763 {
4764  return lhs.compare(rhs) == 0;
4765 }
4766 
4771 template <class CharT, class Traits>
4772 bool
4774  const std::basic_string<CharT, Traits> &rhs)
4775 {
4776  return lhs.compare(rhs) != 0;
4777 }
4778 
4783 template <class CharT, class Traits>
4784 bool
4785 operator<(const basic_string<CharT, Traits> &lhs,
4786  const std::basic_string<CharT, Traits> &rhs)
4787 {
4788  return lhs.compare(rhs) < 0;
4789 }
4790 
4795 template <class CharT, class Traits>
4796 bool
4797 operator<=(const basic_string<CharT, Traits> &lhs,
4798  const std::basic_string<CharT, Traits> &rhs)
4799 {
4800  return lhs.compare(rhs) <= 0;
4801 }
4802 
4807 template <class CharT, class Traits>
4808 bool
4810  const std::basic_string<CharT, Traits> &rhs)
4811 {
4812  return lhs.compare(rhs) > 0;
4813 }
4814 
4819 template <class CharT, class Traits>
4820 bool
4822  const std::basic_string<CharT, Traits> &rhs)
4823 {
4824  return lhs.compare(rhs) >= 0;
4825 }
4826 
4831 template <class CharT, class Traits>
4832 void
4834 {
4835  return lhs.swap(rhs);
4836 }
4837 
4838 } /* namespace obj */
4839 
4840 } /* namespace pmem */
4841 
4842 #endif /* LIBPMEMOBJ_CPP_BASIC_STRING_HPP */
Array container with std::array compatible interface.
Our partial std::string_view implementation.
Definition: string_view.hpp:48
constexpr size_type size() const noexcept
Returns count of characters stored in this pmem::obj::string_view data.
Definition: string_view.hpp:397
size_type find(basic_string_view str, size_type pos=0) const noexcept
Finds the first substring equal to str.
Definition: string_view.hpp:521
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:775
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:950
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:860
size_type rfind(basic_string_view str, size_type pos=npos) const noexcept
Finds the last substring equal to str.
Definition: string_view.hpp:609
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:694
constexpr const CharT * data() const noexcept
Returns pointer to data stored in this pmem::obj::string_view.
Definition: string_view.hpp:359
Persistent string container with std::basic_string compatible interface.
Definition: basic_string.hpp:48
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:1135
void resize(size_type count, CharT ch)
Resize the string to count characters transactionally.
Definition: basic_string.hpp:3744
bool operator>(const basic_string< CharT, Traits > &lhs, const std::basic_string< CharT, Traits > &rhs)
Non-member greater than operator.
Definition: basic_string.hpp:4809
void clear()
Remove all characters from the string transactionally.
Definition: basic_string.hpp:3870
bool operator==(const std::basic_string< CharT, Traits > &lhs, const basic_string< CharT, Traits > &rhs)
Non-member equal operator.
Definition: basic_string.hpp:4689
reverse_iterator rbegin()
Return a reverse iterator to the beginning.
Definition: basic_string.hpp:1226
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:3269
slice< pointer > range(size_type p, size_type count)
Returns slice and snapshots requested range.
Definition: basic_string.hpp:1408
const_iterator cbegin() const noexcept
Return const iterator to the beginning.
Definition: basic_string.hpp:1174
iterator begin()
Return an iterator to the beginning.
Definition: basic_string.hpp:1149
bool empty() const noexcept
Definition: basic_string.hpp:3911
basic_string & erase(size_type index=0, size_type count=npos)
Remove characters from string starting at index transactionally.
Definition: basic_string.hpp:1623
const_reverse_iterator crbegin() const noexcept
Return a const reverse iterator to the beginning.
Definition: basic_string.hpp:1252
void shrink_to_fit()
Remove unused capacity transactionally.
Definition: basic_string.hpp:3845
bool operator>=(const basic_string< CharT, Traits > &lhs, const CharT *rhs)
Non-member greater or equal operator.
Definition: basic_string.hpp:4678
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:1311
basic_string & append(size_type count, CharT ch)
Append count copies of character ch to the string transactionally.
Definition: basic_string.hpp:1754
void push_back(CharT ch)
Append character ch at the end of the string transactionally.
Definition: basic_string.hpp:2027
void swap(basic_string &other)
Swap the content of persistent strings.
Definition: basic_string.hpp:4178
bool operator>=(const CharT *lhs, const basic_string< CharT, Traits > &rhs)
Non-member greater or equal operator.
Definition: basic_string.hpp:4612
void pop_back()
Remove the last character from the string transactionally.
Definition: basic_string.hpp:1728
iterator end()
Return an iterator to past the end.
Definition: basic_string.hpp:1187
bool operator!=(const basic_string< CharT, Traits > &lhs, const std::basic_string< CharT, Traits > &rhs)
Non-member not equal operator.
Definition: basic_string.hpp:4773
size_type length() const noexcept
Definition: basic_string.hpp:3697
bool operator!=(const basic_string< CharT, Traits > &lhs, const CharT *rhs)
Non-member not equal operator.
Definition: basic_string.hpp:4634
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:2978
CharT * data()
Definition: basic_string.hpp:1597
size_type size() const noexcept
Definition: basic_string.hpp:1579
void swap(basic_string< CharT, Traits > &lhs, basic_string< CharT, Traits > &rhs)
Swap the content of persistent strings.
Definition: basic_string.hpp:4833
basic_string & insert(size_type index, size_type count, CharT ch)
Insert count copies of ch character at index transactionally.
Definition: basic_string.hpp:2156
int compare(const basic_string &other) const
Compares this string to other.
Definition: basic_string.hpp:3495
reference operator[](size_type n)
Access element at specific index and snapshot it if there is an active transaction.
Definition: basic_string.hpp:1374
void reserve(size_type new_cap=0)
Increase the capacity of the string to new_cap transactionally.
Definition: basic_string.hpp:3813
reverse_iterator rend()
Return a reverse iterator to the end.
Definition: basic_string.hpp:1265
bool operator==(const CharT *lhs, const basic_string< CharT, Traits > &rhs)
Non-member equal operator.
Definition: basic_string.hpp:4557
bool operator==(const basic_string< CharT, Traits > &lhs, const CharT *rhs)
Non-member equal operator.
Definition: basic_string.hpp:4623
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:2535
basic_string & assign(size_type count, CharT ch)
Replace the contents with count copies of character ch transactionally.
Definition: basic_string.hpp:907
void free_data()
Clears the content of a string and frees all allocated persistent memory for data transactionally.
Definition: basic_string.hpp:3889
bool operator!=(const std::basic_string< CharT, Traits > &lhs, const basic_string< CharT, Traits > &rhs)
Non-member not equal operator.
Definition: basic_string.hpp:4701
const_iterator cend() const noexcept
Return const iterator to past the end.
Definition: basic_string.hpp:1213
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:3345
bool operator>=(const std::basic_string< CharT, Traits > &lhs, const basic_string< CharT, Traits > &rhs)
Non-member greater or equal operator.
Definition: basic_string.hpp:4749
basic_string()
Default constructor.
Definition: basic_string.hpp:434
size_type rfind(const basic_string &str, size_type pos=npos) const noexcept
Finds the last substring equal to str.
Definition: basic_string.hpp:3116
bool operator>(const basic_string< CharT, Traits > &lhs, const basic_string< CharT, Traits > &rhs)
Non-member greater than operator.
Definition: basic_string.hpp:4533
const CharT & cfront() const
Access first element.
Definition: basic_string.hpp:1526
const CharT * cdata() const noexcept
Definition: basic_string.hpp:3667
~basic_string()
Destructor.
Definition: basic_string.hpp:773
basic_string & operator+=(const basic_string &str)
Append string str transactionally.
Definition: basic_string.hpp:2052
bool operator>(const std::basic_string< CharT, Traits > &lhs, const basic_string< CharT, Traits > &rhs)
Non-member greater than operator.
Definition: basic_string.hpp:4737
bool operator>=(const basic_string< CharT, Traits > &lhs, const basic_string< CharT, Traits > &rhs)
Non-member greater or equal operator.
Definition: basic_string.hpp:4545
const CharT & cback() const
Access last element.
Definition: basic_string.hpp:1569
size_type max_size() const noexcept
Definition: basic_string.hpp:3707
bool operator>=(const basic_string< CharT, Traits > &lhs, const std::basic_string< CharT, Traits > &rhs)
Non-member greater or equal operator.
Definition: basic_string.hpp:4821
bool operator!=(const CharT *lhs, const basic_string< CharT, Traits > &rhs)
Non-member not equal operator.
Definition: basic_string.hpp:4568
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:3194
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:3420
CharT & back()
Access last element and snapshot it if there is an active transaction.
Definition: basic_string.hpp:1542
const_reverse_iterator crend() const noexcept
Return a const reverse iterator to the end.
Definition: basic_string.hpp:1291
CharT & front()
Access first element and snapshot it if there is an active transaction.
Definition: basic_string.hpp:1499
size_type find(const basic_string &str, size_type pos=0) const noexcept
Finds the first substring equal str.
Definition: basic_string.hpp:3046
const_reference const_at(size_type n) const
Access element at specific index with bounds checking.
Definition: basic_string.hpp:1351
const CharT * c_str() const noexcept
Definition: basic_string.hpp:3687
bool operator==(const basic_string< CharT, Traits > &lhs, const std::basic_string< CharT, Traits > &rhs)
Non-member equal operator.
Definition: basic_string.hpp:4761
bool operator>(const basic_string< CharT, Traits > &lhs, const CharT *rhs)
Non-member greater than operator.
Definition: basic_string.hpp:4667
bool operator>(const CharT *lhs, const basic_string< CharT, Traits > &rhs)
Non-member greater than operator.
Definition: basic_string.hpp:4601
size_type capacity() const noexcept
Definition: basic_string.hpp:3718
bool operator!=(const basic_string< CharT, Traits > &lhs, const basic_string< CharT, Traits > &rhs)
Non-member not equal operator.
Definition: basic_string.hpp:4497
slice< const_iterator > crange(size_type start, size_type n) const
Returns const slice.
Definition: basic_string.hpp:1479
bool operator==(const basic_string< CharT, Traits > &lhs, const basic_string< CharT, Traits > &rhs)
Non-member equal operator.
Definition: basic_string.hpp:4485
basic_string & operator=(const basic_string &other)
Copy assignment operator.
Definition: basic_string.hpp:793
static void run(obj::pool_base &pool, std::function< void()> tx, Locks &... locks)
Execute a closure-like transaction and lock locks.
Definition: transaction.hpp:810
Resides on pmem class.
Definition: p.hpp:36
Persistent_ptr base (non-template) class.
Definition: persistent_ptr_base.hpp:42
The non-template pool base class.
Definition: pool.hpp:51
Provides interface to access sequence of objects.
Definition: slice.hpp:61
Custom pool error class.
Definition: pexceptions.hpp:84
Custom transaction error class.
Definition: pexceptions.hpp:167
Commonly used functionality.
Iterators for contiguous persistent containers.
Common iterator traits.
Functions for lifetime management.
void conditional_add_to_tx(const T *that, std::size_t count=1, uint64_t flags=0)
Conditionally add 'count' objects to a transaction.
Definition: common.hpp:176
pool_base pool_by_vptr(const T *that)
Retrieve pool handle for the given pointer.
Definition: utils.hpp:32
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
C++ pmemobj transactions.
Libpmemobj C++ utils.
Vector container with std::vector compatible interface.