PMDK C++ bindings  1.11.1
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-2020, 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>;
61  using for_each_ptr_function =
62  std::function<void(persistent_ptr_base &)>;
63 
64  /* Number of characters which can be stored using sso */
65  static constexpr size_type sso_capacity = (32 - 8) / sizeof(CharT) - 1;
66 
67  /* Constructors */
68  basic_string();
69  basic_string(size_type count, CharT ch);
70  basic_string(const basic_string &other, size_type pos,
71  size_type count = npos);
72  basic_string(const std::basic_string<CharT> &other, size_type pos,
73  size_type count = npos);
74  basic_string(const CharT *s, size_type count);
75  basic_string(const CharT *s);
76  template <
77  typename InputIt,
78  typename Enable = typename std::enable_if<
80  basic_string(InputIt first, InputIt last);
81  basic_string(const basic_string &other);
82  basic_string(const std::basic_string<CharT> &other);
83  basic_string(basic_string &&other);
84  basic_string(std::initializer_list<CharT> ilist);
85  template <
86  class T,
87  typename Enable = typename std::enable_if<
88  std::is_convertible<const T &,
90  CharT, Traits>>::value &&
91  !std::is_convertible<const T &, const CharT *>::value>>
92  explicit basic_string(const T &t);
93  template <class T,
94  typename Enable = typename std::enable_if<std::is_convertible<
95  const T &,
97  basic_string(const T &t, size_type pos, size_type n);
98 
99  /* Destructor */
100  ~basic_string();
101 
102  /* Assignment operators */
103  basic_string &operator=(const basic_string &other);
104  basic_string &operator=(const std::basic_string<CharT> &other);
106  basic_string &operator=(const CharT *s);
107  basic_string &operator=(CharT ch);
108  basic_string &operator=(std::initializer_list<CharT> ilist);
109  template <
110  class T,
111  typename Enable = typename std::enable_if<
112  std::is_convertible<const T &,
114  CharT, Traits>>::value &&
115  !std::is_convertible<const T &, const CharT *>::value>>
116  basic_string &operator=(const T &t);
117 
118  /* Assignment methods */
119  basic_string &assign(size_type count, CharT ch);
120  basic_string &assign(const basic_string &other);
121  basic_string &assign(const std::basic_string<CharT> &other);
122  basic_string &assign(const basic_string &other, size_type pos,
123  size_type count = npos);
124  basic_string &assign(const std::basic_string<CharT> &other,
125  size_type pos, size_type count = npos);
126  basic_string &assign(const CharT *s, size_type count);
127  basic_string &assign(const CharT *s);
128  template <typename InputIt,
129  typename Enable = typename pmem::detail::is_input_iterator<
130  InputIt>::type>
131  basic_string &assign(InputIt first, InputIt last);
132  basic_string &assign(basic_string &&other);
133  basic_string &assign(std::initializer_list<CharT> ilist);
134 
135  /* Element access */
136  reference at(size_type n);
137  const_reference at(size_type n) const;
138  const_reference const_at(size_type n) const;
139  reference operator[](size_type n);
140  const_reference operator[](size_type n) const;
141  CharT &front();
142  const CharT &front() const;
143  const CharT &cfront() const;
144  CharT &back();
145  const CharT &back() const;
146  const CharT &cback() const;
147  CharT *data();
148  const CharT *data() const noexcept;
149  const CharT *cdata() const noexcept;
150  const CharT *c_str() const noexcept;
151  void for_each_ptr(for_each_ptr_function func);
152 
153  /* Iterators */
154  iterator begin();
155  const_iterator begin() const noexcept;
156  const_iterator cbegin() const noexcept;
157  iterator end();
158  const_iterator end() const noexcept;
159  const_iterator cend() const noexcept;
160  reverse_iterator rbegin();
161  const_reverse_iterator rbegin() const noexcept;
162  const_reverse_iterator crbegin() const noexcept;
163  reverse_iterator rend();
164  const_reverse_iterator rend() const noexcept;
165  const_reverse_iterator crend() const noexcept;
166 
167  /* Capacity */
168  bool empty() const noexcept;
169  size_type size() const noexcept;
170  size_type length() const noexcept;
171  size_type max_size() const noexcept;
172  size_type capacity() const noexcept;
173  void resize(size_type count, CharT ch);
174  void resize(size_type n);
175  void reserve(size_type new_cap = 0);
176  void shrink_to_fit();
177  void clear();
178  void free_data();
179 
180  /* Modifiers */
181  basic_string &erase(size_type index = 0, size_type count = npos);
182  iterator erase(const_iterator pos);
183  iterator erase(const_iterator first, const_iterator last);
184  /* We add following overloads to resolve erase(0) ambiguity */
185  template <typename T,
186  typename Enable = typename std::enable_if<
187  std::is_convertible<T, size_type>::value>::type>
188  basic_string &erase(T param);
189  template <typename T,
190  typename Enable = typename std::enable_if<
191  !std::is_convertible<T, size_type>::value>::type>
192  iterator erase(T param);
193  void pop_back();
194 
195  basic_string &append(size_type count, CharT ch);
196  basic_string &append(const basic_string &str);
197  basic_string &append(const basic_string &str, size_type pos,
198  size_type count = npos);
199  basic_string &append(const CharT *s, size_type count);
200  basic_string &append(const CharT *s);
201  template <typename InputIt,
202  typename Enable = typename pmem::detail::is_input_iterator<
203  InputIt>::type>
204  basic_string &append(InputIt first, InputIt last);
205  basic_string &append(std::initializer_list<CharT> ilist);
206  void push_back(CharT ch);
207  basic_string &operator+=(const basic_string &str);
208  basic_string &operator+=(const CharT *s);
209  basic_string &operator+=(CharT c);
210  basic_string &operator+=(std::initializer_list<CharT> ilist);
211 
212  basic_string &insert(size_type index, size_type count, CharT ch);
213  basic_string &insert(size_type index, const CharT *s);
214  basic_string &insert(size_type index, const CharT *s, size_type count);
215  basic_string &insert(size_type index, const basic_string &str);
216  basic_string &insert(size_type index1, const basic_string &str,
217  size_type index2, size_type count = npos);
218  iterator insert(const_iterator pos, CharT ch);
219  iterator insert(const_iterator pos, size_type count, CharT ch);
220  template <typename InputIt,
221  typename Enable = typename pmem::detail::is_input_iterator<
222  InputIt>::type>
223  iterator insert(const_iterator pos, InputIt first, InputIt last);
224  iterator insert(const_iterator pos, std::initializer_list<CharT> ilist);
225  template <typename T,
226  typename Enable = typename std::enable_if<
227  std::is_convertible<T, size_type>::value>::type>
228  basic_string &insert(T param, size_type count, CharT ch);
229  template <typename T,
230  typename Enable = typename std::enable_if<
231  !std::is_convertible<T, size_type>::value>::type>
232  iterator insert(T param, size_type count, CharT ch);
233 
234  basic_string &replace(size_type index, size_type count,
235  const basic_string &str);
236  basic_string &replace(const_iterator first, const_iterator last,
237  const basic_string &str);
238  basic_string &replace(size_type index, size_type count,
239  const basic_string &str, size_type index2,
240  size_type count2 = npos);
241  template <typename InputIt,
242  typename Enable = typename pmem::detail::is_input_iterator<
243  InputIt>::type>
244  basic_string &replace(const_iterator first, const_iterator last,
245  InputIt first2, InputIt last2);
246  basic_string &replace(const_iterator first, const_iterator last,
247  const CharT *s, size_type count2);
248  basic_string &replace(const_iterator first, const_iterator last,
249  const CharT *s);
250  basic_string &replace(size_type index, size_type count,
251  size_type count2, CharT ch);
252  basic_string &replace(const_iterator first, const_iterator last,
253  size_type count2, CharT ch);
254  basic_string &replace(size_type index, size_type count, const CharT *s,
255  size_type count2);
256  basic_string &replace(size_type index, size_type count, const CharT *s);
257  basic_string &replace(const_iterator first, const_iterator last,
258  std::initializer_list<CharT> ilist);
259 
260  size_type copy(CharT *s, size_type count, size_type index = 0) const;
261 
262  int compare(const basic_string &other) const;
263  int compare(const std::basic_string<CharT> &other) const;
264  int compare(size_type pos, size_type count,
265  const basic_string &other) const;
266  int compare(size_type pos, size_type count,
267  const std::basic_string<CharT> &other) const;
268  int compare(size_type pos1, size_type count1, const basic_string &other,
269  size_type pos2, size_type count2 = npos) const;
270  int compare(size_type pos1, size_type count1,
271  const std::basic_string<CharT> &other, size_type pos2,
272  size_type count2 = npos) const;
273  int compare(const CharT *s) const;
274  int compare(size_type pos, size_type count, const CharT *s) const;
275  int compare(size_type pos, size_type count1, const CharT *s,
276  size_type count2) const;
277 
278  /* Search */
279  size_type find(const basic_string &str, size_type pos = 0) const
280  noexcept;
281  size_type find(const CharT *s, size_type pos, size_type count) const;
282  size_type find(const CharT *s, size_type pos = 0) const;
283  size_type find(CharT ch, size_type pos = 0) const noexcept;
284  size_type rfind(const basic_string &str, size_type pos = npos) const
285  noexcept;
286  size_type rfind(const CharT *s, size_type pos, size_type count) const;
287  size_type rfind(const CharT *s, size_type pos = npos) const;
288  size_type rfind(CharT ch, size_type pos = npos) const noexcept;
289  size_type find_first_of(const basic_string &str,
290  size_type pos = 0) const noexcept;
291  size_type find_first_of(const CharT *s, size_type pos,
292  size_type count) const;
293  size_type find_first_of(const CharT *s, size_type pos = 0) const;
294  size_type find_first_of(CharT ch, size_type pos = 0) const noexcept;
295  size_type find_first_not_of(const basic_string &str,
296  size_type pos = 0) const noexcept;
297  size_type find_first_not_of(const CharT *s, size_type pos,
298  size_type count) const;
299  size_type find_first_not_of(const CharT *s, size_type pos = 0) const;
300  size_type find_first_not_of(CharT ch, size_type pos = 0) const noexcept;
301  size_type find_last_of(const basic_string &str,
302  size_type pos = npos) const noexcept;
303  size_type find_last_of(const CharT *s, size_type pos,
304  size_type count) const;
305  size_type find_last_of(const CharT *s, size_type pos = npos) const;
306  size_type find_last_of(CharT ch, size_type pos = npos) const noexcept;
307  size_type find_last_not_of(const basic_string &str,
308  size_type pos = npos) const noexcept;
309  size_type find_last_not_of(const CharT *s, size_type pos,
310  size_type count) const;
311  size_type find_last_not_of(const CharT *s, size_type pos = npos) const;
312  size_type find_last_not_of(CharT ch, size_type pos = npos) const
313  noexcept;
314 
315  void swap(basic_string &other);
316 
317  operator basic_string_view<CharT, Traits>() const;
318 
319  /* Special value. The exact meaning depends on the context. */
320  static const size_type npos = static_cast<size_type>(-1);
321 
322 private:
325 
343  union {
344  struct {
345  /*
346  * EXACTLY the same type as first member in vector
347  * Holds size for sso string, bit specified by _sso_mask
348  * indicates if sso is used.
349  */
350  p<size_type> _size;
351 
352  sso_type _data;
353  } sso;
354 
355  struct {
356  non_sso_type _data;
357  } non_sso;
358  };
359 
360  /*
361  * MSB is used because vector is known not to use entire range of
362  * size_type.
363  */
364  static constexpr size_type _sso_mask = 1ULL
365  << (std::numeric_limits<size_type>::digits - 1);
366 
367  /* helper functions */
368  bool is_sso_used() const;
369  void destroy_data();
370  template <
371  typename InputIt,
372  typename Enable = typename std::enable_if<
374  size_type get_size(InputIt first, InputIt last) const;
375  size_type get_size(size_type count, value_type ch) const;
376  size_type get_size(const basic_string &other) const;
377  template <typename... Args>
378  pointer replace_content(Args &&... args);
379  template <typename... Args>
380  pointer initialize(Args &&... args);
381  void allocate(size_type capacity);
382  template <
383  typename InputIt,
384  typename Enable = typename std::enable_if<
386  pointer assign_sso_data(InputIt first, InputIt last);
387  pointer assign_sso_data(size_type count, value_type ch);
388  pointer move_data(basic_string &&other);
389  template <
390  typename InputIt,
391  typename Enable = typename std::enable_if<
393  pointer assign_large_data(InputIt first, InputIt last);
394  pointer assign_large_data(size_type count, value_type ch);
395  pool_base get_pool() const;
396  void check_pmem() const;
397  void check_tx_stage_work() const;
398  void check_pmem_tx() const;
399  void add_sso_to_tx(size_type first, size_type num) const;
400  size_type get_sso_size() const;
401  void enable_sso();
402  void disable_sso();
403  void set_sso_size(size_type new_size);
404  void sso_to_large(size_t new_capacity);
405  void large_to_sso();
406  typename basic_string<CharT, Traits>::non_sso_type &non_sso_data();
407  typename basic_string<CharT, Traits>::sso_type &sso_data();
409  non_sso_data() const;
410  const typename basic_string<CharT, Traits>::sso_type &sso_data() const;
411 };
412 
422 template <typename CharT, typename Traits>
424 {
425  check_pmem_tx();
426  sso._size = 0;
427 
428  allocate(0);
429  initialize(0U, value_type('\0'));
430 }
431 
446 template <typename CharT, typename Traits>
448 {
449  check_pmem_tx();
450  sso._size = 0;
451 
452  allocate(count);
453  initialize(count, ch);
454 }
455 
473 template <typename CharT, typename Traits>
475  size_type pos, size_type count)
476 {
477  check_pmem_tx();
478  sso._size = 0;
479 
480  if (pos > other.size())
481  throw std::out_of_range("Index out of range.");
482 
483  if (count == npos || pos + count > other.size())
484  count = other.size() - pos;
485 
486  auto first = static_cast<difference_type>(pos);
487  auto last = first + static_cast<difference_type>(count);
488 
489  allocate(count);
490  initialize(other.cbegin() + first, other.cbegin() + last);
491 }
492 
511 template <typename CharT, typename Traits>
512 basic_string<CharT, Traits>::basic_string(const std::basic_string<CharT> &other,
513  size_type pos, size_type count)
514  : basic_string(basic_string_view<CharT>(other), pos, count)
515 {
516 }
517 
533 template <typename CharT, typename Traits>
534 basic_string<CharT, Traits>::basic_string(const CharT *s, size_type count)
535 {
536  check_pmem_tx();
537  sso._size = 0;
538 
539  allocate(count);
540  initialize(s, s + count);
541 }
542 
556 template <typename CharT, typename Traits>
558 {
559  check_pmem_tx();
560  sso._size = 0;
561 
562  auto length = traits_type::length(s);
563 
564  allocate(length);
565  initialize(s, s + length);
566 }
567 
584 template <typename CharT, typename Traits>
585 template <typename InputIt, typename Enable>
586 basic_string<CharT, Traits>::basic_string(InputIt first, InputIt last)
587 {
588  auto len = std::distance(first, last);
589  assert(len >= 0);
590 
591  check_pmem_tx();
592  sso._size = 0;
593 
594  allocate(static_cast<size_type>(len));
595  initialize(first, last);
596 }
597 
612 template <typename CharT, typename Traits>
614 {
615  check_pmem_tx();
616  sso._size = 0;
617 
618  allocate(other.size());
619  initialize(other.cbegin(), other.cend());
620 }
621 
637 template <typename CharT, typename Traits>
638 basic_string<CharT, Traits>::basic_string(const std::basic_string<CharT> &other)
639  : basic_string(other.cbegin(), other.cend())
640 {
641 }
642 
657 template <typename CharT, typename Traits>
659 {
660  check_pmem_tx();
661  sso._size = 0;
662 
663  move_data(std::move(other));
664 }
665 
680 template <typename CharT, typename Traits>
681 basic_string<CharT, Traits>::basic_string(std::initializer_list<CharT> ilist)
682 {
683  check_pmem_tx();
684  sso._size = 0;
685 
686  allocate(ilist.size());
687  initialize(ilist.begin(), ilist.end());
688 }
689 
705 template <typename CharT, typename Traits>
706 template <class T, typename Enable>
708 {
709  check_pmem_tx();
710  sso._size = 0;
711 
713 
714  allocate(sv.size());
715  initialize(sv.data(), sv.data() + sv.size());
716 }
717 
735 template <typename CharT, typename Traits>
736 template <class T, typename Enable>
738  size_type n)
739 {
740  check_pmem_tx();
741  sso._size = 0;
742 
744 
745  if (pos > sv.size())
746  throw std::out_of_range("Index out of range.");
747 
748  if (n == npos || pos + n > sv.size())
749  n = sv.size() - pos;
750 
751  auto first = pos;
752  auto last = first + n;
753 
754  allocate(n);
755  initialize(sv.data() + first, sv.data() + last);
756 }
757 
761 template <typename CharT, typename Traits>
763 {
764  try {
765  free_data();
766  } catch (...) {
767  std::terminate();
768  }
769 }
770 
780 template <typename CharT, typename Traits>
783 {
784  return assign(other);
785 }
786 
797 template <typename CharT, typename Traits>
799 basic_string<CharT, Traits>::operator=(const std::basic_string<CharT> &other)
800 {
801  return assign(other);
802 }
803 
813 template <typename CharT, typename Traits>
816 {
817  return assign(std::move(other));
818 }
819 
828 template <typename CharT, typename Traits>
831 {
832  return assign(s);
833 }
834 
843 template <typename CharT, typename Traits>
846 {
847  return assign(1, ch);
848 }
849 
859 template <typename CharT, typename Traits>
861 basic_string<CharT, Traits>::operator=(std::initializer_list<CharT> ilist)
862 {
863  return assign(ilist);
864 }
865 
875 template <typename CharT, typename Traits>
876 template <class T, typename Enable>
879 {
881  return assign(sv.data(), sv.size());
882 }
883 
894 template <typename CharT, typename Traits>
896 basic_string<CharT, Traits>::assign(size_type count, CharT ch)
897 {
898  auto pop = get_pool();
899 
900  transaction::run(pop, [&] { replace_content(count, ch); });
901 
902  return *this;
903 }
904 
914 template <typename CharT, typename Traits>
917 {
918  if (&other == this)
919  return *this;
920 
921  auto pop = get_pool();
922 
924  pop, [&] { replace_content(other.cbegin(), other.cend()); });
925 
926  return *this;
927 }
928 
939 template <typename CharT, typename Traits>
941 basic_string<CharT, Traits>::assign(const std::basic_string<CharT> &other)
942 {
943  return assign(other.cbegin(), other.cend());
944 }
945 
958 template <typename CharT, typename Traits>
961  size_type count)
962 {
963  if (pos > other.size())
964  throw std::out_of_range("Index out of range.");
965 
966  if (count == npos || pos + count > other.size())
967  count = other.size() - pos;
968 
969  auto pop = get_pool();
970  auto first = static_cast<difference_type>(pos);
971  auto last = first + static_cast<difference_type>(count);
972 
973  transaction::run(pop, [&] {
974  replace_content(other.cbegin() + first, other.cbegin() + last);
975  });
976 
977  return *this;
978 }
979 
994 template <typename CharT, typename Traits>
996 basic_string<CharT, Traits>::assign(const std::basic_string<CharT> &other,
997  size_type pos, size_type count)
998 {
999  if (pos > other.size())
1000  throw std::out_of_range("Index out of range.");
1001 
1002  if (count == npos || pos + count > other.size())
1003  count = other.size() - pos;
1004 
1005  return assign(other.c_str() + pos, count);
1006 }
1007 
1018 template <typename CharT, typename Traits>
1020 basic_string<CharT, Traits>::assign(const CharT *s, size_type count)
1021 {
1022  auto pop = get_pool();
1023 
1024  transaction::run(pop, [&] { replace_content(s, s + count); });
1025 
1026  return *this;
1027 }
1028 
1037 template <typename CharT, typename Traits>
1040 {
1041  auto pop = get_pool();
1042 
1043  auto length = traits_type::length(s);
1044 
1045  transaction::run(pop, [&] { replace_content(s, s + length); });
1046 
1047  return *this;
1048 }
1049 
1061 template <typename CharT, typename Traits>
1062 template <typename InputIt, typename Enable>
1064 basic_string<CharT, Traits>::assign(InputIt first, InputIt last)
1065 {
1066  auto pop = get_pool();
1067 
1068  transaction::run(pop, [&] { replace_content(first, last); });
1069 
1070  return *this;
1071 }
1072 
1082 template <typename CharT, typename Traits>
1085 {
1086  if (&other == this)
1087  return *this;
1088 
1089  auto pop = get_pool();
1090 
1091  transaction::run(pop, [&] {
1092  destroy_data();
1093  move_data(std::move(other));
1094  });
1095 
1096  return *this;
1097 }
1098 
1108 template <typename CharT, typename Traits>
1110 basic_string<CharT, Traits>::assign(std::initializer_list<CharT> ilist)
1111 {
1112  return assign(ilist.begin(), ilist.end());
1113 }
1114 
1122 template <typename CharT, typename Traits>
1123 void
1125 {
1126  if (!is_sso_used()) {
1127  non_sso._data.for_each_ptr(func);
1128  }
1129 }
1130 
1136 template <typename CharT, typename Traits>
1139 {
1140  return is_sso_used() ? iterator(&*sso_data().begin())
1141  : iterator(&*non_sso_data().begin());
1142 }
1143 
1149 template <typename CharT, typename Traits>
1150 typename basic_string<CharT, Traits>::const_iterator
1152 {
1153  return cbegin();
1154 }
1155 
1161 template <typename CharT, typename Traits>
1162 typename basic_string<CharT, Traits>::const_iterator
1164 {
1165  return is_sso_used() ? const_iterator(&*sso_data().cbegin())
1166  : const_iterator(&*non_sso_data().cbegin());
1167 }
1168 
1174 template <typename CharT, typename Traits>
1177 {
1178  return begin() + static_cast<difference_type>(size());
1179 }
1180 
1187 template <typename CharT, typename Traits>
1188 typename basic_string<CharT, Traits>::const_iterator
1190 {
1191  return cbegin() + static_cast<difference_type>(size());
1192 }
1193 
1200 template <typename CharT, typename Traits>
1201 typename basic_string<CharT, Traits>::const_iterator
1203 {
1204  return cbegin() + static_cast<difference_type>(size());
1205 }
1206 
1213 template <typename CharT, typename Traits>
1214 typename basic_string<CharT, Traits>::reverse_iterator
1216 {
1217  return reverse_iterator(end());
1218 }
1219 
1226 template <typename CharT, typename Traits>
1227 typename basic_string<CharT, Traits>::const_reverse_iterator
1229 {
1230  return crbegin();
1231 }
1232 
1239 template <typename CharT, typename Traits>
1240 typename basic_string<CharT, Traits>::const_reverse_iterator
1242 {
1243  return const_reverse_iterator(cend());
1244 }
1245 
1252 template <typename CharT, typename Traits>
1253 typename basic_string<CharT, Traits>::reverse_iterator
1255 {
1256  return reverse_iterator(begin());
1257 }
1258 
1265 template <typename CharT, typename Traits>
1266 typename basic_string<CharT, Traits>::const_reverse_iterator
1268 {
1269  return crend();
1270 }
1271 
1278 template <typename CharT, typename Traits>
1279 typename basic_string<CharT, Traits>::const_reverse_iterator
1281 {
1282  return const_reverse_iterator(cbegin());
1283 }
1284 
1298 template <typename CharT, typename Traits>
1299 typename basic_string<CharT, Traits>::reference
1301 {
1302  if (n >= size())
1303  throw std::out_of_range("string::at");
1304 
1305  return is_sso_used() ? sso_data()[n] : non_sso_data()[n];
1306 }
1307 
1318 template <typename CharT, typename Traits>
1319 typename basic_string<CharT, Traits>::const_reference
1321 {
1322  return const_at(n);
1323 }
1324 
1338 template <typename CharT, typename Traits>
1339 typename basic_string<CharT, Traits>::const_reference
1341 {
1342  if (n >= size())
1343  throw std::out_of_range("string::const_at");
1344 
1345  return is_sso_used()
1346  ? static_cast<const sso_type &>(sso_data())[n]
1347  : static_cast<const non_sso_type &>(non_sso_data())[n];
1348 }
1349 
1361 template <typename CharT, typename Traits>
1362 typename basic_string<CharT, Traits>::reference
1364 {
1365  return is_sso_used() ? sso_data()[n] : non_sso_data()[n];
1366 }
1367 
1375 template <typename CharT, typename Traits>
1376 typename basic_string<CharT, Traits>::const_reference
1378 {
1379  return is_sso_used() ? sso_data()[n] : non_sso_data()[n];
1380 }
1381 
1391 template <typename CharT, typename Traits>
1392 CharT &
1394 {
1395  return (*this)[0];
1396 }
1397 
1403 template <typename CharT, typename Traits>
1404 const CharT &
1406 {
1407  return cfront();
1408 }
1409 
1418 template <typename CharT, typename Traits>
1419 const CharT &
1421 {
1422  return static_cast<const basic_string &>(*this)[0];
1423 }
1424 
1434 template <typename CharT, typename Traits>
1435 CharT &
1437 {
1438  return (*this)[size() - 1];
1439 }
1440 
1446 template <typename CharT, typename Traits>
1447 const CharT &
1449 {
1450  return cback();
1451 }
1452 
1461 template <typename CharT, typename Traits>
1462 const CharT &
1464 {
1465  return static_cast<const basic_string &>(*this)[size() - 1];
1466 }
1467 
1471 template <typename CharT, typename Traits>
1472 typename basic_string<CharT, Traits>::size_type
1474 {
1475  if (is_sso_used())
1476  return get_sso_size();
1477  else if (non_sso_data().size() == 0)
1478  return 0;
1479  else
1480  return non_sso_data().size() - 1;
1481 }
1482 
1489 template <typename CharT, typename Traits>
1490 CharT *
1492 {
1493  return is_sso_used() ? sso_data().range(0, get_sso_size() + 1).begin()
1494  : non_sso_data().data();
1495 }
1496 
1515 template <typename CharT, typename Traits>
1517 basic_string<CharT, Traits>::erase(size_type index, size_type count)
1518 {
1519  auto sz = size();
1520 
1521  if (index > sz)
1522  throw std::out_of_range("Index exceeds size.");
1523 
1524  count = (std::min)(count, sz - index);
1525 
1526  auto pop = get_pool();
1527 
1528  auto first = begin() + static_cast<difference_type>(index);
1529  auto last = first + static_cast<difference_type>(count);
1530 
1531  if (is_sso_used()) {
1532  transaction::run(pop, [&] {
1533  auto move_len = sz - index - count;
1534  auto new_size = sz - count;
1535 
1536  if (move_len > 0) {
1537  auto range =
1538  sso_data().range(index, move_len + 1);
1539  traits_type::move(range.begin(), &*last,
1540  move_len);
1541 
1542  assert(range.end() - 1 ==
1543  &sso_data()._data[index + move_len]);
1544  }
1545 
1546  sso_data()[index + move_len] = value_type('\0');
1547  set_sso_size(new_size);
1548  });
1549  } else {
1550  non_sso_data().erase(first, last);
1551  }
1552 
1553  return *this;
1554 }
1555 
1572 template <typename CharT, typename Traits>
1575 {
1576  return erase(pos, pos + 1);
1577 }
1578 
1597 template <typename CharT, typename Traits>
1599 basic_string<CharT, Traits>::erase(const_iterator first, const_iterator last)
1600 {
1601  size_type index =
1602  static_cast<size_type>(std::distance(cbegin(), first));
1603  size_type len = static_cast<size_type>(std::distance(first, last));
1604 
1605  erase(index, len);
1606 
1607  return begin() + static_cast<difference_type>(index);
1608 }
1609 
1620 template <typename CharT, typename Traits>
1621 void
1623 {
1624  erase(size() - 1, 1);
1625 }
1626 
1646 template <typename CharT, typename Traits>
1648 basic_string<CharT, Traits>::append(size_type count, CharT ch)
1649 {
1650  auto sz = size();
1651  auto new_size = sz + count;
1652 
1653  if (new_size > max_size())
1654  throw std::length_error("Size exceeds max size.");
1655 
1656  if (is_sso_used()) {
1657  auto pop = get_pool();
1658 
1659  transaction::run(pop, [&] {
1660  if (new_size > sso_capacity) {
1661  sso_to_large(new_size);
1662 
1663  non_sso_data().insert(
1664  non_sso_data().cbegin() +
1665  static_cast<difference_type>(
1666  sz),
1667  count, ch);
1668  } else {
1669  add_sso_to_tx(sz, count + 1);
1670  traits_type::assign(&sso_data()._data[sz],
1671  count, ch);
1672 
1673  assert(new_size == sz + count);
1674  set_sso_size(new_size);
1675  sso_data()._data[new_size] = value_type('\0');
1676  }
1677  });
1678  } else {
1679  non_sso_data().insert(non_sso_data().cbegin() +
1680  static_cast<difference_type>(sz),
1681  count, ch);
1682  }
1683 
1684  return *this;
1685 }
1686 
1705 template <typename CharT, typename Traits>
1708 {
1709  return append(str.data(), str.size());
1710 }
1711 
1737 template <typename CharT, typename Traits>
1740  size_type count)
1741 {
1742  auto sz = str.size();
1743 
1744  if (pos > sz)
1745  throw std::out_of_range("Index out of range.");
1746 
1747  count = (std::min)(count, sz - pos);
1748 
1749  append(str.data() + pos, count);
1750 
1751  return *this;
1752 }
1753 
1773 template <typename CharT, typename Traits>
1775 basic_string<CharT, Traits>::append(const CharT *s, size_type count)
1776 {
1777  return append(s, s + count);
1778 }
1779 
1799 template <typename CharT, typename Traits>
1802 {
1803  return append(s, traits_type::length(s));
1804 }
1805 
1827 template <typename CharT, typename Traits>
1828 template <typename InputIt, typename Enable>
1830 basic_string<CharT, Traits>::append(InputIt first, InputIt last)
1831 {
1832  auto sz = size();
1833  auto count = static_cast<size_type>(std::distance(first, last));
1834  auto new_size = sz + count;
1835 
1836  if (new_size > max_size())
1837  throw std::length_error("Size exceeds max size.");
1838 
1839  if (is_sso_used()) {
1840  auto pop = get_pool();
1841 
1842  transaction::run(pop, [&] {
1843  if (new_size > sso_capacity) {
1844  /* 1) Cache C-style string in case of
1845  * self-append, because it will be destroyed
1846  * when switching from sso to large string.
1847  *
1848  * 2) We cache in std::vector instead of
1849  * std::string because of overload deduction
1850  * ambiguity on Windows
1851  */
1852  std::vector<value_type> str(first, last);
1853 
1854  sso_to_large(new_size);
1855  non_sso_data().insert(
1856  non_sso_data().cbegin() +
1857  static_cast<difference_type>(
1858  sz),
1859  str.begin(), str.end());
1860  } else {
1861  add_sso_to_tx(sz, count + 1);
1862  std::copy(first, last, &sso_data()._data[sz]);
1863 
1864  assert(new_size == sz + count);
1865  set_sso_size(new_size);
1866  sso_data()._data[new_size] = value_type('\0');
1867  }
1868  });
1869  } else {
1870  non_sso_data().insert(non_sso_data().cbegin() +
1871  static_cast<difference_type>(sz),
1872  first, last);
1873  }
1874 
1875  return *this;
1876 }
1877 
1896 template <typename CharT, typename Traits>
1898 basic_string<CharT, Traits>::append(std::initializer_list<CharT> ilist)
1899 {
1900  return append(ilist.begin(), ilist.end());
1901 }
1902 
1919 template <typename CharT, typename Traits>
1920 void
1922 {
1923  append(static_cast<size_type>(1), ch);
1924 }
1925 
1944 template <typename CharT, typename Traits>
1947 {
1948  return append(str);
1949 }
1950 
1970 template <typename CharT, typename Traits>
1973 {
1974  return append(s);
1975 }
1976 
1993 template <typename CharT, typename Traits>
1996 {
1997  push_back(ch);
1998 
1999  return *this;
2000 }
2001 
2020 template <typename CharT, typename Traits>
2022 basic_string<CharT, Traits>::operator+=(std::initializer_list<CharT> ilist)
2023 {
2024  return append(ilist);
2025 }
2026 
2048 template <typename CharT, typename Traits>
2050 basic_string<CharT, Traits>::insert(size_type index, size_type count, CharT ch)
2051 {
2052  if (index > size())
2053  throw std::out_of_range("Index out of range.");
2054 
2055  auto pos = cbegin() + static_cast<difference_type>(index);
2056 
2057  insert(pos, count, ch);
2058 
2059  return *this;
2060 }
2061 
2083 template <typename CharT, typename Traits>
2085 basic_string<CharT, Traits>::insert(size_type index, const CharT *s)
2086 {
2087  return insert(index, s, traits_type::length(s));
2088 }
2089 
2111 template <typename CharT, typename Traits>
2113 basic_string<CharT, Traits>::insert(size_type index, const CharT *s,
2114  size_type count)
2115 {
2116  if (index > size())
2117  throw std::out_of_range("Index out of range.");
2118 
2119  auto pos = cbegin() + static_cast<difference_type>(index);
2120 
2121  insert(pos, s, s + count);
2122 
2123  return *this;
2124 }
2125 
2146 template <typename CharT, typename Traits>
2149 {
2150  return insert(index, str.data(), str.size());
2151 }
2152 
2175 template <typename CharT, typename Traits>
2178  size_type index2, size_type count)
2179 {
2180  auto sz = str.size();
2181 
2182  if (index1 > size() || index2 > sz)
2183  throw std::out_of_range("Index out of range.");
2184 
2185  count = (std::min)(count, sz - index2);
2186 
2187  return insert(index1, str.data() + index2, count);
2188 }
2189 
2212 template <typename CharT, typename Traits>
2214 basic_string<CharT, Traits>::insert(const_iterator pos, CharT ch)
2215 {
2216  return insert(pos, 1, ch);
2217 }
2218 
2243 template <typename CharT, typename Traits>
2245 basic_string<CharT, Traits>::insert(const_iterator pos, size_type count,
2246  CharT ch)
2247 {
2248  auto sz = size();
2249 
2250  if (sz + count > max_size())
2251  throw std::length_error("Count exceeds max size.");
2252 
2253  auto new_size = sz + count;
2254 
2255  auto pop = get_pool();
2256 
2257  auto index = static_cast<size_type>(std::distance(cbegin(), pos));
2258 
2259  transaction::run(pop, [&] {
2260  if (is_sso_used() && new_size <= sso_capacity) {
2261  auto len = sz - index;
2262 
2263  add_sso_to_tx(index, len + count + 1);
2264 
2265  traits_type::move(&sso_data()._data[index + count],
2266  &sso_data()._data[index], len);
2267  traits_type::assign(&sso_data()._data[index], count,
2268  ch);
2269 
2270  assert(new_size == index + len + count);
2271  set_sso_size(new_size);
2272  sso_data()._data[new_size] = value_type('\0');
2273  } else {
2274  if (is_sso_used())
2275  sso_to_large(new_size);
2276 
2277  non_sso_data().insert(
2278  non_sso_data().begin() +
2279  static_cast<difference_type>(index),
2280  count, ch);
2281  }
2282  });
2283 
2284  return iterator(&data()[static_cast<difference_type>(index)]);
2285 }
2286 
2311 template <typename CharT, typename Traits>
2312 template <typename InputIt, typename Enable>
2314 basic_string<CharT, Traits>::insert(const_iterator pos, InputIt first,
2315  InputIt last)
2316 {
2317  auto sz = size();
2318 
2319  auto count = static_cast<size_type>(std::distance(first, last));
2320 
2321  if (sz + count > max_size())
2322  throw std::length_error("Count exceeds max size.");
2323 
2324  auto pop = get_pool();
2325 
2326  auto new_size = sz + count;
2327 
2328  auto index = static_cast<size_type>(std::distance(cbegin(), pos));
2329 
2330  transaction::run(pop, [&] {
2331  if (is_sso_used() && new_size <= sso_capacity) {
2332  auto len = sz - index;
2333 
2334  add_sso_to_tx(index, len + count + 1);
2335 
2336  traits_type::move(&sso_data()._data[index + count],
2337  &sso_data()._data[index], len);
2338  std::copy(first, last, &sso_data()._data[index]);
2339 
2340  assert(new_size == index + len + count);
2341  set_sso_size(new_size);
2342  sso_data()._data[new_size] = value_type('\0');
2343  } else {
2344  if (is_sso_used()) {
2345  /* 1) Cache C-style string in case of
2346  * self-insert, because it will be destroyed
2347  * when switching from sso to large string.
2348  *
2349  * 2) We cache in std::vector instead of
2350  * std::string because of overload deduction
2351  * ambiguity on Windows
2352  */
2353  std::vector<value_type> str(first, last);
2354 
2355  sso_to_large(new_size);
2356  non_sso_data().insert(
2357  non_sso_data().begin() +
2358  static_cast<difference_type>(
2359  index),
2360  str.begin(), str.end());
2361  } else {
2362  non_sso_data().insert(
2363  non_sso_data().begin() +
2364  static_cast<difference_type>(
2365  index),
2366  first, last);
2367  }
2368  }
2369  });
2370 
2371  return iterator(&data()[static_cast<difference_type>(index)]);
2372 }
2373 
2397 template <typename CharT, typename Traits>
2400  std::initializer_list<CharT> ilist)
2401 {
2402  return insert(pos, ilist.begin(), ilist.end());
2403 }
2404 
2427 template <typename CharT, typename Traits>
2429 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2430  const basic_string &str)
2431 {
2432  return replace(index, count, str.data(), str.size());
2433 }
2434 
2455 template <typename CharT, typename Traits>
2457 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2458  const basic_string &str)
2459 {
2460  return replace(first, last, str.data(), str.data() + str.size());
2461 }
2462 
2489 template <typename CharT, typename Traits>
2491 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2492  const basic_string &str, size_type index2,
2493  size_type count2)
2494 {
2495  auto sz = str.size();
2496 
2497  if (index2 > sz)
2498  throw std::out_of_range("Index out of range.");
2499 
2500  count2 = (std::min)(count2, sz - index2);
2501 
2502  return replace(index, count, str.data() + index2, count2);
2503 }
2504 
2530 template <typename CharT, typename Traits>
2531 template <typename InputIt, typename Enable>
2533 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2534  InputIt first2, InputIt last2)
2535 {
2536  auto sz = size();
2537  auto index = static_cast<size_type>(std::distance(cbegin(), first));
2538  auto count = static_cast<size_type>(std::distance(first, last));
2539  auto count2 = static_cast<size_type>(std::distance(first2, last2));
2540 
2541  count = (std::min)(count, sz - index);
2542 
2543  if (sz - count + count2 > max_size())
2544  throw std::length_error("Count exceeds max size.");
2545 
2546  auto new_size = sz - count + count2;
2547 
2548  auto pop = get_pool();
2549 
2550  transaction::run(pop, [&] {
2551  if (is_sso_used() && new_size <= sso_capacity) {
2552  add_sso_to_tx(index, new_size - index + 1);
2553 
2554  assert(count2 < new_size + 1);
2555  traits_type::move(&sso_data()._data[index + count2],
2556  &sso_data()._data[index + count],
2557  sz - index - count);
2558  std::copy(first2, last2, &sso_data()._data[index]);
2559 
2560  set_sso_size(new_size);
2561  sso_data()._data[new_size] = value_type('\0');
2562  } else {
2563  /* 1) Cache C-style string in case of
2564  * self-replace, because it will be destroyed
2565  * when switching from sso to large string.
2566  *
2567  * 2) We cache in std::vector instead of
2568  * std::string because of overload deduction
2569  * ambiguity on Windows
2570  */
2571  std::vector<value_type> str(first2, last2);
2572 
2573  if (is_sso_used()) {
2574  sso_to_large(new_size);
2575  }
2576 
2577  auto beg =
2578  begin() + static_cast<difference_type>(index);
2579  auto end = beg + static_cast<difference_type>(count);
2580  non_sso_data().erase(beg, end);
2581  non_sso_data().insert(beg, str.begin(), str.end());
2582  }
2583 
2584  if (!is_sso_used() && new_size <= sso_capacity)
2585  large_to_sso();
2586  });
2587 
2588  return *this;
2589 }
2590 
2613 template <typename CharT, typename Traits>
2615 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2616  const CharT *s, size_type count2)
2617 {
2618  return replace(first, last, s, s + count2);
2619 }
2620 
2644 template <typename CharT, typename Traits>
2646 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2647  const CharT *s, size_type count2)
2648 {
2649  if (index > size())
2650  throw std::out_of_range("Index out of range.");
2651 
2652  auto first = cbegin() + static_cast<difference_type>(index);
2653  auto last = first + static_cast<difference_type>(count);
2654 
2655  return replace(first, last, s, s + count2);
2656 }
2657 
2681 template <typename CharT, typename Traits>
2683 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2684  const CharT *s)
2685 {
2686  return replace(index, count, s, traits_type::length(s));
2687 }
2688 
2712 template <typename CharT, typename Traits>
2714 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2715  size_type count2, CharT ch)
2716 {
2717  if (index > size())
2718  throw std::out_of_range("Index out of range.");
2719 
2720  auto first = cbegin() + static_cast<difference_type>(index);
2721  auto last = first + static_cast<difference_type>(count);
2722 
2723  return replace(first, last, count2, ch);
2724 }
2725 
2748 template <typename CharT, typename Traits>
2750 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2751  size_type count2, CharT ch)
2752 {
2753  auto sz = size();
2754  auto index = static_cast<size_type>(std::distance(cbegin(), first));
2755  auto count = static_cast<size_type>(std::distance(first, last));
2756 
2757  count = (std::min)(count, sz - index);
2758 
2759  if (sz - count + count2 > max_size())
2760  throw std::length_error("Count exceeds max size.");
2761 
2762  auto new_size = sz - count + count2;
2763 
2764  auto pop = get_pool();
2765 
2766  transaction::run(pop, [&] {
2767  if (is_sso_used() && new_size <= sso_capacity) {
2768  add_sso_to_tx(index, new_size - index + 1);
2769 
2770  assert(count2 < new_size + 1);
2771  traits_type::move(&sso_data()._data[index + count2],
2772  &sso_data()._data[index + count],
2773  sz - index - count);
2774  traits_type::assign(&sso_data()._data[index], count2,
2775  ch);
2776 
2777  set_sso_size(new_size);
2778  sso_data()._data[new_size] = value_type('\0');
2779  } else {
2780  if (is_sso_used()) {
2781  sso_to_large(new_size);
2782  }
2783 
2784  auto beg =
2785  begin() + static_cast<difference_type>(index);
2786  auto end = beg + static_cast<difference_type>(count);
2787  non_sso_data().erase(beg, end);
2788  non_sso_data().insert(beg, count2, ch);
2789  }
2790 
2791  if (!is_sso_used() && new_size <= sso_capacity)
2792  large_to_sso();
2793  });
2794 
2795  return *this;
2796 }
2797 
2819 template <typename CharT, typename Traits>
2821 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2822  const CharT *s)
2823 {
2824  return replace(first, last, s, traits_type::length(s));
2825 }
2826 
2849 template <typename CharT, typename Traits>
2851 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2852  std::initializer_list<CharT> ilist)
2853 {
2854  return replace(first, last, ilist.begin(), ilist.end());
2855 }
2856 
2870 template <typename CharT, typename Traits>
2871 typename basic_string<CharT, Traits>::size_type
2872 basic_string<CharT, Traits>::copy(CharT *s, size_type count,
2873  size_type index) const
2874 {
2875  auto sz = size();
2876 
2877  if (index > sz)
2878  throw std::out_of_range("Index out of range.");
2879 
2880  auto len = (std::min)(count, sz - index);
2881 
2882  traits_type::copy(s, data() + index, len);
2883 
2884  return len;
2885 }
2886 
2904 template <typename CharT, typename Traits>
2905 int
2906 basic_string<CharT, Traits>::compare(size_type pos, size_type count1,
2907  const CharT *s, size_type count2) const
2908 {
2909  if (pos > size())
2910  throw std::out_of_range("Index out of range.");
2911 
2912  if (count1 > size() - pos)
2913  count1 = size() - pos;
2914 
2915  auto ret = traits_type::compare(cdata() + pos, s,
2916  std::min<size_type>(count1, count2));
2917 
2918  if (ret != 0)
2919  return ret;
2920 
2921  if (count1 < count2)
2922  return -1;
2923  else if (count1 == count2)
2924  return 0;
2925  else
2926  return 1;
2927 }
2928 
2938 template <typename CharT, typename Traits>
2939 typename basic_string<CharT, Traits>::size_type
2940 basic_string<CharT, Traits>::find(const basic_string &str, size_type pos) const
2941  noexcept
2942 {
2943  return find(str.data(), pos, str.size());
2944 }
2945 
2957 template <typename CharT, typename Traits>
2958 typename basic_string<CharT, Traits>::size_type
2959 basic_string<CharT, Traits>::find(const CharT *s, size_type pos,
2960  size_type count) const
2961 {
2962  auto sz = size();
2963 
2964  if (pos > sz)
2965  return npos;
2966 
2967  if (count == 0)
2968  return pos;
2969 
2970  while (pos + count <= sz) {
2971  auto found = traits_type::find(cdata() + pos, sz - pos, s[0]);
2972  if (!found)
2973  return npos;
2974  pos = static_cast<size_type>(std::distance(cdata(), found));
2975  if (traits_type::compare(found, s, count) == 0) {
2976  return pos;
2977  }
2978  ++pos;
2979  }
2980  return npos;
2981 }
2982 
2993 template <typename CharT, typename Traits>
2994 typename basic_string<CharT, Traits>::size_type
2995 basic_string<CharT, Traits>::find(const CharT *s, size_type pos) const
2996 {
2997  return find(s, pos, traits_type::length(s));
2998 }
2999 
3009 template <typename CharT, typename Traits>
3010 typename basic_string<CharT, Traits>::size_type
3011 basic_string<CharT, Traits>::find(CharT ch, size_type pos) const noexcept
3012 {
3013  return find(&ch, pos, 1);
3014 }
3015 
3026 template <typename CharT, typename Traits>
3027 typename basic_string<CharT, Traits>::size_type
3028 basic_string<CharT, Traits>::rfind(const basic_string &str, size_type pos) const
3029  noexcept
3030 {
3031  return rfind(str.cdata(), pos, str.size());
3032 }
3033 
3050 template <typename CharT, typename Traits>
3051 typename basic_string<CharT, Traits>::size_type
3052 basic_string<CharT, Traits>::rfind(const CharT *s, size_type pos,
3053  size_type count) const
3054 {
3055  if (count <= size()) {
3056  pos = (std::min)(size() - count, pos);
3057  do {
3058  if (traits_type::compare(cdata() + pos, s, count) == 0)
3059  return pos;
3060  } while (pos-- > 0);
3061  }
3062  return npos;
3063 }
3064 
3077 template <typename CharT, typename Traits>
3078 typename basic_string<CharT, Traits>::size_type
3079 basic_string<CharT, Traits>::rfind(const CharT *s, size_type pos) const
3080 {
3081  return rfind(s, pos, traits_type::length(s));
3082 }
3083 
3095 template <typename CharT, typename Traits>
3096 typename basic_string<CharT, Traits>::size_type
3097 basic_string<CharT, Traits>::rfind(CharT ch, size_type pos) const noexcept
3098 {
3099  return rfind(&ch, pos, 1);
3100 }
3101 
3111 template <typename CharT, typename Traits>
3112 typename basic_string<CharT, Traits>::size_type
3114  size_type pos) const noexcept
3115 {
3116  return find_first_of(str.cdata(), pos, str.size());
3117 }
3118 
3132 template <typename CharT, typename Traits>
3133 typename basic_string<CharT, Traits>::size_type
3134 basic_string<CharT, Traits>::find_first_of(const CharT *s, size_type pos,
3135  size_type count) const
3136 {
3137  size_type first_of = npos;
3138  for (const CharT *c = s; c != s + count; ++c) {
3139  size_type found = find(*c, pos);
3140  if (found != npos && found < first_of)
3141  first_of = found;
3142  }
3143  return first_of;
3144 }
3145 
3158 template <typename CharT, typename Traits>
3159 typename basic_string<CharT, Traits>::size_type
3160 basic_string<CharT, Traits>::find_first_of(const CharT *s, size_type pos) const
3161 {
3162  return find_first_of(s, pos, traits_type::length(s));
3163 }
3164 
3174 template <typename CharT, typename Traits>
3175 typename basic_string<CharT, Traits>::size_type
3176 basic_string<CharT, Traits>::find_first_of(CharT ch, size_type pos) const
3177  noexcept
3178 {
3179  return find(ch, pos);
3180 }
3181 
3191 template <typename CharT, typename Traits>
3192 typename basic_string<CharT, Traits>::size_type
3194  size_type pos) const noexcept
3195 {
3196  return find_first_not_of(str.cdata(), pos, str.size());
3197 }
3198 
3212 template <typename CharT, typename Traits>
3213 typename basic_string<CharT, Traits>::size_type
3215  size_type count) const
3216 {
3217  if (pos >= size())
3218  return npos;
3219 
3220  for (auto it = cbegin() + pos; it != cend(); ++it)
3221  if (!traits_type::find(s, count, *it))
3222  return static_cast<size_type>(
3223  std::distance(cbegin(), it));
3224  return npos;
3225 }
3226 
3239 template <typename CharT, typename Traits>
3240 typename basic_string<CharT, Traits>::size_type
3242  size_type pos) const
3243 {
3244  return find_first_not_of(s, pos, traits_type::length(s));
3245 }
3246 
3256 template <typename CharT, typename Traits>
3257 typename basic_string<CharT, Traits>::size_type
3259  noexcept
3260 {
3261  return find_first_not_of(&ch, pos, 1);
3262 }
3263 
3273 template <typename CharT, typename Traits>
3274 typename basic_string<CharT, Traits>::size_type
3276  size_type pos) const noexcept
3277 {
3278  return find_last_of(str.cdata(), pos, str.size());
3279 }
3280 
3294 template <typename CharT, typename Traits>
3295 typename basic_string<CharT, Traits>::size_type
3296 basic_string<CharT, Traits>::find_last_of(const CharT *s, size_type pos,
3297  size_type count) const
3298 {
3299  if (size() == 0 || count == 0)
3300  return npos;
3301 
3302  bool found = false;
3303  size_type last_of = 0;
3304  for (const CharT *c = s; c != s + count; ++c) {
3305  size_type position = rfind(*c, pos);
3306  if (position != npos) {
3307  found = true;
3308  if (position > last_of)
3309  last_of = position;
3310  }
3311  }
3312  if (!found)
3313  return npos;
3314  return last_of;
3315 }
3316 
3329 template <typename CharT, typename Traits>
3330 typename basic_string<CharT, Traits>::size_type
3331 basic_string<CharT, Traits>::find_last_of(const CharT *s, size_type pos) const
3332 {
3333  return find_last_of(s, pos, traits_type::length(s));
3334 }
3335 
3345 template <typename CharT, typename Traits>
3346 typename basic_string<CharT, Traits>::size_type
3347 basic_string<CharT, Traits>::find_last_of(CharT ch, size_type pos) const
3348  noexcept
3349 {
3350  return rfind(ch, pos);
3351 }
3352 
3362 template <typename CharT, typename Traits>
3363 typename basic_string<CharT, Traits>::size_type
3365  size_type pos) const noexcept
3366 {
3367  return find_last_not_of(str.cdata(), pos, str.size());
3368 }
3369 
3383 template <typename CharT, typename Traits>
3384 typename basic_string<CharT, Traits>::size_type
3386  size_type count) const
3387 {
3388  if (size() > 0) {
3389  pos = (std::min)(pos, size() - 1);
3390  do {
3391  if (!traits_type::find(s, count, *(cdata() + pos)))
3392  return pos;
3393 
3394  } while (pos-- > 0);
3395  }
3396  return npos;
3397 }
3398 
3411 template <typename CharT, typename Traits>
3412 typename basic_string<CharT, Traits>::size_type
3414  size_type pos) const
3415 {
3416  return find_last_not_of(s, pos, traits_type::length(s));
3417 }
3418 
3428 template <typename CharT, typename Traits>
3429 typename basic_string<CharT, Traits>::size_type
3431  noexcept
3432 {
3433  return find_last_not_of(&ch, pos, 1);
3434 }
3435 
3444 template <typename CharT, typename Traits>
3445 int
3447 {
3448  return compare(0, size(), other.cdata(), other.size());
3449 }
3450 
3459 template <typename CharT, typename Traits>
3460 int
3462  const std::basic_string<CharT> &other) const
3463 {
3464  return compare(0, size(), other.data(), other.size());
3465 }
3466 
3480 template <typename CharT, typename Traits>
3481 int
3482 basic_string<CharT, Traits>::compare(size_type pos, size_type count,
3483  const basic_string &other) const
3484 {
3485  return compare(pos, count, other.cdata(), other.size());
3486 }
3487 
3502 template <typename CharT, typename Traits>
3503 int
3505  size_type pos, size_type count,
3506  const std::basic_string<CharT> &other) const
3507 {
3508  return compare(pos, count, other.data(), other.size());
3509 }
3510 
3529 template <typename CharT, typename Traits>
3530 int
3531 basic_string<CharT, Traits>::compare(size_type pos1, size_type count1,
3532  const basic_string &other, size_type pos2,
3533  size_type count2) const
3534 {
3535  if (pos2 > other.size())
3536  throw std::out_of_range("Index out of range.");
3537 
3538  if (count2 > other.size() - pos2)
3539  count2 = other.size() - pos2;
3540 
3541  return compare(pos1, count1, other.cdata() + pos2, count2);
3542 }
3543 
3562 template <typename CharT, typename Traits>
3563 int
3564 basic_string<CharT, Traits>::compare(size_type pos1, size_type count1,
3565  const std::basic_string<CharT> &other,
3566  size_type pos2, size_type count2) const
3567 {
3568  if (pos2 > other.size())
3569  throw std::out_of_range("Index out of range.");
3570 
3571  if (count2 > other.size() - pos2)
3572  count2 = other.size() - pos2;
3573 
3574  return compare(pos1, count1, other.data() + pos2, count2);
3575 }
3576 
3585 template <typename CharT, typename Traits>
3586 int
3588 {
3589  return compare(0, size(), s, traits_type::length(s));
3590 }
3591 
3605 template <typename CharT, typename Traits>
3606 int
3607 basic_string<CharT, Traits>::compare(size_type pos, size_type count,
3608  const CharT *s) const
3609 {
3610  return compare(pos, count, s, traits_type::length(s));
3611 }
3612 
3616 template <typename CharT, typename Traits>
3617 const CharT *
3619 {
3620  return is_sso_used() ? sso_data().cdata() : non_sso_data().cdata();
3621 }
3622 
3626 template <typename CharT, typename Traits>
3627 const CharT *
3629 {
3630  return cdata();
3631 }
3632 
3636 template <typename CharT, typename Traits>
3637 const CharT *
3639 {
3640  return cdata();
3641 }
3642 
3646 template <typename CharT, typename Traits>
3647 typename basic_string<CharT, Traits>::size_type
3649 {
3650  return size();
3651 }
3652 
3656 template <typename CharT, typename Traits>
3657 typename basic_string<CharT, Traits>::size_type
3659 {
3660  return PMEMOBJ_MAX_ALLOC_SIZE / sizeof(CharT) - 1;
3661 }
3662 
3667 template <typename CharT, typename Traits>
3668 typename basic_string<CharT, Traits>::size_type
3670 {
3671  return is_sso_used() ? sso_capacity : non_sso_data().capacity() - 1;
3672 }
3673 
3693 template <typename CharT, typename Traits>
3694 void
3695 basic_string<CharT, Traits>::resize(size_type count, CharT ch)
3696 {
3697  if (count > max_size())
3698  throw std::length_error("Count exceeds max size.");
3699 
3700  auto sz = size();
3701 
3702  auto pop = get_pool();
3703 
3704  transaction::run(pop, [&] {
3705  if (count > sz) {
3706  append(count - sz, ch);
3707  } else if (is_sso_used()) {
3708  set_sso_size(count);
3709  sso_data()[count] = value_type('\0');
3710  } else {
3711  non_sso_data().resize(count + 1, ch);
3712  non_sso_data().back() = value_type('\0');
3713  }
3714  });
3715 }
3716 
3735 template <typename CharT, typename Traits>
3736 void
3738 {
3739  resize(count, CharT());
3740 }
3741 
3762 template <typename CharT, typename Traits>
3763 void
3765 {
3766  if (new_cap > max_size())
3767  throw std::length_error("New capacity exceeds max size.");
3768 
3769  if (new_cap < capacity() || new_cap <= sso_capacity)
3770  return;
3771 
3772  if (is_sso_used()) {
3773  auto pop = get_pool();
3774 
3775  transaction::run(pop, [&] { sso_to_large(new_cap); });
3776  } else {
3777  non_sso_data().reserve(new_cap + 1);
3778  }
3779 }
3780 
3794 template <typename CharT, typename Traits>
3795 void
3797 {
3798  if (is_sso_used())
3799  return;
3800 
3801  if (size() <= sso_capacity) {
3802  auto pop = get_pool();
3803 
3804  transaction::run(pop, [&] { large_to_sso(); });
3805  } else {
3806  non_sso_data().shrink_to_fit();
3807  }
3808 }
3809 
3819 template <typename CharT, typename Traits>
3820 void
3822 {
3823  erase(begin(), end());
3824 }
3825 
3838 template <typename CharT, typename Traits>
3839 void
3841 {
3842  auto pop = get_pool();
3843 
3844  transaction::run(pop, [&] {
3845  if (is_sso_used()) {
3846  add_sso_to_tx(0, get_sso_size() + 1);
3847  clear();
3848  /* sso.data destructor does not have to be called */
3849  } else {
3850  non_sso_data().free_data();
3851  detail::destroy<non_sso_type>(non_sso_data());
3852  enable_sso();
3853  }
3854  });
3855 }
3856 
3860 template <typename CharT, typename Traits>
3861 bool
3863 {
3864  return size() == 0;
3865 }
3866 
3867 template <typename CharT, typename Traits>
3868 bool
3870 {
3871  return (sso._size & _sso_mask) != 0;
3872 }
3873 
3874 template <typename CharT, typename Traits>
3875 void
3876 basic_string<CharT, Traits>::destroy_data()
3877 {
3878  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3879 
3880  if (is_sso_used()) {
3881  add_sso_to_tx(0, get_sso_size() + 1);
3882  /* sso.data destructor does not have to be called */
3883  } else {
3884  non_sso_data().free_data();
3885  detail::destroy<non_sso_type>(non_sso_data());
3886  }
3887 }
3888 
3895 template <typename CharT, typename Traits>
3896 template <typename InputIt, typename Enable>
3897 typename basic_string<CharT, Traits>::size_type
3898 basic_string<CharT, Traits>::get_size(InputIt first, InputIt last) const
3899 {
3900  return static_cast<size_type>(std::distance(first, last));
3901 }
3902 
3909 template <typename CharT, typename Traits>
3910 typename basic_string<CharT, Traits>::size_type
3911 basic_string<CharT, Traits>::get_size(size_type count, value_type ch) const
3912 {
3913  return count;
3914 }
3915 
3922 template <typename CharT, typename Traits>
3923 typename basic_string<CharT, Traits>::size_type
3925 {
3926  return other.size();
3927 }
3928 
3935 template <typename CharT, typename Traits>
3936 template <typename... Args>
3937 typename basic_string<CharT, Traits>::pointer
3939 {
3940  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3941 
3942  auto new_size = get_size(std::forward<Args>(args)...);
3943 
3944  /* If non_sso.data is used and there is enough capacity */
3945  if (!is_sso_used() && new_size <= capacity())
3946  return assign_large_data(std::forward<Args>(args)...);
3947 
3948  destroy_data();
3949 
3950  allocate(new_size);
3951  return initialize(std::forward<Args>(args)...);
3952 }
3953 
3964 template <typename CharT, typename Traits>
3965 template <typename... Args>
3966 typename basic_string<CharT, Traits>::pointer
3968 {
3969  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3970 
3971  if (is_sso_used()) {
3972  return assign_sso_data(std::forward<Args>(args)...);
3973  } else {
3974  return assign_large_data(std::forward<Args>(args)...);
3975  }
3976 }
3977 
3987 template <typename CharT, typename Traits>
3988 void
3990 {
3991  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3992 
3993  if (n <= sso_capacity) {
3994  enable_sso();
3995  } else {
3996  disable_sso();
3997  }
3998 
3999  /*
4000  * array is aggregate type so it's not required to call
4001  * a constructor.
4002  */
4003  if (!is_sso_used()) {
4004  detail::conditional_add_to_tx(&non_sso_data(), 1,
4005  POBJ_XADD_NO_SNAPSHOT);
4006  detail::create<non_sso_type>(&non_sso_data());
4007  non_sso_data().reserve(n + 1);
4008  }
4009 }
4010 
4014 template <typename CharT, typename Traits>
4015 template <typename InputIt, typename Enable>
4016 typename basic_string<CharT, Traits>::pointer
4018 {
4019  auto size = static_cast<size_type>(std::distance(first, last));
4020 
4021  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4022  assert(size <= sso_capacity);
4023 
4024  add_sso_to_tx(0, size + 1);
4025  std::copy(first, last, &sso_data()._data[0]);
4026 
4027  sso_data()._data[size] = value_type('\0');
4028 
4029  set_sso_size(size);
4030 
4031  return &sso_data()[0];
4032 }
4033 
4037 template <typename CharT, typename Traits>
4038 typename basic_string<CharT, Traits>::pointer
4039 basic_string<CharT, Traits>::assign_sso_data(size_type count, value_type ch)
4040 {
4041  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4042  assert(count <= sso_capacity);
4043 
4044  add_sso_to_tx(0, count + 1);
4045  traits_type::assign(&sso_data()._data[0], count, ch);
4046 
4047  sso_data()._data[count] = value_type('\0');
4048 
4049  set_sso_size(count);
4050 
4051  return &sso_data()[0];
4052 }
4053 
4058 template <typename CharT, typename Traits>
4059 template <typename InputIt, typename Enable>
4060 typename basic_string<CharT, Traits>::pointer
4062 {
4063  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4064 
4065  auto size = static_cast<size_type>(std::distance(first, last));
4066 
4067  non_sso_data().reserve(size + 1);
4068  non_sso_data().assign(first, last);
4069  non_sso_data().push_back(value_type('\0'));
4070 
4071  return non_sso_data().data();
4072 }
4073 
4078 template <typename CharT, typename Traits>
4079 typename basic_string<CharT, Traits>::pointer
4080 basic_string<CharT, Traits>::assign_large_data(size_type count, value_type ch)
4081 {
4082  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4083 
4084  non_sso_data().reserve(count + 1);
4085  non_sso_data().assign(count, ch);
4086  non_sso_data().push_back(value_type('\0'));
4087 
4088  return non_sso_data().data();
4089 }
4090 
4095 template <typename CharT, typename Traits>
4096 typename basic_string<CharT, Traits>::pointer
4098 {
4099  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4100 
4101  typename basic_string::pointer ptr;
4102 
4103  if (other.size() <= sso_capacity) {
4104  enable_sso();
4105  ptr = assign_sso_data(other.cbegin(), other.cend());
4106  } else {
4107  disable_sso();
4108  detail::conditional_add_to_tx(&non_sso_data(), 1,
4109  POBJ_XADD_NO_SNAPSHOT);
4110  detail::create<non_sso_type>(&non_sso_data());
4111 
4112  assert(!other.is_sso_used());
4113  non_sso_data() = std::move(other.non_sso_data());
4114 
4115  ptr = non_sso_data().data();
4116  }
4117 
4118  if (other.is_sso_used())
4119  other.initialize(0U, value_type('\0'));
4120 
4121  return ptr;
4122 }
4123 
4127 template <typename CharT, typename Traits>
4128 void
4130 {
4131  pool_base pb = get_pool();
4132  transaction::run(pb, [&] {
4133  if (is_sso_used() && other.is_sso_used()) {
4134  sso_data().swap(other.sso_data());
4135  pmem::obj::swap(sso._size, other.sso._size);
4136  } else if (!is_sso_used() && !other.is_sso_used()) {
4137  non_sso_data().swap(other.non_sso_data());
4138  } else {
4139  basic_string *_short, *_long;
4140  if (size() > other.size()) {
4141  _short = &other;
4142  _long = this;
4143  } else {
4144  _short = this;
4145  _long = &other;
4146  }
4147 
4148  std::basic_string<CharT, Traits> tmp(_short->c_str(),
4149  _short->size());
4150  *_short = *_long;
4151  *_long = tmp;
4152  }
4153  });
4154 }
4155 
4159 template <typename CharT, typename Traits>
4161 {
4162  return basic_string_view<CharT, Traits>(cdata(), length());
4163 }
4164 
4168 template <typename CharT, typename Traits>
4169 pool_base
4171 {
4172  return pmem::obj::pool_by_vptr(this);
4173 }
4174 
4178 template <typename CharT, typename Traits>
4179 void
4181 {
4182  if (pmemobj_pool_by_ptr(this) == nullptr)
4183  throw pmem::pool_error("Object is not on pmem.");
4184 }
4185 
4189 template <typename CharT, typename Traits>
4190 void
4192 {
4193  if (pmemobj_tx_stage() != TX_STAGE_WORK)
4195  "Call made out of transaction scope.");
4196 }
4197 
4202 template <typename CharT, typename Traits>
4203 void
4205 {
4206  check_pmem();
4207  check_tx_stage_work();
4208 }
4209 
4213 template <typename CharT, typename Traits>
4214 void
4216  size_type num) const
4217 {
4218  assert(idx_first + num <= sso_capacity + 1);
4219  assert(is_sso_used());
4220 
4221  auto initialized_num = get_sso_size() + 1 - idx_first;
4222 
4223  /* Snapshot elements in range [idx_first, sso_size + 1 (null)) */
4224  detail::conditional_add_to_tx(&sso_data()._data[0] + idx_first,
4225  (std::min)(initialized_num, num));
4226 
4227  if (num > initialized_num) {
4228  /* Elements after sso_size + 1 do not have to be snapshotted */
4229  detail::conditional_add_to_tx(
4230  &sso_data()._data[0] + get_sso_size() + 1,
4231  num - initialized_num, POBJ_XADD_NO_SNAPSHOT);
4232  }
4233 }
4234 
4238 template <typename CharT, typename Traits>
4239 typename basic_string<CharT, Traits>::size_type
4241 {
4242  return sso._size & ~_sso_mask;
4243 }
4244 
4248 template <typename CharT, typename Traits>
4249 void
4251 {
4252  /* temporary size_type must be created to avoid undefined reference
4253  * linker error */
4254  sso._size |= (size_type)(_sso_mask);
4255 }
4256 
4260 template <typename CharT, typename Traits>
4261 void
4263 {
4264  sso._size &= ~_sso_mask;
4265 }
4266 
4270 template <typename CharT, typename Traits>
4271 void
4273 {
4274  sso._size = new_size | _sso_mask;
4275 }
4276 
4288 template <typename CharT, typename Traits>
4289 void
4291 {
4292  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4293  assert(new_capacity > sso_capacity);
4294  assert(is_sso_used());
4295 
4296  auto sz = size();
4297 
4298  sso_type tmp;
4299  std::copy(cbegin(), cend(), tmp.data());
4300  tmp[sz] = value_type('\0');
4301 
4302  destroy_data();
4303  allocate(new_capacity);
4304 
4305  auto begin = tmp.cbegin();
4306  auto end = begin + sz;
4307 
4308  initialize(begin, end);
4309 
4310  assert(!is_sso_used());
4311 };
4312 
4322 template <typename CharT, typename Traits>
4323 void
4325 {
4326  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4327  assert(!is_sso_used());
4328 
4329  auto sz = size();
4330 
4331  assert(sz <= sso_capacity);
4332 
4333  sso_type tmp;
4334  std::copy(cbegin(), cbegin() + sz, tmp.data());
4335  tmp[sz] = value_type('\0');
4336 
4337  destroy_data();
4338  allocate(sz);
4339 
4340  auto begin = tmp.cbegin();
4341  auto end = begin + sz;
4342 
4343  initialize(begin, end);
4344 
4345  assert(is_sso_used());
4346 };
4347 
4348 template <typename CharT, typename Traits>
4351 {
4352  assert(!is_sso_used());
4353  return non_sso._data;
4354 }
4355 
4356 template <typename CharT, typename Traits>
4357 typename basic_string<CharT, Traits>::sso_type &
4358 basic_string<CharT, Traits>::sso_data()
4359 {
4360  assert(is_sso_used());
4361  return sso._data;
4362 }
4363 
4364 template <typename CharT, typename Traits>
4365 const typename basic_string<CharT, Traits>::non_sso_type &
4366 basic_string<CharT, Traits>::non_sso_data() const
4367 {
4368  assert(!is_sso_used());
4369  return non_sso._data;
4370 }
4371 
4372 template <typename CharT, typename Traits>
4373 const typename basic_string<CharT, Traits>::sso_type &
4374 basic_string<CharT, Traits>::sso_data() const
4375 {
4376  assert(is_sso_used());
4377  return sso._data;
4378 }
4379 
4384 template <typename CharT, typename Traits>
4385 template <typename T, typename Enable>
4386 basic_string<CharT, Traits> &
4388 {
4389  return erase(static_cast<size_type>(param));
4390 }
4391 
4396 template <typename CharT, typename Traits>
4397 template <typename T, typename Enable>
4400 {
4401  return erase(static_cast<const_iterator>(param));
4402 }
4403 
4409 template <typename CharT, typename Traits>
4410 template <typename T, typename Enable>
4412 basic_string<CharT, Traits>::insert(T param, size_type count, CharT ch)
4413 {
4414  return insert(static_cast<size_type>(param), count, ch);
4415 }
4416 
4422 template <typename CharT, typename Traits>
4423 template <typename T, typename Enable>
4425 basic_string<CharT, Traits>::insert(T param, size_type count, CharT ch)
4426 {
4427  return insert(static_cast<const_iterator>(param), count, ch);
4428 }
4429 
4433 template <class CharT, class Traits>
4434 bool
4436  const basic_string<CharT, Traits> &rhs)
4437 {
4438  return lhs.compare(rhs) == 0;
4439 }
4440 
4444 template <class CharT, class Traits>
4445 bool
4447  const basic_string<CharT, Traits> &rhs)
4448 {
4449  return lhs.compare(rhs) != 0;
4450 }
4451 
4455 template <class CharT, class Traits>
4456 bool
4458  const basic_string<CharT, Traits> &rhs)
4459 {
4460  return lhs.compare(rhs) < 0;
4461 }
4462 
4466 template <class CharT, class Traits>
4467 bool
4469  const basic_string<CharT, Traits> &rhs)
4470 {
4471  return lhs.compare(rhs) <= 0;
4472 }
4473 
4477 template <class CharT, class Traits>
4478 bool
4480  const basic_string<CharT, Traits> &rhs)
4481 {
4482  return lhs.compare(rhs) > 0;
4483 }
4484 
4488 template <class CharT, class Traits>
4489 bool
4491  const basic_string<CharT, Traits> &rhs)
4492 {
4493  return lhs.compare(rhs) >= 0;
4494 }
4495 
4499 template <class CharT, class Traits>
4500 bool
4501 operator==(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4502 {
4503  return rhs.compare(lhs) == 0;
4504 }
4505 
4509 template <class CharT, class Traits>
4510 bool
4511 operator!=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4512 {
4513  return rhs.compare(lhs) != 0;
4514 }
4515 
4519 template <class CharT, class Traits>
4520 bool
4521 operator<(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4522 {
4523  return rhs.compare(lhs) > 0;
4524 }
4525 
4529 template <class CharT, class Traits>
4530 bool
4531 operator<=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4532 {
4533  return rhs.compare(lhs) >= 0;
4534 }
4535 
4539 template <class CharT, class Traits>
4540 bool
4541 operator>(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4542 {
4543  return rhs.compare(lhs) < 0;
4544 }
4545 
4549 template <class CharT, class Traits>
4550 bool
4551 operator>=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4552 {
4553  return rhs.compare(lhs) <= 0;
4554 }
4555 
4559 template <class CharT, class Traits>
4560 bool
4561 operator==(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4562 {
4563  return lhs.compare(rhs) == 0;
4564 }
4565 
4569 template <class CharT, class Traits>
4570 bool
4571 operator!=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4572 {
4573  return lhs.compare(rhs) != 0;
4574 }
4575 
4579 template <class CharT, class Traits>
4580 bool
4581 operator<(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4582 {
4583  return lhs.compare(rhs) < 0;
4584 }
4585 
4589 template <class CharT, class Traits>
4590 bool
4591 operator<=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4592 {
4593  return lhs.compare(rhs) <= 0;
4594 }
4595 
4599 template <class CharT, class Traits>
4600 bool
4601 operator>(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4602 {
4603  return lhs.compare(rhs) > 0;
4604 }
4605 
4609 template <class CharT, class Traits>
4610 bool
4611 operator>=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4612 {
4613  return lhs.compare(rhs) >= 0;
4614 }
4615 
4619 template <class CharT, class Traits>
4620 bool
4621 operator==(const std::basic_string<CharT, Traits> &lhs,
4622  const basic_string<CharT, Traits> &rhs)
4623 {
4624  return rhs.compare(lhs) == 0;
4625 }
4626 
4630 template <class CharT, class Traits>
4631 bool
4632 operator!=(const std::basic_string<CharT, Traits> &lhs,
4633  const basic_string<CharT, Traits> &rhs)
4634 {
4635  return rhs.compare(lhs) != 0;
4636 }
4637 
4641 template <class CharT, class Traits>
4642 bool
4643 operator<(const std::basic_string<CharT, Traits> &lhs,
4644  const basic_string<CharT, Traits> &rhs)
4645 {
4646  return rhs.compare(lhs) > 0;
4647 }
4648 
4652 template <class CharT, class Traits>
4653 bool
4654 operator<=(const std::basic_string<CharT, Traits> &lhs,
4655  const basic_string<CharT, Traits> &rhs)
4656 {
4657  return rhs.compare(lhs) >= 0;
4658 }
4659 
4663 template <class CharT, class Traits>
4664 bool
4665 operator>(const std::basic_string<CharT, Traits> &lhs,
4666  const basic_string<CharT, Traits> &rhs)
4667 {
4668  return rhs.compare(lhs) < 0;
4669 }
4670 
4674 template <class CharT, class Traits>
4675 bool
4676 operator>=(const std::basic_string<CharT, Traits> &lhs,
4677  const basic_string<CharT, Traits> &rhs)
4678 {
4679  return rhs.compare(lhs) <= 0;
4680 }
4681 
4685 template <class CharT, class Traits>
4686 bool
4688  const std::basic_string<CharT, Traits> &rhs)
4689 {
4690  return lhs.compare(rhs) == 0;
4691 }
4692 
4696 template <class CharT, class Traits>
4697 bool
4699  const std::basic_string<CharT, Traits> &rhs)
4700 {
4701  return lhs.compare(rhs) != 0;
4702 }
4703 
4707 template <class CharT, class Traits>
4708 bool
4710  const std::basic_string<CharT, Traits> &rhs)
4711 {
4712  return lhs.compare(rhs) < 0;
4713 }
4714 
4718 template <class CharT, class Traits>
4719 bool
4721  const std::basic_string<CharT, Traits> &rhs)
4722 {
4723  return lhs.compare(rhs) <= 0;
4724 }
4725 
4729 template <class CharT, class Traits>
4730 bool
4732  const std::basic_string<CharT, Traits> &rhs)
4733 {
4734  return lhs.compare(rhs) > 0;
4735 }
4736 
4740 template <class CharT, class Traits>
4741 bool
4743  const std::basic_string<CharT, Traits> &rhs)
4744 {
4745  return lhs.compare(rhs) >= 0;
4746 }
4747 
4751 template <class CharT, class Traits>
4752 void
4754 {
4755  return lhs.swap(rhs);
4756 }
4757 
4758 } /* namespace obj */
4759 
4760 } /* namespace pmem */
4761 
4762 #endif /* LIBPMEMOBJ_CPP_BASIC_STRING_HPP */
pmem::obj::basic_string_view
Our partial std::string_view implementation.
Definition: string_view.hpp:44
pmem::obj::basic_string::sso_to_large
void sso_to_large(size_t new_capacity)
Resize sso string to large string.
Definition: basic_string.hpp:4290
iterator_traits.hpp
Common iterator traits.
pmem::obj::basic_string::clear
void clear()
Remove all characters from the string transactionally.
Definition: basic_string.hpp:3821
pmem::obj::basic_string::check_pmem
void check_pmem() const
Definition: basic_string.hpp:4180
pmem::obj::basic_string::assign
basic_string & assign(size_type count, CharT ch)
Replace the contents with count copies of character ch transactionally.
Definition: basic_string.hpp:896
pmem::obj::operator>
bool operator>(const basic_string< CharT, Traits > &lhs, const std::basic_string< CharT, Traits > &rhs)
Non-member greater than operator.
Definition: basic_string.hpp:4731
pmem::obj::operator==
bool operator==(const basic_string< CharT, Traits > &lhs, const std::basic_string< CharT, Traits > &rhs)
Non-member equal operator.
Definition: basic_string.hpp:4687
vector.hpp
Vector container with std::vector compatible interface.
pmem::obj::basic_string::check_pmem_tx
void check_pmem_tx() const
Definition: basic_string.hpp:4204
pmem::pool_error
Custom pool error class.
Definition: pexceptions.hpp:47
utils.hpp
Libpmemobj C++ utils.
pmem::obj::basic_string::find_first_of
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:3113
pmem::obj::basic_string::get_sso_size
size_type get_sso_size() const
Return size of sso string.
Definition: basic_string.hpp:4240
pmem::obj::basic_string::c_str
const CharT * c_str() const noexcept
Definition: basic_string.hpp:3638
pmem::obj::basic_string::operator+=
basic_string & operator+=(const basic_string &str)
Append string str transactionally.
Definition: basic_string.hpp:1946
pmem::obj::basic_string::size
size_type size() const noexcept
Definition: basic_string.hpp:1473
string_view.hpp
Our partial std::string_view implementation.
pmem
Persistent memory namespace.
Definition: allocation_flag.hpp:15
pmem::obj::basic_string::rfind
size_type rfind(const basic_string &str, size_type pos=npos) const noexcept
Finds the last substring equal to str.
Definition: basic_string.hpp:3028
pmem::obj::begin
pmem::obj::array< T, N >::iterator begin(pmem::obj::array< T, N > &a)
Non-member begin.
Definition: array.hpp:800
common.hpp
Commonly used functionality.
pmem::obj::basic_string::data
CharT * data()
Definition: basic_string.hpp:1491
pmem::obj::array::cbegin
const_iterator cbegin() const noexcept
Returns const iterator to the beginning.
Definition: array.hpp:307
pmem::obj::basic_string::find_first_not_of
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:3193
pmem::obj::basic_string::erase
basic_string & erase(size_type index=0, size_type count=npos)
Remove characters from string starting at index transactionally.
Definition: basic_string.hpp:1517
pmem::obj::basic_string::find
size_type find(const basic_string &str, size_type pos=0) const noexcept
Finds the first substring equal str.
Definition: basic_string.hpp:2940
array.hpp
Array container with std::array compatible interface.
pmem::obj::basic_string::enable_sso
void enable_sso()
Enable sso string.
Definition: basic_string.hpp:4250
pmem::obj::basic_string::initialize
pointer initialize(Args &&... args)
Generic function which initializes memory based on provided parameters - forwards parameters to initi...
Definition: basic_string.hpp:3967
pmem::obj::basic_string::cfront
const CharT & cfront() const
Access first element.
Definition: basic_string.hpp:1420
pmem::obj::operator>=
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:4742
pmem::obj::basic_string::insert
basic_string & insert(size_type index, size_type count, CharT ch)
Insert count copies of ch character at index transactionally.
Definition: basic_string.hpp:2050
pmem::obj::basic_string::replace_content
pointer replace_content(Args &&... args)
Generic function which replace_content current content based on provided parameters.
Definition: basic_string.hpp:3938
pmem::obj::p< size_type >
pmem::obj::basic_string::const_at
const_reference const_at(size_type n) const
Access element at specific index with bounds checking.
Definition: basic_string.hpp:1340
pmem::obj::basic_string::length
size_type length() const noexcept
Definition: basic_string.hpp:3648
pmem::obj::basic_string::back
CharT & back()
Access last element and snapshot it if there is an active transaction.
Definition: basic_string.hpp:1436
pmem::obj::basic_string::cback
const CharT & cback() const
Access last element.
Definition: basic_string.hpp:1463
pmem::obj::crbegin
pmem::obj::array< T, N >::const_reverse_iterator crbegin(const pmem::obj::array< T, N > &a)
Non-member crbegin.
Definition: array.hpp:780
pmem::obj::basic_string::find_last_of
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:3275
pmem::obj::basic_string::swap
void swap(basic_string &other)
Swap the content of persistent strings.
Definition: basic_string.hpp:4129
pmem::obj::basic_string::set_sso_size
void set_sso_size(size_type new_size)
Set size for sso.
Definition: basic_string.hpp:4272
pmem::obj::basic_string::pop_back
void pop_back()
Remove the last character from the string transactionally.
Definition: basic_string.hpp:1622
pmem::obj::basic_string::capacity
size_type capacity() const noexcept
Definition: basic_string.hpp:3669
pmem::obj::basic_string::basic_string
basic_string()
Default constructor.
Definition: basic_string.hpp:423
slice.hpp
Interface to access sequence of objects.
pmem::obj::transaction::run
static void run(pool_base &pool, std::function< void()> tx, Locks &... locks)
Execute a closure-like transaction and lock locks.
Definition: transaction.hpp:406
pmem::obj::basic_string::push_back
void push_back(CharT ch)
Append character ch at the end of the string transactionally.
Definition: basic_string.hpp:1921
pmem::obj::basic_string::disable_sso
void disable_sso()
Disable sso string.
Definition: basic_string.hpp:4262
pmem::obj::basic_string::crend
const_reverse_iterator crend() const noexcept
Return a const reverse iterator to the end.
Definition: basic_string.hpp:1280
pmem::obj::basic_string::copy
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:2872
pmem::obj::basic_string::find_last_not_of
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:3364
pmem::detail::basic_contiguous_iterator
Default non-const iterator which adds element to a transaction on every access.
Definition: contiguous_iterator.hpp:331
pmem::obj::basic_string::get_pool
pool_base get_pool() const
Return pool_base instance and assert that object is on pmem.
Definition: basic_string.hpp:4170
pmem::obj::basic_string::cend
const_iterator cend() const noexcept
Return const iterator to past the end.
Definition: basic_string.hpp:1202
pmem::obj::basic_string::shrink_to_fit
void shrink_to_fit()
Remove unused capacity transactionally.
Definition: basic_string.hpp:3796
pmem::obj::cend
pmem::obj::array< T, N >::const_iterator cend(const pmem::obj::array< T, N > &a)
Non-member cend.
Definition: array.hpp:770
pmem::obj::basic_string::max_size
size_type max_size() const noexcept
Definition: basic_string.hpp:3658
pmem::obj::basic_string::add_sso_to_tx
void add_sso_to_tx(size_type first, size_type num) const
Snapshot sso data.
Definition: basic_string.hpp:4215
pmem::obj::basic_string::get_size
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:3898
pmem::obj::basic_string::free_data
void free_data()
Clears the content of a string and frees all allocated persistent memory for data transactionally.
Definition: basic_string.hpp:3840
pmem::obj::vector< value_type >
pmem::obj::operator!=
bool operator!=(const basic_string< CharT, Traits > &lhs, const std::basic_string< CharT, Traits > &rhs)
Non-member not equal operator.
Definition: basic_string.hpp:4698
contiguous_iterator.hpp
Iterators for contiguous persistent containers.
transaction.hpp
C++ pmemobj transactions.
pmem::obj::basic_string::empty
bool empty() const noexcept
Definition: basic_string.hpp:3862
pmem::obj::basic_string::check_tx_stage_work
void check_tx_stage_work() const
Definition: basic_string.hpp:4191
pmem::detail::is_input_iterator
Type trait to determine if a given parameter type satisfies requirements of InputIterator.
Definition: iterator_traits.hpp:47
pmem::obj::basic_string::begin
iterator begin()
Return an iterator to the beginning.
Definition: basic_string.hpp:1138
pmem::obj::basic_string::allocate
void allocate(size_type capacity)
Allocate storage for container of n elements.
Definition: basic_string.hpp:3989
pmem::obj::basic_string::compare
int compare(const basic_string &other) const
Compares this string to other.
Definition: basic_string.hpp:3446
pmem::obj::operator<
bool operator<(const basic_string< CharT, Traits > &lhs, const std::basic_string< CharT, Traits > &rhs)
Non-member less than operator.
Definition: basic_string.hpp:4709
pmem::obj::basic_string::replace
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:2429
pmem::obj::end
pmem::obj::array< T, N >::iterator end(pmem::obj::array< T, N > &a)
Non-member end.
Definition: array.hpp:820
pmem::obj::basic_string::large_to_sso
void large_to_sso()
Resize large string to sso string of size() size.
Definition: basic_string.hpp:4324
pmem::obj::basic_string::resize
void resize(size_type count, CharT ch)
Resize the string to count characters transactionally.
Definition: basic_string.hpp:3695
pmem::obj::array::data
T * data()
Returns raw pointer to the underlying data and adds entire array to a transaction.
Definition: array.hpp:245
pmem::obj::basic_string::append
basic_string & append(size_type count, CharT ch)
Append count copies of character ch to the string transactionally.
Definition: basic_string.hpp:1648
pmem::obj::basic_string::cdata
const CharT * cdata() const noexcept
Definition: basic_string.hpp:3618
pmem::obj::cbegin
pmem::obj::array< T, N >::const_iterator cbegin(const pmem::obj::array< T, N > &a)
Non-member cbegin.
Definition: array.hpp:760
pmem::obj::basic_string
pmem::obj::string - persistent container with std::basic_string compatible interface.
Definition: basic_string.hpp:46
pmem::obj::basic_string::assign_large_data
pointer assign_large_data(InputIt first, InputIt last)
Initialize non_sso.data - call constructor of non_sso.data.
Definition: basic_string.hpp:4061
pmem::obj::basic_string::operator[]
reference operator[](size_type n)
Access element at specific index and snapshot it if there is an active transaction.
Definition: basic_string.hpp:1363
pmem::obj::basic_string::end
iterator end()
Return an iterator to past the end.
Definition: basic_string.hpp:1176
pmem::obj::array< value_type, sso_capacity+1 >
pmem::obj::basic_string::for_each_ptr
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:1124
pmem::obj::operator<=
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:4720
pmem::obj::basic_string::reserve
void reserve(size_type new_cap=0)
Increase the capacity of the string to new_cap transactionally.
Definition: basic_string.hpp:3764
pext.hpp
Convenience extensions for the resides on pmem property template.
life.hpp
Functions for destroying arrays.
pmem::obj::swap
void swap(basic_string< CharT, Traits > &lhs, basic_string< CharT, Traits > &rhs)
Swap the content of persistent strings.
Definition: basic_string.hpp:4753
pmem::obj::basic_string_view::data
const CharT * data() const noexcept
Returns pointer to data stored in this pmem::obj::string_view.
Definition: string_view.hpp:138
pmem::obj::persistent_ptr_base
Persistent_ptr base (non-template) class.
Definition: persistent_ptr_base.hpp:42
pmem::obj::basic_string::move_data
pointer move_data(basic_string &&other)
Move initialize for basic_string.
Definition: basic_string.hpp:4097
pmem::obj::crend
pmem::obj::array< T, N >::const_reverse_iterator crend(const pmem::obj::array< T, N > &a)
Non-member crend.
Definition: array.hpp:790
pmem::transaction_scope_error
Custom transaction error class.
Definition: pexceptions.hpp:163
pmem::obj::pool_by_vptr
pool_base pool_by_vptr(const T *that)
Retrieve pool handle for the given pointer.
Definition: utils.hpp:32
pmem::obj::basic_string::rend
reverse_iterator rend()
Return a reverse iterator to the end.
Definition: basic_string.hpp:1254
pmem::obj::basic_string::operator=
basic_string & operator=(const basic_string &other)
Copy assignment operator.
Definition: basic_string.hpp:782
pmem::obj::pool_base
The non-template pool base class.
Definition: pool.hpp:46
pmem::obj::basic_string::cbegin
const_iterator cbegin() const noexcept
Return const iterator to the beginning.
Definition: basic_string.hpp:1163
pmem::obj::basic_string::crbegin
const_reverse_iterator crbegin() const noexcept
Return a const reverse iterator to the beginning.
Definition: basic_string.hpp:1241
pmem::obj::basic_string::front
CharT & front()
Access first element and snapshot it if there is an active transaction.
Definition: basic_string.hpp:1393
persistent_ptr.hpp
Persistent smart pointer.
pmem::obj::basic_string::assign_sso_data
pointer assign_sso_data(InputIt first, InputIt last)
Initialize sso data.
Definition: basic_string.hpp:4017
pmem::obj::basic_string_view::size
size_type size() const noexcept
Returns count of characters stored in this pmem::obj::string_view data.
Definition: string_view.hpp:151
pmem::obj::basic_string::at
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:1300
pmem::obj::basic_string::~basic_string
~basic_string()
Destructor.
Definition: basic_string.hpp:762
pmem::obj::basic_string::rbegin
reverse_iterator rbegin()
Return a reverse iterator to the beginning.
Definition: basic_string.hpp:1215