PMDK C++ bindings  1.9.1
This is the C++ bindings documentation for PMDK's libpmemobj.
basic_string.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2019-2020, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * * Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  *
16  * * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
38 #ifndef LIBPMEMOBJ_CPP_BASIC_STRING_HPP
39 #define LIBPMEMOBJ_CPP_BASIC_STRING_HPP
40 
41 #include <algorithm>
42 #include <iterator>
43 #include <limits>
44 #include <string>
45 
53 #include <libpmemobj++/pext.hpp>
54 #include <libpmemobj++/slice.hpp>
56 
57 namespace pmem
58 {
59 
60 namespace obj
61 {
62 
69 template <typename CharT, typename Traits = std::char_traits<CharT>>
70 class basic_string {
71 public:
72  /* Member types */
73  using traits_type = Traits;
74  using value_type = CharT;
75  using size_type = std::size_t;
76  using difference_type = std::ptrdiff_t;
77  using reference = value_type &;
78  using const_reference = const value_type &;
79  using pointer = value_type *;
80  using const_pointer = const value_type *;
82  using const_iterator = const_pointer;
83  using reverse_iterator = std::reverse_iterator<iterator>;
84  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
85  using for_each_ptr_function =
86  std::function<void(persistent_ptr_base &)>;
87 
88  /* Number of characters which can be stored using sso */
89  static constexpr size_type sso_capacity = (32 - 8) / sizeof(CharT) - 1;
90 
91  /* Constructors */
92  basic_string();
93  basic_string(size_type count, CharT ch);
94  basic_string(const basic_string &other, size_type pos,
95  size_type count = npos);
96  basic_string(const std::basic_string<CharT> &other, size_type pos,
97  size_type count = npos);
98  basic_string(const CharT *s, size_type count);
99  basic_string(const CharT *s);
100  template <
101  typename InputIt,
102  typename Enable = typename std::enable_if<
104  basic_string(InputIt first, InputIt last);
105  basic_string(const basic_string &other);
106  basic_string(const std::basic_string<CharT> &other);
107  basic_string(basic_string &&other);
108  basic_string(std::initializer_list<CharT> ilist);
109 
110  /* Destructor */
111  ~basic_string();
112 
113  /* Assignment operators */
114  basic_string &operator=(const basic_string &other);
115  basic_string &operator=(const std::basic_string<CharT> &other);
117  basic_string &operator=(const CharT *s);
118  basic_string &operator=(CharT ch);
119  basic_string &operator=(std::initializer_list<CharT> ilist);
120 
121  /* Assignment methods */
122  basic_string &assign(size_type count, CharT ch);
123  basic_string &assign(const basic_string &other);
124  basic_string &assign(const std::basic_string<CharT> &other);
125  basic_string &assign(const basic_string &other, size_type pos,
126  size_type count = npos);
127  basic_string &assign(const std::basic_string<CharT> &other,
128  size_type pos, size_type count = npos);
129  basic_string &assign(const CharT *s, size_type count);
130  basic_string &assign(const CharT *s);
131  template <typename InputIt,
132  typename Enable = typename pmem::detail::is_input_iterator<
133  InputIt>::type>
134  basic_string &assign(InputIt first, InputIt last);
135  basic_string &assign(basic_string &&other);
136  basic_string &assign(std::initializer_list<CharT> ilist);
137 
138  /* Element access */
139  reference at(size_type n);
140  const_reference at(size_type n) const;
141  const_reference const_at(size_type n) const;
142  reference operator[](size_type n);
143  const_reference operator[](size_type n) const;
144  CharT &front();
145  const CharT &front() const;
146  const CharT &cfront() const;
147  CharT &back();
148  const CharT &back() const;
149  const CharT &cback() const;
150  CharT *data();
151  const CharT *data() const noexcept;
152  const CharT *cdata() const noexcept;
153  const CharT *c_str() const noexcept;
154  void for_each_ptr(for_each_ptr_function func);
155 
156  /* Iterators */
157  iterator begin();
158  const_iterator begin() const noexcept;
159  const_iterator cbegin() const noexcept;
160  iterator end();
161  const_iterator end() const noexcept;
162  const_iterator cend() const noexcept;
163  reverse_iterator rbegin();
164  const_reverse_iterator rbegin() const noexcept;
165  const_reverse_iterator crbegin() const noexcept;
166  reverse_iterator rend();
167  const_reverse_iterator rend() const noexcept;
168  const_reverse_iterator crend() const noexcept;
169 
170  /* Capacity */
171  bool empty() const noexcept;
172  size_type size() const noexcept;
173  size_type length() const noexcept;
174  size_type max_size() const noexcept;
175  size_type capacity() const noexcept;
176  void resize(size_type count, CharT ch);
177  void resize(size_type n);
178  void reserve(size_type new_cap = 0);
179  void shrink_to_fit();
180  void clear();
181 
182  /* Modifiers */
183  basic_string &erase(size_type index = 0, size_type count = npos);
184  iterator erase(const_iterator pos);
185  iterator erase(const_iterator first, const_iterator last);
186  /* We add following overloads to resolve erase(0) ambiguity */
187  template <typename T,
188  typename Enable = typename std::enable_if<
189  std::is_convertible<T, size_type>::value>::type>
190  basic_string &erase(T param);
191  template <typename T,
192  typename Enable = typename std::enable_if<
193  !std::is_convertible<T, size_type>::value>::type>
194  iterator erase(T param);
195  void pop_back();
196 
197  basic_string &append(size_type count, CharT ch);
198  basic_string &append(const basic_string &str);
199  basic_string &append(const basic_string &str, size_type pos,
200  size_type count = npos);
201  basic_string &append(const CharT *s, size_type count);
202  basic_string &append(const CharT *s);
203  template <typename InputIt,
204  typename Enable = typename pmem::detail::is_input_iterator<
205  InputIt>::type>
206  basic_string &append(InputIt first, InputIt last);
207  basic_string &append(std::initializer_list<CharT> ilist);
208  void push_back(CharT ch);
209  basic_string &operator+=(const basic_string &str);
210  basic_string &operator+=(const CharT *s);
211  basic_string &operator+=(CharT c);
212  basic_string &operator+=(std::initializer_list<CharT> ilist);
213 
214  basic_string &insert(size_type index, size_type count, CharT ch);
215  basic_string &insert(size_type index, const CharT *s);
216  basic_string &insert(size_type index, const CharT *s, size_type count);
217  basic_string &insert(size_type index, const basic_string &str);
218  basic_string &insert(size_type index1, const basic_string &str,
219  size_type index2, size_type count = npos);
220  iterator insert(const_iterator pos, CharT ch);
221  iterator insert(const_iterator pos, size_type count, CharT ch);
222  template <typename InputIt,
223  typename Enable = typename pmem::detail::is_input_iterator<
224  InputIt>::type>
225  iterator insert(const_iterator pos, InputIt first, InputIt last);
226  iterator insert(const_iterator pos, std::initializer_list<CharT> ilist);
227  template <typename T,
228  typename Enable = typename std::enable_if<
229  std::is_convertible<T, size_type>::value>::type>
230  basic_string &insert(T param, size_type count, CharT ch);
231  template <typename T,
232  typename Enable = typename std::enable_if<
233  !std::is_convertible<T, size_type>::value>::type>
234  iterator insert(T param, size_type count, CharT ch);
235 
236  basic_string &replace(size_type index, size_type count,
237  const basic_string &str);
238  basic_string &replace(const_iterator first, const_iterator last,
239  const basic_string &str);
240  basic_string &replace(size_type index, size_type count,
241  const basic_string &str, size_type index2,
242  size_type count2 = npos);
243  template <typename InputIt,
244  typename Enable = typename pmem::detail::is_input_iterator<
245  InputIt>::type>
246  basic_string &replace(const_iterator first, const_iterator last,
247  InputIt first2, InputIt last2);
248  basic_string &replace(const_iterator first, const_iterator last,
249  const CharT *s, size_type count2);
250  basic_string &replace(const_iterator first, const_iterator last,
251  const CharT *s);
252  basic_string &replace(size_type index, size_type count,
253  size_type count2, CharT ch);
254  basic_string &replace(const_iterator first, const_iterator last,
255  size_type count2, CharT ch);
256  basic_string &replace(size_type index, size_type count, const CharT *s,
257  size_type count2);
258  basic_string &replace(size_type index, size_type count, const CharT *s);
259  basic_string &replace(const_iterator first, const_iterator last,
260  std::initializer_list<CharT> ilist);
261 
262  size_type copy(CharT *s, size_type count, size_type index = 0) const;
263 
264  int compare(const basic_string &other) const;
265  int compare(const std::basic_string<CharT> &other) const;
266  int compare(size_type pos, size_type count,
267  const basic_string &other) const;
268  int compare(size_type pos, size_type count,
269  const std::basic_string<CharT> &other) const;
270  int compare(size_type pos1, size_type count1, const basic_string &other,
271  size_type pos2, size_type count2 = npos) const;
272  int compare(size_type pos1, size_type count1,
273  const std::basic_string<CharT> &other, size_type pos2,
274  size_type count2 = npos) const;
275  int compare(const CharT *s) const;
276  int compare(size_type pos, size_type count, const CharT *s) const;
277  int compare(size_type pos, size_type count1, const CharT *s,
278  size_type count2) const;
279 
280  /* Search */
281  size_type find(const basic_string &str, size_type pos = 0) const
282  noexcept;
283  size_type find(const CharT *s, size_type pos, size_type count) const;
284  size_type find(const CharT *s, size_type pos = 0) const;
285  size_type find(CharT ch, size_type pos = 0) const noexcept;
286  size_type rfind(const basic_string &str, size_type pos = npos) const
287  noexcept;
288  size_type rfind(const CharT *s, size_type pos, size_type count) const;
289  size_type rfind(const CharT *s, size_type pos = npos) const;
290  size_type rfind(CharT ch, size_type pos = npos) const noexcept;
291  size_type find_first_of(const basic_string &str,
292  size_type pos = 0) const noexcept;
293  size_type find_first_of(const CharT *s, size_type pos,
294  size_type count) const;
295  size_type find_first_of(const CharT *s, size_type pos = 0) const;
296  size_type find_first_of(CharT ch, size_type pos = 0) const noexcept;
297  size_type find_first_not_of(const basic_string &str,
298  size_type pos = 0) const noexcept;
299  size_type find_first_not_of(const CharT *s, size_type pos,
300  size_type count) const;
301  size_type find_first_not_of(const CharT *s, size_type pos = 0) const;
302  size_type find_first_not_of(CharT ch, size_type pos = 0) const noexcept;
303  size_type find_last_of(const basic_string &str,
304  size_type pos = npos) const noexcept;
305  size_type find_last_of(const CharT *s, size_type pos,
306  size_type count) const;
307  size_type find_last_of(const CharT *s, size_type pos = npos) const;
308  size_type find_last_of(CharT ch, size_type pos = npos) const noexcept;
309  size_type find_last_not_of(const basic_string &str,
310  size_type pos = npos) const noexcept;
311  size_type find_last_not_of(const CharT *s, size_type pos,
312  size_type count) const;
313  size_type find_last_not_of(const CharT *s, size_type pos = npos) const;
314  size_type find_last_not_of(CharT ch, size_type pos = npos) const
315  noexcept;
316 
317  /* Special value. The exact meaning depends on the context. */
318  static const size_type npos = static_cast<size_type>(-1);
319 
320 private:
323 
341  union {
342  struct {
343  /*
344  * EXACTLY the same type as first member in vector
345  * Holds size for sso string, bit specified by _sso_mask
346  * indicates if sso is used.
347  */
348  p<size_type> _size;
349 
350  sso_type _data;
351  } sso;
352 
353  struct {
354  non_sso_type _data;
355  } non_sso;
356  };
357 
358  /*
359  * MSB is used because vector is known not to use entire range of
360  * size_type.
361  */
362  static constexpr size_type _sso_mask = 1ULL
363  << (std::numeric_limits<size_type>::digits - 1);
364 
365  /* helper functions */
366  bool is_sso_used() const;
367  void destroy_data();
368  template <
369  typename InputIt,
370  typename Enable = typename std::enable_if<
372  size_type get_size(InputIt first, InputIt last) const;
373  size_type get_size(size_type count, value_type ch) const;
374  size_type get_size(const basic_string &other) const;
375  template <typename... Args>
376  pointer replace_content(Args &&... args);
377  template <typename... Args>
378  pointer initialize(Args &&... args);
379  void allocate(size_type capacity);
380  template <
381  typename InputIt,
382  typename Enable = typename std::enable_if<
384  pointer assign_sso_data(InputIt first, InputIt last);
385  pointer assign_sso_data(size_type count, value_type ch);
386  pointer assign_sso_data(basic_string &&other);
387  template <
388  typename InputIt,
389  typename Enable = typename std::enable_if<
391  pointer assign_large_data(InputIt first, InputIt last);
392  pointer assign_large_data(size_type count, value_type ch);
393  pointer assign_large_data(basic_string &&other);
394  pool_base get_pool() const;
395  void check_pmem() const;
396  void check_tx_stage_work() const;
397  void check_pmem_tx() const;
398  void add_sso_to_tx(size_type first, size_type num) const;
399  size_type get_sso_size() const;
400  void enable_sso();
401  void disable_sso();
402  void set_sso_size(size_type new_size);
403  void sso_to_large(size_t new_capacity);
404  void large_to_sso();
405  typename basic_string<CharT, Traits>::non_sso_type &non_sso_data();
406  typename basic_string<CharT, Traits>::sso_type &sso_data();
408  non_sso_data() const;
409  const typename basic_string<CharT, Traits>::sso_type &sso_data() const;
410 };
411 
421 template <typename CharT, typename Traits>
423 {
424  check_pmem_tx();
425  sso._size = 0;
426 
427  allocate(0);
428  initialize(0U, value_type('\0'));
429 }
430 
445 template <typename CharT, typename Traits>
447 {
448  check_pmem_tx();
449  sso._size = 0;
450 
451  allocate(count);
452  initialize(count, ch);
453 }
454 
472 template <typename CharT, typename Traits>
474  size_type pos, size_type count)
475 {
476  check_pmem_tx();
477  sso._size = 0;
478 
479  if (pos > other.size())
480  throw std::out_of_range("Index out of range.");
481 
482  if (count == npos || pos + count > other.size())
483  count = other.size() - pos;
484 
485  auto first = static_cast<difference_type>(pos);
486  auto last = first + static_cast<difference_type>(count);
487 
488  allocate(count);
489  initialize(other.cbegin() + first, other.cbegin() + last);
490 }
491 
510 template <typename CharT, typename Traits>
511 basic_string<CharT, Traits>::basic_string(const std::basic_string<CharT> &other,
512  size_type pos, size_type count)
513 {
514  check_pmem_tx();
515  sso._size = 0;
516 
517  if (pos > other.size())
518  throw std::out_of_range("Index out of range.");
519 
520  if (count == npos || pos + count > other.size())
521  count = other.size() - pos;
522 
523  auto first = static_cast<difference_type>(pos);
524  auto last = first + static_cast<difference_type>(count);
525 
526  allocate(count);
527  initialize(other.cbegin() + first, other.cbegin() + last);
528 }
529 
545 template <typename CharT, typename Traits>
546 basic_string<CharT, Traits>::basic_string(const CharT *s, size_type count)
547 {
548  check_pmem_tx();
549  sso._size = 0;
550 
551  allocate(count);
552  initialize(s, s + count);
553 }
554 
568 template <typename CharT, typename Traits>
570 {
571  check_pmem_tx();
572  sso._size = 0;
573 
574  auto length = traits_type::length(s);
575 
576  allocate(length);
577  initialize(s, s + length);
578 }
579 
596 template <typename CharT, typename Traits>
597 template <typename InputIt, typename Enable>
598 basic_string<CharT, Traits>::basic_string(InputIt first, InputIt last)
599 {
600  auto len = std::distance(first, last);
601  assert(len >= 0);
602 
603  check_pmem_tx();
604  sso._size = 0;
605 
606  allocate(static_cast<size_type>(len));
607  initialize(first, last);
608 }
609 
624 template <typename CharT, typename Traits>
626 {
627  check_pmem_tx();
628  sso._size = 0;
629 
630  allocate(other.size());
631  initialize(other.cbegin(), other.cend());
632 }
633 
649 template <typename CharT, typename Traits>
650 basic_string<CharT, Traits>::basic_string(const std::basic_string<CharT> &other)
651  : basic_string(other.cbegin(), other.cend())
652 {
653 }
654 
669 template <typename CharT, typename Traits>
671 {
672  check_pmem_tx();
673  sso._size = 0;
674 
675  allocate(other.size());
676  initialize(std::move(other));
677 
678  if (other.is_sso_used())
679  other.initialize(0U, value_type('\0'));
680 }
681 
696 template <typename CharT, typename Traits>
697 basic_string<CharT, Traits>::basic_string(std::initializer_list<CharT> ilist)
698 {
699  check_pmem_tx();
700  sso._size = 0;
701 
702  allocate(ilist.size());
703  initialize(ilist.begin(), ilist.end());
704 }
705 
711 template <typename CharT, typename Traits>
713 {
714  if (!is_sso_used())
715  detail::destroy<non_sso_type>(non_sso_data());
716 }
717 
727 template <typename CharT, typename Traits>
730 {
731  return assign(other);
732 }
733 
744 template <typename CharT, typename Traits>
746 basic_string<CharT, Traits>::operator=(const std::basic_string<CharT> &other)
747 {
748  return assign(other);
749 }
750 
760 template <typename CharT, typename Traits>
763 {
764  return assign(std::move(other));
765 }
766 
775 template <typename CharT, typename Traits>
778 {
779  return assign(s);
780 }
781 
790 template <typename CharT, typename Traits>
793 {
794  return assign(1, ch);
795 }
796 
806 template <typename CharT, typename Traits>
808 basic_string<CharT, Traits>::operator=(std::initializer_list<CharT> ilist)
809 {
810  return assign(ilist);
811 }
812 
823 template <typename CharT, typename Traits>
825 basic_string<CharT, Traits>::assign(size_type count, CharT ch)
826 {
827  auto pop = get_pool();
828 
829  transaction::run(pop, [&] { replace_content(count, ch); });
830 
831  return *this;
832 }
833 
843 template <typename CharT, typename Traits>
846 {
847  if (&other == this)
848  return *this;
849 
850  auto pop = get_pool();
851 
853  pop, [&] { replace_content(other.cbegin(), other.cend()); });
854 
855  return *this;
856 }
857 
868 template <typename CharT, typename Traits>
870 basic_string<CharT, Traits>::assign(const std::basic_string<CharT> &other)
871 {
872  return assign(other.cbegin(), other.cend());
873 }
874 
887 template <typename CharT, typename Traits>
890  size_type count)
891 {
892  if (pos > other.size())
893  throw std::out_of_range("Index out of range.");
894 
895  if (count == npos || pos + count > other.size())
896  count = other.size() - pos;
897 
898  auto pop = get_pool();
899  auto first = static_cast<difference_type>(pos);
900  auto last = first + static_cast<difference_type>(count);
901 
902  transaction::run(pop, [&] {
903  replace_content(other.cbegin() + first, other.cbegin() + last);
904  });
905 
906  return *this;
907 }
908 
923 template <typename CharT, typename Traits>
925 basic_string<CharT, Traits>::assign(const std::basic_string<CharT> &other,
926  size_type pos, size_type count)
927 {
928  if (pos > other.size())
929  throw std::out_of_range("Index out of range.");
930 
931  if (count == npos || pos + count > other.size())
932  count = other.size() - pos;
933 
934  return assign(other.c_str() + pos, count);
935 }
936 
947 template <typename CharT, typename Traits>
949 basic_string<CharT, Traits>::assign(const CharT *s, size_type count)
950 {
951  auto pop = get_pool();
952 
953  transaction::run(pop, [&] { replace_content(s, s + count); });
954 
955  return *this;
956 }
957 
966 template <typename CharT, typename Traits>
969 {
970  auto pop = get_pool();
971 
972  auto length = traits_type::length(s);
973 
974  transaction::run(pop, [&] { replace_content(s, s + length); });
975 
976  return *this;
977 }
978 
990 template <typename CharT, typename Traits>
991 template <typename InputIt, typename Enable>
993 basic_string<CharT, Traits>::assign(InputIt first, InputIt last)
994 {
995  auto pop = get_pool();
996 
997  transaction::run(pop, [&] { replace_content(first, last); });
998 
999  return *this;
1000 }
1001 
1011 template <typename CharT, typename Traits>
1014 {
1015  if (&other == this)
1016  return *this;
1017 
1018  auto pop = get_pool();
1019 
1020  transaction::run(pop, [&] {
1021  replace_content(std::move(other));
1022 
1023  if (other.is_sso_used())
1024  other.initialize(0U, value_type('\0'));
1025  });
1026 
1027  return *this;
1028 }
1029 
1039 template <typename CharT, typename Traits>
1041 basic_string<CharT, Traits>::assign(std::initializer_list<CharT> ilist)
1042 {
1043  return assign(ilist.begin(), ilist.end());
1044 }
1045 
1053 template <typename CharT, typename Traits>
1054 void
1056 {
1057  if (!is_sso_used()) {
1058  non_sso._data.for_each_ptr(func);
1059  }
1060 }
1061 
1067 template <typename CharT, typename Traits>
1070 {
1071  return is_sso_used() ? iterator(&*sso_data().begin())
1072  : iterator(&*non_sso_data().begin());
1073 }
1074 
1080 template <typename CharT, typename Traits>
1081 typename basic_string<CharT, Traits>::const_iterator
1083 {
1084  return cbegin();
1085 }
1086 
1092 template <typename CharT, typename Traits>
1093 typename basic_string<CharT, Traits>::const_iterator
1095 {
1096  return is_sso_used() ? const_iterator(&*sso_data().cbegin())
1097  : const_iterator(&*non_sso_data().cbegin());
1098 }
1099 
1105 template <typename CharT, typename Traits>
1108 {
1109  return begin() + static_cast<difference_type>(size());
1110 }
1111 
1118 template <typename CharT, typename Traits>
1119 typename basic_string<CharT, Traits>::const_iterator
1121 {
1122  return cbegin() + static_cast<difference_type>(size());
1123 }
1124 
1131 template <typename CharT, typename Traits>
1132 typename basic_string<CharT, Traits>::const_iterator
1134 {
1135  return cbegin() + static_cast<difference_type>(size());
1136 }
1137 
1144 template <typename CharT, typename Traits>
1145 typename basic_string<CharT, Traits>::reverse_iterator
1147 {
1148  return reverse_iterator(end());
1149 }
1150 
1157 template <typename CharT, typename Traits>
1158 typename basic_string<CharT, Traits>::const_reverse_iterator
1160 {
1161  return crbegin();
1162 }
1163 
1170 template <typename CharT, typename Traits>
1171 typename basic_string<CharT, Traits>::const_reverse_iterator
1173 {
1174  return const_reverse_iterator(cend());
1175 }
1176 
1183 template <typename CharT, typename Traits>
1184 typename basic_string<CharT, Traits>::reverse_iterator
1186 {
1187  return reverse_iterator(begin());
1188 }
1189 
1196 template <typename CharT, typename Traits>
1197 typename basic_string<CharT, Traits>::const_reverse_iterator
1199 {
1200  return crend();
1201 }
1202 
1209 template <typename CharT, typename Traits>
1210 typename basic_string<CharT, Traits>::const_reverse_iterator
1212 {
1213  return const_reverse_iterator(cbegin());
1214 }
1215 
1229 template <typename CharT, typename Traits>
1230 typename basic_string<CharT, Traits>::reference
1232 {
1233  if (n >= size())
1234  throw std::out_of_range("string::at");
1235 
1236  return is_sso_used() ? sso_data()[n] : non_sso_data()[n];
1237 }
1238 
1249 template <typename CharT, typename Traits>
1250 typename basic_string<CharT, Traits>::const_reference
1252 {
1253  return const_at(n);
1254 }
1255 
1269 template <typename CharT, typename Traits>
1270 typename basic_string<CharT, Traits>::const_reference
1272 {
1273  if (n >= size())
1274  throw std::out_of_range("string::const_at");
1275 
1276  return is_sso_used()
1277  ? static_cast<const sso_type &>(sso_data())[n]
1278  : static_cast<const non_sso_type &>(non_sso_data())[n];
1279 }
1280 
1292 template <typename CharT, typename Traits>
1293 typename basic_string<CharT, Traits>::reference
1295 {
1296  return is_sso_used() ? sso_data()[n] : non_sso_data()[n];
1297 }
1298 
1306 template <typename CharT, typename Traits>
1307 typename basic_string<CharT, Traits>::const_reference
1309 {
1310  return is_sso_used() ? sso_data()[n] : non_sso_data()[n];
1311 }
1312 
1322 template <typename CharT, typename Traits>
1323 CharT &
1325 {
1326  return (*this)[0];
1327 }
1328 
1334 template <typename CharT, typename Traits>
1335 const CharT &
1337 {
1338  return cfront();
1339 }
1340 
1349 template <typename CharT, typename Traits>
1350 const CharT &
1352 {
1353  return static_cast<const basic_string &>(*this)[0];
1354 }
1355 
1365 template <typename CharT, typename Traits>
1366 CharT &
1368 {
1369  return (*this)[size() - 1];
1370 }
1371 
1377 template <typename CharT, typename Traits>
1378 const CharT &
1380 {
1381  return cback();
1382 }
1383 
1392 template <typename CharT, typename Traits>
1393 const CharT &
1395 {
1396  return static_cast<const basic_string &>(*this)[size() - 1];
1397 }
1398 
1402 template <typename CharT, typename Traits>
1403 typename basic_string<CharT, Traits>::size_type
1405 {
1406  if (is_sso_used())
1407  return get_sso_size();
1408  else if (non_sso_data().size() == 0)
1409  return 0;
1410  else
1411  return non_sso_data().size() - 1;
1412 }
1413 
1420 template <typename CharT, typename Traits>
1421 CharT *
1423 {
1424  return is_sso_used() ? sso_data().range(0, get_sso_size() + 1).begin()
1425  : non_sso_data().data();
1426 }
1427 
1446 template <typename CharT, typename Traits>
1448 basic_string<CharT, Traits>::erase(size_type index, size_type count)
1449 {
1450  auto sz = size();
1451 
1452  if (index > sz)
1453  throw std::out_of_range("Index exceeds size.");
1454 
1455  count = (std::min)(count, sz - index);
1456 
1457  auto pop = get_pool();
1458 
1459  auto first = begin() + static_cast<difference_type>(index);
1460  auto last = first + static_cast<difference_type>(count);
1461 
1462  if (is_sso_used()) {
1463  transaction::run(pop, [&] {
1464  auto move_len = sz - index - count;
1465  auto new_size = sz - count;
1466 
1467  auto range = sso_data().range(index, move_len + 1);
1468 
1469  traits_type::move(range.begin(), &*last, move_len);
1470 
1471  set_sso_size(new_size);
1472 
1473  assert(range.end() - 1 ==
1474  &sso_data()._data[index + move_len]);
1475  *(range.end() - 1) = value_type('\0');
1476  });
1477  } else {
1478  non_sso_data().erase(first, last);
1479  }
1480 
1481  return *this;
1482 }
1483 
1500 template <typename CharT, typename Traits>
1503 {
1504  return erase(pos, pos + 1);
1505 }
1506 
1525 template <typename CharT, typename Traits>
1527 basic_string<CharT, Traits>::erase(const_iterator first, const_iterator last)
1528 {
1529  size_type index =
1530  static_cast<size_type>(std::distance(cbegin(), first));
1531  size_type len = static_cast<size_type>(std::distance(first, last));
1532 
1533  erase(index, len);
1534 
1535  return begin() + static_cast<difference_type>(index);
1536 }
1537 
1548 template <typename CharT, typename Traits>
1549 void
1551 {
1552  erase(size() - 1, 1);
1553 }
1554 
1574 template <typename CharT, typename Traits>
1576 basic_string<CharT, Traits>::append(size_type count, CharT ch)
1577 {
1578  auto sz = size();
1579  auto new_size = sz + count;
1580 
1581  if (new_size > max_size())
1582  throw std::length_error("Size exceeds max size.");
1583 
1584  if (is_sso_used()) {
1585  auto pop = get_pool();
1586 
1587  transaction::run(pop, [&] {
1588  if (new_size > sso_capacity) {
1589  sso_to_large(new_size);
1590 
1591  non_sso_data().insert(
1592  non_sso_data().cbegin() +
1593  static_cast<difference_type>(
1594  sz),
1595  count, ch);
1596  } else {
1597  add_sso_to_tx(sz, count + 1);
1598  traits_type::assign(&sso_data()._data[sz],
1599  count, ch);
1600 
1601  assert(new_size == sz + count);
1602  set_sso_size(new_size);
1603  sso_data()._data[new_size] = value_type('\0');
1604  }
1605  });
1606  } else {
1607  non_sso_data().insert(non_sso_data().cbegin() +
1608  static_cast<difference_type>(sz),
1609  count, ch);
1610  }
1611 
1612  return *this;
1613 }
1614 
1633 template <typename CharT, typename Traits>
1636 {
1637  return append(str.data(), str.size());
1638 }
1639 
1665 template <typename CharT, typename Traits>
1668  size_type count)
1669 {
1670  auto sz = str.size();
1671 
1672  if (pos > sz)
1673  throw std::out_of_range("Index out of range.");
1674 
1675  count = (std::min)(count, sz - pos);
1676 
1677  append(str.data() + pos, count);
1678 
1679  return *this;
1680 }
1681 
1701 template <typename CharT, typename Traits>
1703 basic_string<CharT, Traits>::append(const CharT *s, size_type count)
1704 {
1705  return append(s, s + count);
1706 }
1707 
1727 template <typename CharT, typename Traits>
1730 {
1731  return append(s, traits_type::length(s));
1732 }
1733 
1755 template <typename CharT, typename Traits>
1756 template <typename InputIt, typename Enable>
1758 basic_string<CharT, Traits>::append(InputIt first, InputIt last)
1759 {
1760  auto sz = size();
1761  auto count = static_cast<size_type>(std::distance(first, last));
1762  auto new_size = sz + count;
1763 
1764  if (new_size > max_size())
1765  throw std::length_error("Size exceeds max size.");
1766 
1767  if (is_sso_used()) {
1768  auto pop = get_pool();
1769 
1770  transaction::run(pop, [&] {
1771  if (new_size > sso_capacity) {
1772  /* 1) Cache C-style string in case of
1773  * self-append, because it will be destroyed
1774  * when switching from sso to large string.
1775  *
1776  * 2) We cache in std::vector instead of
1777  * std::string because of overload deduction
1778  * ambiguity on Windows
1779  */
1780  std::vector<value_type> str(first, last);
1781 
1782  sso_to_large(new_size);
1783  non_sso_data().insert(
1784  non_sso_data().cbegin() +
1785  static_cast<difference_type>(
1786  sz),
1787  str.begin(), str.end());
1788  } else {
1789  add_sso_to_tx(sz, count + 1);
1790  std::copy(first, last, &sso_data()._data[sz]);
1791 
1792  assert(new_size == sz + count);
1793  set_sso_size(new_size);
1794  sso_data()._data[new_size] = value_type('\0');
1795  }
1796  });
1797  } else {
1798  non_sso_data().insert(non_sso_data().cbegin() +
1799  static_cast<difference_type>(sz),
1800  first, last);
1801  }
1802 
1803  return *this;
1804 }
1805 
1824 template <typename CharT, typename Traits>
1826 basic_string<CharT, Traits>::append(std::initializer_list<CharT> ilist)
1827 {
1828  return append(ilist.begin(), ilist.end());
1829 }
1830 
1847 template <typename CharT, typename Traits>
1848 void
1850 {
1851  append(static_cast<size_type>(1), ch);
1852 }
1853 
1872 template <typename CharT, typename Traits>
1875 {
1876  return append(str);
1877 }
1878 
1898 template <typename CharT, typename Traits>
1901 {
1902  return append(s);
1903 }
1904 
1921 template <typename CharT, typename Traits>
1924 {
1925  push_back(ch);
1926 
1927  return *this;
1928 }
1929 
1948 template <typename CharT, typename Traits>
1950 basic_string<CharT, Traits>::operator+=(std::initializer_list<CharT> ilist)
1951 {
1952  return append(ilist);
1953 }
1954 
1976 template <typename CharT, typename Traits>
1978 basic_string<CharT, Traits>::insert(size_type index, size_type count, CharT ch)
1979 {
1980  if (index > size())
1981  throw std::out_of_range("Index out of range.");
1982 
1983  auto pos = cbegin() + static_cast<difference_type>(index);
1984 
1985  insert(pos, count, ch);
1986 
1987  return *this;
1988 }
1989 
2011 template <typename CharT, typename Traits>
2013 basic_string<CharT, Traits>::insert(size_type index, const CharT *s)
2014 {
2015  return insert(index, s, traits_type::length(s));
2016 }
2017 
2039 template <typename CharT, typename Traits>
2041 basic_string<CharT, Traits>::insert(size_type index, const CharT *s,
2042  size_type count)
2043 {
2044  if (index > size())
2045  throw std::out_of_range("Index out of range.");
2046 
2047  auto pos = cbegin() + static_cast<difference_type>(index);
2048 
2049  insert(pos, s, s + count);
2050 
2051  return *this;
2052 }
2053 
2074 template <typename CharT, typename Traits>
2077 {
2078  return insert(index, str.data(), str.size());
2079 }
2080 
2103 template <typename CharT, typename Traits>
2106  size_type index2, size_type count)
2107 {
2108  auto sz = str.size();
2109 
2110  if (index1 > size() || index2 > sz)
2111  throw std::out_of_range("Index out of range.");
2112 
2113  count = (std::min)(count, sz - index2);
2114 
2115  return insert(index1, str.data() + index2, count);
2116 }
2117 
2140 template <typename CharT, typename Traits>
2142 basic_string<CharT, Traits>::insert(const_iterator pos, CharT ch)
2143 {
2144  return insert(pos, 1, ch);
2145 }
2146 
2171 template <typename CharT, typename Traits>
2173 basic_string<CharT, Traits>::insert(const_iterator pos, size_type count,
2174  CharT ch)
2175 {
2176  auto sz = size();
2177 
2178  if (sz + count > max_size())
2179  throw std::length_error("Count exceeds max size.");
2180 
2181  auto new_size = sz + count;
2182 
2183  auto pop = get_pool();
2184 
2185  auto index = static_cast<size_type>(std::distance(cbegin(), pos));
2186 
2187  transaction::run(pop, [&] {
2188  if (is_sso_used() && new_size <= sso_capacity) {
2189  auto len = sz - index;
2190 
2191  add_sso_to_tx(index, len + count + 1);
2192 
2193  traits_type::move(&sso_data()._data[index + count],
2194  &sso_data()._data[index], len);
2195  traits_type::assign(&sso_data()._data[index], count,
2196  ch);
2197 
2198  assert(new_size == index + len + count);
2199  set_sso_size(new_size);
2200  sso_data()._data[new_size] = value_type('\0');
2201  } else {
2202  if (is_sso_used())
2203  sso_to_large(new_size);
2204 
2205  non_sso_data().insert(
2206  non_sso_data().begin() +
2207  static_cast<difference_type>(index),
2208  count, ch);
2209  }
2210  });
2211 
2212  return iterator(&data()[static_cast<difference_type>(index)]);
2213 }
2214 
2239 template <typename CharT, typename Traits>
2240 template <typename InputIt, typename Enable>
2242 basic_string<CharT, Traits>::insert(const_iterator pos, InputIt first,
2243  InputIt last)
2244 {
2245  auto sz = size();
2246 
2247  auto count = static_cast<size_type>(std::distance(first, last));
2248 
2249  if (sz + count > max_size())
2250  throw std::length_error("Count exceeds max size.");
2251 
2252  auto pop = get_pool();
2253 
2254  auto new_size = sz + count;
2255 
2256  auto index = static_cast<size_type>(std::distance(cbegin(), pos));
2257 
2258  transaction::run(pop, [&] {
2259  if (is_sso_used() && new_size <= sso_capacity) {
2260  auto len = sz - index;
2261 
2262  add_sso_to_tx(index, len + count + 1);
2263 
2264  traits_type::move(&sso_data()._data[index + count],
2265  &sso_data()._data[index], len);
2266  std::copy(first, last, &sso_data()._data[index]);
2267 
2268  assert(new_size == index + len + count);
2269  set_sso_size(new_size);
2270  sso_data()._data[new_size] = value_type('\0');
2271  } else {
2272  if (is_sso_used()) {
2273  /* 1) Cache C-style string in case of
2274  * self-insert, because it will be destroyed
2275  * when switching from sso to large string.
2276  *
2277  * 2) We cache in std::vector instead of
2278  * std::string because of overload deduction
2279  * ambiguity on Windows
2280  */
2281  std::vector<value_type> str(first, last);
2282 
2283  sso_to_large(new_size);
2284  non_sso_data().insert(
2285  non_sso_data().begin() +
2286  static_cast<difference_type>(
2287  index),
2288  str.begin(), str.end());
2289  } else {
2290  non_sso_data().insert(
2291  non_sso_data().begin() +
2292  static_cast<difference_type>(
2293  index),
2294  first, last);
2295  }
2296  }
2297  });
2298 
2299  return iterator(&data()[static_cast<difference_type>(index)]);
2300 }
2301 
2325 template <typename CharT, typename Traits>
2328  std::initializer_list<CharT> ilist)
2329 {
2330  return insert(pos, ilist.begin(), ilist.end());
2331 }
2332 
2355 template <typename CharT, typename Traits>
2357 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2358  const basic_string &str)
2359 {
2360  return replace(index, count, str.data(), str.size());
2361 }
2362 
2383 template <typename CharT, typename Traits>
2385 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2386  const basic_string &str)
2387 {
2388  return replace(first, last, str.data(), str.data() + str.size());
2389 }
2390 
2417 template <typename CharT, typename Traits>
2419 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2420  const basic_string &str, size_type index2,
2421  size_type count2)
2422 {
2423  auto sz = str.size();
2424 
2425  if (index2 > sz)
2426  throw std::out_of_range("Index out of range.");
2427 
2428  count2 = (std::min)(count2, sz - index2);
2429 
2430  return replace(index, count, str.data() + index2, count2);
2431 }
2432 
2458 template <typename CharT, typename Traits>
2459 template <typename InputIt, typename Enable>
2461 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2462  InputIt first2, InputIt last2)
2463 {
2464  auto sz = size();
2465  auto index = static_cast<size_type>(std::distance(cbegin(), first));
2466  auto count = static_cast<size_type>(std::distance(first, last));
2467  auto count2 = static_cast<size_type>(std::distance(first2, last2));
2468 
2469  count = (std::min)(count, sz - index);
2470 
2471  if (sz - count + count2 > max_size())
2472  throw std::length_error("Count exceeds max size.");
2473 
2474  auto new_size = sz - count + count2;
2475 
2476  auto pop = get_pool();
2477 
2478  transaction::run(pop, [&] {
2479  if (is_sso_used() && new_size <= sso_capacity) {
2480  add_sso_to_tx(index, new_size - index + 1);
2481 
2482  assert(count2 < new_size + 1);
2483  traits_type::move(&sso_data()._data[index + count2],
2484  &sso_data()._data[index + count],
2485  sz - index - count);
2486  std::copy(first2, last2, &sso_data()._data[index]);
2487 
2488  set_sso_size(new_size);
2489  sso_data()._data[new_size] = value_type('\0');
2490  } else {
2491  /* 1) Cache C-style string in case of
2492  * self-replace, because it will be destroyed
2493  * when switching from sso to large string.
2494  *
2495  * 2) We cache in std::vector instead of
2496  * std::string because of overload deduction
2497  * ambiguity on Windows
2498  */
2499  std::vector<value_type> str(first2, last2);
2500 
2501  if (is_sso_used()) {
2502  sso_to_large(new_size);
2503  }
2504 
2505  auto beg =
2506  begin() + static_cast<difference_type>(index);
2507  auto end = beg + static_cast<difference_type>(count);
2508  non_sso_data().erase(beg, end);
2509  non_sso_data().insert(beg, str.begin(), str.end());
2510  }
2511 
2512  if (!is_sso_used() && new_size <= sso_capacity)
2513  large_to_sso();
2514  });
2515 
2516  return *this;
2517 }
2518 
2541 template <typename CharT, typename Traits>
2543 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2544  const CharT *s, size_type count2)
2545 {
2546  return replace(first, last, s, s + count2);
2547 }
2548 
2572 template <typename CharT, typename Traits>
2574 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2575  const CharT *s, size_type count2)
2576 {
2577  if (index > size())
2578  throw std::out_of_range("Index out of range.");
2579 
2580  auto first = cbegin() + static_cast<difference_type>(index);
2581  auto last = first + static_cast<difference_type>(count);
2582 
2583  return replace(first, last, s, s + count2);
2584 }
2585 
2609 template <typename CharT, typename Traits>
2611 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2612  const CharT *s)
2613 {
2614  return replace(index, count, s, traits_type::length(s));
2615 }
2616 
2640 template <typename CharT, typename Traits>
2642 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2643  size_type count2, CharT ch)
2644 {
2645  if (index > size())
2646  throw std::out_of_range("Index out of range.");
2647 
2648  auto first = cbegin() + static_cast<difference_type>(index);
2649  auto last = first + static_cast<difference_type>(count);
2650 
2651  return replace(first, last, count2, ch);
2652 }
2653 
2676 template <typename CharT, typename Traits>
2678 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2679  size_type count2, CharT ch)
2680 {
2681  auto sz = size();
2682  auto index = static_cast<size_type>(std::distance(cbegin(), first));
2683  auto count = static_cast<size_type>(std::distance(first, last));
2684 
2685  count = (std::min)(count, sz - index);
2686 
2687  if (sz - count + count2 > max_size())
2688  throw std::length_error("Count exceeds max size.");
2689 
2690  auto new_size = sz - count + count2;
2691 
2692  auto pop = get_pool();
2693 
2694  transaction::run(pop, [&] {
2695  if (is_sso_used() && new_size <= sso_capacity) {
2696  add_sso_to_tx(index, new_size - index + 1);
2697 
2698  assert(count2 < new_size + 1);
2699  traits_type::move(&sso_data()._data[index + count2],
2700  &sso_data()._data[index + count],
2701  sz - index - count);
2702  traits_type::assign(&sso_data()._data[index], count2,
2703  ch);
2704 
2705  set_sso_size(new_size);
2706  sso_data()._data[new_size] = value_type('\0');
2707  } else {
2708  if (is_sso_used()) {
2709  sso_to_large(new_size);
2710  }
2711 
2712  auto beg =
2713  begin() + static_cast<difference_type>(index);
2714  auto end = beg + static_cast<difference_type>(count);
2715  non_sso_data().erase(beg, end);
2716  non_sso_data().insert(beg, count2, ch);
2717  }
2718 
2719  if (!is_sso_used() && new_size <= sso_capacity)
2720  large_to_sso();
2721  });
2722 
2723  return *this;
2724 }
2725 
2747 template <typename CharT, typename Traits>
2749 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2750  const CharT *s)
2751 {
2752  return replace(first, last, s, traits_type::length(s));
2753 }
2754 
2777 template <typename CharT, typename Traits>
2779 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2780  std::initializer_list<CharT> ilist)
2781 {
2782  return replace(first, last, ilist.begin(), ilist.end());
2783 }
2784 
2798 template <typename CharT, typename Traits>
2799 typename basic_string<CharT, Traits>::size_type
2800 basic_string<CharT, Traits>::copy(CharT *s, size_type count,
2801  size_type index) const
2802 {
2803  auto sz = size();
2804 
2805  if (index > sz)
2806  throw std::out_of_range("Index out of range.");
2807 
2808  auto len = (std::min)(count, sz - index);
2809 
2810  traits_type::copy(s, data() + index, len);
2811 
2812  return len;
2813 }
2814 
2832 template <typename CharT, typename Traits>
2833 int
2834 basic_string<CharT, Traits>::compare(size_type pos, size_type count1,
2835  const CharT *s, size_type count2) const
2836 {
2837  if (pos > size())
2838  throw std::out_of_range("Index out of range.");
2839 
2840  if (count1 > size() - pos)
2841  count1 = size() - pos;
2842 
2843  auto ret = traits_type::compare(cdata() + pos, s,
2844  std::min<size_type>(count1, count2));
2845 
2846  if (ret != 0)
2847  return ret;
2848 
2849  if (count1 < count2)
2850  return -1;
2851  else if (count1 == count2)
2852  return 0;
2853  else
2854  return 1;
2855 }
2856 
2866 template <typename CharT, typename Traits>
2867 typename basic_string<CharT, Traits>::size_type
2868 basic_string<CharT, Traits>::find(const basic_string &str, size_type pos) const
2869  noexcept
2870 {
2871  return find(str.data(), pos, str.size());
2872 }
2873 
2885 template <typename CharT, typename Traits>
2886 typename basic_string<CharT, Traits>::size_type
2887 basic_string<CharT, Traits>::find(const CharT *s, size_type pos,
2888  size_type count) const
2889 {
2890  auto sz = size();
2891 
2892  if (pos > sz)
2893  return npos;
2894 
2895  if (count == 0)
2896  return pos;
2897 
2898  while (pos + count <= sz) {
2899  auto found = traits_type::find(cdata() + pos, sz - pos, s[0]);
2900  if (!found)
2901  return npos;
2902  pos = static_cast<size_type>(std::distance(cdata(), found));
2903  if (traits_type::compare(found, s, count) == 0) {
2904  return pos;
2905  }
2906  ++pos;
2907  }
2908  return npos;
2909 }
2910 
2921 template <typename CharT, typename Traits>
2922 typename basic_string<CharT, Traits>::size_type
2923 basic_string<CharT, Traits>::find(const CharT *s, size_type pos) const
2924 {
2925  return find(s, pos, traits_type::length(s));
2926 }
2927 
2937 template <typename CharT, typename Traits>
2938 typename basic_string<CharT, Traits>::size_type
2939 basic_string<CharT, Traits>::find(CharT ch, size_type pos) const noexcept
2940 {
2941  return find(&ch, pos, 1);
2942 }
2943 
2954 template <typename CharT, typename Traits>
2955 typename basic_string<CharT, Traits>::size_type
2956 basic_string<CharT, Traits>::rfind(const basic_string &str, size_type pos) const
2957  noexcept
2958 {
2959  return rfind(str.cdata(), pos, str.size());
2960 }
2961 
2978 template <typename CharT, typename Traits>
2979 typename basic_string<CharT, Traits>::size_type
2980 basic_string<CharT, Traits>::rfind(const CharT *s, size_type pos,
2981  size_type count) const
2982 {
2983  if (count <= size()) {
2984  pos = (std::min)(size() - count, pos);
2985  do {
2986  if (traits_type::compare(cdata() + pos, s, count) == 0)
2987  return pos;
2988  } while (pos-- > 0);
2989  }
2990  return npos;
2991 }
2992 
3005 template <typename CharT, typename Traits>
3006 typename basic_string<CharT, Traits>::size_type
3007 basic_string<CharT, Traits>::rfind(const CharT *s, size_type pos) const
3008 {
3009  return rfind(s, pos, traits_type::length(s));
3010 }
3011 
3023 template <typename CharT, typename Traits>
3024 typename basic_string<CharT, Traits>::size_type
3025 basic_string<CharT, Traits>::rfind(CharT ch, size_type pos) const noexcept
3026 {
3027  return rfind(&ch, pos, 1);
3028 }
3029 
3039 template <typename CharT, typename Traits>
3040 typename basic_string<CharT, Traits>::size_type
3042  size_type pos) const noexcept
3043 {
3044  return find_first_of(str.cdata(), pos, str.size());
3045 }
3046 
3060 template <typename CharT, typename Traits>
3061 typename basic_string<CharT, Traits>::size_type
3062 basic_string<CharT, Traits>::find_first_of(const CharT *s, size_type pos,
3063  size_type count) const
3064 {
3065  size_type first_of = npos;
3066  for (const CharT *c = s; c != s + count; ++c) {
3067  size_type found = find(*c, pos);
3068  if (found != npos && found < first_of)
3069  first_of = found;
3070  }
3071  return first_of;
3072 }
3073 
3086 template <typename CharT, typename Traits>
3087 typename basic_string<CharT, Traits>::size_type
3088 basic_string<CharT, Traits>::find_first_of(const CharT *s, size_type pos) const
3089 {
3090  return find_first_of(s, pos, traits_type::length(s));
3091 }
3092 
3102 template <typename CharT, typename Traits>
3103 typename basic_string<CharT, Traits>::size_type
3104 basic_string<CharT, Traits>::find_first_of(CharT ch, size_type pos) const
3105  noexcept
3106 {
3107  return find(ch, pos);
3108 }
3109 
3119 template <typename CharT, typename Traits>
3120 typename basic_string<CharT, Traits>::size_type
3122  size_type pos) const noexcept
3123 {
3124  return find_first_not_of(str.cdata(), pos, str.size());
3125 }
3126 
3140 template <typename CharT, typename Traits>
3141 typename basic_string<CharT, Traits>::size_type
3143  size_type count) const
3144 {
3145  if (pos >= size())
3146  return npos;
3147 
3148  for (auto it = cbegin() + pos; it != cend(); ++it)
3149  if (!traits_type::find(s, count, *it))
3150  return static_cast<size_type>(
3151  std::distance(cbegin(), it));
3152  return npos;
3153 }
3154 
3167 template <typename CharT, typename Traits>
3168 typename basic_string<CharT, Traits>::size_type
3170  size_type pos) const
3171 {
3172  return find_first_not_of(s, pos, traits_type::length(s));
3173 }
3174 
3184 template <typename CharT, typename Traits>
3185 typename basic_string<CharT, Traits>::size_type
3187  noexcept
3188 {
3189  return find_first_not_of(&ch, pos, 1);
3190 }
3191 
3201 template <typename CharT, typename Traits>
3202 typename basic_string<CharT, Traits>::size_type
3204  size_type pos) const noexcept
3205 {
3206  return find_last_of(str.cdata(), pos, str.size());
3207 }
3208 
3222 template <typename CharT, typename Traits>
3223 typename basic_string<CharT, Traits>::size_type
3224 basic_string<CharT, Traits>::find_last_of(const CharT *s, size_type pos,
3225  size_type count) const
3226 {
3227  if (size() == 0 || count == 0)
3228  return npos;
3229 
3230  bool found = false;
3231  size_type last_of = 0;
3232  for (const CharT *c = s; c != s + count; ++c) {
3233  size_type position = rfind(*c, pos);
3234  if (position != npos) {
3235  found = true;
3236  if (position > last_of)
3237  last_of = position;
3238  }
3239  }
3240  if (!found)
3241  return npos;
3242  return last_of;
3243 }
3244 
3257 template <typename CharT, typename Traits>
3258 typename basic_string<CharT, Traits>::size_type
3259 basic_string<CharT, Traits>::find_last_of(const CharT *s, size_type pos) const
3260 {
3261  return find_last_of(s, pos, traits_type::length(s));
3262 }
3263 
3273 template <typename CharT, typename Traits>
3274 typename basic_string<CharT, Traits>::size_type
3275 basic_string<CharT, Traits>::find_last_of(CharT ch, size_type pos) const
3276  noexcept
3277 {
3278  return rfind(ch, pos);
3279 }
3280 
3290 template <typename CharT, typename Traits>
3291 typename basic_string<CharT, Traits>::size_type
3293  size_type pos) const noexcept
3294 {
3295  return find_last_not_of(str.cdata(), pos, str.size());
3296 }
3297 
3311 template <typename CharT, typename Traits>
3312 typename basic_string<CharT, Traits>::size_type
3314  size_type count) const
3315 {
3316  if (size() > 0) {
3317  pos = (std::min)(pos, size() - 1);
3318  do {
3319  if (!traits_type::find(s, count, *(cdata() + pos)))
3320  return pos;
3321 
3322  } while (pos-- > 0);
3323  }
3324  return npos;
3325 }
3326 
3339 template <typename CharT, typename Traits>
3340 typename basic_string<CharT, Traits>::size_type
3342  size_type pos) const
3343 {
3344  return find_last_not_of(s, pos, traits_type::length(s));
3345 }
3346 
3356 template <typename CharT, typename Traits>
3357 typename basic_string<CharT, Traits>::size_type
3359  noexcept
3360 {
3361  return find_last_not_of(&ch, pos, 1);
3362 }
3363 
3372 template <typename CharT, typename Traits>
3373 int
3375 {
3376  return compare(0, size(), other.cdata(), other.size());
3377 }
3378 
3387 template <typename CharT, typename Traits>
3388 int
3390  const std::basic_string<CharT> &other) const
3391 {
3392  return compare(0, size(), other.data(), other.size());
3393 }
3394 
3408 template <typename CharT, typename Traits>
3409 int
3410 basic_string<CharT, Traits>::compare(size_type pos, size_type count,
3411  const basic_string &other) const
3412 {
3413  return compare(pos, count, other.cdata(), other.size());
3414 }
3415 
3430 template <typename CharT, typename Traits>
3431 int
3433  size_type pos, size_type count,
3434  const std::basic_string<CharT> &other) const
3435 {
3436  return compare(pos, count, other.data(), other.size());
3437 }
3438 
3457 template <typename CharT, typename Traits>
3458 int
3459 basic_string<CharT, Traits>::compare(size_type pos1, size_type count1,
3460  const basic_string &other, size_type pos2,
3461  size_type count2) const
3462 {
3463  if (pos2 > other.size())
3464  throw std::out_of_range("Index out of range.");
3465 
3466  if (count2 > other.size() - pos2)
3467  count2 = other.size() - pos2;
3468 
3469  return compare(pos1, count1, other.cdata() + pos2, count2);
3470 }
3471 
3490 template <typename CharT, typename Traits>
3491 int
3492 basic_string<CharT, Traits>::compare(size_type pos1, size_type count1,
3493  const std::basic_string<CharT> &other,
3494  size_type pos2, size_type count2) const
3495 {
3496  if (pos2 > other.size())
3497  throw std::out_of_range("Index out of range.");
3498 
3499  if (count2 > other.size() - pos2)
3500  count2 = other.size() - pos2;
3501 
3502  return compare(pos1, count1, other.data() + pos2, count2);
3503 }
3504 
3513 template <typename CharT, typename Traits>
3514 int
3516 {
3517  return compare(0, size(), s, traits_type::length(s));
3518 }
3519 
3533 template <typename CharT, typename Traits>
3534 int
3535 basic_string<CharT, Traits>::compare(size_type pos, size_type count,
3536  const CharT *s) const
3537 {
3538  return compare(pos, count, s, traits_type::length(s));
3539 }
3540 
3544 template <typename CharT, typename Traits>
3545 const CharT *
3547 {
3548  return is_sso_used() ? sso_data().cdata() : non_sso_data().cdata();
3549 }
3550 
3554 template <typename CharT, typename Traits>
3555 const CharT *
3557 {
3558  return cdata();
3559 }
3560 
3564 template <typename CharT, typename Traits>
3565 const CharT *
3567 {
3568  return cdata();
3569 }
3570 
3574 template <typename CharT, typename Traits>
3575 typename basic_string<CharT, Traits>::size_type
3577 {
3578  return size();
3579 }
3580 
3584 template <typename CharT, typename Traits>
3585 typename basic_string<CharT, Traits>::size_type
3587 {
3588  return PMEMOBJ_MAX_ALLOC_SIZE / sizeof(CharT) - 1;
3589 }
3590 
3595 template <typename CharT, typename Traits>
3596 typename basic_string<CharT, Traits>::size_type
3598 {
3599  return is_sso_used() ? sso_capacity : non_sso_data().capacity() - 1;
3600 }
3601 
3621 template <typename CharT, typename Traits>
3622 void
3623 basic_string<CharT, Traits>::resize(size_type count, CharT ch)
3624 {
3625  if (count > max_size())
3626  throw std::length_error("Count exceeds max size.");
3627 
3628  auto sz = size();
3629 
3630  auto pop = get_pool();
3631 
3632  transaction::run(pop, [&] {
3633  if (count > sz) {
3634  append(count - sz, ch);
3635  } else if (is_sso_used()) {
3636  set_sso_size(count);
3637  sso_data()[count] = value_type('\0');
3638  } else {
3639  non_sso_data().resize(count + 1, ch);
3640  non_sso_data().back() = value_type('\0');
3641  }
3642  });
3643 }
3644 
3663 template <typename CharT, typename Traits>
3664 void
3666 {
3667  resize(count, CharT());
3668 }
3669 
3690 template <typename CharT, typename Traits>
3691 void
3693 {
3694  if (new_cap > max_size())
3695  throw std::length_error("New capacity exceeds max size.");
3696 
3697  if (new_cap < capacity() || new_cap <= sso_capacity)
3698  return;
3699 
3700  if (is_sso_used()) {
3701  auto pop = get_pool();
3702 
3703  transaction::run(pop, [&] { sso_to_large(new_cap); });
3704  } else {
3705  non_sso_data().reserve(new_cap + 1);
3706  }
3707 }
3708 
3722 template <typename CharT, typename Traits>
3723 void
3725 {
3726  if (is_sso_used())
3727  return;
3728 
3729  if (size() <= sso_capacity) {
3730  auto pop = get_pool();
3731 
3732  transaction::run(pop, [&] { large_to_sso(); });
3733  } else {
3734  non_sso_data().shrink_to_fit();
3735  }
3736 }
3737 
3747 template <typename CharT, typename Traits>
3748 void
3750 {
3751  erase(begin(), end());
3752 }
3753 
3757 template <typename CharT, typename Traits>
3758 bool
3760 {
3761  return size() == 0;
3762 }
3763 
3764 template <typename CharT, typename Traits>
3765 bool
3767 {
3768  return (sso._size & _sso_mask) != 0;
3769 }
3770 
3771 template <typename CharT, typename Traits>
3772 void
3773 basic_string<CharT, Traits>::destroy_data()
3774 {
3775  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3776 
3777  if (is_sso_used()) {
3778  add_sso_to_tx(0, get_sso_size() + 1);
3779  /* sso.data destructor does not have to be called */
3780  } else {
3781  non_sso_data().free_data();
3782  detail::destroy<non_sso_type>(non_sso_data());
3783  }
3784 }
3785 
3792 template <typename CharT, typename Traits>
3793 template <typename InputIt, typename Enable>
3794 typename basic_string<CharT, Traits>::size_type
3795 basic_string<CharT, Traits>::get_size(InputIt first, InputIt last) const
3796 {
3797  return static_cast<size_type>(std::distance(first, last));
3798 }
3799 
3806 template <typename CharT, typename Traits>
3807 typename basic_string<CharT, Traits>::size_type
3808 basic_string<CharT, Traits>::get_size(size_type count, value_type ch) const
3809 {
3810  return count;
3811 }
3812 
3819 template <typename CharT, typename Traits>
3820 typename basic_string<CharT, Traits>::size_type
3822 {
3823  return other.size();
3824 }
3825 
3833 template <typename CharT, typename Traits>
3834 template <typename... Args>
3835 typename basic_string<CharT, Traits>::pointer
3837 {
3838  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3839 
3840  auto new_size = get_size(std::forward<Args>(args)...);
3841 
3842  /* If non_sso.data is used and there is enough capacity */
3843  if (!is_sso_used() && new_size <= capacity())
3844  return assign_large_data(std::forward<Args>(args)...);
3845 
3846  destroy_data();
3847 
3848  allocate(new_size);
3849  return initialize(std::forward<Args>(args)...);
3850 }
3851 
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  auto size = get_size(std::forward<Args>(args)...);
3871 
3872  if (is_sso_used()) {
3873  auto ptr = assign_sso_data(std::forward<Args>(args)...);
3874  set_sso_size(size);
3875 
3876  return ptr;
3877  } else {
3878  return assign_large_data(std::forward<Args>(args)...);
3879  }
3880 }
3881 
3891 template <typename CharT, typename Traits>
3892 void
3894 {
3895  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3896 
3897  if (capacity <= sso_capacity) {
3898  enable_sso();
3899  } else {
3900  disable_sso();
3901  }
3902 
3903  /*
3904  * array is aggregate type so it's not required to call
3905  * a constructor.
3906  */
3907  if (!is_sso_used()) {
3908  detail::conditional_add_to_tx(&non_sso_data(), 1,
3909  POBJ_XADD_NO_SNAPSHOT);
3910  detail::create<non_sso_type>(&non_sso_data());
3911  non_sso_data().reserve(capacity + 1);
3912  }
3913 }
3914 
3918 template <typename CharT, typename Traits>
3919 template <typename InputIt, typename Enable>
3920 typename basic_string<CharT, Traits>::pointer
3922 {
3923  auto size = static_cast<size_type>(std::distance(first, last));
3924 
3925  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3926  assert(size <= sso_capacity);
3927 
3928  add_sso_to_tx(0, size + 1);
3929  std::copy(first, last, &sso_data()._data[0]);
3930 
3931  sso_data()._data[size] = value_type('\0');
3932 
3933  return &sso_data()[0];
3934 }
3935 
3939 template <typename CharT, typename Traits>
3940 typename basic_string<CharT, Traits>::pointer
3941 basic_string<CharT, Traits>::assign_sso_data(size_type count, value_type ch)
3942 {
3943  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3944  assert(count <= sso_capacity);
3945 
3946  add_sso_to_tx(0, count + 1);
3947  traits_type::assign(&sso_data()._data[0], count, ch);
3948 
3949  sso_data()._data[count] = value_type('\0');
3950 
3951  return &sso_data()[0];
3952 }
3953 
3957 template <typename CharT, typename Traits>
3958 typename basic_string<CharT, Traits>::pointer
3960 {
3961  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3962 
3963  return assign_sso_data(other.cbegin(), other.cend());
3964 }
3965 
3970 template <typename CharT, typename Traits>
3971 template <typename InputIt, typename Enable>
3972 typename basic_string<CharT, Traits>::pointer
3974 {
3975  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3976 
3977  auto size = static_cast<size_type>(std::distance(first, last));
3978 
3979  non_sso_data().reserve(size + 1);
3980  non_sso_data().assign(first, last);
3981  non_sso_data().push_back(value_type('\0'));
3982 
3983  return non_sso_data().data();
3984 }
3985 
3990 template <typename CharT, typename Traits>
3991 typename basic_string<CharT, Traits>::pointer
3992 basic_string<CharT, Traits>::assign_large_data(size_type count, value_type ch)
3993 {
3994  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3995 
3996  non_sso_data().reserve(count + 1);
3997  non_sso_data().assign(count, ch);
3998  non_sso_data().push_back(value_type('\0'));
3999 
4000  return non_sso_data().data();
4001 }
4002 
4007 template <typename CharT, typename Traits>
4008 typename basic_string<CharT, Traits>::pointer
4010 {
4011  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4012 
4013  if (other.is_sso_used())
4014  return assign_large_data(other.cbegin(), other.cend());
4015 
4016  non_sso_data() = std::move(other.non_sso_data());
4017 
4018  return non_sso_data().data();
4019 }
4020 
4024 template <typename CharT, typename Traits>
4025 pool_base
4027 {
4028  auto pop = pmemobj_pool_by_ptr(this);
4029  assert(pop != nullptr);
4030 
4031  return pool_base(pop);
4032 }
4033 
4037 template <typename CharT, typename Traits>
4038 void
4040 {
4041  if (pmemobj_pool_by_ptr(this) == nullptr)
4042  throw pmem::pool_error("Object is not on pmem.");
4043 }
4044 
4048 template <typename CharT, typename Traits>
4049 void
4051 {
4052  if (pmemobj_tx_stage() != TX_STAGE_WORK)
4054  "Call made out of transaction scope.");
4055 }
4056 
4061 template <typename CharT, typename Traits>
4062 void
4064 {
4065  check_pmem();
4066  check_tx_stage_work();
4067 }
4068 
4072 template <typename CharT, typename Traits>
4073 void
4075  size_type num) const
4076 {
4077  assert(idx_first + num <= sso_capacity + 1);
4078  assert(is_sso_used());
4079 
4080  auto initialized_num = get_sso_size() + 1 - idx_first;
4081 
4082  /* Snapshot elements in range [idx_first, sso_size + 1 (null)) */
4083  detail::conditional_add_to_tx(&sso_data()._data[0] + idx_first,
4084  (std::min)(initialized_num, num));
4085 
4086  if (num > initialized_num) {
4087  /* Elements after sso_size + 1 do not have to be snapshotted */
4088  detail::conditional_add_to_tx(
4089  &sso_data()._data[0] + get_sso_size() + 1,
4090  num - initialized_num, POBJ_XADD_NO_SNAPSHOT);
4091  }
4092 }
4093 
4097 template <typename CharT, typename Traits>
4098 typename basic_string<CharT, Traits>::size_type
4100 {
4101  return sso._size & ~_sso_mask;
4102 }
4103 
4107 template <typename CharT, typename Traits>
4108 void
4110 {
4111  /* temporary size_type must be created to avoid undefined reference
4112  * linker error */
4113  sso._size |= (size_type)(_sso_mask);
4114 }
4115 
4119 template <typename CharT, typename Traits>
4120 void
4122 {
4123  sso._size &= ~_sso_mask;
4124 }
4125 
4129 template <typename CharT, typename Traits>
4130 void
4132 {
4133  sso._size = new_size | _sso_mask;
4134 }
4135 
4147 template <typename CharT, typename Traits>
4148 void
4150 {
4151  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4152  assert(new_capacity > sso_capacity);
4153  assert(is_sso_used());
4154 
4155  auto sz = size();
4156 
4157  sso_type tmp;
4158  std::copy(cbegin(), cend(), tmp.data());
4159  tmp[sz] = value_type('\0');
4160 
4161  destroy_data();
4162  allocate(new_capacity);
4163 
4164  auto begin = tmp.cbegin();
4165  auto end = begin + sz;
4166 
4167  initialize(begin, end);
4168 
4169  assert(!is_sso_used());
4170 };
4171 
4181 template <typename CharT, typename Traits>
4182 void
4184 {
4185  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
4186  assert(!is_sso_used());
4187 
4188  auto sz = size();
4189 
4190  assert(sz <= sso_capacity);
4191 
4192  sso_type tmp;
4193  std::copy(cbegin(), cbegin() + sz, tmp.data());
4194  tmp[sz] = value_type('\0');
4195 
4196  destroy_data();
4197  allocate(sz);
4198 
4199  auto begin = tmp.cbegin();
4200  auto end = begin + sz;
4201 
4202  initialize(begin, end);
4203 
4204  assert(is_sso_used());
4205 };
4206 
4207 template <typename CharT, typename Traits>
4210 {
4211  assert(!is_sso_used());
4212  return non_sso._data;
4213 }
4214 
4215 template <typename CharT, typename Traits>
4216 typename basic_string<CharT, Traits>::sso_type &
4217 basic_string<CharT, Traits>::sso_data()
4218 {
4219  assert(is_sso_used());
4220  return sso._data;
4221 }
4222 
4223 template <typename CharT, typename Traits>
4224 const typename basic_string<CharT, Traits>::non_sso_type &
4225 basic_string<CharT, Traits>::non_sso_data() const
4226 {
4227  assert(!is_sso_used());
4228  return non_sso._data;
4229 }
4230 
4231 template <typename CharT, typename Traits>
4232 const typename basic_string<CharT, Traits>::sso_type &
4233 basic_string<CharT, Traits>::sso_data() const
4234 {
4235  assert(is_sso_used());
4236  return sso._data;
4237 }
4238 
4243 template <typename CharT, typename Traits>
4244 template <typename T, typename Enable>
4245 basic_string<CharT, Traits> &
4247 {
4248  return erase(static_cast<size_type>(param));
4249 }
4250 
4255 template <typename CharT, typename Traits>
4256 template <typename T, typename Enable>
4259 {
4260  return erase(static_cast<const_iterator>(param));
4261 }
4262 
4268 template <typename CharT, typename Traits>
4269 template <typename T, typename Enable>
4271 basic_string<CharT, Traits>::insert(T param, size_type count, CharT ch)
4272 {
4273  return insert(static_cast<size_type>(param), count, ch);
4274 }
4275 
4281 template <typename CharT, typename Traits>
4282 template <typename T, typename Enable>
4284 basic_string<CharT, Traits>::insert(T param, size_type count, CharT ch)
4285 {
4286  return insert(static_cast<const_iterator>(param), count, ch);
4287 }
4288 
4292 template <class CharT, class Traits>
4293 bool
4295  const basic_string<CharT, Traits> &rhs)
4296 {
4297  return lhs.compare(rhs) == 0;
4298 }
4299 
4303 template <class CharT, class Traits>
4304 bool
4306  const basic_string<CharT, Traits> &rhs)
4307 {
4308  return lhs.compare(rhs) != 0;
4309 }
4310 
4314 template <class CharT, class Traits>
4315 bool
4317  const basic_string<CharT, Traits> &rhs)
4318 {
4319  return lhs.compare(rhs) < 0;
4320 }
4321 
4325 template <class CharT, class Traits>
4326 bool
4328  const basic_string<CharT, Traits> &rhs)
4329 {
4330  return lhs.compare(rhs) <= 0;
4331 }
4332 
4336 template <class CharT, class Traits>
4337 bool
4339  const basic_string<CharT, Traits> &rhs)
4340 {
4341  return lhs.compare(rhs) > 0;
4342 }
4343 
4347 template <class CharT, class Traits>
4348 bool
4350  const basic_string<CharT, Traits> &rhs)
4351 {
4352  return lhs.compare(rhs) >= 0;
4353 }
4354 
4358 template <class CharT, class Traits>
4359 bool
4360 operator==(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4361 {
4362  return rhs.compare(lhs) == 0;
4363 }
4364 
4368 template <class CharT, class Traits>
4369 bool
4370 operator!=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4371 {
4372  return rhs.compare(lhs) != 0;
4373 }
4374 
4378 template <class CharT, class Traits>
4379 bool
4380 operator<(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4381 {
4382  return rhs.compare(lhs) > 0;
4383 }
4384 
4388 template <class CharT, class Traits>
4389 bool
4390 operator<=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4391 {
4392  return rhs.compare(lhs) >= 0;
4393 }
4394 
4398 template <class CharT, class Traits>
4399 bool
4400 operator>(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4401 {
4402  return rhs.compare(lhs) < 0;
4403 }
4404 
4408 template <class CharT, class Traits>
4409 bool
4410 operator>=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
4411 {
4412  return rhs.compare(lhs) <= 0;
4413 }
4414 
4418 template <class CharT, class Traits>
4419 bool
4420 operator==(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4421 {
4422  return lhs.compare(rhs) == 0;
4423 }
4424 
4428 template <class CharT, class Traits>
4429 bool
4430 operator!=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4431 {
4432  return lhs.compare(rhs) != 0;
4433 }
4434 
4438 template <class CharT, class Traits>
4439 bool
4440 operator<(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4441 {
4442  return lhs.compare(rhs) < 0;
4443 }
4444 
4448 template <class CharT, class Traits>
4449 bool
4450 operator<=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4451 {
4452  return lhs.compare(rhs) <= 0;
4453 }
4454 
4458 template <class CharT, class Traits>
4459 bool
4460 operator>(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4461 {
4462  return lhs.compare(rhs) > 0;
4463 }
4464 
4468 template <class CharT, class Traits>
4469 bool
4470 operator>=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
4471 {
4472  return lhs.compare(rhs) >= 0;
4473 }
4474 
4478 template <class CharT, class Traits>
4479 bool
4480 operator==(const std::basic_string<CharT, Traits> &lhs,
4481  const basic_string<CharT, Traits> &rhs)
4482 {
4483  return rhs.compare(lhs) == 0;
4484 }
4485 
4489 template <class CharT, class Traits>
4490 bool
4491 operator!=(const std::basic_string<CharT, Traits> &lhs,
4492  const basic_string<CharT, Traits> &rhs)
4493 {
4494  return rhs.compare(lhs) != 0;
4495 }
4496 
4500 template <class CharT, class Traits>
4501 bool
4502 operator<(const std::basic_string<CharT, Traits> &lhs,
4503  const basic_string<CharT, Traits> &rhs)
4504 {
4505  return rhs.compare(lhs) > 0;
4506 }
4507 
4511 template <class CharT, class Traits>
4512 bool
4513 operator<=(const std::basic_string<CharT, Traits> &lhs,
4514  const basic_string<CharT, Traits> &rhs)
4515 {
4516  return rhs.compare(lhs) >= 0;
4517 }
4518 
4522 template <class CharT, class Traits>
4523 bool
4524 operator>(const std::basic_string<CharT, Traits> &lhs,
4525  const basic_string<CharT, Traits> &rhs)
4526 {
4527  return rhs.compare(lhs) < 0;
4528 }
4529 
4533 template <class CharT, class Traits>
4534 bool
4535 operator>=(const std::basic_string<CharT, Traits> &lhs,
4536  const basic_string<CharT, Traits> &rhs)
4537 {
4538  return rhs.compare(lhs) <= 0;
4539 }
4540 
4544 template <class CharT, class Traits>
4545 bool
4547  const std::basic_string<CharT, Traits> &rhs)
4548 {
4549  return lhs.compare(rhs) == 0;
4550 }
4551 
4555 template <class CharT, class Traits>
4556 bool
4558  const std::basic_string<CharT, Traits> &rhs)
4559 {
4560  return lhs.compare(rhs) != 0;
4561 }
4562 
4566 template <class CharT, class Traits>
4567 bool
4569  const std::basic_string<CharT, Traits> &rhs)
4570 {
4571  return lhs.compare(rhs) < 0;
4572 }
4573 
4577 template <class CharT, class Traits>
4578 bool
4580  const std::basic_string<CharT, Traits> &rhs)
4581 {
4582  return lhs.compare(rhs) <= 0;
4583 }
4584 
4588 template <class CharT, class Traits>
4589 bool
4591  const std::basic_string<CharT, Traits> &rhs)
4592 {
4593  return lhs.compare(rhs) > 0;
4594 }
4595 
4599 template <class CharT, class Traits>
4600 bool
4602  const std::basic_string<CharT, Traits> &rhs)
4603 {
4604  return lhs.compare(rhs) >= 0;
4605 }
4606 
4607 } /* namespace obj */
4608 
4609 } /* namespace pmem */
4610 
4611 #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:4149
iterator_traits.hpp
Common iterator traits.
pmem::obj::basic_string::clear
void clear()
Remove all characters from the string transactionally.
Definition: basic_string.hpp:3749
pmem::obj::basic_string::check_pmem
void check_pmem() const
Definition: basic_string.hpp:4039
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:825
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:4063
pmem::pool_error
Custom pool error class.
Definition: pexceptions.hpp:76
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:3041
pmem::obj::basic_string::get_sso_size
size_type get_sso_size() const
Return size of sso string.
Definition: basic_string.hpp:4099
pmem::obj::basic_string::c_str
const CharT * c_str() const noexcept
Definition: basic_string.hpp:3566
pmem::obj::basic_string::operator+=
basic_string & operator+=(const basic_string &str)
Append string str transactionally.
Definition: basic_string.hpp:1874
pmem::obj::basic_string::size
size_type size() const noexcept
Definition: basic_string.hpp:1404
pmem
Persistent memory namespace.
Definition: allocation_flag.hpp:44
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:2956
pmem::obj::begin
pmem::obj::array< T, N >::iterator begin(pmem::obj::array< T, N > &a)
Non-member begin.
Definition: array.hpp:833
common.hpp
Commonly used functionality.
pmem::obj::basic_string::data
CharT * data()
Definition: basic_string.hpp:1422
pmem::obj::array::cbegin
const_iterator cbegin() const noexcept
Returns const iterator to the beginning.
Definition: array.hpp:335
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:3121
pmem::obj::operator>
bool operator>(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater than operator.
Definition: array.hpp:763
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:1448
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:2868
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:4109
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:1351
pmem::obj::operator>=
bool operator>=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater or equal operator.
Definition: array.hpp:773
pmem::obj::operator==
bool operator==(standard_alloc_policy< T > const &, standard_alloc_policy< T2 > const &)
Determines if memory from another allocator can be deallocated from this one.
Definition: allocator.hpp:402
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:1978
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:3836
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:1271
pmem::obj::basic_string::length
size_type length() const noexcept
Definition: basic_string.hpp:3576
pmem::obj::basic_string::back
CharT & back()
Access last element and snapshot it if there is an active transaction.
Definition: basic_string.hpp:1367
pmem::obj::basic_string::cback
const CharT & cback() const
Access last element.
Definition: basic_string.hpp:1394
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:813
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:3203
pmem::obj::basic_string::set_sso_size
void set_sso_size(size_type new_size)
Set size for sso.
Definition: basic_string.hpp:4131
pmem::obj::basic_string::pop_back
void pop_back()
Remove the last character from the string transactionally.
Definition: basic_string.hpp:1550
pmem::obj::basic_string::capacity
size_type capacity() const noexcept
Definition: basic_string.hpp:3597
pmem::obj::basic_string::basic_string
basic_string()
Default constructor.
Definition: basic_string.hpp:422
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:422
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:1849
pmem::obj::basic_string::disable_sso
void disable_sso()
Disable sso string.
Definition: basic_string.hpp:4121
pmem::obj::basic_string::crend
const_reverse_iterator crend() const noexcept
Return a const reverse iterator to the end.
Definition: basic_string.hpp:1211
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:2800
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:3292
pmem::detail::basic_contiguous_iterator
Default non-const iterator which adds element to a transaction on every access.
Definition: contiguous_iterator.hpp:360
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:4026
pmem::obj::basic_string::cend
const_iterator cend() const noexcept
Return const iterator to past the end.
Definition: basic_string.hpp:1133
pmem::obj::operator!=
bool operator!=(const allocator< T, P, Tr > &lhs, const OtherAllocator &rhs)
Determines if memory from another allocator can be deallocated from this one.
Definition: allocator.hpp:518
pmem::obj::basic_string::shrink_to_fit
void shrink_to_fit()
Remove unused capacity transactionally.
Definition: basic_string.hpp:3724
pmem::obj::cend
pmem::obj::array< T, N >::const_iterator cend(const pmem::obj::array< T, N > &a)
Non-member cend.
Definition: array.hpp:803
pmem::obj::basic_string::max_size
size_type max_size() const noexcept
Definition: basic_string.hpp:3586
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:4074
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:3795
pmem::obj::vector< value_type >
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:3759
pmem::obj::basic_string::check_tx_stage_work
void check_tx_stage_work() const
Definition: basic_string.hpp:4050
pmem::detail::is_input_iterator
Type trait to determine if a given parameter type satisfies requirements of InputIterator.
Definition: iterator_traits.hpp:76
pmem::obj::basic_string::begin
iterator begin()
Return an iterator to the beginning.
Definition: basic_string.hpp:1069
pmem::obj::basic_string::allocate
void allocate(size_type capacity)
Allocate storage for container of capacity bytes.
Definition: basic_string.hpp:3893
pmem::obj::basic_string::compare
int compare(const basic_string &other) const
Compares this string to other.
Definition: basic_string.hpp:3374
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:2357
pmem::obj::end
pmem::obj::array< T, N >::iterator end(pmem::obj::array< T, N > &a)
Non-member end.
Definition: array.hpp:853
pmem::obj::basic_string::large_to_sso
void large_to_sso()
Resize large string to sso string of size() size.
Definition: basic_string.hpp:4183
pmem::obj::basic_string::resize
void resize(size_type count, CharT ch)
Resize the string to count characters transactionally.
Definition: basic_string.hpp:3623
pmem::obj::array::data
T * data()
Returns raw pointer to the underlying data and adds entire array to a transaction.
Definition: array.hpp:273
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:1576
pmem::obj::operator<
bool operator<(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less than operator.
Definition: array.hpp:752
pmem::obj::basic_string::cdata
const CharT * cdata() const noexcept
Definition: basic_string.hpp:3546
pmem::obj::cbegin
pmem::obj::array< T, N >::const_iterator cbegin(const pmem::obj::array< T, N > &a)
Non-member cbegin.
Definition: array.hpp:793
pmem::obj::basic_string
pmem::obj::string - persistent container with std::basic_string compatible interface.
Definition: basic_string.hpp:70
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:3973
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:1294
pmem::obj::basic_string::end
iterator end()
Return an iterator to past the end.
Definition: basic_string.hpp:1107
pmem::obj::operator<=
bool operator<=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less or equal operator.
Definition: array.hpp:783
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:1055
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:3692
pext.hpp
Convenience extensions for the resides on pmem property template.
life.hpp
Functions for destroying arrays.
pmem::obj::persistent_ptr_base
Persistent_ptr base (non-template) class.
Definition: persistent_ptr_base.hpp:71
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:823
pmem::transaction_scope_error
Custom transaction error class.
Definition: pexceptions.hpp:192
pmem::obj::basic_string::rend
reverse_iterator rend()
Return a reverse iterator to the end.
Definition: basic_string.hpp:1185
pmem::obj::basic_string::operator=
basic_string & operator=(const basic_string &other)
Copy assignment operator.
Definition: basic_string.hpp:729
pmem::obj::pool_base
The non-template pool base class.
Definition: pool.hpp:75
pmem::obj::basic_string::cbegin
const_iterator cbegin() const noexcept
Return const iterator to the beginning.
Definition: basic_string.hpp:1094
pmem::obj::basic_string::crbegin
const_reverse_iterator crbegin() const noexcept
Return a const reverse iterator to the beginning.
Definition: basic_string.hpp:1172
pmem::obj::basic_string::front
CharT & front()
Access first element and snapshot it if there is an active transaction.
Definition: basic_string.hpp:1324
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:3921
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:1231
pmem::obj::basic_string::~basic_string
~basic_string()
Destructor.
Definition: basic_string.hpp:712
pmem::obj::basic_string::rbegin
reverse_iterator rbegin()
Return a reverse iterator to the beginning.
Definition: basic_string.hpp:1146