PMDK C++ bindings  1.8.2
This is the C++ bindings documentation for PMDK's libpmemobj.
basic_string.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2019, 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 <limits>
43 #include <string>
44 
52 #include <libpmemobj++/pext.hpp>
53 #include <libpmemobj++/slice.hpp>
55 
56 namespace pmem
57 {
58 
59 namespace obj
60 {
61 
68 template <typename CharT, typename Traits = std::char_traits<CharT>>
69 class basic_string {
70 public:
71  /* Member types */
72  using traits_type = Traits;
73  using value_type = CharT;
74  using size_type = std::size_t;
75  using difference_type = std::ptrdiff_t;
76  using reference = value_type &;
77  using const_reference = const value_type &;
78  using pointer = value_type *;
79  using const_pointer = const value_type *;
81  using const_iterator = const_pointer;
82  using reverse_iterator = std::reverse_iterator<iterator>;
83  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
84 
85  /* Number of characters which can be stored using sso */
86  static constexpr size_type sso_capacity = (32 - 8) / sizeof(CharT) - 1;
87 
88  /* Constructors */
89  basic_string();
90  basic_string(size_type count, CharT ch);
91  basic_string(const basic_string &other, size_type pos,
92  size_type count = npos);
93  basic_string(const std::basic_string<CharT> &other, size_type pos,
94  size_type count = npos);
95  basic_string(const CharT *s, size_type count);
96  basic_string(const CharT *s);
97  template <
98  typename InputIt,
99  typename Enable = typename std::enable_if<
101  basic_string(InputIt first, InputIt last);
102  basic_string(const basic_string &other);
103  basic_string(const std::basic_string<CharT> &other);
104  basic_string(basic_string &&other);
105  basic_string(std::initializer_list<CharT> ilist);
106 
107  /* Destructor */
108  ~basic_string();
109 
110  /* Assignment operators */
111  basic_string &operator=(const basic_string &other);
112  basic_string &operator=(const std::basic_string<CharT> &other);
114  basic_string &operator=(const CharT *s);
115  basic_string &operator=(CharT ch);
116  basic_string &operator=(std::initializer_list<CharT> ilist);
117 
118  /* Assignment methods */
119  basic_string &assign(size_type count, CharT ch);
120  basic_string &assign(const basic_string &other);
121  basic_string &assign(const std::basic_string<CharT> &other);
122  basic_string &assign(const basic_string &other, size_type pos,
123  size_type count = npos);
124  basic_string &assign(const std::basic_string<CharT> &other,
125  size_type pos, size_type count = npos);
126  basic_string &assign(const CharT *s, size_type count);
127  basic_string &assign(const CharT *s);
128  template <typename InputIt,
129  typename Enable = typename pmem::detail::is_input_iterator<
130  InputIt>::type>
131  basic_string &assign(InputIt first, InputIt last);
132  basic_string &assign(basic_string &&other);
133  basic_string &assign(std::initializer_list<CharT> ilist);
134 
135  /* Element access */
136  reference at(size_type n);
137  const_reference at(size_type n) const;
138  const_reference const_at(size_type n) const;
139  reference operator[](size_type n);
140  const_reference operator[](size_type n) const;
141  CharT &front();
142  const CharT &front() const;
143  const CharT &cfront() const;
144  CharT &back();
145  const CharT &back() const;
146  const CharT &cback() const;
147  CharT *data();
148  const CharT *data() const noexcept;
149  const CharT *cdata() const noexcept;
150  const CharT *c_str() const noexcept;
151 
152  /* Iterators */
153  iterator begin();
154  const_iterator begin() const noexcept;
155  const_iterator cbegin() const noexcept;
156  iterator end();
157  const_iterator end() const noexcept;
158  const_iterator cend() const noexcept;
159  reverse_iterator rbegin();
160  const_reverse_iterator rbegin() const noexcept;
161  const_reverse_iterator crbegin() const noexcept;
162  reverse_iterator rend();
163  const_reverse_iterator rend() const noexcept;
164  const_reverse_iterator crend() const noexcept;
165 
166  /* Capacity */
167  bool empty() const noexcept;
168  size_type size() const noexcept;
169  size_type length() const noexcept;
170  size_type max_size() const noexcept;
171  size_type capacity() const noexcept;
172  void resize(size_type count, CharT ch);
173  void resize(size_type n);
174  void reserve(size_type new_cap = 0);
175  void shrink_to_fit();
176  void clear();
177 
178  /* Modifiers */
179  basic_string &erase(size_type index = 0, size_type count = npos);
180  iterator erase(const_iterator pos);
181  iterator erase(const_iterator first, const_iterator last);
182  /* We add following overloads to resolve erase(0) ambiguity */
183  template <typename T,
184  typename Enable = typename std::enable_if<
185  std::is_convertible<T, size_type>::value>::type>
186  basic_string &erase(T param);
187  template <typename T,
188  typename Enable = typename std::enable_if<
189  !std::is_convertible<T, size_type>::value>::type>
190  iterator erase(T param);
191  void pop_back();
192 
193  basic_string &append(size_type count, CharT ch);
194  basic_string &append(const basic_string &str);
195  basic_string &append(const basic_string &str, size_type pos,
196  size_type count = npos);
197  basic_string &append(const CharT *s, size_type count);
198  basic_string &append(const CharT *s);
199  template <typename InputIt,
200  typename Enable = typename pmem::detail::is_input_iterator<
201  InputIt>::type>
202  basic_string &append(InputIt first, InputIt last);
203  basic_string &append(std::initializer_list<CharT> ilist);
204  void push_back(CharT ch);
205  basic_string &operator+=(const basic_string &str);
206  basic_string &operator+=(const CharT *s);
207  basic_string &operator+=(CharT c);
208  basic_string &operator+=(std::initializer_list<CharT> ilist);
209 
210  basic_string &insert(size_type index, size_type count, CharT ch);
211  basic_string &insert(size_type index, const CharT *s);
212  basic_string &insert(size_type index, const CharT *s, size_type count);
213  basic_string &insert(size_type index, const basic_string &str);
214  basic_string &insert(size_type index1, const basic_string &str,
215  size_type index2, size_type count = npos);
216  iterator insert(const_iterator pos, CharT ch);
217  iterator insert(const_iterator pos, size_type count, CharT ch);
218  template <typename InputIt,
219  typename Enable = typename pmem::detail::is_input_iterator<
220  InputIt>::type>
221  iterator insert(const_iterator pos, InputIt first, InputIt last);
222  iterator insert(const_iterator pos, std::initializer_list<CharT> ilist);
223  template <typename T,
224  typename Enable = typename std::enable_if<
225  std::is_convertible<T, size_type>::value>::type>
226  basic_string &insert(T param, size_type count, CharT ch);
227  template <typename T,
228  typename Enable = typename std::enable_if<
229  !std::is_convertible<T, size_type>::value>::type>
230  iterator insert(T param, size_type count, CharT ch);
231 
232  basic_string &replace(size_type index, size_type count,
233  const basic_string &str);
234  basic_string &replace(const_iterator first, const_iterator last,
235  const basic_string &str);
236  basic_string &replace(size_type index, size_type count,
237  const basic_string &str, size_type index2,
238  size_type count2 = npos);
239  template <typename InputIt,
240  typename Enable = typename pmem::detail::is_input_iterator<
241  InputIt>::type>
242  basic_string &replace(const_iterator first, const_iterator last,
243  InputIt first2, InputIt last2);
244  basic_string &replace(const_iterator first, const_iterator last,
245  const CharT *s, size_type count2);
246  basic_string &replace(const_iterator first, const_iterator last,
247  const CharT *s);
248  basic_string &replace(size_type index, size_type count,
249  size_type count2, CharT ch);
250  basic_string &replace(const_iterator first, const_iterator last,
251  size_type count2, CharT ch);
252  basic_string &replace(size_type index, size_type count, const CharT *s,
253  size_type count2);
254  basic_string &replace(size_type index, size_type count, const CharT *s);
255  basic_string &replace(const_iterator first, const_iterator last,
256  std::initializer_list<CharT> ilist);
257 
258  size_type copy(CharT *s, size_type count, size_type index = 0) const;
259 
260  int compare(const basic_string &other) const;
261  int compare(const std::basic_string<CharT> &other) const;
262  int compare(size_type pos, size_type count,
263  const basic_string &other) const;
264  int compare(size_type pos, size_type count,
265  const std::basic_string<CharT> &other) const;
266  int compare(size_type pos1, size_type count1, const basic_string &other,
267  size_type pos2, size_type count2 = npos) const;
268  int compare(size_type pos1, size_type count1,
269  const std::basic_string<CharT> &other, size_type pos2,
270  size_type count2 = npos) const;
271  int compare(const CharT *s) const;
272  int compare(size_type pos, size_type count, const CharT *s) const;
273  int compare(size_type pos, size_type count1, const CharT *s,
274  size_type count2) const;
275 
276  /* Special value. The exact meaning depends on the context. */
277  static const size_type npos = static_cast<size_type>(-1);
278 
279 private:
282 
300  union {
301  struct {
302  /*
303  * EXACTLY the same type as first member in vector
304  * Holds size for sso string, bit specified by _sso_mask
305  * indicates if sso is used.
306  */
307  p<size_type> _size;
308 
309  sso_type _data;
310  } sso;
311 
312  struct {
313  non_sso_type _data;
314  } non_sso;
315  };
316 
317  /*
318  * MSB is used because vector is known not to use entire range of
319  * size_type.
320  */
321  static constexpr size_type _sso_mask = 1ULL
322  << (std::numeric_limits<size_type>::digits - 1);
323 
324  /* helper functions */
325  bool is_sso_used() const;
326  void destroy_data();
327  template <
328  typename InputIt,
329  typename Enable = typename std::enable_if<
331  size_type get_size(InputIt first, InputIt last) const;
332  size_type get_size(size_type count, value_type ch) const;
333  size_type get_size(const basic_string &other) const;
334  template <typename... Args>
335  pointer replace_content(Args &&... args);
336  template <typename... Args>
337  pointer initialize(Args &&... args);
338  void allocate(size_type capacity);
339  template <
340  typename InputIt,
341  typename Enable = typename std::enable_if<
343  pointer assign_sso_data(InputIt first, InputIt last);
344  pointer assign_sso_data(size_type count, value_type ch);
345  pointer assign_sso_data(basic_string &&other);
346  template <
347  typename InputIt,
348  typename Enable = typename std::enable_if<
350  pointer assign_large_data(InputIt first, InputIt last);
351  pointer assign_large_data(size_type count, value_type ch);
352  pointer assign_large_data(basic_string &&other);
353  pool_base get_pool() const;
354  void check_pmem() const;
355  void check_tx_stage_work() const;
356  void check_pmem_tx() const;
357  void add_sso_to_tx(size_type first, size_type num) const;
358  size_type get_sso_size() const;
359  void enable_sso();
360  void disable_sso();
361  void set_sso_size(size_type new_size);
362  void sso_to_large(size_t new_capacity);
363  void large_to_sso();
364  typename basic_string<CharT, Traits>::non_sso_type &non_sso_data();
365  typename basic_string<CharT, Traits>::sso_type &sso_data();
367  non_sso_data() const;
368  const typename basic_string<CharT, Traits>::sso_type &sso_data() const;
369 };
370 
380 template <typename CharT, typename Traits>
382 {
383  check_pmem_tx();
384  sso._size = 0;
385 
386  allocate(0);
387  initialize(0U, value_type('\0'));
388 }
389 
404 template <typename CharT, typename Traits>
406 {
407  check_pmem_tx();
408  sso._size = 0;
409 
410  allocate(count);
411  initialize(count, ch);
412 }
413 
431 template <typename CharT, typename Traits>
433  size_type pos, size_type count)
434 {
435  check_pmem_tx();
436  sso._size = 0;
437 
438  if (pos > other.size())
439  throw std::out_of_range("Index out of range.");
440 
441  if (count == npos || pos + count > other.size())
442  count = other.size() - pos;
443 
444  auto first = static_cast<difference_type>(pos);
445  auto last = first + static_cast<difference_type>(count);
446 
447  allocate(count);
448  initialize(other.cbegin() + first, other.cbegin() + last);
449 }
450 
469 template <typename CharT, typename Traits>
470 basic_string<CharT, Traits>::basic_string(const std::basic_string<CharT> &other,
471  size_type pos, size_type count)
472 {
473  check_pmem_tx();
474  sso._size = 0;
475 
476  if (pos > other.size())
477  throw std::out_of_range("Index out of range.");
478 
479  if (count == npos || pos + count > other.size())
480  count = other.size() - pos;
481 
482  auto first = static_cast<difference_type>(pos);
483  auto last = first + static_cast<difference_type>(count);
484 
485  allocate(count);
486  initialize(other.cbegin() + first, other.cbegin() + last);
487 }
488 
504 template <typename CharT, typename Traits>
505 basic_string<CharT, Traits>::basic_string(const CharT *s, size_type count)
506 {
507  check_pmem_tx();
508  sso._size = 0;
509 
510  allocate(count);
511  initialize(s, s + count);
512 }
513 
527 template <typename CharT, typename Traits>
529 {
530  check_pmem_tx();
531  sso._size = 0;
532 
533  auto length = traits_type::length(s);
534 
535  allocate(length);
536  initialize(s, s + length);
537 }
538 
555 template <typename CharT, typename Traits>
556 template <typename InputIt, typename Enable>
557 basic_string<CharT, Traits>::basic_string(InputIt first, InputIt last)
558 {
559  auto len = std::distance(first, last);
560  assert(len >= 0);
561 
562  check_pmem_tx();
563  sso._size = 0;
564 
565  allocate(static_cast<size_type>(len));
566  initialize(first, last);
567 }
568 
583 template <typename CharT, typename Traits>
585 {
586  check_pmem_tx();
587  sso._size = 0;
588 
589  allocate(other.size());
590  initialize(other.cbegin(), other.cend());
591 }
592 
608 template <typename CharT, typename Traits>
609 basic_string<CharT, Traits>::basic_string(const std::basic_string<CharT> &other)
610  : basic_string(other.cbegin(), other.cend())
611 {
612 }
613 
628 template <typename CharT, typename Traits>
630 {
631  check_pmem_tx();
632  sso._size = 0;
633 
634  allocate(other.size());
635  initialize(std::move(other));
636 
637  if (other.is_sso_used())
638  other.initialize(0U, value_type('\0'));
639 }
640 
655 template <typename CharT, typename Traits>
656 basic_string<CharT, Traits>::basic_string(std::initializer_list<CharT> ilist)
657 {
658  check_pmem_tx();
659  sso._size = 0;
660 
661  allocate(ilist.size());
662  initialize(ilist.begin(), ilist.end());
663 }
664 
670 template <typename CharT, typename Traits>
672 {
673  if (!is_sso_used())
674  detail::destroy<non_sso_type>(non_sso_data());
675 }
676 
686 template <typename CharT, typename Traits>
689 {
690  return assign(other);
691 }
692 
703 template <typename CharT, typename Traits>
705 basic_string<CharT, Traits>::operator=(const std::basic_string<CharT> &other)
706 {
707  return assign(other);
708 }
709 
719 template <typename CharT, typename Traits>
722 {
723  return assign(std::move(other));
724 }
725 
734 template <typename CharT, typename Traits>
737 {
738  return assign(s);
739 }
740 
749 template <typename CharT, typename Traits>
752 {
753  return assign(1, ch);
754 }
755 
765 template <typename CharT, typename Traits>
767 basic_string<CharT, Traits>::operator=(std::initializer_list<CharT> ilist)
768 {
769  return assign(ilist);
770 }
771 
782 template <typename CharT, typename Traits>
784 basic_string<CharT, Traits>::assign(size_type count, CharT ch)
785 {
786  auto pop = get_pool();
787 
788  transaction::run(pop, [&] { replace_content(count, ch); });
789 
790  return *this;
791 }
792 
802 template <typename CharT, typename Traits>
805 {
806  if (&other == this)
807  return *this;
808 
809  auto pop = get_pool();
810 
812  pop, [&] { replace_content(other.cbegin(), other.cend()); });
813 
814  return *this;
815 }
816 
827 template <typename CharT, typename Traits>
829 basic_string<CharT, Traits>::assign(const std::basic_string<CharT> &other)
830 {
831  return assign(other.cbegin(), other.cend());
832 }
833 
846 template <typename CharT, typename Traits>
849  size_type count)
850 {
851  if (pos > other.size())
852  throw std::out_of_range("Index out of range.");
853 
854  if (count == npos || pos + count > other.size())
855  count = other.size() - pos;
856 
857  auto pop = get_pool();
858  auto first = static_cast<difference_type>(pos);
859  auto last = first + static_cast<difference_type>(count);
860 
861  transaction::run(pop, [&] {
862  replace_content(other.cbegin() + first, other.cbegin() + last);
863  });
864 
865  return *this;
866 }
867 
882 template <typename CharT, typename Traits>
884 basic_string<CharT, Traits>::assign(const std::basic_string<CharT> &other,
885  size_type pos, size_type count)
886 {
887  if (pos > other.size())
888  throw std::out_of_range("Index out of range.");
889 
890  if (count == npos || pos + count > other.size())
891  count = other.size() - pos;
892 
893  return assign(other.c_str() + pos, count);
894 }
895 
906 template <typename CharT, typename Traits>
908 basic_string<CharT, Traits>::assign(const CharT *s, size_type count)
909 {
910  auto pop = get_pool();
911 
912  transaction::run(pop, [&] { replace_content(s, s + count); });
913 
914  return *this;
915 }
916 
925 template <typename CharT, typename Traits>
928 {
929  auto pop = get_pool();
930 
931  auto length = traits_type::length(s);
932 
933  transaction::run(pop, [&] { replace_content(s, s + length); });
934 
935  return *this;
936 }
937 
949 template <typename CharT, typename Traits>
950 template <typename InputIt, typename Enable>
952 basic_string<CharT, Traits>::assign(InputIt first, InputIt last)
953 {
954  auto pop = get_pool();
955 
956  transaction::run(pop, [&] { replace_content(first, last); });
957 
958  return *this;
959 }
960 
970 template <typename CharT, typename Traits>
973 {
974  if (&other == this)
975  return *this;
976 
977  auto pop = get_pool();
978 
979  transaction::run(pop, [&] {
980  replace_content(std::move(other));
981 
982  if (other.is_sso_used())
983  other.initialize(0U, value_type('\0'));
984  });
985 
986  return *this;
987 }
988 
998 template <typename CharT, typename Traits>
1000 basic_string<CharT, Traits>::assign(std::initializer_list<CharT> ilist)
1001 {
1002  return assign(ilist.begin(), ilist.end());
1003 }
1004 
1010 template <typename CharT, typename Traits>
1013 {
1014  return is_sso_used() ? iterator(&*sso_data().begin())
1015  : iterator(&*non_sso_data().begin());
1016 }
1017 
1023 template <typename CharT, typename Traits>
1024 typename basic_string<CharT, Traits>::const_iterator
1026 {
1027  return cbegin();
1028 }
1029 
1035 template <typename CharT, typename Traits>
1036 typename basic_string<CharT, Traits>::const_iterator
1038 {
1039  return is_sso_used() ? const_iterator(&*sso_data().cbegin())
1040  : const_iterator(&*non_sso_data().cbegin());
1041 }
1042 
1048 template <typename CharT, typename Traits>
1051 {
1052  return begin() + static_cast<difference_type>(size());
1053 }
1054 
1061 template <typename CharT, typename Traits>
1062 typename basic_string<CharT, Traits>::const_iterator
1064 {
1065  return cbegin() + static_cast<difference_type>(size());
1066 }
1067 
1074 template <typename CharT, typename Traits>
1075 typename basic_string<CharT, Traits>::const_iterator
1077 {
1078  return cbegin() + static_cast<difference_type>(size());
1079 }
1080 
1087 template <typename CharT, typename Traits>
1088 typename basic_string<CharT, Traits>::reverse_iterator
1090 {
1091  return reverse_iterator(end());
1092 }
1093 
1100 template <typename CharT, typename Traits>
1101 typename basic_string<CharT, Traits>::const_reverse_iterator
1103 {
1104  return crbegin();
1105 }
1106 
1113 template <typename CharT, typename Traits>
1114 typename basic_string<CharT, Traits>::const_reverse_iterator
1116 {
1117  return const_reverse_iterator(cend());
1118 }
1119 
1126 template <typename CharT, typename Traits>
1127 typename basic_string<CharT, Traits>::reverse_iterator
1129 {
1130  return reverse_iterator(begin());
1131 }
1132 
1139 template <typename CharT, typename Traits>
1140 typename basic_string<CharT, Traits>::const_reverse_iterator
1142 {
1143  return crend();
1144 }
1145 
1152 template <typename CharT, typename Traits>
1153 typename basic_string<CharT, Traits>::const_reverse_iterator
1155 {
1156  return const_reverse_iterator(cbegin());
1157 }
1158 
1172 template <typename CharT, typename Traits>
1173 typename basic_string<CharT, Traits>::reference
1175 {
1176  if (n >= size())
1177  throw std::out_of_range("string::at");
1178 
1179  return is_sso_used() ? sso_data()[n] : non_sso_data()[n];
1180 }
1181 
1192 template <typename CharT, typename Traits>
1193 typename basic_string<CharT, Traits>::const_reference
1195 {
1196  return const_at(n);
1197 }
1198 
1212 template <typename CharT, typename Traits>
1213 typename basic_string<CharT, Traits>::const_reference
1215 {
1216  if (n >= size())
1217  throw std::out_of_range("string::const_at");
1218 
1219  return is_sso_used()
1220  ? static_cast<const sso_type &>(sso_data())[n]
1221  : static_cast<const non_sso_type &>(non_sso_data())[n];
1222 }
1223 
1235 template <typename CharT, typename Traits>
1236 typename basic_string<CharT, Traits>::reference basic_string<CharT, Traits>::
1237 operator[](size_type n)
1238 {
1239  return is_sso_used() ? sso_data()[n] : non_sso_data()[n];
1240 }
1241 
1249 template <typename CharT, typename Traits>
1250 typename basic_string<CharT, Traits>::const_reference
1252 {
1253  return is_sso_used() ? sso_data()[n] : non_sso_data()[n];
1254 }
1255 
1265 template <typename CharT, typename Traits>
1266 CharT &
1268 {
1269  return (*this)[0];
1270 }
1271 
1277 template <typename CharT, typename Traits>
1278 const CharT &
1280 {
1281  return cfront();
1282 }
1283 
1292 template <typename CharT, typename Traits>
1293 const CharT &
1295 {
1296  return static_cast<const basic_string &>(*this)[0];
1297 }
1298 
1308 template <typename CharT, typename Traits>
1309 CharT &
1311 {
1312  return (*this)[size() - 1];
1313 }
1314 
1320 template <typename CharT, typename Traits>
1321 const CharT &
1323 {
1324  return cback();
1325 }
1326 
1335 template <typename CharT, typename Traits>
1336 const CharT &
1338 {
1339  return static_cast<const basic_string &>(*this)[size() - 1];
1340 }
1341 
1345 template <typename CharT, typename Traits>
1346 typename basic_string<CharT, Traits>::size_type
1348 {
1349  if (is_sso_used())
1350  return get_sso_size();
1351  else if (non_sso_data().size() == 0)
1352  return 0;
1353  else
1354  return non_sso_data().size() - 1;
1355 }
1356 
1363 template <typename CharT, typename Traits>
1364 CharT *
1366 {
1367  return is_sso_used() ? sso_data().range(0, get_sso_size() + 1).begin()
1368  : non_sso_data().data();
1369 }
1370 
1389 template <typename CharT, typename Traits>
1391 basic_string<CharT, Traits>::erase(size_type index, size_type count)
1392 {
1393  auto sz = size();
1394 
1395  if (index > sz)
1396  throw std::out_of_range("Index exceeds size.");
1397 
1398  count = (std::min)(count, sz - index);
1399 
1400  auto pop = get_pool();
1401 
1402  auto first = begin() + static_cast<difference_type>(index);
1403  auto last = first + static_cast<difference_type>(count);
1404 
1405  if (is_sso_used()) {
1406  transaction::run(pop, [&] {
1407  auto move_len = sz - index - count;
1408  auto new_size = sz - count;
1409 
1410  auto range = sso_data().range(index, move_len + 1);
1411 
1412  traits_type::move(range.begin(), &*last, move_len);
1413 
1414  set_sso_size(new_size);
1415 
1416  assert(range.end() - 1 ==
1417  &sso_data()._data[index + move_len]);
1418  *(range.end() - 1) = value_type('\0');
1419  });
1420  } else {
1421  non_sso_data().erase(first, last);
1422  }
1423 
1424  return *this;
1425 }
1426 
1443 template <typename CharT, typename Traits>
1446 {
1447  return erase(pos, pos + 1);
1448 }
1449 
1468 template <typename CharT, typename Traits>
1470 basic_string<CharT, Traits>::erase(const_iterator first, const_iterator last)
1471 {
1472  size_type index =
1473  static_cast<size_type>(std::distance(cbegin(), first));
1474  size_type len = static_cast<size_type>(std::distance(first, last));
1475 
1476  erase(index, len);
1477 
1478  return begin() + static_cast<difference_type>(index);
1479 }
1480 
1491 template <typename CharT, typename Traits>
1492 void
1494 {
1495  erase(size() - 1, 1);
1496 }
1497 
1517 template <typename CharT, typename Traits>
1519 basic_string<CharT, Traits>::append(size_type count, CharT ch)
1520 {
1521  auto sz = size();
1522  auto new_size = sz + count;
1523 
1524  if (new_size > max_size())
1525  throw std::length_error("Size exceeds max size.");
1526 
1527  if (is_sso_used()) {
1528  auto pop = get_pool();
1529 
1530  transaction::run(pop, [&] {
1531  if (new_size > sso_capacity) {
1532  sso_to_large(new_size);
1533 
1534  non_sso_data().insert(
1535  non_sso_data().cbegin() +
1536  static_cast<difference_type>(
1537  sz),
1538  count, ch);
1539  } else {
1540  add_sso_to_tx(sz, count + 1);
1541  traits_type::assign(&sso_data()._data[sz],
1542  count, ch);
1543 
1544  assert(new_size == sz + count);
1545  set_sso_size(new_size);
1546  sso_data()._data[new_size] = value_type('\0');
1547  }
1548  });
1549  } else {
1550  non_sso_data().insert(non_sso_data().cbegin() +
1551  static_cast<difference_type>(sz),
1552  count, ch);
1553  }
1554 
1555  return *this;
1556 }
1557 
1576 template <typename CharT, typename Traits>
1579 {
1580  return append(str.data(), str.size());
1581 }
1582 
1608 template <typename CharT, typename Traits>
1611  size_type count)
1612 {
1613  auto sz = str.size();
1614 
1615  if (pos > sz)
1616  throw std::out_of_range("Index out of range.");
1617 
1618  count = (std::min)(count, sz - pos);
1619 
1620  append(str.data() + pos, count);
1621 
1622  return *this;
1623 }
1624 
1644 template <typename CharT, typename Traits>
1646 basic_string<CharT, Traits>::append(const CharT *s, size_type count)
1647 {
1648  return append(s, s + count);
1649 }
1650 
1670 template <typename CharT, typename Traits>
1673 {
1674  return append(s, traits_type::length(s));
1675 }
1676 
1698 template <typename CharT, typename Traits>
1699 template <typename InputIt, typename Enable>
1701 basic_string<CharT, Traits>::append(InputIt first, InputIt last)
1702 {
1703  auto sz = size();
1704  auto count = static_cast<size_type>(std::distance(first, last));
1705  auto new_size = sz + count;
1706 
1707  if (new_size > max_size())
1708  throw std::length_error("Size exceeds max size.");
1709 
1710  if (is_sso_used()) {
1711  auto pop = get_pool();
1712 
1713  transaction::run(pop, [&] {
1714  if (new_size > sso_capacity) {
1715  /* 1) Cache C-style string in case of
1716  * self-append, because it will be destroyed
1717  * when switching from sso to large string.
1718  *
1719  * 2) We cache in std::vector instead of
1720  * std::string because of overload deduction
1721  * ambiguity on Windows
1722  */
1723  std::vector<value_type> str(first, last);
1724 
1725  sso_to_large(new_size);
1726  non_sso_data().insert(
1727  non_sso_data().cbegin() +
1728  static_cast<difference_type>(
1729  sz),
1730  str.begin(), str.end());
1731  } else {
1732  add_sso_to_tx(sz, count + 1);
1733  std::copy(first, last, &sso_data()._data[sz]);
1734 
1735  assert(new_size == sz + count);
1736  set_sso_size(new_size);
1737  sso_data()._data[new_size] = value_type('\0');
1738  }
1739  });
1740  } else {
1741  non_sso_data().insert(non_sso_data().cbegin() +
1742  static_cast<difference_type>(sz),
1743  first, last);
1744  }
1745 
1746  return *this;
1747 }
1748 
1767 template <typename CharT, typename Traits>
1769 basic_string<CharT, Traits>::append(std::initializer_list<CharT> ilist)
1770 {
1771  return append(ilist.begin(), ilist.end());
1772 }
1773 
1790 template <typename CharT, typename Traits>
1791 void
1793 {
1794  append(static_cast<size_type>(1), ch);
1795 }
1796 
1815 template <typename CharT, typename Traits>
1818 {
1819  return append(str);
1820 }
1821 
1841 template <typename CharT, typename Traits>
1844 {
1845  return append(s);
1846 }
1847 
1864 template <typename CharT, typename Traits>
1867 {
1868  push_back(ch);
1869 
1870  return *this;
1871 }
1872 
1891 template <typename CharT, typename Traits>
1893 basic_string<CharT, Traits>::operator+=(std::initializer_list<CharT> ilist)
1894 {
1895  return append(ilist);
1896 }
1897 
1919 template <typename CharT, typename Traits>
1921 basic_string<CharT, Traits>::insert(size_type index, size_type count, CharT ch)
1922 {
1923  if (index > size())
1924  throw std::out_of_range("Index out of range.");
1925 
1926  auto pos = cbegin() + static_cast<difference_type>(index);
1927 
1928  insert(pos, count, ch);
1929 
1930  return *this;
1931 }
1932 
1954 template <typename CharT, typename Traits>
1956 basic_string<CharT, Traits>::insert(size_type index, const CharT *s)
1957 {
1958  return insert(index, s, traits_type::length(s));
1959 }
1960 
1982 template <typename CharT, typename Traits>
1984 basic_string<CharT, Traits>::insert(size_type index, const CharT *s,
1985  size_type count)
1986 {
1987  if (index > size())
1988  throw std::out_of_range("Index out of range.");
1989 
1990  auto pos = cbegin() + static_cast<difference_type>(index);
1991 
1992  insert(pos, s, s + count);
1993 
1994  return *this;
1995 }
1996 
2017 template <typename CharT, typename Traits>
2020 {
2021  return insert(index, str.data(), str.size());
2022 }
2023 
2046 template <typename CharT, typename Traits>
2049  size_type index2, size_type count)
2050 {
2051  auto sz = str.size();
2052 
2053  if (index1 > size() || index2 > sz)
2054  throw std::out_of_range("Index out of range.");
2055 
2056  count = (std::min)(count, sz - index2);
2057 
2058  return insert(index1, str.data() + index2, count);
2059 }
2060 
2083 template <typename CharT, typename Traits>
2085 basic_string<CharT, Traits>::insert(const_iterator pos, CharT ch)
2086 {
2087  return insert(pos, 1, ch);
2088 }
2089 
2114 template <typename CharT, typename Traits>
2116 basic_string<CharT, Traits>::insert(const_iterator pos, size_type count,
2117  CharT ch)
2118 {
2119  auto sz = size();
2120 
2121  if (sz + count > max_size())
2122  throw std::length_error("Count exceeds max size.");
2123 
2124  auto new_size = sz + count;
2125 
2126  auto pop = get_pool();
2127 
2128  auto index = static_cast<size_type>(std::distance(cbegin(), pos));
2129 
2130  transaction::run(pop, [&] {
2131  if (is_sso_used() && new_size <= sso_capacity) {
2132  auto len = sz - index;
2133 
2134  add_sso_to_tx(index, len + count + 1);
2135 
2136  traits_type::move(&sso_data()._data[index + count],
2137  &sso_data()._data[index], len);
2138  traits_type::assign(&sso_data()._data[index], count,
2139  ch);
2140 
2141  assert(new_size == index + len + count);
2142  set_sso_size(new_size);
2143  sso_data()._data[new_size] = value_type('\0');
2144  } else {
2145  if (is_sso_used())
2146  sso_to_large(new_size);
2147 
2148  non_sso_data().insert(
2149  non_sso_data().begin() +
2150  static_cast<difference_type>(index),
2151  count, ch);
2152  }
2153  });
2154 
2155  return iterator(&data()[static_cast<difference_type>(index)]);
2156 }
2157 
2182 template <typename CharT, typename Traits>
2183 template <typename InputIt, typename Enable>
2185 basic_string<CharT, Traits>::insert(const_iterator pos, InputIt first,
2186  InputIt last)
2187 {
2188  auto sz = size();
2189 
2190  auto count = static_cast<size_type>(std::distance(first, last));
2191 
2192  if (sz + count > max_size())
2193  throw std::length_error("Count exceeds max size.");
2194 
2195  auto pop = get_pool();
2196 
2197  auto new_size = sz + count;
2198 
2199  auto index = static_cast<size_type>(std::distance(cbegin(), pos));
2200 
2201  transaction::run(pop, [&] {
2202  if (is_sso_used() && new_size <= sso_capacity) {
2203  auto len = sz - index;
2204 
2205  add_sso_to_tx(index, len + count + 1);
2206 
2207  traits_type::move(&sso_data()._data[index + count],
2208  &sso_data()._data[index], len);
2209  std::copy(first, last, &sso_data()._data[index]);
2210 
2211  assert(new_size == index + len + count);
2212  set_sso_size(new_size);
2213  sso_data()._data[new_size] = value_type('\0');
2214  } else {
2215  if (is_sso_used()) {
2216  /* 1) Cache C-style string in case of
2217  * self-insert, because it will be destroyed
2218  * when switching from sso to large string.
2219  *
2220  * 2) We cache in std::vector instead of
2221  * std::string because of overload deduction
2222  * ambiguity on Windows
2223  */
2224  std::vector<value_type> str(first, last);
2225 
2226  sso_to_large(new_size);
2227  non_sso_data().insert(
2228  non_sso_data().begin() +
2229  static_cast<difference_type>(
2230  index),
2231  str.begin(), str.end());
2232  } else {
2233  non_sso_data().insert(
2234  non_sso_data().begin() +
2235  static_cast<difference_type>(
2236  index),
2237  first, last);
2238  }
2239  }
2240  });
2241 
2242  return iterator(&data()[static_cast<difference_type>(index)]);
2243 }
2244 
2268 template <typename CharT, typename Traits>
2271  std::initializer_list<CharT> ilist)
2272 {
2273  return insert(pos, ilist.begin(), ilist.end());
2274 }
2275 
2298 template <typename CharT, typename Traits>
2300 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2301  const basic_string &str)
2302 {
2303  return replace(index, count, str.data(), str.size());
2304 }
2305 
2326 template <typename CharT, typename Traits>
2328 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2329  const basic_string &str)
2330 {
2331  return replace(first, last, str.data(), str.data() + str.size());
2332 }
2333 
2360 template <typename CharT, typename Traits>
2362 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2363  const basic_string &str, size_type index2,
2364  size_type count2)
2365 {
2366  auto sz = str.size();
2367 
2368  if (index2 > sz)
2369  throw std::out_of_range("Index out of range.");
2370 
2371  count2 = (std::min)(count2, sz - index2);
2372 
2373  return replace(index, count, str.data() + index2, count2);
2374 }
2375 
2401 template <typename CharT, typename Traits>
2402 template <typename InputIt, typename Enable>
2404 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2405  InputIt first2, InputIt last2)
2406 {
2407  auto sz = size();
2408  auto index = static_cast<size_type>(std::distance(cbegin(), first));
2409  auto count = static_cast<size_type>(std::distance(first, last));
2410  auto count2 = static_cast<size_type>(std::distance(first2, last2));
2411 
2412  count = (std::min)(count, sz - index);
2413 
2414  if (sz - count + count2 > max_size())
2415  throw std::length_error("Count exceeds max size.");
2416 
2417  auto new_size = sz - count + count2;
2418 
2419  auto pop = get_pool();
2420 
2421  transaction::run(pop, [&] {
2422  if (is_sso_used() && new_size <= sso_capacity) {
2423  add_sso_to_tx(index, new_size - index + 1);
2424 
2425  assert(count2 < new_size + 1);
2426  traits_type::move(&sso_data()._data[index + count2],
2427  &sso_data()._data[index + count],
2428  sz - index - count);
2429  std::copy(first2, last2, &sso_data()._data[index]);
2430 
2431  set_sso_size(new_size);
2432  sso_data()._data[new_size] = value_type('\0');
2433  } else {
2434  /* 1) Cache C-style string in case of
2435  * self-replace, because it will be destroyed
2436  * when switching from sso to large string.
2437  *
2438  * 2) We cache in std::vector instead of
2439  * std::string because of overload deduction
2440  * ambiguity on Windows
2441  */
2442  std::vector<value_type> str(first2, last2);
2443 
2444  if (is_sso_used()) {
2445  sso_to_large(new_size);
2446  }
2447 
2448  auto beg =
2449  begin() + static_cast<difference_type>(index);
2450  auto end = beg + static_cast<difference_type>(count);
2451  non_sso_data().erase(beg, end);
2452  non_sso_data().insert(beg, str.begin(), str.end());
2453  }
2454 
2455  if (!is_sso_used() && new_size <= sso_capacity)
2456  large_to_sso();
2457  });
2458 
2459  return *this;
2460 }
2461 
2484 template <typename CharT, typename Traits>
2486 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2487  const CharT *s, size_type count2)
2488 {
2489  return replace(first, last, s, s + count2);
2490 }
2491 
2515 template <typename CharT, typename Traits>
2517 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2518  const CharT *s, size_type count2)
2519 {
2520  if (index > size())
2521  throw std::out_of_range("Index out of range.");
2522 
2523  auto first = cbegin() + static_cast<difference_type>(index);
2524  auto last = first + static_cast<difference_type>(count);
2525 
2526  return replace(first, last, s, s + count2);
2527 }
2528 
2552 template <typename CharT, typename Traits>
2554 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2555  const CharT *s)
2556 {
2557  return replace(index, count, s, traits_type::length(s));
2558 }
2559 
2583 template <typename CharT, typename Traits>
2585 basic_string<CharT, Traits>::replace(size_type index, size_type count,
2586  size_type count2, CharT ch)
2587 {
2588  if (index > size())
2589  throw std::out_of_range("Index out of range.");
2590 
2591  auto first = cbegin() + static_cast<difference_type>(index);
2592  auto last = first + static_cast<difference_type>(count);
2593 
2594  return replace(first, last, count2, ch);
2595 }
2596 
2619 template <typename CharT, typename Traits>
2621 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2622  size_type count2, CharT ch)
2623 {
2624  auto sz = size();
2625  auto index = static_cast<size_type>(std::distance(cbegin(), first));
2626  auto count = static_cast<size_type>(std::distance(first, last));
2627 
2628  count = (std::min)(count, sz - index);
2629 
2630  if (sz - count + count2 > max_size())
2631  throw std::length_error("Count exceeds max size.");
2632 
2633  auto new_size = sz - count + count2;
2634 
2635  auto pop = get_pool();
2636 
2637  transaction::run(pop, [&] {
2638  if (is_sso_used() && new_size <= sso_capacity) {
2639  add_sso_to_tx(index, new_size - index + 1);
2640 
2641  assert(count2 < new_size + 1);
2642  traits_type::move(&sso_data()._data[index + count2],
2643  &sso_data()._data[index + count],
2644  sz - index - count);
2645  traits_type::assign(&sso_data()._data[index], count2,
2646  ch);
2647 
2648  set_sso_size(new_size);
2649  sso_data()._data[new_size] = value_type('\0');
2650  } else {
2651  if (is_sso_used()) {
2652  sso_to_large(new_size);
2653  }
2654 
2655  auto beg =
2656  begin() + static_cast<difference_type>(index);
2657  auto end = beg + static_cast<difference_type>(count);
2658  non_sso_data().erase(beg, end);
2659  non_sso_data().insert(beg, count2, ch);
2660  }
2661 
2662  if (!is_sso_used() && new_size <= sso_capacity)
2663  large_to_sso();
2664  });
2665 
2666  return *this;
2667 }
2668 
2690 template <typename CharT, typename Traits>
2692 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2693  const CharT *s)
2694 {
2695  return replace(first, last, s, traits_type::length(s));
2696 }
2697 
2720 template <typename CharT, typename Traits>
2722 basic_string<CharT, Traits>::replace(const_iterator first, const_iterator last,
2723  std::initializer_list<CharT> ilist)
2724 {
2725  return replace(first, last, ilist.begin(), ilist.end());
2726 }
2727 
2741 template <typename CharT, typename Traits>
2742 typename basic_string<CharT, Traits>::size_type
2743 basic_string<CharT, Traits>::copy(CharT *s, size_type count,
2744  size_type index) const
2745 {
2746  auto sz = size();
2747 
2748  if (index > sz)
2749  throw std::out_of_range("Index out of range.");
2750 
2751  auto len = (std::min)(count, sz - index);
2752 
2753  traits_type::copy(s, data() + index, len);
2754 
2755  return len;
2756 }
2757 
2775 template <typename CharT, typename Traits>
2776 int
2777 basic_string<CharT, Traits>::compare(size_type pos, size_type count1,
2778  const CharT *s, size_type count2) const
2779 {
2780  if (pos > size())
2781  throw std::out_of_range("Index out of range.");
2782 
2783  if (count1 > size() - pos)
2784  count1 = size() - pos;
2785 
2786  auto ret = traits_type::compare(cdata() + pos, s,
2787  std::min<size_type>(count1, count2));
2788 
2789  if (ret != 0)
2790  return ret;
2791 
2792  if (count1 < count2)
2793  return -1;
2794  else if (count1 == count2)
2795  return 0;
2796  else
2797  return 1;
2798 }
2799 
2808 template <typename CharT, typename Traits>
2809 int
2811 {
2812  return compare(0, size(), other.cdata(), other.size());
2813 }
2814 
2823 template <typename CharT, typename Traits>
2824 int
2826  const std::basic_string<CharT> &other) const
2827 {
2828  return compare(0, size(), other.data(), other.size());
2829 }
2830 
2844 template <typename CharT, typename Traits>
2845 int
2846 basic_string<CharT, Traits>::compare(size_type pos, size_type count,
2847  const basic_string &other) const
2848 {
2849  return compare(pos, count, other.cdata(), other.size());
2850 }
2851 
2866 template <typename CharT, typename Traits>
2867 int
2869  size_type pos, size_type count,
2870  const std::basic_string<CharT> &other) const
2871 {
2872  return compare(pos, count, other.data(), other.size());
2873 }
2874 
2893 template <typename CharT, typename Traits>
2894 int
2895 basic_string<CharT, Traits>::compare(size_type pos1, size_type count1,
2896  const basic_string &other, size_type pos2,
2897  size_type count2) const
2898 {
2899  if (pos2 > other.size())
2900  throw std::out_of_range("Index out of range.");
2901 
2902  if (count2 > other.size() - pos2)
2903  count2 = other.size() - pos2;
2904 
2905  return compare(pos1, count1, other.cdata() + pos2, count2);
2906 }
2907 
2926 template <typename CharT, typename Traits>
2927 int
2928 basic_string<CharT, Traits>::compare(size_type pos1, size_type count1,
2929  const std::basic_string<CharT> &other,
2930  size_type pos2, size_type count2) const
2931 {
2932  if (pos2 > other.size())
2933  throw std::out_of_range("Index out of range.");
2934 
2935  if (count2 > other.size() - pos2)
2936  count2 = other.size() - pos2;
2937 
2938  return compare(pos1, count1, other.data() + pos2, count2);
2939 }
2940 
2949 template <typename CharT, typename Traits>
2950 int
2952 {
2953  return compare(0, size(), s, traits_type::length(s));
2954 }
2955 
2969 template <typename CharT, typename Traits>
2970 int
2971 basic_string<CharT, Traits>::compare(size_type pos, size_type count,
2972  const CharT *s) const
2973 {
2974  return compare(pos, count, s, traits_type::length(s));
2975 }
2976 
2980 template <typename CharT, typename Traits>
2981 const CharT *
2983 {
2984  return is_sso_used() ? sso_data().cdata() : non_sso_data().cdata();
2985 }
2986 
2990 template <typename CharT, typename Traits>
2991 const CharT *
2993 {
2994  return cdata();
2995 }
2996 
3000 template <typename CharT, typename Traits>
3001 const CharT *
3003 {
3004  return cdata();
3005 }
3006 
3010 template <typename CharT, typename Traits>
3011 typename basic_string<CharT, Traits>::size_type
3013 {
3014  return size();
3015 }
3016 
3020 template <typename CharT, typename Traits>
3021 typename basic_string<CharT, Traits>::size_type
3023 {
3024  return PMEMOBJ_MAX_ALLOC_SIZE / sizeof(CharT) - 1;
3025 }
3026 
3031 template <typename CharT, typename Traits>
3032 typename basic_string<CharT, Traits>::size_type
3034 {
3035  return is_sso_used() ? sso_capacity : non_sso_data().capacity() - 1;
3036 }
3037 
3057 template <typename CharT, typename Traits>
3058 void
3059 basic_string<CharT, Traits>::resize(size_type count, CharT ch)
3060 {
3061  if (count > max_size())
3062  throw std::length_error("Count exceeds max size.");
3063 
3064  auto sz = size();
3065 
3066  auto pop = get_pool();
3067 
3068  transaction::run(pop, [&] {
3069  if (count > sz) {
3070  append(count - sz, ch);
3071  } else if (is_sso_used()) {
3072  set_sso_size(count);
3073  sso_data()[count] = value_type('\0');
3074  } else {
3075  non_sso_data().resize(count + 1, ch);
3076  non_sso_data().back() = value_type('\0');
3077  }
3078  });
3079 }
3080 
3099 template <typename CharT, typename Traits>
3100 void
3102 {
3103  resize(count, CharT());
3104 }
3105 
3126 template <typename CharT, typename Traits>
3127 void
3129 {
3130  if (new_cap > max_size())
3131  throw std::length_error("New capacity exceeds max size.");
3132 
3133  if (new_cap < capacity() || new_cap <= sso_capacity)
3134  return;
3135 
3136  if (is_sso_used()) {
3137  auto pop = get_pool();
3138 
3139  transaction::run(pop, [&] { sso_to_large(new_cap); });
3140  } else {
3141  non_sso_data().reserve(new_cap + 1);
3142  }
3143 }
3144 
3158 template <typename CharT, typename Traits>
3159 void
3161 {
3162  if (is_sso_used())
3163  return;
3164 
3165  if (size() <= sso_capacity) {
3166  auto pop = get_pool();
3167 
3168  transaction::run(pop, [&] { large_to_sso(); });
3169  } else {
3170  non_sso_data().shrink_to_fit();
3171  }
3172 }
3173 
3183 template <typename CharT, typename Traits>
3184 void
3186 {
3187  erase(begin(), end());
3188 }
3189 
3193 template <typename CharT, typename Traits>
3194 bool
3196 {
3197  return size() == 0;
3198 }
3199 
3200 template <typename CharT, typename Traits>
3201 bool
3203 {
3204  return (sso._size & _sso_mask) != 0;
3205 }
3206 
3207 template <typename CharT, typename Traits>
3208 void
3209 basic_string<CharT, Traits>::destroy_data()
3210 {
3211  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3212 
3213  if (is_sso_used()) {
3214  add_sso_to_tx(0, get_sso_size() + 1);
3215  /* sso.data destructor does not have to be called */
3216  } else {
3217  non_sso_data().free_data();
3218  detail::destroy<non_sso_type>(non_sso_data());
3219  }
3220 }
3221 
3228 template <typename CharT, typename Traits>
3229 template <typename InputIt, typename Enable>
3230 typename basic_string<CharT, Traits>::size_type
3231 basic_string<CharT, Traits>::get_size(InputIt first, InputIt last) const
3232 {
3233  return static_cast<size_type>(std::distance(first, last));
3234 }
3235 
3242 template <typename CharT, typename Traits>
3243 typename basic_string<CharT, Traits>::size_type
3244 basic_string<CharT, Traits>::get_size(size_type count, value_type ch) const
3245 {
3246  return count;
3247 }
3248 
3255 template <typename CharT, typename Traits>
3256 typename basic_string<CharT, Traits>::size_type
3258 {
3259  return other.size();
3260 }
3261 
3269 template <typename CharT, typename Traits>
3270 template <typename... Args>
3271 typename basic_string<CharT, Traits>::pointer
3273 {
3274  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3275 
3276  auto new_size = get_size(std::forward<Args>(args)...);
3277 
3278  /* If non_sso.data is used and there is enough capacity */
3279  if (!is_sso_used() && new_size <= capacity())
3280  return assign_large_data(std::forward<Args>(args)...);
3281 
3282  destroy_data();
3283 
3284  allocate(new_size);
3285  return initialize(std::forward<Args>(args)...);
3286 }
3287 
3299 template <typename CharT, typename Traits>
3300 template <typename... Args>
3301 typename basic_string<CharT, Traits>::pointer
3303 {
3304  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3305 
3306  auto size = get_size(std::forward<Args>(args)...);
3307 
3308  if (is_sso_used()) {
3309  auto ptr = assign_sso_data(std::forward<Args>(args)...);
3310  set_sso_size(size);
3311 
3312  return ptr;
3313  } else {
3314  return assign_large_data(std::forward<Args>(args)...);
3315  }
3316 }
3317 
3327 template <typename CharT, typename Traits>
3328 void
3330 {
3331  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3332 
3333  if (capacity <= sso_capacity) {
3334  enable_sso();
3335  } else {
3336  disable_sso();
3337  }
3338 
3339  /*
3340  * array is aggregate type so it's not required to call
3341  * a constructor.
3342  */
3343  if (!is_sso_used()) {
3344  detail::conditional_add_to_tx(&non_sso_data(), 1,
3345  POBJ_XADD_NO_SNAPSHOT);
3346  detail::create<non_sso_type>(&non_sso_data());
3347  non_sso_data().reserve(capacity + 1);
3348  }
3349 }
3350 
3354 template <typename CharT, typename Traits>
3355 template <typename InputIt, typename Enable>
3356 typename basic_string<CharT, Traits>::pointer
3358 {
3359  auto size = static_cast<size_type>(std::distance(first, last));
3360 
3361  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3362  assert(size <= sso_capacity);
3363 
3364  add_sso_to_tx(0, size + 1);
3365  std::copy(first, last, &sso_data()._data[0]);
3366 
3367  sso_data()._data[size] = value_type('\0');
3368 
3369  return &sso_data()[0];
3370 }
3371 
3375 template <typename CharT, typename Traits>
3376 typename basic_string<CharT, Traits>::pointer
3377 basic_string<CharT, Traits>::assign_sso_data(size_type count, value_type ch)
3378 {
3379  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3380  assert(count <= sso_capacity);
3381 
3382  add_sso_to_tx(0, count + 1);
3383  traits_type::assign(&sso_data()._data[0], count, ch);
3384 
3385  sso_data()._data[count] = value_type('\0');
3386 
3387  return &sso_data()[0];
3388 }
3389 
3393 template <typename CharT, typename Traits>
3394 typename basic_string<CharT, Traits>::pointer
3396 {
3397  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3398 
3399  return assign_sso_data(other.cbegin(), other.cend());
3400 }
3401 
3406 template <typename CharT, typename Traits>
3407 template <typename InputIt, typename Enable>
3408 typename basic_string<CharT, Traits>::pointer
3410 {
3411  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3412 
3413  auto size = static_cast<size_type>(std::distance(first, last));
3414 
3415  non_sso_data().reserve(size + 1);
3416  non_sso_data().assign(first, last);
3417  non_sso_data().push_back(value_type('\0'));
3418 
3419  return non_sso_data().data();
3420 }
3421 
3426 template <typename CharT, typename Traits>
3427 typename basic_string<CharT, Traits>::pointer
3428 basic_string<CharT, Traits>::assign_large_data(size_type count, value_type ch)
3429 {
3430  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3431 
3432  non_sso_data().reserve(count + 1);
3433  non_sso_data().assign(count, ch);
3434  non_sso_data().push_back(value_type('\0'));
3435 
3436  return non_sso_data().data();
3437 }
3438 
3443 template <typename CharT, typename Traits>
3444 typename basic_string<CharT, Traits>::pointer
3446 {
3447  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3448 
3449  if (other.is_sso_used())
3450  return assign_large_data(other.cbegin(), other.cend());
3451 
3452  non_sso_data() = std::move(other.non_sso_data());
3453 
3454  return non_sso_data().data();
3455 }
3456 
3460 template <typename CharT, typename Traits>
3461 pool_base
3463 {
3464  auto pop = pmemobj_pool_by_ptr(this);
3465  assert(pop != nullptr);
3466 
3467  return pool_base(pop);
3468 }
3469 
3473 template <typename CharT, typename Traits>
3474 void
3476 {
3477  if (pmemobj_pool_by_ptr(this) == nullptr)
3478  throw pmem::pool_error("Object is not on pmem.");
3479 }
3480 
3484 template <typename CharT, typename Traits>
3485 void
3487 {
3488  if (pmemobj_tx_stage() != TX_STAGE_WORK)
3490  "Call made out of transaction scope.");
3491 }
3492 
3497 template <typename CharT, typename Traits>
3498 void
3500 {
3501  check_pmem();
3502  check_tx_stage_work();
3503 }
3504 
3508 template <typename CharT, typename Traits>
3509 void
3511  size_type num) const
3512 {
3513  assert(idx_first + num <= sso_capacity + 1);
3514  assert(is_sso_used());
3515 
3516  auto initialized_num = get_sso_size() + 1 - idx_first;
3517 
3518  /* Snapshot elements in range [idx_first, sso_size + 1 (null)) */
3519  detail::conditional_add_to_tx(&sso_data()._data[0] + idx_first,
3520  (std::min)(initialized_num, num));
3521 
3522  if (num > initialized_num) {
3523  /* Elements after sso_size + 1 do not have to be snapshotted */
3524  detail::conditional_add_to_tx(
3525  &sso_data()._data[0] + get_sso_size() + 1,
3526  num - initialized_num, POBJ_XADD_NO_SNAPSHOT);
3527  }
3528 }
3529 
3533 template <typename CharT, typename Traits>
3534 typename basic_string<CharT, Traits>::size_type
3536 {
3537  return sso._size & ~_sso_mask;
3538 }
3539 
3543 template <typename CharT, typename Traits>
3544 void
3546 {
3547  /* temporary size_type must be created to avoid undefined reference
3548  * linker error */
3549  sso._size |= (size_type)(_sso_mask);
3550 }
3551 
3555 template <typename CharT, typename Traits>
3556 void
3558 {
3559  sso._size &= ~_sso_mask;
3560 }
3561 
3565 template <typename CharT, typename Traits>
3566 void
3568 {
3569  sso._size = new_size | _sso_mask;
3570 }
3571 
3583 template <typename CharT, typename Traits>
3584 void
3586 {
3587  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3588  assert(new_capacity > sso_capacity);
3589  assert(is_sso_used());
3590 
3591  auto sz = size();
3592 
3593  sso_type tmp;
3594  std::copy(cbegin(), cend(), tmp.data());
3595  tmp[sz] = value_type('\0');
3596 
3597  destroy_data();
3598  allocate(new_capacity);
3599 
3600  auto begin = tmp.cbegin();
3601  auto end = begin + sz;
3602 
3603  initialize(begin, end);
3604 
3605  assert(!is_sso_used());
3606 };
3607 
3617 template <typename CharT, typename Traits>
3618 void
3620 {
3621  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
3622  assert(!is_sso_used());
3623 
3624  auto sz = size();
3625 
3626  assert(sz <= sso_capacity);
3627 
3628  sso_type tmp;
3629  std::copy(cbegin(), cbegin() + sz, tmp.data());
3630  tmp[sz] = value_type('\0');
3631 
3632  destroy_data();
3633  allocate(sz);
3634 
3635  auto begin = tmp.cbegin();
3636  auto end = begin + sz;
3637 
3638  initialize(begin, end);
3639 
3640  assert(is_sso_used());
3641 };
3642 
3643 template <typename CharT, typename Traits>
3646 {
3647  assert(!is_sso_used());
3648  return non_sso._data;
3649 }
3650 
3651 template <typename CharT, typename Traits>
3652 typename basic_string<CharT, Traits>::sso_type &
3653 basic_string<CharT, Traits>::sso_data()
3654 {
3655  assert(is_sso_used());
3656  return sso._data;
3657 }
3658 
3659 template <typename CharT, typename Traits>
3660 const typename basic_string<CharT, Traits>::non_sso_type &
3661 basic_string<CharT, Traits>::non_sso_data() const
3662 {
3663  assert(!is_sso_used());
3664  return non_sso._data;
3665 }
3666 
3667 template <typename CharT, typename Traits>
3668 const typename basic_string<CharT, Traits>::sso_type &
3669 basic_string<CharT, Traits>::sso_data() const
3670 {
3671  assert(is_sso_used());
3672  return sso._data;
3673 }
3674 
3679 template <typename CharT, typename Traits>
3680 template <typename T, typename Enable>
3681 basic_string<CharT, Traits> &
3683 {
3684  return erase(static_cast<size_type>(param));
3685 }
3686 
3691 template <typename CharT, typename Traits>
3692 template <typename T, typename Enable>
3695 {
3696  return erase(static_cast<const_iterator>(param));
3697 }
3698 
3704 template <typename CharT, typename Traits>
3705 template <typename T, typename Enable>
3707 basic_string<CharT, Traits>::insert(T param, size_type count, CharT ch)
3708 {
3709  return insert(static_cast<size_type>(param), count, ch);
3710 }
3711 
3717 template <typename CharT, typename Traits>
3718 template <typename T, typename Enable>
3720 basic_string<CharT, Traits>::insert(T param, size_type count, CharT ch)
3721 {
3722  return insert(static_cast<const_iterator>(param), count, ch);
3723 }
3724 
3728 template <class CharT, class Traits>
3729 bool
3731  const basic_string<CharT, Traits> &rhs)
3732 {
3733  return lhs.compare(rhs) == 0;
3734 }
3735 
3739 template <class CharT, class Traits>
3740 bool
3742  const basic_string<CharT, Traits> &rhs)
3743 {
3744  return lhs.compare(rhs) != 0;
3745 }
3746 
3750 template <class CharT, class Traits>
3751 bool
3753  const basic_string<CharT, Traits> &rhs)
3754 {
3755  return lhs.compare(rhs) < 0;
3756 }
3757 
3761 template <class CharT, class Traits>
3762 bool
3764  const basic_string<CharT, Traits> &rhs)
3765 {
3766  return lhs.compare(rhs) <= 0;
3767 }
3768 
3772 template <class CharT, class Traits>
3773 bool
3775  const basic_string<CharT, Traits> &rhs)
3776 {
3777  return lhs.compare(rhs) > 0;
3778 }
3779 
3783 template <class CharT, class Traits>
3784 bool
3786  const basic_string<CharT, Traits> &rhs)
3787 {
3788  return lhs.compare(rhs) >= 0;
3789 }
3790 
3794 template <class CharT, class Traits>
3795 bool
3796 operator==(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
3797 {
3798  return rhs.compare(lhs) == 0;
3799 }
3800 
3804 template <class CharT, class Traits>
3805 bool
3806 operator!=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
3807 {
3808  return rhs.compare(lhs) != 0;
3809 }
3810 
3814 template <class CharT, class Traits>
3815 bool
3816 operator<(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
3817 {
3818  return rhs.compare(lhs) > 0;
3819 }
3820 
3824 template <class CharT, class Traits>
3825 bool
3826 operator<=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
3827 {
3828  return rhs.compare(lhs) >= 0;
3829 }
3830 
3834 template <class CharT, class Traits>
3835 bool
3836 operator>(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
3837 {
3838  return rhs.compare(lhs) < 0;
3839 }
3840 
3844 template <class CharT, class Traits>
3845 bool
3846 operator>=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
3847 {
3848  return rhs.compare(lhs) <= 0;
3849 }
3850 
3854 template <class CharT, class Traits>
3855 bool
3856 operator==(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
3857 {
3858  return lhs.compare(rhs) == 0;
3859 }
3860 
3864 template <class CharT, class Traits>
3865 bool
3866 operator!=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
3867 {
3868  return lhs.compare(rhs) != 0;
3869 }
3870 
3874 template <class CharT, class Traits>
3875 bool
3876 operator<(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
3877 {
3878  return lhs.compare(rhs) < 0;
3879 }
3880 
3884 template <class CharT, class Traits>
3885 bool
3886 operator<=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
3887 {
3888  return lhs.compare(rhs) <= 0;
3889 }
3890 
3894 template <class CharT, class Traits>
3895 bool
3896 operator>(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
3897 {
3898  return lhs.compare(rhs) > 0;
3899 }
3900 
3904 template <class CharT, class Traits>
3905 bool
3906 operator>=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
3907 {
3908  return lhs.compare(rhs) >= 0;
3909 }
3910 
3914 template <class CharT, class Traits>
3915 bool
3916 operator==(const std::basic_string<CharT, Traits> &lhs,
3917  const basic_string<CharT, Traits> &rhs)
3918 {
3919  return rhs.compare(lhs) == 0;
3920 }
3921 
3925 template <class CharT, class Traits>
3926 bool
3927 operator!=(const std::basic_string<CharT, Traits> &lhs,
3928  const basic_string<CharT, Traits> &rhs)
3929 {
3930  return rhs.compare(lhs) != 0;
3931 }
3932 
3936 template <class CharT, class Traits>
3937 bool
3938 operator<(const std::basic_string<CharT, Traits> &lhs,
3939  const basic_string<CharT, Traits> &rhs)
3940 {
3941  return rhs.compare(lhs) > 0;
3942 }
3943 
3947 template <class CharT, class Traits>
3948 bool
3949 operator<=(const std::basic_string<CharT, Traits> &lhs,
3950  const basic_string<CharT, Traits> &rhs)
3951 {
3952  return rhs.compare(lhs) >= 0;
3953 }
3954 
3958 template <class CharT, class Traits>
3959 bool
3960 operator>(const std::basic_string<CharT, Traits> &lhs,
3961  const basic_string<CharT, Traits> &rhs)
3962 {
3963  return rhs.compare(lhs) < 0;
3964 }
3965 
3969 template <class CharT, class Traits>
3970 bool
3971 operator>=(const std::basic_string<CharT, Traits> &lhs,
3972  const basic_string<CharT, Traits> &rhs)
3973 {
3974  return rhs.compare(lhs) <= 0;
3975 }
3976 
3980 template <class CharT, class Traits>
3981 bool
3983  const std::basic_string<CharT, Traits> &rhs)
3984 {
3985  return lhs.compare(rhs) == 0;
3986 }
3987 
3991 template <class CharT, class Traits>
3992 bool
3994  const std::basic_string<CharT, Traits> &rhs)
3995 {
3996  return lhs.compare(rhs) != 0;
3997 }
3998 
4002 template <class CharT, class Traits>
4003 bool
4005  const std::basic_string<CharT, Traits> &rhs)
4006 {
4007  return lhs.compare(rhs) < 0;
4008 }
4009 
4013 template <class CharT, class Traits>
4014 bool
4016  const std::basic_string<CharT, Traits> &rhs)
4017 {
4018  return lhs.compare(rhs) <= 0;
4019 }
4020 
4024 template <class CharT, class Traits>
4025 bool
4027  const std::basic_string<CharT, Traits> &rhs)
4028 {
4029  return lhs.compare(rhs) > 0;
4030 }
4031 
4035 template <class CharT, class Traits>
4036 bool
4038  const std::basic_string<CharT, Traits> &rhs)
4039 {
4040  return lhs.compare(rhs) >= 0;
4041 }
4042 
4043 } /* namespace obj */
4044 
4045 } /* namespace pmem */
4046 
4047 #endif /* LIBPMEMOBJ_CPP_BASIC_STRING_HPP */
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
void check_tx_stage_work() const
Definition: basic_string.hpp:3486
int compare(const basic_string &other) const
Compares this string to other.
Definition: basic_string.hpp:2810
void resize(size_type count, CharT ch)
Resize the string to count characters transactionally.
Definition: basic_string.hpp:3059
iterator end()
Return an iterator to past the end.
Definition: basic_string.hpp:1050
pointer initialize(Args &&... args)
Generic function which initializes memory based on provided parameters - forwards parameters to initi...
Definition: basic_string.hpp:3302
const CharT * cdata() const noexcept
Definition: basic_string.hpp:2982
void allocate(size_type capacity)
Allocate storage for container of capacity bytes.
Definition: basic_string.hpp:3329
size_type max_size() const noexcept
Definition: basic_string.hpp:3022
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:3231
pmem::obj::array< T, N >::const_reverse_iterator crend(const pmem::obj::array< T, N > &a)
Non-member crend.
Definition: array.hpp:823
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:1174
Common iterator traits.
The non-template pool base class.
Definition: pool.hpp:67
size_type capacity() const noexcept
Definition: basic_string.hpp:3033
void disable_sso()
Disable sso string.
Definition: basic_string.hpp:3557
void clear()
Remove all characters from the string transactionally.
Definition: basic_string.hpp:3185
void large_to_sso()
Resize large string to sso string of size() size.
Definition: basic_string.hpp:3619
basic_string & assign(size_type count, CharT ch)
Replace the contents with count copies of character ch transactionally.
Definition: basic_string.hpp:784
Custom pool error class.
Definition: pexceptions.hpp:72
void shrink_to_fit()
Remove unused capacity transactionally.
Definition: basic_string.hpp:3160
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:2300
const CharT * c_str() const noexcept
Definition: basic_string.hpp:3002
bool operator<(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less than operator.
Definition: array.hpp:752
pointer assign_sso_data(InputIt first, InputIt last)
Initialize sso data.
Definition: basic_string.hpp:3357
T * data()
Returns raw pointer to the underlying data and adds entire array to a transaction.
Definition: array.hpp:273
C++ pmemobj transactions.
Convenience extensions for the resides on pmem property template.
Functions for destroying arrays.
reverse_iterator rend()
Return a reverse iterator to the end.
Definition: basic_string.hpp:1128
basic_string & append(size_type count, CharT ch)
Append count copies of character ch to the string transactionally.
Definition: basic_string.hpp:1519
Commonly used functionality.
bool operator<=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less or equal operator.
Definition: array.hpp:783
void reserve(size_type new_cap=0)
Increase the capacity of the string to new_cap transactionally.
Definition: basic_string.hpp:3128
void enable_sso()
Enable sso string.
Definition: basic_string.hpp:3545
Iterators for contiguous persistent containers.
pmem::obj::array< T, N >::const_reverse_iterator crbegin(const pmem::obj::array< T, N > &a)
Non-member crbegin.
Definition: array.hpp:813
const_reverse_iterator crbegin() const noexcept
Return a const reverse iterator to the beginning.
Definition: basic_string.hpp:1115
void check_pmem_tx() const
Definition: basic_string.hpp:3499
basic_string & erase(size_type index=0, size_type count=npos)
Remove characters from string starting at index transactionally.
Definition: basic_string.hpp:1391
reverse_iterator rbegin()
Return a reverse iterator to the beginning.
Definition: basic_string.hpp:1089
Array container with std::array compatible interface.
reference operator[](size_type n)
Access element at specific index and snapshot it if there is an active transaction.
Definition: basic_string.hpp:1237
void sso_to_large(size_t new_capacity)
Resize sso string to large string.
Definition: basic_string.hpp:3585
void check_pmem() const
Definition: basic_string.hpp:3475
pmem::obj::array< T, N >::iterator end(pmem::obj::array< T, N > &a)
Non-member end.
Definition: array.hpp:853
size_type length() const noexcept
Definition: basic_string.hpp:3012
Default non-const iterator which adds element to a transaction on every access.
Definition: contiguous_iterator.hpp:359
Type trait to determine if a given parameter type satisfies requirements of InputIterator.
Definition: iterator_traits.hpp:75
pmem::obj::array< T, N >::iterator begin(pmem::obj::array< T, N > &a)
Non-member begin.
Definition: array.hpp:833
const_iterator cbegin() const noexcept
Return const iterator to the beginning.
Definition: basic_string.hpp:1037
void add_sso_to_tx(size_type first, size_type num) const
Snapshot sso data.
Definition: basic_string.hpp:3510
pointer replace_content(Args &&... args)
Generic function which replace_content current content based on provided parameters.
Definition: basic_string.hpp:3272
void pop_back()
Remove the last character from the string transactionally.
Definition: basic_string.hpp:1493
basic_string()
Default constructor.
Definition: basic_string.hpp:381
basic_string & operator=(const basic_string &other)
Copy assignment operator.
Definition: basic_string.hpp:688
bool empty() const noexcept
Definition: basic_string.hpp:3195
const CharT & cback() const
Access last element.
Definition: basic_string.hpp:1337
CharT & front()
Access first element and snapshot it if there is an active transaction.
Definition: basic_string.hpp:1267
bool operator>(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater than operator.
Definition: array.hpp:763
basic_string & insert(size_type index, size_type count, CharT ch)
Insert count copies of ch character at index transactionally.
Definition: basic_string.hpp:1921
iterator begin()
Return an iterator to the beginning.
Definition: basic_string.hpp:1012
Vector container with std::vector compatible interface.
Persistent smart pointer.
void set_sso_size(size_type new_size)
Set size for sso.
Definition: basic_string.hpp:3567
Iterface to access sequence of objects.
void push_back(CharT ch)
Append character ch at the end of the string transactionally.
Definition: basic_string.hpp:1792
pmem::obj::array< T, N >::const_iterator cbegin(const pmem::obj::array< T, N > &a)
Non-member cbegin.
Definition: array.hpp:793
~basic_string()
Destructor.
Definition: basic_string.hpp:671
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
size_type get_sso_size() const
Return size of sso string.
Definition: basic_string.hpp:3535
Custom transaction error class.
Definition: pexceptions.hpp:185
A persistent version of concurrent hash map implementation Ref: https://arxiv.org/abs/1509....
Definition: allocation_flag.hpp:43
size_type size() const noexcept
Definition: basic_string.hpp:1347
pmem::obj::string - persistent container with std::basic_string compatible interface.
Definition: basic_string.hpp:69
CharT & back()
Access last element and snapshot it if there is an active transaction.
Definition: basic_string.hpp:1310
const CharT & cfront() const
Access first element.
Definition: basic_string.hpp:1294
pool_base get_pool() const
Return pool_base instance and assert that object is on pmem.
Definition: basic_string.hpp:3462
const_iterator cend() const noexcept
Return const iterator to past the end.
Definition: basic_string.hpp:1076
CharT * data()
Definition: basic_string.hpp:1365
basic_string & operator+=(const basic_string &str)
Append string str transactionally.
Definition: basic_string.hpp:1817
pointer assign_large_data(InputIt first, InputIt last)
Initialize non_sso.data - call constructor of non_sso.data.
Definition: basic_string.hpp:3409
pmem::obj::array< T, N >::const_iterator cend(const pmem::obj::array< T, N > &a)
Non-member cend.
Definition: array.hpp:803
const_reference const_at(size_type n) const
Access element at specific index with bounds checking.
Definition: basic_string.hpp:1214
bool operator>=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater or equal operator.
Definition: array.hpp:773
static void run(pool_base &pool, std::function< void()> tx, Locks &... locks)
Execute a closure-like transaction and lock locks.
Definition: transaction.hpp:403
const_reverse_iterator crend() const noexcept
Return a const reverse iterator to the end.
Definition: basic_string.hpp:1154
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:2743