PMDK C++ bindings  1.10
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>
27 
28 namespace pmem
29 {
30 
31 namespace obj
32 {
33 
40 template <typename CharT, typename Traits = std::char_traits<CharT>>
41 class basic_string {
42 public:
43  /* Member types */
44  using traits_type = Traits;
45  using value_type = CharT;
46  using size_type = std::size_t;
47  using difference_type = std::ptrdiff_t;
48  using reference = value_type &;
49  using const_reference = const value_type &;
50  using pointer = value_type *;
51  using const_pointer = const value_type *;
53  using const_iterator = const_pointer;
54  using reverse_iterator = std::reverse_iterator<iterator>;
55  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
56  using for_each_ptr_function =
57  std::function<void(persistent_ptr_base &)>;
58 
59  /* Number of characters which can be stored using sso */
60  static constexpr size_type sso_capacity = (32 - 8) / sizeof(CharT) - 1;
61 
62  /* Constructors */
63  basic_string();
64  basic_string(size_type count, CharT ch);
65  basic_string(const basic_string &other, size_type pos,
66  size_type count = npos);
67  basic_string(const std::basic_string<CharT> &other, size_type pos,
68  size_type count = npos);
69  basic_string(const CharT *s, size_type count);
70  basic_string(const CharT *s);
71  template <
72  typename InputIt,
73  typename Enable = typename std::enable_if<
75  basic_string(InputIt first, InputIt last);
76  basic_string(const basic_string &other);
77  basic_string(const std::basic_string<CharT> &other);
78  basic_string(basic_string &&other);
79  basic_string(std::initializer_list<CharT> ilist);
80 
81  /* Destructor */
82  ~basic_string();
83 
84  /* Assignment operators */
85  basic_string &operator=(const basic_string &other);
86  basic_string &operator=(const std::basic_string<CharT> &other);
88  basic_string &operator=(const CharT *s);
89  basic_string &operator=(CharT ch);
90  basic_string &operator=(std::initializer_list<CharT> ilist);
91 
92  /* Assignment methods */
93  basic_string &assign(size_type count, CharT ch);
94  basic_string &assign(const basic_string &other);
95  basic_string &assign(const std::basic_string<CharT> &other);
96  basic_string &assign(const basic_string &other, size_type pos,
97  size_type count = npos);
98  basic_string &assign(const std::basic_string<CharT> &other,
99  size_type pos, size_type count = npos);
100  basic_string &assign(const CharT *s, size_type count);
101  basic_string &assign(const CharT *s);
102  template <typename InputIt,
103  typename Enable = typename pmem::detail::is_input_iterator<
104  InputIt>::type>
105  basic_string &assign(InputIt first, InputIt last);
106  basic_string &assign(basic_string &&other);
107  basic_string &assign(std::initializer_list<CharT> ilist);
108 
109  /* Element access */
110  reference at(size_type n);
111  const_reference at(size_type n) const;
112  const_reference const_at(size_type n) const;
113  reference operator[](size_type n);
114  const_reference operator[](size_type n) const;
115  CharT &front();
116  const CharT &front() const;
117  const CharT &cfront() const;
118  CharT &back();
119  const CharT &back() const;
120  const CharT &cback() const;
121  CharT *data();
122  const CharT *data() const noexcept;
123  const CharT *cdata() const noexcept;
124  const CharT *c_str() const noexcept;
125  void for_each_ptr(for_each_ptr_function func);
126 
127  /* Iterators */
128  iterator begin();
129  const_iterator begin() const noexcept;
130  const_iterator cbegin() const noexcept;
131  iterator end();
132  const_iterator end() const noexcept;
133  const_iterator cend() const noexcept;
134  reverse_iterator rbegin();
135  const_reverse_iterator rbegin() const noexcept;
136  const_reverse_iterator crbegin() const noexcept;
137  reverse_iterator rend();
138  const_reverse_iterator rend() const noexcept;
139  const_reverse_iterator crend() const noexcept;
140 
141  /* Capacity */
142  bool empty() const noexcept;
143  size_type size() const noexcept;
144  size_type length() const noexcept;
145  size_type max_size() const noexcept;
146  size_type capacity() const noexcept;
147  void resize(size_type count, CharT ch);
148  void resize(size_type n);
149  void reserve(size_type new_cap = 0);
150  void shrink_to_fit();
151  void clear();
152  void free_data();
153 
154  /* Modifiers */
155  basic_string &erase(size_type index = 0, size_type count = npos);
156  iterator erase(const_iterator pos);
157  iterator erase(const_iterator first, const_iterator last);
158  /* We add following overloads to resolve erase(0) ambiguity */
159  template <typename T,
160  typename Enable = typename std::enable_if<
161  std::is_convertible<T, size_type>::value>::type>
162  basic_string &erase(T param);
163  template <typename T,
164  typename Enable = typename std::enable_if<
165  !std::is_convertible<T, size_type>::value>::type>
166  iterator erase(T param);
167  void pop_back();
168 
169  basic_string &append(size_type count, CharT ch);
170  basic_string &append(const basic_string &str);
171  basic_string &append(const basic_string &str, size_type pos,
172  size_type count = npos);
173  basic_string &append(const CharT *s, size_type count);
174  basic_string &append(const CharT *s);
175  template <typename InputIt,
176  typename Enable = typename pmem::detail::is_input_iterator<
177  InputIt>::type>
178  basic_string &append(InputIt first, InputIt last);
179  basic_string &append(std::initializer_list<CharT> ilist);
180  void push_back(CharT ch);
181  basic_string &operator+=(const basic_string &str);
182  basic_string &operator+=(const CharT *s);
183  basic_string &operator+=(CharT c);
184  basic_string &operator+=(std::initializer_list<CharT> ilist);
185 
186  basic_string &insert(size_type index, size_type count, CharT ch);
187  basic_string &insert(size_type index, const CharT *s);
188  basic_string &insert(size_type index, const CharT *s, size_type count);
189  basic_string &insert(size_type index, const basic_string &str);
190  basic_string &insert(size_type index1, const basic_string &str,
191  size_type index2, size_type count = npos);
192  iterator insert(const_iterator pos, CharT ch);
193  iterator insert(const_iterator pos, size_type count, CharT ch);
194  template <typename InputIt,
195  typename Enable = typename pmem::detail::is_input_iterator<
196  InputIt>::type>
197  iterator insert(const_iterator pos, InputIt first, InputIt last);
198  iterator insert(const_iterator pos, std::initializer_list<CharT> ilist);
199  template <typename T,
200  typename Enable = typename std::enable_if<
201  std::is_convertible<T, size_type>::value>::type>
202  basic_string &insert(T param, size_type count, CharT ch);
203  template <typename T,
204  typename Enable = typename std::enable_if<
205  !std::is_convertible<T, size_type>::value>::type>
206  iterator insert(T param, size_type count, CharT ch);
207 
208  basic_string &replace(size_type index, size_type count,
209  const basic_string &str);
210  basic_string &replace(const_iterator first, const_iterator last,
211  const basic_string &str);
212  basic_string &replace(size_type index, size_type count,
213  const basic_string &str, size_type index2,
214  size_type count2 = npos);
215  template <typename InputIt,
216  typename Enable = typename pmem::detail::is_input_iterator<
217  InputIt>::type>
218  basic_string &replace(const_iterator first, const_iterator last,
219  InputIt first2, InputIt last2);
220  basic_string &replace(const_iterator first, const_iterator last,
221  const CharT *s, size_type count2);
222  basic_string &replace(const_iterator first, const_iterator last,
223  const CharT *s);
224  basic_string &replace(size_type index, size_type count,
225  size_type count2, CharT ch);
226  basic_string &replace(const_iterator first, const_iterator last,
227  size_type count2, CharT ch);
228  basic_string &replace(size_type index, size_type count, const CharT *s,
229  size_type count2);
230  basic_string &replace(size_type index, size_type count, const CharT *s);
231  basic_string &replace(const_iterator first, const_iterator last,
232  std::initializer_list<CharT> ilist);
233 
234  size_type copy(CharT *s, size_type count, size_type index = 0) const;
235 
236  int compare(const basic_string &other) const;
237  int compare(const std::basic_string<CharT> &other) const;
238  int compare(size_type pos, size_type count,
239  const basic_string &other) const;
240  int compare(size_type pos, size_type count,
241  const std::basic_string<CharT> &other) const;
242  int compare(size_type pos1, size_type count1, const basic_string &other,
243  size_type pos2, size_type count2 = npos) const;
244  int compare(size_type pos1, size_type count1,
245  const std::basic_string<CharT> &other, size_type pos2,
246  size_type count2 = npos) const;
247  int compare(const CharT *s) const;
248  int compare(size_type pos, size_type count, const CharT *s) const;
249  int compare(size_type pos, size_type count1, const CharT *s,
250  size_type count2) const;
251 
252  /* Search */
253  size_type find(const basic_string &str, size_type pos = 0) const
254  noexcept;
255  size_type find(const CharT *s, size_type pos, size_type count) const;
256  size_type find(const CharT *s, size_type pos = 0) const;
257  size_type find(CharT ch, size_type pos = 0) const noexcept;
258  size_type rfind(const basic_string &str, size_type pos = npos) const
259  noexcept;
260  size_type rfind(const CharT *s, size_type pos, size_type count) const;
261  size_type rfind(const CharT *s, size_type pos = npos) const;
262  size_type rfind(CharT ch, size_type pos = npos) const noexcept;
263  size_type find_first_of(const basic_string &str,
264  size_type pos = 0) const noexcept;
265  size_type find_first_of(const CharT *s, size_type pos,
266  size_type count) const;
267  size_type find_first_of(const CharT *s, size_type pos = 0) const;
268  size_type find_first_of(CharT ch, size_type pos = 0) const noexcept;
269  size_type find_first_not_of(const basic_string &str,
270  size_type pos = 0) const noexcept;
271  size_type find_first_not_of(const CharT *s, size_type pos,
272  size_type count) const;
273  size_type find_first_not_of(const CharT *s, size_type pos = 0) const;
274  size_type find_first_not_of(CharT ch, size_type pos = 0) const noexcept;
275  size_type find_last_of(const basic_string &str,
276  size_type pos = npos) const noexcept;
277  size_type find_last_of(const CharT *s, size_type pos,
278  size_type count) const;
279  size_type find_last_of(const CharT *s, size_type pos = npos) const;
280  size_type find_last_of(CharT ch, size_type pos = npos) const noexcept;
281  size_type find_last_not_of(const basic_string &str,
282  size_type pos = npos) const noexcept;
283  size_type find_last_not_of(const CharT *s, size_type pos,
284  size_type count) const;
285  size_type find_last_not_of(const CharT *s, size_type pos = npos) const;
286  size_type find_last_not_of(CharT ch, size_type pos = npos) const
287  noexcept;
288 
289  void swap(basic_string &other);
290 
291  /* Special value. The exact meaning depends on the context. */
292  static const size_type npos = static_cast<size_type>(-1);
293 
294 private:
297 
315  union {
316  struct {
317  /*
318  * EXACTLY the same type as first member in vector
319  * Holds size for sso string, bit specified by _sso_mask
320  * indicates if sso is used.
321  */
322  p<size_type> _size;
323 
324  sso_type _data;
325  } sso;
326 
327  struct {
328  non_sso_type _data;
329  } non_sso;
330  };
331 
332  /*
333  * MSB is used because vector is known not to use entire range of
334  * size_type.
335  */
336  static constexpr size_type _sso_mask = 1ULL
337  << (std::numeric_limits<size_type>::digits - 1);
338 
339  /* helper functions */
340  bool is_sso_used() const;
341  void destroy_data();
342  template <
343  typename InputIt,
344  typename Enable = typename std::enable_if<
346  size_type get_size(InputIt first, InputIt last) const;
347  size_type get_size(size_type count, value_type ch) const;
348  size_type get_size(const basic_string &other) const;
349  template <typename... Args>
350  pointer replace_content(Args &&... args);
351  template <typename... Args>
352  pointer initialize(Args &&... args);
353  void allocate(size_type capacity);
354  template <
355  typename InputIt,
356  typename Enable = typename std::enable_if<
358  pointer assign_sso_data(InputIt first, InputIt last);
359  pointer assign_sso_data(size_type count, value_type ch);
360  pointer move_data(basic_string &&other);
361  template <
362  typename InputIt,
363  typename Enable = typename std::enable_if<
365  pointer assign_large_data(InputIt first, InputIt last);
366  pointer assign_large_data(size_type count, value_type ch);
367  pool_base get_pool() const;
368  void check_pmem() const;
369  void check_tx_stage_work() const;
370  void check_pmem_tx() const;
371  void add_sso_to_tx(size_type first, size_type num) const;
372  size_type get_sso_size() const;
373  void enable_sso();
374  void disable_sso();
375  void set_sso_size(size_type new_size);
376  void sso_to_large(size_t new_capacity);
377  void large_to_sso();
378  typename basic_string<CharT, Traits>::non_sso_type &non_sso_data();
379  typename basic_string<CharT, Traits>::sso_type &sso_data();
381  non_sso_data() const;
382  const typename basic_string<CharT, Traits>::sso_type &sso_data() const;
383 };
384 
394 template <typename CharT, typename Traits>
396 {
397  check_pmem_tx();
398  sso._size = 0;
399 
400  allocate(0);
401  initialize(0U, value_type('\0'));
402 }
403 
418 template <typename CharT, typename Traits>
420 {
421  check_pmem_tx();
422  sso._size = 0;
423 
424  allocate(count);
425  initialize(count, ch);
426 }
427 
445 template <typename CharT, typename Traits>
447  size_type pos, size_type count)
448 {
449  check_pmem_tx();
450  sso._size = 0;
451 
452  if (pos > other.size())
453  throw std::out_of_range("Index out of range.");
454 
455  if (count == npos || pos + count > other.size())
456  count = other.size() - pos;
457 
458  auto first = static_cast<difference_type>(pos);
459  auto last = first + static_cast<difference_type>(count);
460 
461  allocate(count);
462  initialize(other.cbegin() + first, other.cbegin() + last);
463 }
464 
483 template <typename CharT, typename Traits>
484 basic_string<CharT, Traits>::basic_string(const std::basic_string<CharT> &other,
485  size_type pos, size_type count)
486 {
487  check_pmem_tx();
488  sso._size = 0;
489 
490  if (pos > other.size())
491  throw std::out_of_range("Index out of range.");
492 
493  if (count == npos || pos + count > other.size())
494  count = other.size() - pos;
495 
496  auto first = static_cast<difference_type>(pos);
497  auto last = first + static_cast<difference_type>(count);
498 
499  allocate(count);
500  initialize(other.cbegin() + first, other.cbegin() + last);
501 }
502 
518 template <typename CharT, typename Traits>
519 basic_string<CharT, Traits>::basic_string(const CharT *s, size_type count)
520 {
521  check_pmem_tx();
522  sso._size = 0;
523 
524  allocate(count);
525  initialize(s, s + count);
526 }
527 
541 template <typename CharT, typename Traits>
543 {
544  check_pmem_tx();
545  sso._size = 0;
546 
547  auto length = traits_type::length(s);
548 
549  allocate(length);
550  initialize(s, s + length);
551 }
552 
569 template <typename CharT, typename Traits>
570 template <typename InputIt, typename Enable>
571 basic_string<CharT, Traits>::basic_string(InputIt first, InputIt last)
572 {
573  auto len = std::distance(first, last);
574  assert(len >= 0);
575 
576  check_pmem_tx();
577  sso._size = 0;
578 
579  allocate(static_cast<size_type>(len));
580  initialize(first, last);
581 }
582 
597 template <typename CharT, typename Traits>
599 {
600  check_pmem_tx();
601  sso._size = 0;
602 
603  allocate(other.size());
604  initialize(other.cbegin(), other.cend());
605 }
606 
622 template <typename CharT, typename Traits>
623 basic_string<CharT, Traits>::basic_string(const std::basic_string<CharT> &other)
624  : basic_string(other.cbegin(), other.cend())
625 {
626 }
627 
642 template <typename CharT, typename Traits>
644 {
645  check_pmem_tx();
646  sso._size = 0;
647 
648  move_data(std::move(other));
649 }
650 
665 template <typename CharT, typename Traits>
666 basic_string<CharT, Traits>::basic_string(std::initializer_list<CharT> ilist)
667 {
668  check_pmem_tx();
669  sso._size = 0;
670 
671  allocate(ilist.size());
672  initialize(ilist.begin(), ilist.end());
673 }
674 
678 template <typename CharT, typename Traits>
680 {
681  try {
682  free_data();
683  } catch (...) {
684  std::terminate();
685  }
686 }
687 
697 template <typename CharT, typename Traits>
700 {
701  return assign(other);
702 }
703 
714 template <typename CharT, typename Traits>
716 basic_string<CharT, Traits>::operator=(const std::basic_string<CharT> &other)
717 {
718  return assign(other);
719 }
720 
730 template <typename CharT, typename Traits>
733 {
734  return assign(std::move(other));
735 }
736 
745 template <typename CharT, typename Traits>
748 {
749  return assign(s);
750 }
751 
760 template <typename CharT, typename Traits>
763 {
764  return assign(1, ch);
765 }
766 
776 template <typename CharT, typename Traits>
778 basic_string<CharT, Traits>::operator=(std::initializer_list<CharT> ilist)
779 {
780  return assign(ilist);
781 }
782 
793 template <typename CharT, typename Traits>
795 basic_string<CharT, Traits>::assign(size_type count, CharT ch)
796 {
797  auto pop = get_pool();
798 
799  transaction::run(pop, [&] { replace_content(count, ch); });
800 
801  return *this;
802 }
803 
813 template <typename CharT, typename Traits>
816 {
817  if (&other == this)
818  return *this;
819 
820  auto pop = get_pool();
821 
823  pop, [&] { replace_content(other.cbegin(), other.cend()); });
824 
825  return *this;
826 }
827 
838 template <typename CharT, typename Traits>
840 basic_string<CharT, Traits>::assign(const std::basic_string<CharT> &other)
841 {
842  return assign(other.cbegin(), other.cend());
843 }
844 
857 template <typename CharT, typename Traits>
860  size_type count)
861 {
862  if (pos > other.size())
863  throw std::out_of_range("Index out of range.");
864 
865  if (count == npos || pos + count > other.size())
866  count = other.size() - pos;
867 
868  auto pop = get_pool();
869  auto first = static_cast<difference_type>(pos);
870  auto last = first + static_cast<difference_type>(count);
871 
872  transaction::run(pop, [&] {
873  replace_content(other.cbegin() + first, other.cbegin() + last);
874  });
875 
876  return *this;
877 }
878 
893 template <typename CharT, typename Traits>
895 basic_string<CharT, Traits>::assign(const std::basic_string<CharT> &other,
896  size_type pos, size_type count)
897 {
898  if (pos > other.size())
899  throw std::out_of_range("Index out of range.");
900 
901  if (count == npos || pos + count > other.size())
902  count = other.size() - pos;
903 
904  return assign(other.c_str() + pos, count);
905 }
906 
917 template <typename CharT, typename Traits>
919 basic_string<CharT, Traits>::assign(const CharT *s, size_type count)
920 {
921  auto pop = get_pool();
922 
923  transaction::run(pop, [&] { replace_content(s, s + count); });
924 
925  return *this;
926 }
927 
936 template <typename CharT, typename Traits>
939 {
940  auto pop = get_pool();
941 
942  auto length = traits_type::length(s);
943 
944  transaction::run(pop, [&] { replace_content(s, s + length); });
945 
946  return *this;
947 }
948 
960 template <typename CharT, typename Traits>
961 template <typename InputIt, typename Enable>
963 basic_string<CharT, Traits>::assign(InputIt first, InputIt last)
964 {
965  auto pop = get_pool();
966 
967  transaction::run(pop, [&] { replace_content(first, last); });
968 
969  return *this;
970 }
971 
981 template <typename CharT, typename Traits>
984 {
985  if (&other == this)
986  return *this;
987 
988  auto pop = get_pool();
989 
990  transaction::run(pop, [&] {
991  destroy_data();
992  move_data(std::move(other));
993  });
994 
995  return *this;
996 }
997 
1007 template <typename CharT, typename Traits>
1009 basic_string<CharT, Traits>::assign(std::initializer_list<CharT> ilist)
1010 {
1011  return assign(ilist.begin(), ilist.end());
1012 }
1013 
1021 template <typename CharT, typename Traits>
1022 void
1024 {
1025  if (!is_sso_used()) {
1026  non_sso._data.for_each_ptr(func);
1027  }
1028 }
1029 
1035 template <typename CharT, typename Traits>
1038 {
1039  return is_sso_used() ? iterator(&*sso_data().begin())
1040  : iterator(&*non_sso_data().begin());
1041 }
1042 
1048 template <typename CharT, typename Traits>
1049 typename basic_string<CharT, Traits>::const_iterator
1051 {
1052  return cbegin();
1053 }
1054 
1060 template <typename CharT, typename Traits>
1061 typename basic_string<CharT, Traits>::const_iterator
1063 {
1064  return is_sso_used() ? const_iterator(&*sso_data().cbegin())
1065  : const_iterator(&*non_sso_data().cbegin());
1066 }
1067 
1073 template <typename CharT, typename Traits>
1076 {
1077  return begin() + static_cast<difference_type>(size());
1078 }
1079 
1086 template <typename CharT, typename Traits>
1087 typename basic_string<CharT, Traits>::const_iterator
1089 {
1090  return cbegin() + static_cast<difference_type>(size());
1091 }
1092 
1099 template <typename CharT, typename Traits>
1100 typename basic_string<CharT, Traits>::const_iterator
1102 {
1103  return cbegin() + static_cast<difference_type>(size());
1104 }
1105 
1112 template <typename CharT, typename Traits>
1113 typename basic_string<CharT, Traits>::reverse_iterator
1115 {
1116  return reverse_iterator(end());
1117 }
1118 
1125 template <typename CharT, typename Traits>
1126 typename basic_string<CharT, Traits>::const_reverse_iterator
1128 {
1129  return crbegin();
1130 }
1131 
1138 template <typename CharT, typename Traits>
1139 typename basic_string<CharT, Traits>::const_reverse_iterator
1141 {
1142  return const_reverse_iterator(cend());
1143 }
1144 
1151 template <typename CharT, typename Traits>
1152 typename basic_string<CharT, Traits>::reverse_iterator
1154 {
1155  return reverse_iterator(begin());
1156 }
1157 
1164 template <typename CharT, typename Traits>
1165 typename basic_string<CharT, Traits>::const_reverse_iterator
1167 {
1168  return crend();
1169 }
1170 
1177 template <typename CharT, typename Traits>
1178 typename basic_string<CharT, Traits>::const_reverse_iterator
1180 {
1181  return const_reverse_iterator(cbegin());
1182 }
1183 
1197 template <typename CharT, typename Traits>
1198 typename basic_string<CharT, Traits>::reference
1200 {
1201  if (n >= size())
1202  throw std::out_of_range("string::at");
1203 
1204  return is_sso_used() ? sso_data()[n] : non_sso_data()[n];
1205 }
1206 
1217 template <typename CharT, typename Traits>
1218 typename basic_string<CharT, Traits>::const_reference
1220 {
1221  return const_at(n);
1222 }
1223 
1237 template <typename CharT, typename Traits>
1238 typename basic_string<CharT, Traits>::const_reference
1240 {
1241  if (n >= size())
1242  throw std::out_of_range("string::const_at");
1243 
1244  return is_sso_used()
1245  ? static_cast<const sso_type &>(sso_data())[n]
1246  : static_cast<const non_sso_type &>(non_sso_data())[n];
1247 }
1248 
1260 template <typename CharT, typename Traits>
1261 typename basic_string<CharT, Traits>::reference
1263 {
1264  return is_sso_used() ? sso_data()[n] : non_sso_data()[n];
1265 }
1266 
1274 template <typename CharT, typename Traits>
1275 typename basic_string<CharT, Traits>::const_reference
1277 {
1278  return is_sso_used() ? sso_data()[n] : non_sso_data()[n];
1279 }
1280 
1290 template <typename CharT, typename Traits>
1291 CharT &
1293 {
1294  return (*this)[0];
1295 }
1296 
1302 template <typename CharT, typename Traits>
1303 const CharT &
1305 {
1306  return cfront();
1307 }
1308 
1317 template <typename CharT, typename Traits>
1318 const CharT &
1320 {
1321  return static_cast<const basic_string &>(*this)[0];
1322 }
1323 
1333 template <typename CharT, typename Traits>
1334 CharT &
1336 {
1337  return (*this)[size() - 1];
1338 }
1339 
1345 template <typename CharT, typename Traits>
1346 const CharT &
1348 {
1349  return cback();
1350 }
1351 
1360 template <typename CharT, typename Traits>
1361 const CharT &
1363 {
1364  return static_cast<const basic_string &>(*this)[size() - 1];
1365 }
1366 
1370 template <typename CharT, typename Traits>
1371 typename basic_string<CharT, Traits>::size_type
1373 {
1374  if (is_sso_used())
1375  return get_sso_size();
1376  else if (non_sso_data().size() == 0)
1377  return 0;
1378  else
1379  return non_sso_data().size() - 1;
1380 }
1381 
1388 template <typename CharT, typename Traits>
1389 CharT *
1391 {
1392  return is_sso_used() ? sso_data().range(0, get_sso_size() + 1).begin()
1393  : non_sso_data().data();
1394 }
1395 
1414 template <typename CharT, typename Traits>
1416 basic_string<CharT, Traits>::erase(size_type index, size_type count)
1417 {
1418  auto sz = size();
1419 
1420  if (index > sz)
1421  throw std::out_of_range("Index exceeds size.");
1422 
1423  count = (std::min)(count, sz - index);
1424 
1425  auto pop = get_pool();
1426 
1427  auto first = begin() + static_cast<difference_type>(index);
1428  auto last = first + static_cast<difference_type>(count);
1429 
1430  if (is_sso_used()) {
1431  transaction::run(pop, [&] {
1432  auto move_len = sz - index - count;
1433  auto new_size = sz - count;
1434 
1435  if (move_len > 0) {
1436  auto range =
1437  sso_data().range(index, move_len + 1);
1438  traits_type::move(range.begin(), &*last,
1439  move_len);
1440 
1441  assert(range.end() - 1 ==
1442  &sso_data()._data[index + move_len]);
1443  }
1444 
1445  sso_data()[index + move_len] = value_type('\0');
1446  set_sso_size(new_size);
1447  });
1448  } else {
1449  non_sso_data().erase(first, last);
1450  }
1451 
1452  return *this;
1453 }
1454 
1471 template <typename CharT, typename Traits>
1474 {
1475  return erase(pos, pos + 1);
1476 }
1477 
1496 template <typename CharT, typename Traits>
1498 basic_string<CharT, Traits>::erase(const_iterator first, const_iterator last)
1499 {
1500  size_type index =
1501  static_cast<size_type>(std::distance(cbegin(), first));
1502  size_type len = static_cast<size_type>(std::distance(first, last));
1503 
1504  erase(index, len);
1505 
1506  return begin() + static_cast<difference_type>(index);
1507 }
1508 
1519 template <typename CharT, typename Traits>
1520 void
1522 {
1523  erase(size() - 1, 1);
1524 }
1525 
1545 template <typename CharT, typename Traits>
1547 basic_string<CharT, Traits>::append(size_type count, CharT ch)
1548 {
1549  auto sz = size();
1550  auto new_size = sz + count;
1551 
1552  if (new_size > max_size())
1553  throw std::length_error("Size exceeds max size.");
1554 
1555  if (is_sso_used()) {
1556  auto pop = get_pool();
1557 
1558  transaction::run(pop, [&] {
1559  if (new_size > sso_capacity) {
1560  sso_to_large(new_size);
1561 
1562  non_sso_data().insert(
1563  non_sso_data().cbegin() +
1564  static_cast<difference_type>(
1565  sz),
1566  count, ch);
1567  } else {
1568  add_sso_to_tx(sz, count + 1);
1569  traits_type::assign(&sso_data()._data[sz],
1570  count, ch);
1571 
1572  assert(new_size == sz + count);
1573  set_sso_size(new_size);
1574  sso_data()._data[new_size] = value_type('\0');
1575  }
1576  });
1577  } else {
1578  non_sso_data().insert(non_sso_data().cbegin() +
1579  static_cast<difference_type>(sz),
1580  count, ch);
1581  }
1582 
1583  return *this;
1584 }
1585 
1604 template <typename CharT, typename Traits>
1607 {
1608  return append(str.data(), str.size());
1609 }
1610 
1636 template <typename CharT, typename Traits>
1639  size_type count)
1640 {
1641  auto sz = str.size();
1642 
1643  if (pos > sz)
1644  throw std::out_of_range("Index out of range.");
1645 
1646  count = (std::min)(count, sz - pos);
1647 
1648  append(str.data() + pos, count);
1649 
1650  return *this;
1651 }
1652 
1672 template <typename CharT, typename Traits>
1674 basic_string<CharT, Traits>::append(const CharT *s, size_type count)
1675 {
1676  return append(s, s + count);
1677 }
1678 
1698 template <typename CharT, typename Traits>
1701 {
1702  return append(s, traits_type::length(s));
1703 }
1704 
1726 template <typename CharT, typename Traits>
1727 template <typename InputIt, typename Enable>
1729 basic_string<CharT, Traits>::append(InputIt first, InputIt last)
1730 {
1731  auto sz = size();
1732  auto count = static_cast<size_type>(std::distance(first, last));
1733  auto new_size = sz + count;
1734 
1735  if (new_size > max_size())
1736  throw std::length_error("Size exceeds max size.");
1737 
1738  if (is_sso_used()) {
1739  auto pop = get_pool();
1740 
1741  transaction::run(pop, [&] {
1742  if (new_size > sso_capacity) {
1743  /* 1) Cache C-style string in case of
1744  * self-append, because it will be destroyed
1745  * when switching from sso to large string.
1746  *
1747  * 2) We cache in std::vector instead of
1748  * std::string because of overload deduction
1749  * ambiguity on Windows
1750  */
1751  std::vector<value_type> str(first, last);
1752 
1753  sso_to_large(new_size);
1754  non_sso_data().insert(
1755  non_sso_data().cbegin() +
1756  static_cast<difference_type>(
1757  sz),
1758  str.begin(), str.end());
1759  } else {
1760  add_sso_to_tx(sz, count + 1);
1761  std::copy(first, last, &sso_data()._data[sz]);
1762 
1763  assert(new_size == sz + count);
1764  set_sso_size(new_size);
1765  sso_data()._data[new_size] = value_type('\0');
1766  }
1767  });
1768  } else {
1769  non_sso_data().insert(non_sso_data().cbegin() +
1770  static_cast<difference_type>(sz),
1771  first, last);
1772  }
1773 
1774  return *this;
1775 }
1776 
1795 template <typename CharT, typename Traits>
1797 basic_string<CharT, Traits>::append(std::initializer_list<CharT> ilist)
1798 {
1799  return append(ilist.begin(), ilist.end());
1800 }
1801 
1818 template <typename CharT, typename Traits>
1819 void
1821 {
1822  append(static_cast<size_type>(1), ch);
1823 }
1824 
1843 template <typename CharT, typename Traits>
1846 {
1847  return append(str);
1848 }
1849 
1869 template <typename CharT, typename Traits>
1872 {
1873  return append(s);
1874 }
1875 
1892 template <typename CharT, typename Traits>
1895 {
1896  push_back(ch);
1897 
1898  return *this;
1899 }
1900 
1919 template <typename CharT, typename Traits>
1921 basic_string<CharT, Traits>::operator+=(std::initializer_list<CharT> ilist)
1922 {
1923  return append(ilist);
1924 }
1925 
1947 template <typename CharT, typename Traits>
1949 basic_string<CharT, Traits>::insert(size_type index, size_type count, CharT ch)
1950 {
1951  if (index > size())
1952  throw std::out_of_range("Index out of range.");
1953 
1954  auto pos = cbegin() + static_cast<difference_type>(index);
1955 
1956  insert(pos, count, ch);
1957 
1958  return *this;
1959 }
1960 
1982 template <typename CharT, typename Traits>
1984 basic_string<CharT, Traits>::insert(size_type index, const CharT *s)
1985 {
1986  return insert(index, s, traits_type::length(s));
1987 }
1988 
2010 template <typename CharT, typename Traits>
2012 basic_string<CharT, Traits>::insert(size_type index, const CharT *s,
2013  size_type count)
2014 {
2015  if (index > size())
2016  throw std::out_of_range("Index out of range.");
2017 
2018  auto pos = cbegin() + static_cast<difference_type>(index);
2019 
2020  insert(pos, s, s + count);
2021 
2022  return *this;
2023 }
2024 
2045 template <typename CharT, typename Traits>
2048 {
2049  return insert(index, str.data(), str.size());
2050 }
2051 
2074 template <typename CharT, typename Traits>
2077  size_type index2, size_type count)
2078 {
2079  auto sz = str.size();
2080 
2081  if (index1 > size() || index2 > sz)
2082  throw std::out_of_range("Index out of range.");
2083 
2084  count = (std::min)(count, sz - index2);
2085 
2086  return insert(index1, str.data() + index2, count);
2087 }
2088 
2111 template <typename CharT, typename Traits>
2113 basic_string<CharT, Traits>::insert(const_iterator pos, CharT ch)
2114 {
2115  return insert(pos, 1, ch);
2116 }
2117 
2142 template <typename CharT, typename Traits>
2144 basic_string<CharT, Traits>::insert(const_iterator pos, size_type count,
2145  CharT ch)
2146 {
2147  auto sz = size();
2148 
2149  if (sz + count > max_size())
2150  throw std::length_error("Count exceeds max size.");
2151 
2152  auto new_size = sz + count;
2153 
2154  auto pop = get_pool();
2155 
2156  auto index = static_cast<size_type>(std::distance(cbegin(), pos));
2157 
2158  transaction::run(pop, [&] {
2159  if (is_sso_used() && new_size <= sso_capacity) {
2160  auto len = sz - index;
2161 
2162  add_sso_to_tx(index, len + count + 1);
2163 
2164  traits_type::move(&sso_data()._data[index + count],
2165  &sso_data()._data[index], len);
2166  traits_type::assign(&sso_data()._data[index], count,
2167  ch);
2168 
2169  assert(new_size == index + len + count);
2170  set_sso_size(new_size);
2171  sso_data()._data[new_size] = value_type('\0');
2172  } else {
2173  if (is_sso_used())
2174  sso_to_large(new_size);
2175 
2176  non_sso_data().insert(
2177  non_sso_data().begin() +
2178  static_cast<difference_type>(index),
2179  count, ch);
2180  }
2181  });
2182 
2183  return iterator(&data()[static_cast<difference_type>(index)]);
2184 }
2185 
2210 template <typename CharT, typename Traits>
2211 template <typename InputIt, typename Enable>
2213 basic_string<CharT, Traits>::insert(const_iterator pos, InputIt first,
2214  InputIt last)
2215 {
2216  auto sz = size();
2217 
2218  auto count = static_cast<size_type>(std::distance(first, last));
2219 
2220  if (sz + count > max_size())
2221  throw std::length_error("Count exceeds max size.");
2222 
2223  auto pop = get_pool();
2224 
2225  auto new_size = sz + count;
2226 
2227  auto index = static_cast<size_type>(std::distance(cbegin(), pos));
2228 
2229  transaction::run(pop, [&] {
2230  if (is_sso_used() && new_size <= sso_capacity) {
2231  auto len = sz - index;
2232 
2233  add_sso_to_tx(index, len + count + 1);
2234 
2235  traits_type::move(&sso_data()._data[index + count],
2236  &sso_data()._data[index], len);
2237  std::copy(first, last, &sso_data()._data[index]);
2238 
2239  assert(new_size == index + len + count);
2240  set_sso_size(new_size);
2241  sso_data()._data[new_size] = value_type('\0');
2242  } else {
2243  if (is_sso_used()) {
2244  /* 1) Cache C-style string in case of
2245  * self-insert, because it will be destroyed
2246  * when switching from sso to large string.
2247  *
2248  * 2) We cache in std::vector instead of
2249  * std::string because of overload deduction
2250  * ambiguity on Windows
2251  */
2252  std::vector<value_type> str(first, last);
2253 
2254  sso_to_large(new_size);
2255  non_sso_data().insert(
2256  non_sso_data().begin() +
2257  static_cast<difference_type>(
2258  index),
2259  str.begin(), str.end());
2260  } else {
2261  non_sso_data().insert(
2262  non_sso_data().begin() +
2263  static_cast<difference_type>(
2264  index),
2265  first, last);
2266  }
2267  }
2268  });
2269 
2270  return iterator(&data()[static_cast<difference_type>(index)]);
2271 }
2272 
2296 template <typename CharT, typename Traits>
2299  std::initializer_list<CharT> ilist)
2300 {
2301  return insert(pos, ilist.begin(), ilist.end());
2302 }
2303 
2326 template <typename CharT, typename Traits>
2328 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2329  const basic_string &str)
2330 {
2331  return replace(index, count, str.data(), str.size());
2332 }
2333 
2354 template <typename CharT, typename Traits>
2356 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2357  const basic_string &str)
2358 {
2359  return replace(first, last, str.data(), str.data() + str.size());
2360 }
2361 
2388 template <typename CharT, typename Traits>
2390 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2391  const basic_string &str, size_type index2,
2392  size_type count2)
2393 {
2394  auto sz = str.size();
2395 
2396  if (index2 > sz)
2397  throw std::out_of_range("Index out of range.");
2398 
2399  count2 = (std::min)(count2, sz - index2);
2400 
2401  return replace(index, count, str.data() + index2, count2);
2402 }
2403 
2429 template <typename CharT, typename Traits>
2430 template <typename InputIt, typename Enable>
2432 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2433  InputIt first2, InputIt last2)
2434 {
2435  auto sz = size();
2436  auto index = static_cast<size_type>(std::distance(cbegin(), first));
2437  auto count = static_cast<size_type>(std::distance(first, last));
2438  auto count2 = static_cast<size_type>(std::distance(first2, last2));
2439 
2440  count = (std::min)(count, sz - index);
2441 
2442  if (sz - count + count2 > max_size())
2443  throw std::length_error("Count exceeds max size.");
2444 
2445  auto new_size = sz - count + count2;
2446 
2447  auto pop = get_pool();
2448 
2449  transaction::run(pop, [&] {
2450  if (is_sso_used() && new_size <= sso_capacity) {
2451  add_sso_to_tx(index, new_size - index + 1);
2452 
2453  assert(count2 < new_size + 1);
2454  traits_type::move(&sso_data()._data[index + count2],
2455  &sso_data()._data[index + count],
2456  sz - index - count);
2457  std::copy(first2, last2, &sso_data()._data[index]);
2458 
2459  set_sso_size(new_size);
2460  sso_data()._data[new_size] = value_type('\0');
2461  } else {
2462  /* 1) Cache C-style string in case of
2463  * self-replace, because it will be destroyed
2464  * when switching from sso to large string.
2465  *
2466  * 2) We cache in std::vector instead of
2467  * std::string because of overload deduction
2468  * ambiguity on Windows
2469  */
2470  std::vector<value_type> str(first2, last2);
2471 
2472  if (is_sso_used()) {
2473  sso_to_large(new_size);
2474  }
2475 
2476  auto beg =
2477  begin() + static_cast<difference_type>(index);
2478  auto end = beg + static_cast<difference_type>(count);
2479  non_sso_data().erase(beg, end);
2480  non_sso_data().insert(beg, str.begin(), str.end());
2481  }
2482 
2483  if (!is_sso_used() && new_size <= sso_capacity)
2484  large_to_sso();
2485  });
2486 
2487  return *this;
2488 }
2489 
2512 template <typename CharT, typename Traits>
2514 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2515  const CharT *s, size_type count2)
2516 {
2517  return replace(first, last, s, s + count2);
2518 }
2519 
2543 template <typename CharT, typename Traits>
2545 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2546  const CharT *s, size_type count2)
2547 {
2548  if (index > size())
2549  throw std::out_of_range("Index out of range.");
2550 
2551  auto first = cbegin() + static_cast<difference_type>(index);
2552  auto last = first + static_cast<difference_type>(count);
2553 
2554  return replace(first, last, s, s + count2);
2555 }
2556 
2580 template <typename CharT, typename Traits>
2582 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2583  const CharT *s)
2584 {
2585  return replace(index, count, s, traits_type::length(s));
2586 }
2587 
2611 template <typename CharT, typename Traits>
2613 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2614  size_type count2, CharT ch)
2615 {
2616  if (index > size())
2617  throw std::out_of_range("Index out of range.");
2618 
2619  auto first = cbegin() + static_cast<difference_type>(index);
2620  auto last = first + static_cast<difference_type>(count);
2621 
2622  return replace(first, last, count2, ch);
2623 }
2624 
2647 template <typename CharT, typename Traits>
2649 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2650  size_type count2, CharT ch)
2651 {
2652  auto sz = size();
2653  auto index = static_cast<size_type>(std::distance(cbegin(), first));
2654  auto count = static_cast<size_type>(std::distance(first, last));
2655 
2656  count = (std::min)(count, sz - index);
2657 
2658  if (sz - count + count2 > max_size())
2659  throw std::length_error("Count exceeds max size.");
2660 
2661  auto new_size = sz - count + count2;
2662 
2663  auto pop = get_pool();
2664 
2665  transaction::run(pop, [&] {
2666  if (is_sso_used() && new_size <= sso_capacity) {
2667  add_sso_to_tx(index, new_size - index + 1);
2668 
2669  assert(count2 < new_size + 1);
2670  traits_type::move(&sso_data()._data[index + count2],
2671  &sso_data()._data[index + count],
2672  sz - index - count);
2673  traits_type::assign(&sso_data()._data[index], count2,
2674  ch);
2675 
2676  set_sso_size(new_size);
2677  sso_data()._data[new_size] = value_type('\0');
2678  } else {
2679  if (is_sso_used()) {
2680  sso_to_large(new_size);
2681  }
2682 
2683  auto beg =
2684  begin() + static_cast<difference_type>(index);
2685  auto end = beg + static_cast<difference_type>(count);
2686  non_sso_data().erase(beg, end);
2687  non_sso_data().insert(beg, count2, ch);
2688  }
2689 
2690  if (!is_sso_used() && new_size <= sso_capacity)
2691  large_to_sso();
2692  });
2693 
2694  return *this;
2695 }
2696 
2718 template <typename CharT, typename Traits>
2720 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2721  const CharT *s)
2722 {
2723  return replace(first, last, s, traits_type::length(s));
2724 }
2725 
2748 template <typename CharT, typename Traits>
2750 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2751  std::initializer_list<CharT> ilist)
2752 {
2753  return replace(first, last, ilist.begin(), ilist.end());
2754 }
2755 
2769 template <typename CharT, typename Traits>
2770 typename basic_string<CharT, Traits>::size_type
2771 basic_string<CharT, Traits>::copy(CharT *s, size_type count,
2772  size_type index) const
2773 {
2774  auto sz = size();
2775 
2776  if (index > sz)
2777  throw std::out_of_range("Index out of range.");
2778 
2779  auto len = (std::min)(count, sz - index);
2780 
2781  traits_type::copy(s, data() + index, len);
2782 
2783  return len;
2784 }
2785 
2803 template <typename CharT, typename Traits>
2804 int
2805 basic_string<CharT, Traits>::compare(size_type pos, size_type count1,
2806  const CharT *s, size_type count2) const
2807 {
2808  if (pos > size())
2809  throw std::out_of_range("Index out of range.");
2810 
2811  if (count1 > size() - pos)
2812  count1 = size() - pos;
2813 
2814  auto ret = traits_type::compare(cdata() + pos, s,
2815  std::min<size_type>(count1, count2));
2816 
2817  if (ret != 0)
2818  return ret;
2819 
2820  if (count1 < count2)
2821  return -1;
2822  else if (count1 == count2)
2823  return 0;
2824  else
2825  return 1;
2826 }
2827 
2837 template <typename CharT, typename Traits>
2838 typename basic_string<CharT, Traits>::size_type
2839 basic_string<CharT, Traits>::find(const basic_string &str, size_type pos) const
2840  noexcept
2841 {
2842  return find(str.data(), pos, str.size());
2843 }
2844 
2856 template <typename CharT, typename Traits>
2857 typename basic_string<CharT, Traits>::size_type
2858 basic_string<CharT, Traits>::find(const CharT *s, size_type pos,
2859  size_type count) const
2860 {
2861  auto sz = size();
2862 
2863  if (pos > sz)
2864  return npos;
2865 
2866  if (count == 0)
2867  return pos;
2868 
2869  while (pos + count <= sz) {
2870  auto found = traits_type::find(cdata() + pos, sz - pos, s[0]);
2871  if (!found)
2872  return npos;
2873  pos = static_cast<size_type>(std::distance(cdata(), found));
2874  if (traits_type::compare(found, s, count) == 0) {
2875  return pos;
2876  }
2877  ++pos;
2878  }
2879  return npos;
2880 }
2881 
2892 template <typename CharT, typename Traits>
2893 typename basic_string<CharT, Traits>::size_type
2894 basic_string<CharT, Traits>::find(const CharT *s, size_type pos) const
2895 {
2896  return find(s, pos, traits_type::length(s));
2897 }
2898 
2908 template <typename CharT, typename Traits>
2909 typename basic_string<CharT, Traits>::size_type
2910 basic_string<CharT, Traits>::find(CharT ch, size_type pos) const noexcept
2911 {
2912  return find(&ch, pos, 1);
2913 }
2914 
2925 template <typename CharT, typename Traits>
2926 typename basic_string<CharT, Traits>::size_type
2927 basic_string<CharT, Traits>::rfind(const basic_string &str, size_type pos) const
2928  noexcept
2929 {
2930  return rfind(str.cdata(), pos, str.size());
2931 }
2932 
2949 template <typename CharT, typename Traits>
2950 typename basic_string<CharT, Traits>::size_type
2951 basic_string<CharT, Traits>::rfind(const CharT *s, size_type pos,
2952  size_type count) const
2953 {
2954  if (count <= size()) {
2955  pos = (std::min)(size() - count, pos);
2956  do {
2957  if (traits_type::compare(cdata() + pos, s, count) == 0)
2958  return pos;
2959  } while (pos-- > 0);
2960  }
2961  return npos;
2962 }
2963 
2976 template <typename CharT, typename Traits>
2977 typename basic_string<CharT, Traits>::size_type
2978 basic_string<CharT, Traits>::rfind(const CharT *s, size_type pos) const
2979 {
2980  return rfind(s, pos, traits_type::length(s));
2981 }
2982 
2994 template <typename CharT, typename Traits>
2995 typename basic_string<CharT, Traits>::size_type
2996 basic_string<CharT, Traits>::rfind(CharT ch, size_type pos) const noexcept
2997 {
2998  return rfind(&ch, pos, 1);
2999 }
3000 
3010 template <typename CharT, typename Traits>
3011 typename basic_string<CharT, Traits>::size_type
3013  size_type pos) const noexcept
3014 {
3015  return find_first_of(str.cdata(), pos, str.size());
3016 }
3017 
3031 template <typename CharT, typename Traits>
3032 typename basic_string<CharT, Traits>::size_type
3033 basic_string<CharT, Traits>::find_first_of(const CharT *s, size_type pos,
3034  size_type count) const
3035 {
3036  size_type first_of = npos;
3037  for (const CharT *c = s; c != s + count; ++c) {
3038  size_type found = find(*c, pos);
3039  if (found != npos && found < first_of)
3040  first_of = found;
3041  }
3042  return first_of;
3043 }
3044 
3057 template <typename CharT, typename Traits>
3058 typename basic_string<CharT, Traits>::size_type
3059 basic_string<CharT, Traits>::find_first_of(const CharT *s, size_type pos) const
3060 {
3061  return find_first_of(s, pos, traits_type::length(s));
3062 }
3063 
3073 template <typename CharT, typename Traits>
3074 typename basic_string<CharT, Traits>::size_type
3075 basic_string<CharT, Traits>::find_first_of(CharT ch, size_type pos) const
3076  noexcept
3077 {
3078  return find(ch, pos);
3079 }
3080 
3090 template <typename CharT, typename Traits>
3091 typename basic_string<CharT, Traits>::size_type
3093  size_type pos) const noexcept
3094 {
3095  return find_first_not_of(str.cdata(), pos, str.size());
3096 }
3097 
3111 template <typename CharT, typename Traits>
3112 typename basic_string<CharT, Traits>::size_type
3114  size_type count) const
3115 {
3116  if (pos >= size())
3117  return npos;
3118 
3119  for (auto it = cbegin() + pos; it != cend(); ++it)
3120  if (!traits_type::find(s, count, *it))
3121  return static_cast<size_type>(
3122  std::distance(cbegin(), it));
3123  return npos;
3124 }
3125 
3138 template <typename CharT, typename Traits>
3139 typename basic_string<CharT, Traits>::size_type
3141  size_type pos) const
3142 {
3143  return find_first_not_of(s, pos, traits_type::length(s));
3144 }
3145 
3155 template <typename CharT, typename Traits>
3156 typename basic_string<CharT, Traits>::size_type
3158  noexcept
3159 {
3160  return find_first_not_of(&ch, pos, 1);
3161 }
3162 
3172 template <typename CharT, typename Traits>
3173 typename basic_string<CharT, Traits>::size_type
3175  size_type pos) const noexcept
3176 {
3177  return find_last_of(str.cdata(), pos, str.size());
3178 }
3179 
3193 template <typename CharT, typename Traits>
3194 typename basic_string<CharT, Traits>::size_type
3195 basic_string<CharT, Traits>::find_last_of(const CharT *s, size_type pos,
3196  size_type count) const
3197 {
3198  if (size() == 0 || count == 0)
3199  return npos;
3200 
3201  bool found = false;
3202  size_type last_of = 0;
3203  for (const CharT *c = s; c != s + count; ++c) {
3204  size_type position = rfind(*c, pos);
3205  if (position != npos) {
3206  found = true;
3207  if (position > last_of)
3208  last_of = position;
3209  }
3210  }
3211  if (!found)
3212  return npos;
3213  return last_of;
3214 }
3215 
3228 template <typename CharT, typename Traits>
3229 typename basic_string<CharT, Traits>::size_type
3230 basic_string<CharT, Traits>::find_last_of(const CharT *s, size_type pos) const
3231 {
3232  return find_last_of(s, pos, traits_type::length(s));
3233 }
3234 
3244 template <typename CharT, typename Traits>
3245 typename basic_string<CharT, Traits>::size_type
3246 basic_string<CharT, Traits>::find_last_of(CharT ch, size_type pos) const
3247  noexcept
3248 {
3249  return rfind(ch, pos);
3250 }
3251 
3261 template <typename CharT, typename Traits>
3262 typename basic_string<CharT, Traits>::size_type
3264  size_type pos) const noexcept
3265 {
3266  return find_last_not_of(str.cdata(), pos, str.size());
3267 }
3268 
3282 template <typename CharT, typename Traits>
3283 typename basic_string<CharT, Traits>::size_type
3285  size_type count) const
3286 {
3287  if (size() > 0) {
3288  pos = (std::min)(pos, size() - 1);
3289  do {
3290  if (!traits_type::find(s, count, *(cdata() + pos)))
3291  return pos;
3292 
3293  } while (pos-- > 0);
3294  }
3295  return npos;
3296 }
3297 
3310 template <typename CharT, typename Traits>
3311 typename basic_string<CharT, Traits>::size_type
3313  size_type pos) const
3314 {
3315  return find_last_not_of(s, pos, traits_type::length(s));
3316 }
3317 
3327 template <typename CharT, typename Traits>
3328 typename basic_string<CharT, Traits>::size_type
3330  noexcept
3331 {
3332  return find_last_not_of(&ch, pos, 1);
3333 }
3334 
3343 template <typename CharT, typename Traits>
3344 int
3346 {
3347  return compare(0, size(), other.cdata(), other.size());
3348 }
3349 
3358 template <typename CharT, typename Traits>
3359 int
3361  const std::basic_string<CharT> &other) const
3362 {
3363  return compare(0, size(), other.data(), other.size());
3364 }
3365 
3379 template <typename CharT, typename Traits>
3380 int
3381 basic_string<CharT, Traits>::compare(size_type pos, size_type count,
3382  const basic_string &other) const
3383 {
3384  return compare(pos, count, other.cdata(), other.size());
3385 }
3386 
3401 template <typename CharT, typename Traits>
3402 int
3404  size_type pos, size_type count,
3405  const std::basic_string<CharT> &other) const
3406 {
3407  return compare(pos, count, other.data(), other.size());
3408 }
3409 
3428 template <typename CharT, typename Traits>
3429 int
3430 basic_string<CharT, Traits>::compare(size_type pos1, size_type count1,
3431  const basic_string &other, size_type pos2,
3432  size_type count2) const
3433 {
3434  if (pos2 > other.size())
3435  throw std::out_of_range("Index out of range.");
3436 
3437  if (count2 > other.size() - pos2)
3438  count2 = other.size() - pos2;
3439 
3440  return compare(pos1, count1, other.cdata() + pos2, count2);
3441 }
3442 
3461 template <typename CharT, typename Traits>
3462 int
3463 basic_string<CharT, Traits>::compare(size_type pos1, size_type count1,
3464  const std::basic_string<CharT> &other,
3465  size_type pos2, size_type count2) const
3466 {
3467  if (pos2 > other.size())
3468  throw std::out_of_range("Index out of range.");
3469 
3470  if (count2 > other.size() - pos2)
3471  count2 = other.size() - pos2;
3472 
3473  return compare(pos1, count1, other.data() + pos2, count2);
3474 }
3475 
3484 template <typename CharT, typename Traits>
3485 int
3487 {
3488  return compare(0, size(), s, traits_type::length(s));
3489 }
3490 
3504 template <typename CharT, typename Traits>
3505 int
3506 basic_string<CharT, Traits>::compare(size_type pos, size_type count,
3507  const CharT *s) const
3508 {
3509  return compare(pos, count, s, traits_type::length(s));
3510 }
3511 
3515 template <typename CharT, typename Traits>
3516 const CharT *
3518 {
3519  return is_sso_used() ? sso_data().cdata() : non_sso_data().cdata();
3520 }
3521 
3525 template <typename CharT, typename Traits>
3526 const CharT *
3528 {
3529  return cdata();
3530 }
3531 
3535 template <typename CharT, typename Traits>
3536 const CharT *
3538 {
3539  return cdata();
3540 }
3541 
3545 template <typename CharT, typename Traits>
3546 typename basic_string<CharT, Traits>::size_type
3548 {
3549  return size();
3550 }
3551 
3555 template <typename CharT, typename Traits>
3556 typename basic_string<CharT, Traits>::size_type
3558 {
3559  return PMEMOBJ_MAX_ALLOC_SIZE / sizeof(CharT) - 1;
3560 }
3561 
3566 template <typename CharT, typename Traits>
3567 typename basic_string<CharT, Traits>::size_type
3569 {
3570  return is_sso_used() ? sso_capacity : non_sso_data().capacity() - 1;
3571 }
3572 
3592 template <typename CharT, typename Traits>
3593 void
3594 basic_string<CharT, Traits>::resize(size_type count, CharT ch)
3595 {
3596  if (count > max_size())
3597  throw std::length_error("Count exceeds max size.");
3598 
3599  auto sz = size();
3600 
3601  auto pop = get_pool();
3602 
3603  transaction::run(pop, [&] {
3604  if (count > sz) {
3605  append(count - sz, ch);
3606  } else if (is_sso_used()) {
3607  set_sso_size(count);
3608  sso_data()[count] = value_type('\0');
3609  } else {
3610  non_sso_data().resize(count + 1, ch);
3611  non_sso_data().back() = value_type('\0');
3612  }
3613  });
3614 }
3615 
3634 template <typename CharT, typename Traits>
3635 void
3637 {
3638  resize(count, CharT());
3639 }
3640 
3661 template <typename CharT, typename Traits>
3662 void
3664 {
3665  if (new_cap > max_size())
3666  throw std::length_error("New capacity exceeds max size.");
3667 
3668  if (new_cap < capacity() || new_cap <= sso_capacity)
3669  return;
3670 
3671  if (is_sso_used()) {
3672  auto pop = get_pool();
3673 
3674  transaction::run(pop, [&] { sso_to_large(new_cap); });
3675  } else {
3676  non_sso_data().reserve(new_cap + 1);
3677  }
3678 }
3679 
3693 template <typename CharT, typename Traits>
3694 void
3696 {
3697  if (is_sso_used())
3698  return;
3699 
3700  if (size() <= sso_capacity) {
3701  auto pop = get_pool();
3702 
3703  transaction::run(pop, [&] { large_to_sso(); });
3704  } else {
3705  non_sso_data().shrink_to_fit();
3706  }
3707 }
3708 
3718 template <typename CharT, typename Traits>
3719 void
3721 {
3722  erase(begin(), end());
3723 }
3724 
3737 template <typename CharT, typename Traits>
3738 void
3740 {
3741  auto pop = get_pool();
3742 
3743  transaction::run(pop, [&] {
3744  if (is_sso_used()) {
3745  add_sso_to_tx(0, get_sso_size() + 1);
3746  clear();
3747  /* sso.data destructor does not have to be called */
3748  } else {
3749  non_sso_data().free_data();
3750  detail::destroy<non_sso_type>(non_sso_data());
3751  enable_sso();
3752  }
3753  });
3754 }
3755 
3759 template <typename CharT, typename Traits>
3760 bool
3762 {
3763  return size() == 0;
3764 }
3765 
3766 template <typename CharT, typename Traits>
3767 bool
3769 {
3770  return (sso._size & _sso_mask) != 0;
3771 }
3772 
3773 template <typename CharT, typename Traits>
3774 void
3775 basic_string<CharT, Traits>::destroy_data()
3776 {
3777  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3778 
3779  if (is_sso_used()) {
3780  add_sso_to_tx(0, get_sso_size() + 1);
3781  /* sso.data destructor does not have to be called */
3782  } else {
3783  non_sso_data().free_data();
3784  detail::destroy<non_sso_type>(non_sso_data());
3785  }
3786 }
3787 
3794 template <typename CharT, typename Traits>
3795 template <typename InputIt, typename Enable>
3796 typename basic_string<CharT, Traits>::size_type
3797 basic_string<CharT, Traits>::get_size(InputIt first, InputIt last) const
3798 {
3799  return static_cast<size_type>(std::distance(first, last));
3800 }
3801 
3808 template <typename CharT, typename Traits>
3809 typename basic_string<CharT, Traits>::size_type
3810 basic_string<CharT, Traits>::get_size(size_type count, value_type ch) const
3811 {
3812  return count;
3813 }
3814 
3821 template <typename CharT, typename Traits>
3822 typename basic_string<CharT, Traits>::size_type
3824 {
3825  return other.size();
3826 }
3827 
3834 template <typename CharT, typename Traits>
3835 template <typename... Args>
3836 typename basic_string<CharT, Traits>::pointer
3838 {
3839  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3840 
3841  auto new_size = get_size(std::forward<Args>(args)...);
3842 
3843  /* If non_sso.data is used and there is enough capacity */
3844  if (!is_sso_used() && new_size <= capacity())
3845  return assign_large_data(std::forward<Args>(args)...);
3846 
3847  destroy_data();
3848 
3849  allocate(new_size);
3850  return initialize(std::forward<Args>(args)...);
3851 }
3852 
3863 template <typename CharT, typename Traits>
3864 template <typename... Args>
3865 typename basic_string<CharT, Traits>::pointer
3867 {
3868  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3869 
3870  if (is_sso_used()) {
3871  return assign_sso_data(std::forward<Args>(args)...);
3872  } else {
3873  return assign_large_data(std::forward<Args>(args)...);
3874  }
3875 }
3876 
3886 template <typename CharT, typename Traits>
3887 void
3889 {
3890  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3891 
3892  if (capacity <= sso_capacity) {
3893  enable_sso();
3894  } else {
3895  disable_sso();
3896  }
3897 
3898  /*
3899  * array is aggregate type so it's not required to call
3900  * a constructor.
3901  */
3902  if (!is_sso_used()) {
3903  detail::conditional_add_to_tx(&non_sso_data(), 1,
3904  POBJ_XADD_NO_SNAPSHOT);
3905  detail::create<non_sso_type>(&non_sso_data());
3906  non_sso_data().reserve(capacity + 1);
3907  }
3908 }
3909 
3913 template <typename CharT, typename Traits>
3914 template <typename InputIt, typename Enable>
3915 typename basic_string<CharT, Traits>::pointer
3917 {
3918  auto size = static_cast<size_type>(std::distance(first, last));
3919 
3920  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3921  assert(size <= sso_capacity);
3922 
3923  add_sso_to_tx(0, size + 1);
3924  std::copy(first, last, &sso_data()._data[0]);
3925 
3926  sso_data()._data[size] = value_type('\0');
3927 
3928  set_sso_size(size);
3929 
3930  return &sso_data()[0];
3931 }
3932 
3936 template <typename CharT, typename Traits>
3937 typename basic_string<CharT, Traits>::pointer
3938 basic_string<CharT, Traits>::assign_sso_data(size_type count, value_type ch)
3939 {
3940  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3941  assert(count <= sso_capacity);
3942 
3943  add_sso_to_tx(0, count + 1);
3944  traits_type::assign(&sso_data()._data[0], count, ch);
3945 
3946  sso_data()._data[count] = value_type('\0');
3947 
3948  set_sso_size(count);
3949 
3950  return &sso_data()[0];
3951 }
3952 
3957 template <typename CharT, typename Traits>
3958 template <typename InputIt, typename Enable>
3959 typename basic_string<CharT, Traits>::pointer
3961 {
3962  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3963 
3964  auto size = static_cast<size_type>(std::distance(first, last));
3965 
3966  non_sso_data().reserve(size + 1);
3967  non_sso_data().assign(first, last);
3968  non_sso_data().push_back(value_type('\0'));
3969 
3970  return non_sso_data().data();
3971 }
3972 
3977 template <typename CharT, typename Traits>
3978 typename basic_string<CharT, Traits>::pointer
3979 basic_string<CharT, Traits>::assign_large_data(size_type count, value_type ch)
3980 {
3981  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3982 
3983  non_sso_data().reserve(count + 1);
3984  non_sso_data().assign(count, ch);
3985  non_sso_data().push_back(value_type('\0'));
3986 
3987  return non_sso_data().data();
3988 }
3989 
3994 template <typename CharT, typename Traits>
3995 typename basic_string<CharT, Traits>::pointer
3997 {
3998  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3999 
4000  typename basic_string::pointer ptr;
4001 
4002  if (other.size() <= sso_capacity) {
4003  enable_sso();
4004  ptr = assign_sso_data(other.cbegin(), other.cend());
4005  } else {
4006  disable_sso();
4007  detail::conditional_add_to_tx(&non_sso_data(), 1,
4008  POBJ_XADD_NO_SNAPSHOT);
4009  detail::create<non_sso_type>(&non_sso_data());
4010 
4011  assert(!other.is_sso_used());
4012  non_sso_data() = std::move(other.non_sso_data());
4013 
4014  ptr = non_sso_data().data();
4015  }
4016 
4017  if (other.is_sso_used())
4018  other.initialize(0U, value_type('\0'));
4019 
4020  return ptr;
4021 }
4022 
4026 template <typename CharT, typename Traits>
4027 void
4029 {
4030  pool_base pb = get_pool();
4031  transaction::run(pb, [&] {
4032  if (is_sso_used() && other.is_sso_used()) {
4033  sso_data().swap(other.sso_data());
4034  pmem::obj::swap(sso._size, other.sso._size);
4035  } else if (!is_sso_used() && !other.is_sso_used()) {
4036  non_sso_data().swap(other.non_sso_data());
4037  } else {
4038  basic_string *_short, *_long;
4039  if (size() > other.size()) {
4040  _short = &other;
4041  _long = this;
4042  } else {
4043  _short = this;
4044  _long = &other;
4045  }
4046 
4047  std::basic_string<CharT, Traits> tmp(_short->c_str(),
4048  _short->size());
4049  *_short = *_long;
4050  *_long = tmp;
4051  }
4052  });
4053 }
4054 
4058 template <typename CharT, typename Traits>
4059 pool_base
4061 {
4062  auto pop = pmemobj_pool_by_ptr(this);
4063  assert(pop != nullptr);
4064 
4065  return pool_base(pop);
4066 }
4067 
4071 template <typename CharT, typename Traits>
4072 void
4074 {
4075  if (pmemobj_pool_by_ptr(this) == nullptr)
4076  throw pmem::pool_error("Object is not on pmem.");
4077 }
4078 
4082 template <typename CharT, typename Traits>
4083 void
4085 {
4086  if (pmemobj_tx_stage() != TX_STAGE_WORK)
4088  "Call made out of transaction scope.");
4089 }
4090 
4095 template <typename CharT, typename Traits>
4096 void
4098 {
4099  check_pmem();
4100  check_tx_stage_work();
4101 }
4102 
4106 template <typename CharT, typename Traits>
4107 void
4109  size_type num) const
4110 {
4111  assert(idx_first + num <= sso_capacity + 1);
4112  assert(is_sso_used());
4113 
4114  auto initialized_num = get_sso_size() + 1 - idx_first;
4115 
4116  /* Snapshot elements in range [idx_first, sso_size + 1 (null)) */
4117  detail::conditional_add_to_tx(&sso_data()._data[0] + idx_first,
4118  (std::min)(initialized_num, num));
4119 
4120  if (num > initialized_num) {
4121  /* Elements after sso_size + 1 do not have to be snapshotted */
4122  detail::conditional_add_to_tx(
4123  &sso_data()._data[0] + get_sso_size() + 1,
4124  num - initialized_num, POBJ_XADD_NO_SNAPSHOT);
4125  }
4126 }
4127 
4131 template <typename CharT, typename Traits>
4132 typename basic_string<CharT, Traits>::size_type
4134 {
4135  return sso._size & ~_sso_mask;
4136 }
4137 
4141 template <typename CharT, typename Traits>
4142 void
4144 {
4145  /* temporary size_type must be created to avoid undefined reference
4146  * linker error */
4147  sso._size |= (size_type)(_sso_mask);
4148 }
4149 
4153 template <typename CharT, typename Traits>
4154 void
4156 {
4157  sso._size &= ~_sso_mask;
4158 }
4159 
4163 template <typename CharT, typename Traits>
4164 void
4166 {
4167  sso._size = new_size | _sso_mask;
4168 }
4169 
4181 template <typename CharT, typename Traits>
4182 void
4184 {
4185  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4186  assert(new_capacity > sso_capacity);
4187  assert(is_sso_used());
4188 
4189  auto sz = size();
4190 
4191  sso_type tmp;
4192  std::copy(cbegin(), cend(), tmp.data());
4193  tmp[sz] = value_type('\0');
4194 
4195  destroy_data();
4196  allocate(new_capacity);
4197 
4198  auto begin = tmp.cbegin();
4199  auto end = begin + sz;
4200 
4201  initialize(begin, end);
4202 
4203  assert(!is_sso_used());
4204 };
4205 
4215 template <typename CharT, typename Traits>
4216 void
4218 {
4219  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4220  assert(!is_sso_used());
4221 
4222  auto sz = size();
4223 
4224  assert(sz <= sso_capacity);
4225 
4226  sso_type tmp;
4227  std::copy(cbegin(), cbegin() + sz, tmp.data());
4228  tmp[sz] = value_type('\0');
4229 
4230  destroy_data();
4231  allocate(sz);
4232 
4233  auto begin = tmp.cbegin();
4234  auto end = begin + sz;
4235 
4236  initialize(begin, end);
4237 
4238  assert(is_sso_used());
4239 };
4240 
4241 template <typename CharT, typename Traits>
4244 {
4245  assert(!is_sso_used());
4246  return non_sso._data;
4247 }
4248 
4249 template <typename CharT, typename Traits>
4250 typename basic_string<CharT, Traits>::sso_type &
4251 basic_string<CharT, Traits>::sso_data()
4252 {
4253  assert(is_sso_used());
4254  return sso._data;
4255 }
4256 
4257 template <typename CharT, typename Traits>
4258 const typename basic_string<CharT, Traits>::non_sso_type &
4259 basic_string<CharT, Traits>::non_sso_data() const
4260 {
4261  assert(!is_sso_used());
4262  return non_sso._data;
4263 }
4264 
4265 template <typename CharT, typename Traits>
4266 const typename basic_string<CharT, Traits>::sso_type &
4267 basic_string<CharT, Traits>::sso_data() const
4268 {
4269  assert(is_sso_used());
4270  return sso._data;
4271 }
4272 
4277 template <typename CharT, typename Traits>
4278 template <typename T, typename Enable>
4279 basic_string<CharT, Traits> &
4281 {
4282  return erase(static_cast<size_type>(param));
4283 }
4284 
4289 template <typename CharT, typename Traits>
4290 template <typename T, typename Enable>
4293 {
4294  return erase(static_cast<const_iterator>(param));
4295 }
4296 
4302 template <typename CharT, typename Traits>
4303 template <typename T, typename Enable>
4305 basic_string<CharT, Traits>::insert(T param, size_type count, CharT ch)
4306 {
4307  return insert(static_cast<size_type>(param), count, ch);
4308 }
4309 
4315 template <typename CharT, typename Traits>
4316 template <typename T, typename Enable>
4318 basic_string<CharT, Traits>::insert(T param, size_type count, CharT ch)
4319 {
4320  return insert(static_cast<const_iterator>(param), count, ch);
4321 }
4322 
4326 template <class CharT, class Traits>
4327 bool
4329  const basic_string<CharT, Traits> &rhs)
4330 {
4331  return lhs.compare(rhs) == 0;
4332 }
4333 
4337 template <class CharT, class Traits>
4338 bool
4340  const basic_string<CharT, Traits> &rhs)
4341 {
4342  return lhs.compare(rhs) != 0;
4343 }
4344 
4348 template <class CharT, class Traits>
4349 bool
4351  const basic_string<CharT, Traits> &rhs)
4352 {
4353  return lhs.compare(rhs) < 0;
4354 }
4355 
4359 template <class CharT, class Traits>
4360 bool
4362  const basic_string<CharT, Traits> &rhs)
4363 {
4364  return lhs.compare(rhs) <= 0;
4365 }
4366 
4370 template <class CharT, class Traits>
4371 bool
4373  const basic_string<CharT, Traits> &rhs)
4374 {
4375  return lhs.compare(rhs) > 0;
4376 }
4377 
4381 template <class CharT, class Traits>
4382 bool
4384  const basic_string<CharT, Traits> &rhs)
4385 {
4386  return lhs.compare(rhs) >= 0;
4387 }
4388 
4392 template <class CharT, class Traits>
4393 bool
4394 operator==(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4395 {
4396  return rhs.compare(lhs) == 0;
4397 }
4398 
4402 template <class CharT, class Traits>
4403 bool
4404 operator!=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4405 {
4406  return rhs.compare(lhs) != 0;
4407 }
4408 
4412 template <class CharT, class Traits>
4413 bool
4414 operator<(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4415 {
4416  return rhs.compare(lhs) > 0;
4417 }
4418 
4422 template <class CharT, class Traits>
4423 bool
4424 operator<=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4425 {
4426  return rhs.compare(lhs) >= 0;
4427 }
4428 
4432 template <class CharT, class Traits>
4433 bool
4434 operator>(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4435 {
4436  return rhs.compare(lhs) < 0;
4437 }
4438 
4442 template <class CharT, class Traits>
4443 bool
4444 operator>=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4445 {
4446  return rhs.compare(lhs) <= 0;
4447 }
4448 
4452 template <class CharT, class Traits>
4453 bool
4454 operator==(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4455 {
4456  return lhs.compare(rhs) == 0;
4457 }
4458 
4462 template <class CharT, class Traits>
4463 bool
4464 operator!=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4465 {
4466  return lhs.compare(rhs) != 0;
4467 }
4468 
4472 template <class CharT, class Traits>
4473 bool
4474 operator<(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4475 {
4476  return lhs.compare(rhs) < 0;
4477 }
4478 
4482 template <class CharT, class Traits>
4483 bool
4484 operator<=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4485 {
4486  return lhs.compare(rhs) <= 0;
4487 }
4488 
4492 template <class CharT, class Traits>
4493 bool
4494 operator>(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4495 {
4496  return lhs.compare(rhs) > 0;
4497 }
4498 
4502 template <class CharT, class Traits>
4503 bool
4504 operator>=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4505 {
4506  return lhs.compare(rhs) >= 0;
4507 }
4508 
4512 template <class CharT, class Traits>
4513 bool
4514 operator==(const std::basic_string<CharT, Traits> &lhs,
4515  const basic_string<CharT, Traits> &rhs)
4516 {
4517  return rhs.compare(lhs) == 0;
4518 }
4519 
4523 template <class CharT, class Traits>
4524 bool
4525 operator!=(const std::basic_string<CharT, Traits> &lhs,
4526  const basic_string<CharT, Traits> &rhs)
4527 {
4528  return rhs.compare(lhs) != 0;
4529 }
4530 
4534 template <class CharT, class Traits>
4535 bool
4536 operator<(const std::basic_string<CharT, Traits> &lhs,
4537  const basic_string<CharT, Traits> &rhs)
4538 {
4539  return rhs.compare(lhs) > 0;
4540 }
4541 
4545 template <class CharT, class Traits>
4546 bool
4547 operator<=(const std::basic_string<CharT, Traits> &lhs,
4548  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 std::basic_string<CharT, Traits> &lhs,
4559  const basic_string<CharT, Traits> &rhs)
4560 {
4561  return rhs.compare(lhs) < 0;
4562 }
4563 
4567 template <class CharT, class Traits>
4568 bool
4569 operator>=(const std::basic_string<CharT, Traits> &lhs,
4570  const basic_string<CharT, Traits> &rhs)
4571 {
4572  return rhs.compare(lhs) <= 0;
4573 }
4574 
4578 template <class CharT, class Traits>
4579 bool
4581  const std::basic_string<CharT, Traits> &rhs)
4582 {
4583  return lhs.compare(rhs) == 0;
4584 }
4585 
4589 template <class CharT, class Traits>
4590 bool
4592  const std::basic_string<CharT, Traits> &rhs)
4593 {
4594  return lhs.compare(rhs) != 0;
4595 }
4596 
4600 template <class CharT, class Traits>
4601 bool
4603  const std::basic_string<CharT, Traits> &rhs)
4604 {
4605  return lhs.compare(rhs) < 0;
4606 }
4607 
4611 template <class CharT, class Traits>
4612 bool
4614  const std::basic_string<CharT, Traits> &rhs)
4615 {
4616  return lhs.compare(rhs) <= 0;
4617 }
4618 
4622 template <class CharT, class Traits>
4623 bool
4625  const std::basic_string<CharT, Traits> &rhs)
4626 {
4627  return lhs.compare(rhs) > 0;
4628 }
4629 
4633 template <class CharT, class Traits>
4634 bool
4636  const std::basic_string<CharT, Traits> &rhs)
4637 {
4638  return lhs.compare(rhs) >= 0;
4639 }
4640 
4644 template <class CharT, class Traits>
4645 void
4647 {
4648  return lhs.swap(rhs);
4649 }
4650 
4651 } /* namespace obj */
4652 
4653 } /* namespace pmem */
4654 
4655 #endif /* LIBPMEMOBJ_CPP_BASIC_STRING_HPP */
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:4183
iterator_traits.hpp
Common iterator traits.
pmem::obj::basic_string::clear
void clear()
Remove all characters from the string transactionally.
Definition: basic_string.hpp:3720
pmem::obj::basic_string::check_pmem
void check_pmem() const
Definition: basic_string.hpp:4073
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:795
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:4624
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:4580
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:4097
pmem::pool_error
Custom pool error class.
Definition: pexceptions.hpp:45
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:3012
pmem::obj::basic_string::get_sso_size
size_type get_sso_size() const
Return size of sso string.
Definition: basic_string.hpp:4133
pmem::obj::basic_string::c_str
const CharT * c_str() const noexcept
Definition: basic_string.hpp:3537
pmem::obj::basic_string::operator+=
basic_string & operator+=(const basic_string &str)
Append string str transactionally.
Definition: basic_string.hpp:1845
pmem::obj::basic_string::size
size_type size() const noexcept
Definition: basic_string.hpp:1372
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:2927
pmem::obj::begin
pmem::obj::array< T, N >::iterator begin(pmem::obj::array< T, N > &a)
Non-member begin.
Definition: array.hpp:804
common.hpp
Commonly used functionality.
pmem::obj::basic_string::data
CharT * data()
Definition: basic_string.hpp:1390
pmem::obj::array::cbegin
const_iterator cbegin() const noexcept
Returns const iterator to the beginning.
Definition: array.hpp:306
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:3092
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:1416
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:2839
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:4143
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:3866
pmem::obj::basic_string::cfront
const CharT & cfront() const
Access first element.
Definition: basic_string.hpp:1319
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:4635
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:1949
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:3837
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:1239
pmem::obj::basic_string::length
size_type length() const noexcept
Definition: basic_string.hpp:3547
pmem::obj::basic_string::back
CharT & back()
Access last element and snapshot it if there is an active transaction.
Definition: basic_string.hpp:1335
pmem::obj::basic_string::cback
const CharT & cback() const
Access last element.
Definition: basic_string.hpp:1362
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:784
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:3174
pmem::obj::basic_string::swap
void swap(basic_string &other)
Swap the content of persistent strings.
Definition: basic_string.hpp:4028
pmem::obj::basic_string::set_sso_size
void set_sso_size(size_type new_size)
Set size for sso.
Definition: basic_string.hpp:4165
pmem::obj::basic_string::pop_back
void pop_back()
Remove the last character from the string transactionally.
Definition: basic_string.hpp:1521
pmem::obj::basic_string::capacity
size_type capacity() const noexcept
Definition: basic_string.hpp:3568
pmem::obj::basic_string::basic_string
basic_string()
Default constructor.
Definition: basic_string.hpp:395
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:393
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:1820
pmem::obj::basic_string::disable_sso
void disable_sso()
Disable sso string.
Definition: basic_string.hpp:4155
pmem::obj::basic_string::crend
const_reverse_iterator crend() const noexcept
Return a const reverse iterator to the end.
Definition: basic_string.hpp:1179
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:2771
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:3263
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:4060
pmem::obj::basic_string::cend
const_iterator cend() const noexcept
Return const iterator to past the end.
Definition: basic_string.hpp:1101
pmem::obj::basic_string::shrink_to_fit
void shrink_to_fit()
Remove unused capacity transactionally.
Definition: basic_string.hpp:3695
pmem::obj::cend
pmem::obj::array< T, N >::const_iterator cend(const pmem::obj::array< T, N > &a)
Non-member cend.
Definition: array.hpp:774
pmem::obj::basic_string::max_size
size_type max_size() const noexcept
Definition: basic_string.hpp:3557
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:4108
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:3797
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:3739
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:4591
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:3761
pmem::obj::basic_string::check_tx_stage_work
void check_tx_stage_work() const
Definition: basic_string.hpp:4084
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:1037
pmem::obj::basic_string::allocate
void allocate(size_type capacity)
Allocate storage for container of capacity bytes.
Definition: basic_string.hpp:3888
pmem::obj::basic_string::compare
int compare(const basic_string &other) const
Compares this string to other.
Definition: basic_string.hpp:3345
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:4602
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:2328
pmem::obj::end
pmem::obj::array< T, N >::iterator end(pmem::obj::array< T, N > &a)
Non-member end.
Definition: array.hpp:824
pmem::obj::basic_string::large_to_sso
void large_to_sso()
Resize large string to sso string of size() size.
Definition: basic_string.hpp:4217
pmem::obj::basic_string::resize
void resize(size_type count, CharT ch)
Resize the string to count characters transactionally.
Definition: basic_string.hpp:3594
pmem::obj::array::data
T * data()
Returns raw pointer to the underlying data and adds entire array to a transaction.
Definition: array.hpp:244
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:1547
pmem::obj::basic_string::cdata
const CharT * cdata() const noexcept
Definition: basic_string.hpp:3517
pmem::obj::cbegin
pmem::obj::array< T, N >::const_iterator cbegin(const pmem::obj::array< T, N > &a)
Non-member cbegin.
Definition: array.hpp:764
pmem::obj::basic_string
pmem::obj::string - persistent container with std::basic_string compatible interface.
Definition: basic_string.hpp:41
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:3960
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:1262
pmem::obj::basic_string::end
iterator end()
Return an iterator to past the end.
Definition: basic_string.hpp:1075
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:1023
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:4613
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:3663
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:4646
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:3996
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:794
pmem::transaction_scope_error
Custom transaction error class.
Definition: pexceptions.hpp:158
pmem::obj::basic_string::rend
reverse_iterator rend()
Return a reverse iterator to the end.
Definition: basic_string.hpp:1153
pmem::obj::basic_string::operator=
basic_string & operator=(const basic_string &other)
Copy assignment operator.
Definition: basic_string.hpp:699
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:1062
pmem::obj::basic_string::crbegin
const_reverse_iterator crbegin() const noexcept
Return a const reverse iterator to the beginning.
Definition: basic_string.hpp:1140
pmem::obj::basic_string::front
CharT & front()
Access first element and snapshot it if there is an active transaction.
Definition: basic_string.hpp:1292
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:3916
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:1199
pmem::obj::basic_string::~basic_string
~basic_string()
Destructor.
Definition: basic_string.hpp:679
pmem::obj::basic_string::rbegin
reverse_iterator rbegin()
Return a reverse iterator to the beginning.
Definition: basic_string.hpp:1114