PMDK C++ bindings  1.13.0-git23.gf49772ac
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 
45 template <typename CharT, typename Traits = std::char_traits<CharT>>
46 class basic_string {
47 public:
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 */
70  basic_string();
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);
85  basic_string(basic_string &&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 */
102  ~basic_string();
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);
134  basic_string &assign(basic_string &&other);
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);
216  basic_string &operator+=(const basic_string &str);
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 
331 private:
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 
431 template <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 
455 template <typename CharT, typename Traits>
457 {
458  check_pmem_tx();
459  sso._size = 0;
460 
461  allocate(count);
462  initialize(count, ch);
463 }
464 
482 template <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 
520 template <typename CharT, typename Traits>
521 basic_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 
542 template <typename CharT, typename Traits>
543 basic_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 
565 template <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 
593 template <typename CharT, typename Traits>
594 template <typename InputIt, typename Enable>
595 basic_string<CharT, Traits>::basic_string(InputIt first, InputIt last)
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 
621 template <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 
646 template <typename CharT, typename Traits>
647 basic_string<CharT, Traits>::basic_string(const std::basic_string<CharT> &other)
648  : basic_string(other.cbegin(), other.cend())
649 {
650 }
651 
666 template <typename CharT, typename Traits>
668 {
669  check_pmem_tx();
670  sso._size = 0;
671 
672  move_data(std::move(other));
673 }
674 
689 template <typename CharT, typename Traits>
690 basic_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 
714 template <typename CharT, typename Traits>
715 template <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 
744 template <typename CharT, typename Traits>
745 template <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 
770 template <typename CharT, typename Traits>
772 {
773  try {
774  free_data();
775  } catch (...) {
776  std::terminate();
777  }
778 }
779 
789 template <typename CharT, typename Traits>
792 {
793  return assign(other);
794 }
795 
806 template <typename CharT, typename Traits>
808 basic_string<CharT, Traits>::operator=(const std::basic_string<CharT> &other)
809 {
810  return assign(other);
811 }
812 
822 template <typename CharT, typename Traits>
825 {
826  return assign(std::move(other));
827 }
828 
837 template <typename CharT, typename Traits>
840 {
841  return assign(s);
842 }
843 
852 template <typename CharT, typename Traits>
855 {
856  return assign(1, ch);
857 }
858 
868 template <typename CharT, typename Traits>
870 basic_string<CharT, Traits>::operator=(std::initializer_list<CharT> ilist)
871 {
872  return assign(ilist);
873 }
874 
884 template <typename CharT, typename Traits>
885 template <class T, typename Enable>
888 {
890  return assign(sv.data(), sv.size());
891 }
892 
903 template <typename CharT, typename Traits>
905 basic_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 
923 template <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 
948 template <typename CharT, typename Traits>
950 basic_string<CharT, Traits>::assign(const std::basic_string<CharT> &other)
951 {
952  return assign(other.cbegin(), other.cend());
953 }
954 
967 template <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 
1003 template <typename CharT, typename Traits>
1005 basic_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 
1027 template <typename CharT, typename Traits>
1029 basic_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 
1046 template <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 
1070 template <typename CharT, typename Traits>
1071 template <typename InputIt, typename Enable>
1073 basic_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 
1091 template <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 
1117 template <typename CharT, typename Traits>
1119 basic_string<CharT, Traits>::assign(std::initializer_list<CharT> ilist)
1120 {
1121  return assign(ilist.begin(), ilist.end());
1122 }
1123 
1131 template <typename CharT, typename Traits>
1132 void
1134 {
1135  if (!is_sso_used()) {
1136  non_sso._data.for_each_ptr(func);
1137  }
1138 }
1139 
1145 template <typename CharT, typename Traits>
1148 {
1149  return is_sso_used() ? iterator(&*sso_data().begin())
1150  : iterator(&*non_sso_data().begin());
1151 }
1152 
1158 template <typename CharT, typename Traits>
1159 typename basic_string<CharT, Traits>::const_iterator
1161 {
1162  return cbegin();
1163 }
1164 
1170 template <typename CharT, typename Traits>
1171 typename 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 
1183 template <typename CharT, typename Traits>
1186 {
1187  return begin() + static_cast<difference_type>(size());
1188 }
1189 
1196 template <typename CharT, typename Traits>
1197 typename basic_string<CharT, Traits>::const_iterator
1199 {
1200  return cbegin() + static_cast<difference_type>(size());
1201 }
1202 
1209 template <typename CharT, typename Traits>
1210 typename basic_string<CharT, Traits>::const_iterator
1212 {
1213  return cbegin() + static_cast<difference_type>(size());
1214 }
1215 
1222 template <typename CharT, typename Traits>
1223 typename basic_string<CharT, Traits>::reverse_iterator
1225 {
1226  return reverse_iterator(end());
1227 }
1228 
1235 template <typename CharT, typename Traits>
1236 typename basic_string<CharT, Traits>::const_reverse_iterator
1238 {
1239  return crbegin();
1240 }
1241 
1248 template <typename CharT, typename Traits>
1249 typename basic_string<CharT, Traits>::const_reverse_iterator
1251 {
1252  return const_reverse_iterator(cend());
1253 }
1254 
1261 template <typename CharT, typename Traits>
1262 typename basic_string<CharT, Traits>::reverse_iterator
1264 {
1265  return reverse_iterator(begin());
1266 }
1267 
1274 template <typename CharT, typename Traits>
1275 typename basic_string<CharT, Traits>::const_reverse_iterator
1277 {
1278  return crend();
1279 }
1280 
1287 template <typename CharT, typename Traits>
1288 typename basic_string<CharT, Traits>::const_reverse_iterator
1290 {
1291  return const_reverse_iterator(cbegin());
1292 }
1293 
1307 template <typename CharT, typename Traits>
1308 typename 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 
1327 template <typename CharT, typename Traits>
1328 typename basic_string<CharT, Traits>::const_reference
1330 {
1331  return const_at(n);
1332 }
1333 
1347 template <typename CharT, typename Traits>
1348 typename 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 
1370 template <typename CharT, typename Traits>
1371 typename basic_string<CharT, Traits>::reference
1373 {
1374  return is_sso_used() ? sso_data()[n] : non_sso_data()[n];
1375 }
1376 
1384 template <typename CharT, typename Traits>
1385 typename basic_string<CharT, Traits>::const_reference
1387 {
1388  return is_sso_used() ? sso_data()[n] : non_sso_data()[n];
1389 }
1390 
1404 template <typename CharT, typename Traits>
1406 basic_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 
1431 template <typename CharT, typename Traits>
1433 basic_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 
1457 template <typename CharT, typename Traits>
1459 basic_string<CharT, Traits>::range(size_type start, size_type n) const
1460 {
1461  return crange(start, n);
1462 }
1463 
1475 template <typename CharT, typename Traits>
1477 basic_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 
1495 template <typename CharT, typename Traits>
1496 CharT &
1498 {
1499  return (*this)[0];
1500 }
1501 
1507 template <typename CharT, typename Traits>
1508 const CharT &
1510 {
1511  return cfront();
1512 }
1513 
1522 template <typename CharT, typename Traits>
1523 const CharT &
1525 {
1526  return static_cast<const basic_string &>(*this)[0];
1527 }
1528 
1538 template <typename CharT, typename Traits>
1539 CharT &
1541 {
1542  return (*this)[size() - 1];
1543 }
1544 
1550 template <typename CharT, typename Traits>
1551 const CharT &
1553 {
1554  return cback();
1555 }
1556 
1565 template <typename CharT, typename Traits>
1566 const CharT &
1568 {
1569  return static_cast<const basic_string &>(*this)[size() - 1];
1570 }
1571 
1575 template <typename CharT, typename Traits>
1576 typename 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 
1593 template <typename CharT, typename Traits>
1594 CharT *
1596 {
1597  return is_sso_used() ? sso_data().range(0, get_sso_size() + 1).begin()
1598  : non_sso_data().data();
1599 }
1600 
1619 template <typename CharT, typename Traits>
1621 basic_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 
1676 template <typename CharT, typename Traits>
1679 {
1680  return erase(pos, pos + 1);
1681 }
1682 
1701 template <typename CharT, typename Traits>
1703 basic_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 
1724 template <typename CharT, typename Traits>
1725 void
1727 {
1728  erase(size() - 1, 1);
1729 }
1730 
1750 template <typename CharT, typename Traits>
1752 basic_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 
1809 template <typename CharT, typename Traits>
1812 {
1813  return append(str.data(), str.size());
1814 }
1815 
1841 template <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 
1877 template <typename CharT, typename Traits>
1879 basic_string<CharT, Traits>::append(const CharT *s, size_type count)
1880 {
1881  return append(s, s + count);
1882 }
1883 
1903 template <typename CharT, typename Traits>
1906 {
1907  return append(s, traits_type::length(s));
1908 }
1909 
1931 template <typename CharT, typename Traits>
1932 template <typename InputIt, typename Enable>
1934 basic_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 
2000 template <typename CharT, typename Traits>
2002 basic_string<CharT, Traits>::append(std::initializer_list<CharT> ilist)
2003 {
2004  return append(ilist.begin(), ilist.end());
2005 }
2006 
2023 template <typename CharT, typename Traits>
2024 void
2026 {
2027  append(static_cast<size_type>(1), ch);
2028 }
2029 
2048 template <typename CharT, typename Traits>
2051 {
2052  return append(str);
2053 }
2054 
2074 template <typename CharT, typename Traits>
2077 {
2078  return append(s);
2079 }
2080 
2097 template <typename CharT, typename Traits>
2100 {
2101  push_back(ch);
2102 
2103  return *this;
2104 }
2105 
2124 template <typename CharT, typename Traits>
2126 basic_string<CharT, Traits>::operator+=(std::initializer_list<CharT> ilist)
2127 {
2128  return append(ilist);
2129 }
2130 
2152 template <typename CharT, typename Traits>
2154 basic_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 
2187 template <typename CharT, typename Traits>
2189 basic_string<CharT, Traits>::insert(size_type index, const CharT *s)
2190 {
2191  return insert(index, s, traits_type::length(s));
2192 }
2193 
2215 template <typename CharT, typename Traits>
2217 basic_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 
2250 template <typename CharT, typename Traits>
2253 {
2254  return insert(index, str.data(), str.size());
2255 }
2256 
2279 template <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 
2316 template <typename CharT, typename Traits>
2318 basic_string<CharT, Traits>::insert(const_iterator pos, CharT ch)
2319 {
2320  return insert(pos, 1, ch);
2321 }
2322 
2347 template <typename CharT, typename Traits>
2349 basic_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 
2415 template <typename CharT, typename Traits>
2416 template <typename InputIt, typename Enable>
2418 basic_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 
2501 template <typename CharT, typename Traits>
2504  std::initializer_list<CharT> ilist)
2505 {
2506  return insert(pos, ilist.begin(), ilist.end());
2507 }
2508 
2531 template <typename CharT, typename Traits>
2533 basic_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 
2559 template <typename CharT, typename Traits>
2561 basic_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 
2593 template <typename CharT, typename Traits>
2595 basic_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 
2634 template <typename CharT, typename Traits>
2635 template <typename InputIt, typename Enable>
2637 basic_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 
2717 template <typename CharT, typename Traits>
2719 basic_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 
2748 template <typename CharT, typename Traits>
2750 basic_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 
2785 template <typename CharT, typename Traits>
2787 basic_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 
2816 template <typename CharT, typename Traits>
2818 basic_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 
2852 template <typename CharT, typename Traits>
2854 basic_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 
2923 template <typename CharT, typename Traits>
2925 basic_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 
2953 template <typename CharT, typename Traits>
2955 basic_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 
2974 template <typename CharT, typename Traits>
2975 typename basic_string<CharT, Traits>::size_type
2976 basic_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 
3008 template <typename CharT, typename Traits>
3009 int
3010 basic_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 
3042 template <typename CharT, typename Traits>
3043 typename basic_string<CharT, Traits>::size_type
3044 basic_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 
3061 template <typename CharT, typename Traits>
3062 typename basic_string<CharT, Traits>::size_type
3063 basic_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 
3079 template <typename CharT, typename Traits>
3080 typename basic_string<CharT, Traits>::size_type
3081 basic_string<CharT, Traits>::find(const CharT *s, size_type pos) const
3082 {
3083  return find(s, pos, traits_type::length(s));
3084 }
3085 
3095 template <typename CharT, typename Traits>
3096 typename basic_string<CharT, Traits>::size_type
3097 basic_string<CharT, Traits>::find(CharT ch, size_type pos) const noexcept
3098 {
3099  return find(&ch, pos, 1);
3100 }
3101 
3112 template <typename CharT, typename Traits>
3113 typename basic_string<CharT, Traits>::size_type
3114 basic_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 
3136 template <typename CharT, typename Traits>
3137 typename basic_string<CharT, Traits>::size_type
3138 basic_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 
3156 template <typename CharT, typename Traits>
3157 typename basic_string<CharT, Traits>::size_type
3158 basic_string<CharT, Traits>::rfind(const CharT *s, size_type pos) const
3159 {
3160  return rfind(s, pos, traits_type::length(s));
3161 }
3162 
3174 template <typename CharT, typename Traits>
3175 typename basic_string<CharT, Traits>::size_type
3176 basic_string<CharT, Traits>::rfind(CharT ch, size_type pos) const noexcept
3177 {
3178  return rfind(&ch, pos, 1);
3179 }
3180 
3190 template <typename CharT, typename Traits>
3191 typename 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 
3211 template <typename CharT, typename Traits>
3212 typename basic_string<CharT, Traits>::size_type
3213 basic_string<CharT, Traits>::find_first_of(const CharT *s, size_type pos,
3214  size_type count) const
3215 {
3216  return operator basic_string_view<CharT, Traits>().find_first_of(s, pos,
3217  count);
3218 }
3219 
3232 template <typename CharT, typename Traits>
3233 typename basic_string<CharT, Traits>::size_type
3234 basic_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 
3248 template <typename CharT, typename Traits>
3249 typename basic_string<CharT, Traits>::size_type
3250 basic_string<CharT, Traits>::find_first_of(CharT ch, size_type pos) const
3251  noexcept
3252 {
3253  return find(ch, pos);
3254 }
3255 
3265 template <typename CharT, typename Traits>
3266 typename 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 
3286 template <typename CharT, typename Traits>
3287 typename basic_string<CharT, Traits>::size_type
3289  size_type count) const
3290 {
3292  s, pos, count);
3293 }
3294 
3307 template <typename CharT, typename Traits>
3308 typename 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 
3324 template <typename CharT, typename Traits>
3325 typename basic_string<CharT, Traits>::size_type
3327  noexcept
3328 {
3329  return find_first_not_of(&ch, pos, 1);
3330 }
3331 
3341 template <typename CharT, typename Traits>
3342 typename 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 
3362 template <typename CharT, typename Traits>
3363 typename basic_string<CharT, Traits>::size_type
3364 basic_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 
3383 template <typename CharT, typename Traits>
3384 typename basic_string<CharT, Traits>::size_type
3385 basic_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 
3399 template <typename CharT, typename Traits>
3400 typename basic_string<CharT, Traits>::size_type
3401 basic_string<CharT, Traits>::find_last_of(CharT ch, size_type pos) const
3402  noexcept
3403 {
3404  return rfind(ch, pos);
3405 }
3406 
3416 template <typename CharT, typename Traits>
3417 typename 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 
3437 template <typename CharT, typename Traits>
3438 typename basic_string<CharT, Traits>::size_type
3440  size_type count) const
3441 {
3443  s, pos, count);
3444 }
3445 
3458 template <typename CharT, typename Traits>
3459 typename 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 
3475 template <typename CharT, typename Traits>
3476 typename basic_string<CharT, Traits>::size_type
3478  noexcept
3479 {
3480  return find_last_not_of(&ch, pos, 1);
3481 }
3482 
3491 template <typename CharT, typename Traits>
3492 int
3494 {
3495  return compare(0, size(), other.cdata(), other.size());
3496 }
3497 
3506 template <typename CharT, typename Traits>
3507 int
3509  const std::basic_string<CharT> &other) const
3510 {
3511  return compare(0, size(), other.data(), other.size());
3512 }
3513 
3527 template <typename CharT, typename Traits>
3528 int
3529 basic_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 
3549 template <typename CharT, typename Traits>
3550 int
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 
3576 template <typename CharT, typename Traits>
3577 int
3578 basic_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 
3609 template <typename CharT, typename Traits>
3610 int
3611 basic_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 
3632 template <typename CharT, typename Traits>
3633 int
3635 {
3636  return compare(0, size(), s, traits_type::length(s));
3637 }
3638 
3652 template <typename CharT, typename Traits>
3653 int
3654 basic_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 
3663 template <typename CharT, typename Traits>
3664 const CharT *
3666 {
3667  return is_sso_used() ? sso_data().cdata() : non_sso_data().cdata();
3668 }
3669 
3673 template <typename CharT, typename Traits>
3674 const CharT *
3676 {
3677  return cdata();
3678 }
3679 
3683 template <typename CharT, typename Traits>
3684 const CharT *
3686 {
3687  return cdata();
3688 }
3689 
3693 template <typename CharT, typename Traits>
3694 typename basic_string<CharT, Traits>::size_type
3696 {
3697  return size();
3698 }
3699 
3703 template <typename CharT, typename Traits>
3704 typename basic_string<CharT, Traits>::size_type
3706 {
3707  return PMEMOBJ_MAX_ALLOC_SIZE / sizeof(CharT) - 1;
3708 }
3709 
3714 template <typename CharT, typename Traits>
3715 typename basic_string<CharT, Traits>::size_type
3717 {
3718  return is_sso_used() ? sso_capacity : non_sso_data().capacity() - 1;
3719 }
3720 
3740 template <typename CharT, typename Traits>
3741 void
3742 basic_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 
3782 template <typename CharT, typename Traits>
3783 void
3785 {
3786  resize(count, CharT());
3787 }
3788 
3809 template <typename CharT, typename Traits>
3810 void
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 
3841 template <typename CharT, typename Traits>
3842 void
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 
3866 template <typename CharT, typename Traits>
3867 void
3869 {
3870  erase(begin(), end());
3871 }
3872 
3885 template <typename CharT, typename Traits>
3886 void
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 
3907 template <typename CharT, typename Traits>
3908 bool
3910 {
3911  return size() == 0;
3912 }
3913 
3914 template <typename CharT, typename Traits>
3915 bool
3917 {
3918  return (sso._size & _sso_mask) != 0;
3919 }
3920 
3921 template <typename CharT, typename Traits>
3922 void
3923 basic_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 
3942 template <typename CharT, typename Traits>
3943 template <typename InputIt, typename Enable>
3944 typename basic_string<CharT, Traits>::size_type
3945 basic_string<CharT, Traits>::get_size(InputIt first, InputIt last) const
3946 {
3947  return static_cast<size_type>(std::distance(first, last));
3948 }
3949 
3956 template <typename CharT, typename Traits>
3957 typename basic_string<CharT, Traits>::size_type
3958 basic_string<CharT, Traits>::get_size(size_type count, value_type ch) const
3959 {
3960  return count;
3961 }
3962 
3969 template <typename CharT, typename Traits>
3970 typename basic_string<CharT, Traits>::size_type
3972 {
3973  return other.size();
3974 }
3975 
3982 template <typename CharT, typename Traits>
3983 template <typename... Args>
3984 typename 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 
4011 template <typename CharT, typename Traits>
4012 template <typename... Args>
4013 typename 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 
4034 template <typename CharT, typename Traits>
4035 void
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 
4061 template <typename CharT, typename Traits>
4062 template <typename InputIt, typename Enable>
4063 typename 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 
4084 template <typename CharT, typename Traits>
4085 typename basic_string<CharT, Traits>::pointer
4086 basic_string<CharT, Traits>::assign_sso_data(size_type count, value_type ch)
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 
4105 template <typename CharT, typename Traits>
4106 template <typename InputIt, typename Enable>
4107 typename 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 
4125 template <typename CharT, typename Traits>
4126 typename basic_string<CharT, Traits>::pointer
4127 basic_string<CharT, Traits>::assign_large_data(size_type count, value_type ch)
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 
4142 template <typename CharT, typename Traits>
4143 typename 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 
4174 template <typename CharT, typename Traits>
4175 void
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 
4206 template <typename CharT, typename Traits>
4208 {
4209  return basic_string_view<CharT, Traits>(cdata(), length());
4210 }
4211 
4215 template <typename CharT, typename Traits>
4216 pool_base
4218 {
4219  return pmem::obj::pool_by_vptr(this);
4220 }
4221 
4225 template <typename CharT, typename Traits>
4226 void
4228 {
4229  if (pmemobj_pool_by_ptr(this) == nullptr)
4230  throw pmem::pool_error("Object is not on pmem.");
4231 }
4232 
4236 template <typename CharT, typename Traits>
4237 void
4239 {
4240  if (pmemobj_tx_stage() != TX_STAGE_WORK)
4242  "Call made out of transaction scope.");
4243 }
4244 
4249 template <typename CharT, typename Traits>
4250 void
4252 {
4253  check_pmem();
4254  check_tx_stage_work();
4255 }
4256 
4260 template <typename CharT, typename Traits>
4261 void
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 
4285 template <typename CharT, typename Traits>
4286 typename basic_string<CharT, Traits>::size_type
4288 {
4289  return sso._size & ~_sso_mask;
4290 }
4291 
4295 template <typename CharT, typename Traits>
4296 void
4298 {
4299  /* temporary size_type must be created to avoid undefined reference
4300  * linker error */
4301  sso._size |= (size_type)(_sso_mask);
4302 }
4303 
4307 template <typename CharT, typename Traits>
4308 void
4310 {
4311  sso._size &= ~_sso_mask;
4312 }
4313 
4317 template <typename CharT, typename Traits>
4318 void
4320 {
4321  sso._size = new_size | _sso_mask;
4322 }
4323 
4335 template <typename CharT, typename Traits>
4336 void
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 
4369 template <typename CharT, typename Traits>
4370 void
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 
4395 template <typename CharT, typename Traits>
4398 {
4399  assert(!is_sso_used());
4400  return non_sso._data;
4401 }
4402 
4403 template <typename CharT, typename Traits>
4404 typename basic_string<CharT, Traits>::sso_type &
4405 basic_string<CharT, Traits>::sso_data()
4406 {
4407  assert(is_sso_used());
4408  return sso._data;
4409 }
4410 
4411 template <typename CharT, typename Traits>
4412 const typename basic_string<CharT, Traits>::non_sso_type &
4413 basic_string<CharT, Traits>::non_sso_data() const
4414 {
4415  assert(!is_sso_used());
4416  return non_sso._data;
4417 }
4418 
4419 template <typename CharT, typename Traits>
4420 const typename basic_string<CharT, Traits>::sso_type &
4421 basic_string<CharT, Traits>::sso_data() const
4422 {
4423  assert(is_sso_used());
4424  return sso._data;
4425 }
4426 
4431 template <typename CharT, typename Traits>
4432 template <typename T, typename Enable>
4433 basic_string<CharT, Traits> &
4435 {
4436  return erase(static_cast<size_type>(param));
4437 }
4438 
4443 template <typename CharT, typename Traits>
4444 template <typename T, typename Enable>
4447 {
4448  return erase(static_cast<const_iterator>(param));
4449 }
4450 
4456 template <typename CharT, typename Traits>
4457 template <typename T, typename Enable>
4459 basic_string<CharT, Traits>::insert(T param, size_type count, CharT ch)
4460 {
4461  return insert(static_cast<size_type>(param), count, ch);
4462 }
4463 
4469 template <typename CharT, typename Traits>
4470 template <typename T, typename Enable>
4472 basic_string<CharT, Traits>::insert(T param, size_type count, CharT ch)
4473 {
4474  return insert(static_cast<const_iterator>(param), count, ch);
4475 }
4476 
4480 template <class CharT, class Traits>
4481 bool
4483  const basic_string<CharT, Traits> &rhs)
4484 {
4485  return lhs.compare(rhs) == 0;
4486 }
4487 
4491 template <class CharT, class Traits>
4492 bool
4494  const basic_string<CharT, Traits> &rhs)
4495 {
4496  return lhs.compare(rhs) != 0;
4497 }
4498 
4502 template <class CharT, class Traits>
4503 bool
4505  const basic_string<CharT, Traits> &rhs)
4506 {
4507  return lhs.compare(rhs) < 0;
4508 }
4509 
4513 template <class CharT, class Traits>
4514 bool
4516  const basic_string<CharT, Traits> &rhs)
4517 {
4518  return lhs.compare(rhs) <= 0;
4519 }
4520 
4524 template <class CharT, class Traits>
4525 bool
4527  const basic_string<CharT, Traits> &rhs)
4528 {
4529  return lhs.compare(rhs) > 0;
4530 }
4531 
4535 template <class CharT, class Traits>
4536 bool
4538  const basic_string<CharT, Traits> &rhs)
4539 {
4540  return lhs.compare(rhs) >= 0;
4541 }
4542 
4546 template <class CharT, class Traits>
4547 bool
4548 operator==(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4549 {
4550  return rhs.compare(lhs) == 0;
4551 }
4552 
4556 template <class CharT, class Traits>
4557 bool
4558 operator!=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4559 {
4560  return rhs.compare(lhs) != 0;
4561 }
4562 
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 
4576 template <class CharT, class Traits>
4577 bool
4578 operator<=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4579 {
4580  return rhs.compare(lhs) >= 0;
4581 }
4582 
4586 template <class CharT, class Traits>
4587 bool
4588 operator>(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4589 {
4590  return rhs.compare(lhs) < 0;
4591 }
4592 
4596 template <class CharT, class Traits>
4597 bool
4598 operator>=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4599 {
4600  return rhs.compare(lhs) <= 0;
4601 }
4602 
4606 template <class CharT, class Traits>
4607 bool
4608 operator==(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4609 {
4610  return lhs.compare(rhs) == 0;
4611 }
4612 
4616 template <class CharT, class Traits>
4617 bool
4618 operator!=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4619 {
4620  return lhs.compare(rhs) != 0;
4621 }
4622 
4626 template <class CharT, class Traits>
4627 bool
4628 operator<(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4629 {
4630  return lhs.compare(rhs) < 0;
4631 }
4632 
4636 template <class CharT, class Traits>
4637 bool
4638 operator<=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4639 {
4640  return lhs.compare(rhs) <= 0;
4641 }
4642 
4646 template <class CharT, class Traits>
4647 bool
4648 operator>(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4649 {
4650  return lhs.compare(rhs) > 0;
4651 }
4652 
4656 template <class CharT, class Traits>
4657 bool
4658 operator>=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4659 {
4660  return lhs.compare(rhs) >= 0;
4661 }
4662 
4666 template <class CharT, class Traits>
4667 bool
4668 operator==(const std::basic_string<CharT, Traits> &lhs,
4669  const basic_string<CharT, Traits> &rhs)
4670 {
4671  return rhs.compare(lhs) == 0;
4672 }
4673 
4677 template <class CharT, class Traits>
4678 bool
4679 operator!=(const std::basic_string<CharT, Traits> &lhs,
4680  const basic_string<CharT, Traits> &rhs)
4681 {
4682  return rhs.compare(lhs) != 0;
4683 }
4684 
4688 template <class CharT, class Traits>
4689 bool
4690 operator<(const std::basic_string<CharT, Traits> &lhs,
4691  const basic_string<CharT, Traits> &rhs)
4692 {
4693  return rhs.compare(lhs) > 0;
4694 }
4695 
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 
4710 template <class CharT, class Traits>
4711 bool
4712 operator>(const std::basic_string<CharT, Traits> &lhs,
4713  const basic_string<CharT, Traits> &rhs)
4714 {
4715  return rhs.compare(lhs) < 0;
4716 }
4717 
4721 template <class CharT, class Traits>
4722 bool
4723 operator>=(const std::basic_string<CharT, Traits> &lhs,
4724  const basic_string<CharT, Traits> &rhs)
4725 {
4726  return rhs.compare(lhs) <= 0;
4727 }
4728 
4732 template <class CharT, class Traits>
4733 bool
4735  const std::basic_string<CharT, Traits> &rhs)
4736 {
4737  return lhs.compare(rhs) == 0;
4738 }
4739 
4743 template <class CharT, class Traits>
4744 bool
4746  const std::basic_string<CharT, Traits> &rhs)
4747 {
4748  return lhs.compare(rhs) != 0;
4749 }
4750 
4754 template <class CharT, class Traits>
4755 bool
4757  const std::basic_string<CharT, Traits> &rhs)
4758 {
4759  return lhs.compare(rhs) < 0;
4760 }
4761 
4765 template <class CharT, class Traits>
4766 bool
4768  const std::basic_string<CharT, Traits> &rhs)
4769 {
4770  return lhs.compare(rhs) <= 0;
4771 }
4772 
4776 template <class CharT, class Traits>
4777 bool
4779  const std::basic_string<CharT, Traits> &rhs)
4780 {
4781  return lhs.compare(rhs) > 0;
4782 }
4783 
4787 template <class CharT, class Traits>
4788 bool
4790  const std::basic_string<CharT, Traits> &rhs)
4791 {
4792  return lhs.compare(rhs) >= 0;
4793 }
4794 
4798 template <class CharT, class Traits>
4799 void
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 basic_string< CharT, Traits > &lhs, const std::basic_string< CharT, Traits > &rhs)
Non-member greater than operator.
Definition: basic_string.hpp:4778
bool operator==(const basic_string< CharT, Traits > &lhs, const std::basic_string< CharT, Traits > &rhs)
Non-member equal operator.
Definition: basic_string.hpp:4734
bool operator<(const basic_string< CharT, Traits > &lhs, const std::basic_string< CharT, Traits > &rhs)
Non-member less than operator.
Definition: basic_string.hpp:4756
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 >::const_reverse_iterator crend(const pmem::obj::array< T, N > &a)
Non-member crend.
Definition: array.hpp:819
pmem::obj::array< T, N >::const_reverse_iterator crbegin(const pmem::obj::array< T, N > &a)
Non-member crbegin.
Definition: array.hpp:809
bool operator<=(const basic_string< CharT, Traits > &lhs, const std::basic_string< CharT, Traits > &rhs)
Non-member less or equal operator.
Definition: basic_string.hpp:4767
pmem::obj::array< T, N >::iterator end(pmem::obj::array< T, N > &a)
Non-member end.
Definition: array.hpp:849
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:4789
pool_base pool_by_vptr(const T *that)
Retrieve pool handle for the given pointer.
Definition: utils.hpp:32
void swap(basic_string< CharT, Traits > &lhs, basic_string< CharT, Traits > &rhs)
Swap the content of persistent strings.
Definition: basic_string.hpp:4800
bool operator!=(const basic_string< CharT, Traits > &lhs, const std::basic_string< CharT, Traits > &rhs)
Non-member not equal operator.
Definition: basic_string.hpp:4745
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 begin(pmem::obj::array< T, N > &a)
Non-member begin.
Definition: array.hpp:829
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.