PMDK C++ bindings  1.2.0
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 
53 #include <libpmemobj++/pext.hpp>
55 
56 namespace pmem
57 {
58 
59 namespace obj
60 {
61 
62 namespace experimental
63 {
64 
71 template <typename CharT, typename Traits = std::char_traits<CharT>>
72 class basic_string {
73 public:
74  /* Member types */
75  using traits_type = Traits;
76  using value_type = CharT;
77  using size_type = std::size_t;
78  using difference_type = std::ptrdiff_t;
79  using reference = value_type &;
80  using const_reference = const value_type &;
81  using pointer = value_type *;
82  using const_pointer = const value_type *;
84  using const_iterator = const_pointer;
85  using reverse_iterator = std::reverse_iterator<iterator>;
86  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
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 
155  /* Iterators */
156  iterator begin();
157  const_iterator begin() const noexcept;
158  const_iterator cbegin() const noexcept;
159  iterator end();
160  const_iterator end() const noexcept;
161  const_iterator cend() const noexcept;
162  reverse_iterator rbegin();
163  const_reverse_iterator rbegin() const noexcept;
164  const_reverse_iterator crbegin() const noexcept;
165  reverse_iterator rend();
166  const_reverse_iterator rend() const noexcept;
167  const_reverse_iterator crend() const noexcept;
168 
169  /* Capacity */
170  bool empty() const noexcept;
171  size_type size() const noexcept;
172  size_type length() const noexcept;
173  size_type max_size() const noexcept;
174  size_type capacity() const noexcept;
175  void resize(size_type count, CharT ch);
176  void resize(size_type n);
177  void reserve(size_type new_cap = 0);
178  void shrink_to_fit();
179  void clear();
180 
181  /* Modifiers */
182  basic_string &erase(size_type index = 0, size_type count = npos);
183  iterator erase(const_iterator pos);
184  iterator erase(const_iterator first, const_iterator last);
185  /* We add following overloads to resolve erase(0) ambiguity */
186  template <typename T,
187  typename Enable = typename std::enable_if<
188  std::is_convertible<T, size_type>::value>::type>
189  basic_string &erase(T param);
190  template <typename T,
191  typename Enable = typename std::enable_if<
192  !std::is_convertible<T, size_type>::value>::type>
193  iterator erase(T param);
194 
195  basic_string &append(size_type count, CharT ch);
196  basic_string &append(const basic_string &str);
197  basic_string &append(const basic_string &str, size_type pos,
198  size_type count = npos);
199  basic_string &append(const CharT *s, size_type count);
200  basic_string &append(const CharT *s);
201  template <typename InputIt,
202  typename Enable = typename pmem::detail::is_input_iterator<
203  InputIt>::type>
204  basic_string &append(InputIt first, InputIt last);
205  basic_string &append(std::initializer_list<CharT> ilist);
206 
207  int compare(const basic_string &other) const;
208  int compare(const std::basic_string<CharT> &other) const;
209  int compare(size_type pos, size_type count,
210  const basic_string &other) const;
211  int compare(size_type pos, size_type count,
212  const std::basic_string<CharT> &other) const;
213  int compare(size_type pos1, size_type count1, const basic_string &other,
214  size_type pos2, size_type count2 = npos) const;
215  int compare(size_type pos1, size_type count1,
216  const std::basic_string<CharT> &other, size_type pos2,
217  size_type count2 = npos) const;
218  int compare(const CharT *s) const;
219  int compare(size_type pos, size_type count, const CharT *s) const;
220  int compare(size_type pos, size_type count1, const CharT *s,
221  size_type count2) const;
222 
223  /* Special value. The exact meaning depends on the context. */
224  static const size_type npos = static_cast<size_type>(-1);
225 
226 private:
229 
247  union {
248  struct {
249  /*
250  * EXACTLY the same type as first member in vector
251  * Holds size for sso string, bit specified by _sso_mask
252  * indicates if sso is used.
253  */
254  p<size_type> _size;
255 
257  } sso;
258 
259  struct {
260  non_sso_type data;
261  } non_sso;
262  };
263 
264  /*
265  * MSB is used because vector is known not to use entire range of
266  * size_type.
267  */
268  static constexpr size_type _sso_mask = 1ULL
269  << (std::numeric_limits<size_type>::digits - 1);
270 
271  /* helper functions */
272  bool is_sso_used() const;
273  void destroy_data();
274  template <
275  typename InputIt,
276  typename Enable = typename std::enable_if<
278  size_type get_size(InputIt first, InputIt last) const;
279  size_type get_size(size_type count, value_type ch) const;
280  size_type get_size(const basic_string &other) const;
281  template <typename... Args>
282  pointer replace(Args &&... args);
283  template <typename... Args>
284  pointer initialize(Args &&... args);
285  void allocate(size_type capacity);
286  template <
287  typename InputIt,
288  typename Enable = typename std::enable_if<
290  pointer assign_sso_data(InputIt first, InputIt last);
291  pointer assign_sso_data(size_type count, value_type ch);
292  pointer assign_sso_data(basic_string &&other);
293  template <
294  typename InputIt,
295  typename Enable = typename std::enable_if<
297  pointer assign_large_data(InputIt first, InputIt last);
298  pointer assign_large_data(size_type count, value_type ch);
299  pointer assign_large_data(basic_string &&other);
300  pool_base get_pool() const;
301  void check_pmem() const;
302  void check_tx_stage_work() const;
303  void check_pmem_tx() const;
304  void snapshot_sso() const;
305  size_type get_sso_size() const;
306  void enable_sso();
307  void disable_sso();
308  void set_sso_size(size_type new_size);
309  void sso_to_large(size_t new_capacity);
310  void large_to_sso();
311 };
312 
322 template <typename CharT, typename Traits>
324 {
325  check_pmem_tx();
326 
327  allocate(0);
328  initialize(0U, value_type('\0'));
329 }
330 
345 template <typename CharT, typename Traits>
347 {
348  check_pmem_tx();
349 
350  allocate(count);
351  initialize(count, ch);
352 }
353 
371 template <typename CharT, typename Traits>
373  size_type pos, size_type count)
374 {
375  check_pmem_tx();
376 
377  if (pos > other.size())
378  throw std::out_of_range("Index out of range.");
379 
380  if (count == npos || pos + count > other.size())
381  count = other.size() - pos;
382 
383  auto first = static_cast<difference_type>(pos);
384  auto last = first + static_cast<difference_type>(count);
385 
386  allocate(count);
387  initialize(other.cbegin() + first, other.cbegin() + last);
388 }
389 
408 template <typename CharT, typename Traits>
409 basic_string<CharT, Traits>::basic_string(const std::basic_string<CharT> &other,
410  size_type pos, size_type count)
411 {
412  check_pmem_tx();
413 
414  if (pos > other.size())
415  throw std::out_of_range("Index out of range.");
416 
417  if (count == npos || pos + count > other.size())
418  count = other.size() - pos;
419 
420  auto first = static_cast<difference_type>(pos);
421  auto last = first + static_cast<difference_type>(count);
422 
423  allocate(count);
424  initialize(other.cbegin() + first, other.cbegin() + last);
425 }
426 
442 template <typename CharT, typename Traits>
443 basic_string<CharT, Traits>::basic_string(const CharT *s, size_type count)
444 {
445  check_pmem_tx();
446 
447  allocate(count);
448  initialize(s, s + count);
449 }
450 
464 template <typename CharT, typename Traits>
466 {
467  check_pmem_tx();
468 
469  auto length = traits_type::length(s);
470 
471  allocate(length);
472  initialize(s, s + length);
473 }
474 
491 template <typename CharT, typename Traits>
492 template <typename InputIt, typename Enable>
493 basic_string<CharT, Traits>::basic_string(InputIt first, InputIt last)
494 {
495  auto len = std::distance(first, last);
496  assert(len >= 0);
497 
498  check_pmem_tx();
499 
500  allocate(static_cast<size_type>(len));
501  initialize(first, last);
502 }
503 
518 template <typename CharT, typename Traits>
520 {
521  check_pmem_tx();
522 
523  allocate(other.size());
524  initialize(other.cbegin(), other.cend());
525 }
526 
542 template <typename CharT, typename Traits>
543 basic_string<CharT, Traits>::basic_string(const std::basic_string<CharT> &other)
544  : basic_string(other.cbegin(), other.cend())
545 {
546 }
547 
562 template <typename CharT, typename Traits>
564 {
565  check_pmem_tx();
566 
567  allocate(other.size());
568  initialize(std::move(other));
569 
570  if (other.is_sso_used())
571  other.initialize(0U, value_type('\0'));
572 }
573 
588 template <typename CharT, typename Traits>
589 basic_string<CharT, Traits>::basic_string(std::initializer_list<CharT> ilist)
590 {
591  check_pmem_tx();
592 
593  allocate(ilist.size());
594  initialize(ilist.begin(), ilist.end());
595 }
596 
602 template <typename CharT, typename Traits>
604 {
605  if (!is_sso_used())
606  detail::destroy<non_sso_type>(non_sso.data);
607 }
608 
618 template <typename CharT, typename Traits>
621 {
622  return assign(other);
623 }
624 
635 template <typename CharT, typename Traits>
637 basic_string<CharT, Traits>::operator=(const std::basic_string<CharT> &other)
638 {
639  return assign(other);
640 }
641 
651 template <typename CharT, typename Traits>
654 {
655  return assign(std::move(other));
656 }
657 
666 template <typename CharT, typename Traits>
669 {
670  return assign(s);
671 }
672 
681 template <typename CharT, typename Traits>
684 {
685  return assign(1, ch);
686 }
687 
697 template <typename CharT, typename Traits>
699 basic_string<CharT, Traits>::operator=(std::initializer_list<CharT> ilist)
700 {
701  return assign(ilist);
702 }
703 
714 template <typename CharT, typename Traits>
716 basic_string<CharT, Traits>::assign(size_type count, CharT ch)
717 {
718  auto pop = get_pool();
719 
720  transaction::run(pop, [&] { replace(count, ch); });
721 
722  return *this;
723 }
724 
734 template <typename CharT, typename Traits>
737 {
738  if (&other == this)
739  return *this;
740 
741  auto pop = get_pool();
742 
743  transaction::run(pop, [&] { replace(other.cbegin(), other.cend()); });
744 
745  return *this;
746 }
747 
758 template <typename CharT, typename Traits>
760 basic_string<CharT, Traits>::assign(const std::basic_string<CharT> &other)
761 {
762  return assign(other.cbegin(), other.cend());
763 }
764 
777 template <typename CharT, typename Traits>
780  size_type count)
781 {
782  if (pos > other.size())
783  throw std::out_of_range("Index out of range.");
784 
785  if (count == npos || pos + count > other.size())
786  count = other.size() - pos;
787 
788  auto pop = get_pool();
789  auto first = static_cast<difference_type>(pos);
790  auto last = first + static_cast<difference_type>(count);
791 
792  transaction::run(pop, [&] {
793  replace(other.cbegin() + first, other.cbegin() + last);
794  });
795 
796  return *this;
797 }
798 
813 template <typename CharT, typename Traits>
815 basic_string<CharT, Traits>::assign(const std::basic_string<CharT> &other,
816  size_type pos, size_type count)
817 {
818  if (pos > other.size())
819  throw std::out_of_range("Index out of range.");
820 
821  if (count == npos || pos + count > other.size())
822  count = other.size() - pos;
823 
824  return assign(other.c_str() + pos, count);
825 }
826 
837 template <typename CharT, typename Traits>
839 basic_string<CharT, Traits>::assign(const CharT *s, size_type count)
840 {
841  auto pop = get_pool();
842 
843  transaction::run(pop, [&] { replace(s, s + count); });
844 
845  return *this;
846 }
847 
856 template <typename CharT, typename Traits>
859 {
860  auto pop = get_pool();
861 
862  auto length = traits_type::length(s);
863 
864  transaction::run(pop, [&] { replace(s, s + length); });
865 
866  return *this;
867 }
868 
880 template <typename CharT, typename Traits>
881 template <typename InputIt, typename Enable>
883 basic_string<CharT, Traits>::assign(InputIt first, InputIt last)
884 {
885  auto pop = get_pool();
886 
887  transaction::run(pop, [&] { replace(first, last); });
888 
889  return *this;
890 }
891 
901 template <typename CharT, typename Traits>
904 {
905  if (&other == this)
906  return *this;
907 
908  auto pop = get_pool();
909 
910  transaction::run(pop, [&] {
911  replace(std::move(other));
912 
913  if (other.is_sso_used())
914  other.initialize(0U, value_type('\0'));
915  });
916 
917  return *this;
918 }
919 
929 template <typename CharT, typename Traits>
931 basic_string<CharT, Traits>::assign(std::initializer_list<CharT> ilist)
932 {
933  return assign(ilist.begin(), ilist.end());
934 }
935 
941 template <typename CharT, typename Traits>
944 {
945  return is_sso_used() ? iterator(&*sso.data.begin())
946  : iterator(&*non_sso.data.begin());
947 }
948 
954 template <typename CharT, typename Traits>
955 typename basic_string<CharT, Traits>::const_iterator
957 {
958  return cbegin();
959 }
960 
966 template <typename CharT, typename Traits>
967 typename basic_string<CharT, Traits>::const_iterator
969 {
970  return is_sso_used() ? const_iterator(&*sso.data.cbegin())
971  : const_iterator(&*non_sso.data.cbegin());
972 }
973 
979 template <typename CharT, typename Traits>
982 {
983  return begin() + static_cast<difference_type>(size());
984 }
985 
992 template <typename CharT, typename Traits>
993 typename basic_string<CharT, Traits>::const_iterator
995 {
996  return cbegin() + static_cast<difference_type>(size());
997 }
998 
1005 template <typename CharT, typename Traits>
1006 typename basic_string<CharT, Traits>::const_iterator
1008 {
1009  return cbegin() + static_cast<difference_type>(size());
1010 }
1011 
1018 template <typename CharT, typename Traits>
1019 typename basic_string<CharT, Traits>::reverse_iterator
1021 {
1022  return reverse_iterator(end());
1023 }
1024 
1031 template <typename CharT, typename Traits>
1032 typename basic_string<CharT, Traits>::const_reverse_iterator
1034 {
1035  return crbegin();
1036 }
1037 
1044 template <typename CharT, typename Traits>
1045 typename basic_string<CharT, Traits>::const_reverse_iterator
1047 {
1048  return const_reverse_iterator(cend());
1049 }
1050 
1057 template <typename CharT, typename Traits>
1058 typename basic_string<CharT, Traits>::reverse_iterator
1060 {
1061  return reverse_iterator(begin());
1062 }
1063 
1070 template <typename CharT, typename Traits>
1071 typename basic_string<CharT, Traits>::const_reverse_iterator
1073 {
1074  return crend();
1075 }
1076 
1083 template <typename CharT, typename Traits>
1084 typename basic_string<CharT, Traits>::const_reverse_iterator
1086 {
1087  return const_reverse_iterator(cbegin());
1088 }
1089 
1103 template <typename CharT, typename Traits>
1104 typename basic_string<CharT, Traits>::reference
1106 {
1107  if (n >= size())
1108  throw std::out_of_range("string::at");
1109 
1110  return is_sso_used() ? sso.data[n] : non_sso.data[n];
1111 }
1112 
1123 template <typename CharT, typename Traits>
1124 typename basic_string<CharT, Traits>::const_reference
1126 {
1127  return const_at(n);
1128 }
1129 
1143 template <typename CharT, typename Traits>
1144 typename basic_string<CharT, Traits>::const_reference
1146 {
1147  if (n >= size())
1148  throw std::out_of_range("string::const_at");
1149 
1150  return is_sso_used()
1151  ? static_cast<const sso_type &>(sso.data)[n]
1152  : static_cast<const non_sso_type &>(non_sso.data)[n];
1153 }
1154 
1166 template <typename CharT, typename Traits>
1167 typename basic_string<CharT, Traits>::reference basic_string<CharT, Traits>::
1168 operator[](size_type n)
1169 {
1170  return is_sso_used() ? sso.data[n] : non_sso.data[n];
1171 }
1172 
1180 template <typename CharT, typename Traits>
1181 typename basic_string<CharT, Traits>::const_reference
1183 {
1184  return is_sso_used() ? sso.data[n] : non_sso.data[n];
1185 }
1186 
1196 template <typename CharT, typename Traits>
1197 CharT &
1199 {
1200  return (*this)[0];
1201 }
1202 
1208 template <typename CharT, typename Traits>
1209 const CharT &
1211 {
1212  return cfront();
1213 }
1214 
1223 template <typename CharT, typename Traits>
1224 const CharT &
1226 {
1227  return static_cast<const basic_string &>(*this)[0];
1228 }
1229 
1239 template <typename CharT, typename Traits>
1240 CharT &
1242 {
1243  return (*this)[size() - 1];
1244 }
1245 
1251 template <typename CharT, typename Traits>
1252 const CharT &
1254 {
1255  return cback();
1256 }
1257 
1266 template <typename CharT, typename Traits>
1267 const CharT &
1269 {
1270  return static_cast<const basic_string &>(*this)[size() - 1];
1271 }
1272 
1276 template <typename CharT, typename Traits>
1277 typename basic_string<CharT, Traits>::size_type
1279 {
1280  if (is_sso_used())
1281  return get_sso_size();
1282  else if (non_sso.data.size() == 0)
1283  return 0;
1284  else
1285  return non_sso.data.size() - 1;
1286 }
1287 
1294 template <typename CharT, typename Traits>
1295 CharT *
1297 {
1298  return is_sso_used() ? sso.data.range(0, get_sso_size() + 1).begin()
1299  : non_sso.data.data();
1300 }
1301 
1320 template <typename CharT, typename Traits>
1321 basic_string<CharT, Traits> &
1322 basic_string<CharT, Traits>::erase(size_type index, size_type count)
1323 {
1324  auto sz = size();
1325 
1326  if (index > sz)
1327  throw std::out_of_range("Index exceeds size.");
1328 
1329  count = (std::min)(count, sz - index);
1330 
1331  auto pop = get_pool();
1332 
1333  auto first = begin() + static_cast<difference_type>(index);
1334  auto last = first + static_cast<difference_type>(count);
1335 
1336  if (is_sso_used()) {
1337  transaction::run(pop, [&] {
1338  auto move_len = sz - index - count;
1339 
1340  auto dest = sso.data.range(index, move_len + 1).begin();
1341 
1342  traits_type::move(dest, &*last, move_len);
1343 
1344  auto new_size = sz - count;
1345  set_sso_size(new_size);
1346  sso.data[new_size] = value_type('\0');
1347  });
1348  } else {
1349  non_sso.data.erase(first, last);
1350  }
1351 
1352  return *this;
1353 };
1354 
1371 template <typename CharT, typename Traits>
1374 {
1375  return erase(pos, pos + 1);
1376 };
1377 
1396 template <typename CharT, typename Traits>
1398 basic_string<CharT, Traits>::erase(const_iterator first, const_iterator last)
1399 {
1400  size_type index =
1401  static_cast<size_type>(std::distance(cbegin(), first));
1402  size_type len = static_cast<size_type>(std::distance(first, last));
1403 
1404  erase(index, len);
1405 
1406  return begin() + static_cast<difference_type>(index);
1407 };
1408 
1428 template <typename CharT, typename Traits>
1430 basic_string<CharT, Traits>::append(size_type count, CharT ch)
1431 {
1432  auto sz = size();
1433  auto new_size = sz + count;
1434 
1435  if (new_size > max_size())
1436  throw std::length_error("Size exceeds max size.");
1437 
1438  if (is_sso_used()) {
1439  auto pop = get_pool();
1440 
1441  transaction::run(pop, [&] {
1442  if (new_size > sso_capacity) {
1443  sso_to_large(new_size);
1444 
1445  non_sso.data.insert(
1446  non_sso.data.cbegin() +
1447  static_cast<difference_type>(
1448  sz),
1449  count, ch);
1450  } else {
1451  /*
1452  * XXX: There is no necessity to snapshot
1453  * uninitialized data. However, we need
1454  * libpmemobj support for that, because right
1455  * now pmemcheck will report an error
1456  * (uninitialized part of data not added to tx).
1457  *
1458  * XXX: future optimization: we don't have to
1459  * snapshot data which we will not overwrite. We
1460  * should snapshot terminating null character
1461  * only.
1462  */
1463  snapshot_sso();
1464  auto dest =
1465  sso.data.range(sz, count + 1).begin();
1466  traits_type::assign(dest, count, ch);
1467 
1468  set_sso_size(new_size);
1469  sso.data[new_size] = value_type('\0');
1470  }
1471  });
1472  } else {
1473  non_sso.data.insert(non_sso.data.cbegin() +
1474  static_cast<difference_type>(sz),
1475  count, ch);
1476  }
1477 
1478  return *this;
1479 }
1480 
1499 template <typename CharT, typename Traits>
1502 {
1503  return append(str.data(), str.size());
1504 }
1505 
1531 template <typename CharT, typename Traits>
1534  size_type count)
1535 {
1536  auto sz = str.size();
1537 
1538  if (pos > sz)
1539  throw std::out_of_range("Index out of range.");
1540 
1541  count = (std::min)(count, sz - pos);
1542 
1543  append(str.data() + pos, count);
1544 
1545  return *this;
1546 }
1547 
1567 template <typename CharT, typename Traits>
1569 basic_string<CharT, Traits>::append(const CharT *s, size_type count)
1570 {
1571  return append(s, s + count);
1572 }
1573 
1593 template <typename CharT, typename Traits>
1596 {
1597  return append(s, traits_type::length(s));
1598 }
1599 
1621 template <typename CharT, typename Traits>
1622 template <typename InputIt, typename Enable>
1624 basic_string<CharT, Traits>::append(InputIt first, InputIt last)
1625 {
1626  auto sz = size();
1627  auto count = static_cast<size_type>(std::distance(first, last));
1628  auto new_size = sz + count;
1629 
1630  if (new_size > max_size())
1631  throw std::length_error("Size exceeds max size.");
1632 
1633  if (is_sso_used()) {
1634  auto pop = get_pool();
1635 
1636  transaction::run(pop, [&] {
1637  if (new_size > sso_capacity) {
1638  /* 1) Cache C-style string in case of
1639  * self-append, because it will be destroyed
1640  * when switching from sso to large string.
1641  *
1642  * 2) We cache in std::vector instead of
1643  * std::string because of overload deduction
1644  * ambiguity on Windows
1645  */
1646  std::vector<value_type> str(first, last);
1647 
1648  sso_to_large(new_size);
1649  non_sso.data.insert(
1650  non_sso.data.cbegin() +
1651  static_cast<difference_type>(
1652  sz),
1653  str.begin(), str.end());
1654  } else {
1655  /*
1656  * XXX: future optimization: we don't have to
1657  * snapshot data which we will not overwrite. We
1658  * should snapshot terminating null character
1659  * only.
1660  */
1661  snapshot_sso();
1662  auto dest =
1663  sso.data.range(sz, count + 1).begin();
1664  std::copy(first, last, dest);
1665 
1666  set_sso_size(new_size);
1667  sso.data[new_size] = value_type('\0');
1668  }
1669  });
1670  } else {
1671  non_sso.data.insert(non_sso.data.cbegin() +
1672  static_cast<difference_type>(sz),
1673  first, last);
1674  }
1675 
1676  return *this;
1677 }
1678 
1697 template <typename CharT, typename Traits>
1699 basic_string<CharT, Traits>::append(std::initializer_list<CharT> ilist)
1700 {
1701  return append(ilist.begin(), ilist.end());
1702 }
1703 
1721 template <typename CharT, typename Traits>
1722 int
1723 basic_string<CharT, Traits>::compare(size_type pos, size_type count1,
1724  const CharT *s, size_type count2) const
1725 {
1726  if (pos > size())
1727  throw std::out_of_range("Index out of range.");
1728 
1729  if (count1 > size() - pos)
1730  count1 = size() - pos;
1731 
1732  auto ret = traits_type::compare(cdata() + pos, s,
1733  std::min<size_type>(count1, count2));
1734 
1735  if (ret != 0)
1736  return ret;
1737 
1738  if (count1 < count2)
1739  return -1;
1740  else if (count1 == count2)
1741  return 0;
1742  else
1743  return 1;
1744 }
1745 
1754 template <typename CharT, typename Traits>
1755 int
1757 {
1758  return compare(0, size(), other.cdata(), other.size());
1759 }
1760 
1769 template <typename CharT, typename Traits>
1770 int
1772  const std::basic_string<CharT> &other) const
1773 {
1774  return compare(0, size(), other.data(), other.size());
1775 }
1776 
1790 template <typename CharT, typename Traits>
1791 int
1792 basic_string<CharT, Traits>::compare(size_type pos, size_type count,
1793  const basic_string &other) const
1794 {
1795  return compare(pos, count, other.cdata(), other.size());
1796 }
1797 
1812 template <typename CharT, typename Traits>
1813 int
1815  size_type pos, size_type count,
1816  const std::basic_string<CharT> &other) const
1817 {
1818  return compare(pos, count, other.data(), other.size());
1819 }
1820 
1839 template <typename CharT, typename Traits>
1840 int
1841 basic_string<CharT, Traits>::compare(size_type pos1, size_type count1,
1842  const basic_string &other, size_type pos2,
1843  size_type count2) const
1844 {
1845  if (pos2 > other.size())
1846  throw std::out_of_range("Index out of range.");
1847 
1848  if (count2 > other.size() - pos2)
1849  count2 = other.size() - pos2;
1850 
1851  return compare(pos1, count1, other.cdata() + pos2, count2);
1852 }
1853 
1872 template <typename CharT, typename Traits>
1873 int
1874 basic_string<CharT, Traits>::compare(size_type pos1, size_type count1,
1875  const std::basic_string<CharT> &other,
1876  size_type pos2, size_type count2) const
1877 {
1878  if (pos2 > other.size())
1879  throw std::out_of_range("Index out of range.");
1880 
1881  if (count2 > other.size() - pos2)
1882  count2 = other.size() - pos2;
1883 
1884  return compare(pos1, count1, other.data() + pos2, count2);
1885 }
1886 
1895 template <typename CharT, typename Traits>
1896 int
1898 {
1899  return compare(0, size(), s, traits_type::length(s));
1900 }
1901 
1915 template <typename CharT, typename Traits>
1916 int
1917 basic_string<CharT, Traits>::compare(size_type pos, size_type count,
1918  const CharT *s) const
1919 {
1920  return compare(pos, count, s, traits_type::length(s));
1921 }
1922 
1926 template <typename CharT, typename Traits>
1927 const CharT *
1929 {
1930  return is_sso_used() ? sso.data.cdata() : non_sso.data.cdata();
1931 }
1932 
1936 template <typename CharT, typename Traits>
1937 const CharT *
1938 basic_string<CharT, Traits>::data() const noexcept
1939 {
1940  return cdata();
1941 }
1942 
1946 template <typename CharT, typename Traits>
1947 const CharT *
1949 {
1950  return cdata();
1951 }
1952 
1956 template <typename CharT, typename Traits>
1957 typename basic_string<CharT, Traits>::size_type
1959 {
1960  return size();
1961 }
1962 
1966 template <typename CharT, typename Traits>
1967 typename basic_string<CharT, Traits>::size_type
1969 {
1970  return PMEMOBJ_MAX_ALLOC_SIZE / sizeof(CharT) - 1;
1971 }
1972 
1977 template <typename CharT, typename Traits>
1978 typename basic_string<CharT, Traits>::size_type
1980 {
1981  return is_sso_used() ? sso_capacity : non_sso.data.capacity() - 1;
1982 }
1983 
2002 template <typename CharT, typename Traits>
2003 void
2004 basic_string<CharT, Traits>::resize(size_type count, CharT ch)
2005 {
2006  if (count > max_size())
2007  throw std::length_error("Count exceeds max size.");
2008 
2009  auto sz = size();
2010 
2011  auto pop = get_pool();
2012 
2013  transaction::run(pop, [&] {
2014  if (count > sz) {
2015  append(count - sz, ch);
2016  } else if (is_sso_used()) {
2017  set_sso_size(count);
2018  sso.data[count] = value_type('\0');
2019  } else {
2020  non_sso.data.resize(count + 1, ch);
2021  non_sso.data.back() = value_type('\0');
2022  }
2023  });
2024 }
2025 
2043 template <typename CharT, typename Traits>
2044 void
2046 {
2047  resize(count, CharT());
2048 }
2049 
2068 template <typename CharT, typename Traits>
2069 void
2071 {
2072  if (new_cap > max_size())
2073  throw std::length_error("New capacity exceeds max size.");
2074 
2075  if (new_cap < capacity() || new_cap <= sso_capacity)
2076  return;
2077 
2078  if (is_sso_used()) {
2079  auto pop = get_pool();
2080 
2081  transaction::run(pop, [&] { sso_to_large(new_cap); });
2082  } else {
2083  non_sso.data.reserve(new_cap + 1);
2084  }
2085 }
2086 
2099 template <typename CharT, typename Traits>
2100 void
2102 {
2103  if (is_sso_used())
2104  return;
2105 
2106  if (size() <= sso_capacity) {
2107  auto pop = get_pool();
2108 
2109  transaction::run(pop, [&] { large_to_sso(); });
2110  } else {
2111  non_sso.data.shrink_to_fit();
2112  }
2113 }
2114 
2124 template <typename CharT, typename Traits>
2125 void
2127 {
2128  erase(begin(), end());
2129 }
2130 
2134 template <typename CharT, typename Traits>
2135 bool
2137 {
2138  return size() == 0;
2139 }
2140 
2141 template <typename CharT, typename Traits>
2142 bool
2144 {
2145  return sso._size & _sso_mask;
2146 }
2147 
2148 template <typename CharT, typename Traits>
2149 void
2150 basic_string<CharT, Traits>::destroy_data()
2151 {
2152  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2153 
2154  if (is_sso_used()) {
2155  snapshot_sso();
2156  /* sso.data destructor does not have to be called */
2157  } else {
2158  non_sso.data.free_data();
2159  detail::destroy<decltype(non_sso.data)>(non_sso.data);
2160  }
2161 }
2162 
2169 template <typename CharT, typename Traits>
2170 template <typename InputIt, typename Enable>
2171 typename basic_string<CharT, Traits>::size_type
2172 basic_string<CharT, Traits>::get_size(InputIt first, InputIt last) const
2173 {
2174  return static_cast<size_type>(std::distance(first, last));
2175 }
2176 
2183 template <typename CharT, typename Traits>
2184 typename basic_string<CharT, Traits>::size_type
2185 basic_string<CharT, Traits>::get_size(size_type count, value_type ch) const
2186 {
2187  return count;
2188 }
2189 
2196 template <typename CharT, typename Traits>
2197 typename basic_string<CharT, Traits>::size_type
2199 {
2200  return other.size();
2201 }
2202 
2210 template <typename CharT, typename Traits>
2211 template <typename... Args>
2212 typename basic_string<CharT, Traits>::pointer
2214 {
2215  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2216 
2217  auto new_size = get_size(std::forward<Args>(args)...);
2218 
2219  /* If non_sso.data is used and there is enough capacity */
2220  if (!is_sso_used() && new_size <= capacity())
2221  return assign_large_data(std::forward<Args>(args)...);
2222 
2223  destroy_data();
2224 
2225  allocate(new_size);
2226  return initialize(std::forward<Args>(args)...);
2227 }
2228 
2240 template <typename CharT, typename Traits>
2241 template <typename... Args>
2242 typename basic_string<CharT, Traits>::pointer
2244 {
2245  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2246 
2247  auto size = get_size(std::forward<Args>(args)...);
2248 
2249  if (is_sso_used()) {
2250  set_sso_size(size);
2251  return assign_sso_data(std::forward<Args>(args)...);
2252  } else {
2253  return assign_large_data(std::forward<Args>(args)...);
2254  }
2255 }
2256 
2266 template <typename CharT, typename Traits>
2267 void
2269 {
2270  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2271 
2272  if (capacity <= sso_capacity) {
2273  enable_sso();
2274  } else {
2275  disable_sso();
2276  }
2277 
2278  /*
2279  * array is aggregate type so it's not required to call
2280  * a constructor.
2281  */
2282  if (!is_sso_used()) {
2283  detail::conditional_add_to_tx(&non_sso.data);
2284  detail::create<decltype(non_sso.data)>(&non_sso.data);
2285  non_sso.data.reserve(capacity + sizeof('\0'));
2286  }
2287 }
2288 
2292 template <typename CharT, typename Traits>
2293 template <typename InputIt, typename Enable>
2294 typename basic_string<CharT, Traits>::pointer
2296 {
2297  auto size = static_cast<size_type>(std::distance(first, last));
2298 
2299  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2300  assert(size <= sso_capacity);
2301 
2302  auto dest = sso.data.range(0, size + 1).begin();
2303  std::copy(first, last, dest);
2304 
2305  dest[size] = value_type('\0');
2306 
2307  return dest;
2308 }
2309 
2313 template <typename CharT, typename Traits>
2314 typename basic_string<CharT, Traits>::pointer
2315 basic_string<CharT, Traits>::assign_sso_data(size_type count, value_type ch)
2316 {
2317  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2318  assert(count <= sso_capacity);
2319 
2320  auto dest = sso.data.range(0, count + 1).begin();
2321  traits_type::assign(dest, count, ch);
2322 
2323  dest[count] = value_type('\0');
2324 
2325  return dest;
2326 }
2327 
2331 template <typename CharT, typename Traits>
2332 typename basic_string<CharT, Traits>::pointer
2334 {
2335  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2336 
2337  return assign_sso_data(other.cbegin(), other.cend());
2338 }
2339 
2344 template <typename CharT, typename Traits>
2345 template <typename InputIt, typename Enable>
2346 typename basic_string<CharT, Traits>::pointer
2348 {
2349  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2350 
2351  auto size = static_cast<size_type>(std::distance(first, last));
2352 
2353  non_sso.data.reserve(size + 1);
2354  non_sso.data.assign(first, last);
2355  non_sso.data.push_back(value_type('\0'));
2356 
2357  return non_sso.data.data();
2358 }
2359 
2364 template <typename CharT, typename Traits>
2365 typename basic_string<CharT, Traits>::pointer
2366 basic_string<CharT, Traits>::assign_large_data(size_type count, value_type ch)
2367 {
2368  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2369 
2370  non_sso.data.reserve(count + 1);
2371  non_sso.data.assign(count, ch);
2372  non_sso.data.push_back(value_type('\0'));
2373 
2374  return non_sso.data.data();
2375 }
2376 
2381 template <typename CharT, typename Traits>
2382 typename basic_string<CharT, Traits>::pointer
2384 {
2385  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2386 
2387  if (other.is_sso_used())
2388  return assign_large_data(other.cbegin(), other.cend());
2389 
2390  non_sso.data = std::move(other.non_sso.data);
2391 
2392  return non_sso.data.data();
2393 }
2394 
2398 template <typename CharT, typename Traits>
2399 pool_base
2401 {
2402  auto pop = pmemobj_pool_by_ptr(this);
2403  assert(pop != nullptr);
2404 
2405  return pool_base(pop);
2406 }
2407 
2411 template <typename CharT, typename Traits>
2412 void
2414 {
2415  if (pmemobj_pool_by_ptr(this) == nullptr)
2416  throw pool_error("Object is not on pmem.");
2417 }
2418 
2422 template <typename CharT, typename Traits>
2423 void
2425 {
2426  if (pmemobj_tx_stage() != TX_STAGE_WORK)
2427  throw transaction_error("Call made out of transaction scope.");
2428 }
2429 
2434 template <typename CharT, typename Traits>
2435 void
2437 {
2438  check_pmem();
2439  check_tx_stage_work();
2440 }
2441 
2445 template <typename CharT, typename Traits>
2446 void
2448 {
2449 /*
2450  * XXX: this can be optimized - only snapshot length() elements.
2451  */
2452 #if LIBPMEMOBJ_CPP_VG_MEMCHECK_ENABLED
2453  VALGRIND_MAKE_MEM_DEFINED(&sso.data, sizeof(sso.data));
2454 #endif
2455  sso.data.data();
2456 };
2457 
2461 template <typename CharT, typename Traits>
2462 typename basic_string<CharT, Traits>::size_type
2464 {
2465  return sso._size & ~_sso_mask;
2466 }
2467 
2471 template <typename CharT, typename Traits>
2472 void
2474 {
2475  /* temporary size_type must be created to avoid undefined reference
2476  * linker error */
2477  sso._size |= (size_type)(_sso_mask);
2478 }
2479 
2483 template <typename CharT, typename Traits>
2484 void
2486 {
2487  sso._size &= ~_sso_mask;
2488 }
2489 
2493 template <typename CharT, typename Traits>
2494 void
2496 {
2497  sso._size = new_size | _sso_mask;
2498 }
2499 
2511 template <typename CharT, typename Traits>
2512 void
2514 {
2515  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2516  assert(new_capacity > sso_capacity);
2517 
2518  auto sz = size();
2519 
2520  sso_type tmp;
2521  std::copy(cbegin(), cend(), tmp.data());
2522  tmp[sz] = value_type('\0');
2523 
2524  destroy_data();
2525  allocate(new_capacity);
2526 
2527  auto begin = tmp.cbegin();
2528  auto end = begin + sz;
2529 
2530  initialize(begin, end);
2531 
2532  assert(!is_sso_used());
2533 };
2534 
2544 template <typename CharT, typename Traits>
2545 void
2547 {
2548  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2549 
2550  auto sz = size();
2551 
2552  assert(sz <= sso_capacity);
2553 
2554  sso_type tmp;
2555  std::copy(cbegin(), cbegin() + sz, tmp.data());
2556  tmp[sz] = value_type('\0');
2557 
2558  destroy_data();
2559  allocate(sz);
2560 
2561  auto begin = tmp.cbegin();
2562  auto end = begin + sz;
2563 
2564  initialize(begin, end);
2565 
2566  assert(is_sso_used());
2567 };
2568 
2573 template <typename CharT, typename Traits>
2574 template <typename T, typename Enable>
2577 {
2578  return erase(static_cast<size_type>(param));
2579 }
2580 
2585 template <typename CharT, typename Traits>
2586 template <typename T, typename Enable>
2589 {
2590  return erase(static_cast<const_iterator>(param));
2591 }
2592 
2596 template <class CharT, class Traits>
2597 bool
2599  const basic_string<CharT, Traits> &rhs)
2600 {
2601  return lhs.compare(rhs) == 0;
2602 }
2603 
2607 template <class CharT, class Traits>
2608 bool
2610  const basic_string<CharT, Traits> &rhs)
2611 {
2612  return lhs.compare(rhs) != 0;
2613 }
2614 
2618 template <class CharT, class Traits>
2619 bool
2621  const basic_string<CharT, Traits> &rhs)
2622 {
2623  return lhs.compare(rhs) < 0;
2624 }
2625 
2629 template <class CharT, class Traits>
2630 bool
2632  const basic_string<CharT, Traits> &rhs)
2633 {
2634  return lhs.compare(rhs) <= 0;
2635 }
2636 
2640 template <class CharT, class Traits>
2641 bool
2643  const basic_string<CharT, Traits> &rhs)
2644 {
2645  return lhs.compare(rhs) > 0;
2646 }
2647 
2651 template <class CharT, class Traits>
2652 bool
2654  const basic_string<CharT, Traits> &rhs)
2655 {
2656  return lhs.compare(rhs) >= 0;
2657 }
2658 
2662 template <class CharT, class Traits>
2663 bool
2664 operator==(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
2665 {
2666  return rhs.compare(lhs) == 0;
2667 }
2668 
2672 template <class CharT, class Traits>
2673 bool
2674 operator!=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
2675 {
2676  return rhs.compare(lhs) != 0;
2677 }
2678 
2682 template <class CharT, class Traits>
2683 bool
2684 operator<(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
2685 {
2686  return rhs.compare(lhs) > 0;
2687 }
2688 
2692 template <class CharT, class Traits>
2693 bool
2694 operator<=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
2695 {
2696  return rhs.compare(lhs) >= 0;
2697 }
2698 
2702 template <class CharT, class Traits>
2703 bool
2704 operator>(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
2705 {
2706  return rhs.compare(lhs) < 0;
2707 }
2708 
2712 template <class CharT, class Traits>
2713 bool
2714 operator>=(const CharT *lhs, const basic_string<CharT, Traits> &rhs)
2715 {
2716  return rhs.compare(lhs) <= 0;
2717 }
2718 
2722 template <class CharT, class Traits>
2723 bool
2724 operator==(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
2725 {
2726  return lhs.compare(rhs) == 0;
2727 }
2728 
2732 template <class CharT, class Traits>
2733 bool
2734 operator!=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
2735 {
2736  return lhs.compare(rhs) != 0;
2737 }
2738 
2742 template <class CharT, class Traits>
2743 bool
2744 operator<(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
2745 {
2746  return lhs.compare(rhs) < 0;
2747 }
2748 
2752 template <class CharT, class Traits>
2753 bool
2754 operator<=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
2755 {
2756  return lhs.compare(rhs) <= 0;
2757 }
2758 
2762 template <class CharT, class Traits>
2763 bool
2764 operator>(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
2765 {
2766  return lhs.compare(rhs) > 0;
2767 }
2768 
2772 template <class CharT, class Traits>
2773 bool
2774 operator>=(const basic_string<CharT, Traits> &lhs, const CharT *rhs)
2775 {
2776  return lhs.compare(rhs) >= 0;
2777 }
2778 
2782 template <class CharT, class Traits>
2783 bool
2784 operator==(const std::basic_string<CharT, Traits> &lhs,
2785  const basic_string<CharT, Traits> &rhs)
2786 {
2787  return rhs.compare(lhs) == 0;
2788 }
2789 
2793 template <class CharT, class Traits>
2794 bool
2795 operator!=(const std::basic_string<CharT, Traits> &lhs,
2796  const basic_string<CharT, Traits> &rhs)
2797 {
2798  return rhs.compare(lhs) != 0;
2799 }
2800 
2804 template <class CharT, class Traits>
2805 bool
2806 operator<(const std::basic_string<CharT, Traits> &lhs,
2807  const basic_string<CharT, Traits> &rhs)
2808 {
2809  return rhs.compare(lhs) > 0;
2810 }
2811 
2815 template <class CharT, class Traits>
2816 bool
2817 operator<=(const std::basic_string<CharT, Traits> &lhs,
2818  const basic_string<CharT, Traits> &rhs)
2819 {
2820  return rhs.compare(lhs) >= 0;
2821 }
2822 
2826 template <class CharT, class Traits>
2827 bool
2828 operator>(const std::basic_string<CharT, Traits> &lhs,
2829  const basic_string<CharT, Traits> &rhs)
2830 {
2831  return rhs.compare(lhs) < 0;
2832 }
2833 
2837 template <class CharT, class Traits>
2838 bool
2839 operator>=(const std::basic_string<CharT, Traits> &lhs,
2840  const basic_string<CharT, Traits> &rhs)
2841 {
2842  return rhs.compare(lhs) <= 0;
2843 }
2844 
2848 template <class CharT, class Traits>
2849 bool
2851  const std::basic_string<CharT, Traits> &rhs)
2852 {
2853  return lhs.compare(rhs) == 0;
2854 }
2855 
2859 template <class CharT, class Traits>
2860 bool
2862  const std::basic_string<CharT, Traits> &rhs)
2863 {
2864  return lhs.compare(rhs) != 0;
2865 }
2866 
2870 template <class CharT, class Traits>
2871 bool
2873  const std::basic_string<CharT, Traits> &rhs)
2874 {
2875  return lhs.compare(rhs) < 0;
2876 }
2877 
2881 template <class CharT, class Traits>
2882 bool
2884  const std::basic_string<CharT, Traits> &rhs)
2885 {
2886  return lhs.compare(rhs) <= 0;
2887 }
2888 
2892 template <class CharT, class Traits>
2893 bool
2895  const std::basic_string<CharT, Traits> &rhs)
2896 {
2897  return lhs.compare(rhs) > 0;
2898 }
2899 
2903 template <class CharT, class Traits>
2904 bool
2906  const std::basic_string<CharT, Traits> &rhs)
2907 {
2908  return lhs.compare(rhs) >= 0;
2909 }
2910 
2911 } /* namespace experimental */
2912 
2913 } /* namespace obj */
2914 
2915 } /* namespace pmem */
2916 
2917 #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:400
void reserve(size_type new_cap=0)
Increase the capacity of the string to new_cap transactionally.
Definition: basic_string.hpp:2070
pmem::obj::experimental::string - EXPERIMENTAL persistent container with std::basic_string compatible...
Definition: basic_string.hpp:72
basic_string & assign(size_type count, CharT ch)
Replace the contents with count copies of character ch transactionally.
Definition: basic_string.hpp:716
size_type size() const noexcept
Definition: basic_string.hpp:1278
bool operator>=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater or equal operator.
Definition: array.hpp:757
sso_type data
Definition: basic_string.hpp:256
pmem::obj::experimental::array< T, N >::const_iterator cend(const pmem::obj::experimental::array< T, N > &a)
Non-member cend.
Definition: array.hpp:787
void large_to_sso()
Resize large string to sso string of size() size.
Definition: basic_string.hpp:2546
Default non-const iterator which adds element to a transaction on every access.
Definition: contiguous_iterator.hpp:360
void check_tx_stage_work() const
Definition: basic_string.hpp:2424
const_reverse_iterator crend() const noexcept
Return a const reverse iterator to the end.
Definition: basic_string.hpp:1085
size_type capacity() const noexcept
Definition: basic_string.hpp:1979
const_iterator cbegin() const noexcept
Return const iterator to the beginning.
Definition: basic_string.hpp:968
Common iterator traits.
void disable_sso()
Disable sso string.
Definition: basic_string.hpp:2485
The non-template pool base class.
Definition: pool.hpp:67
pmem::obj::experimental::array< T, N >::iterator begin(pmem::obj::experimental::array< T, N > &a)
Non-member begin.
Definition: array.hpp:817
CharT & front()
Access first element and snapshot it if there is an active transaction.
Definition: basic_string.hpp:1198
pmem::obj::experimental::array< T, N >::const_reverse_iterator crbegin(const pmem::obj::experimental::array< T, N > &a)
Non-member crbegin.
Definition: array.hpp:797
size_type get_sso_size() const
Return size of sso string.
Definition: basic_string.hpp:2463
Custom pool error class.
Definition: pexceptions.hpp:53
pointer initialize(Args &&... args)
Generic function which initializes memory based on provided parameters - forwards parameters to initi...
Definition: basic_string.hpp:2243
void sso_to_large(size_t new_capacity)
Resize sso string to large string.
Definition: basic_string.hpp:2513
const CharT * c_str() const noexcept
Definition: basic_string.hpp:1948
pmem::obj::experimental::array< T, N >::const_reverse_iterator crend(const pmem::obj::experimental::array< T, N > &a)
Non-member crend.
Definition: array.hpp:807
size_type length() const noexcept
Definition: basic_string.hpp:1958
basic_string()
Default constructor.
Definition: basic_string.hpp:323
void allocate(size_type capacity)
Allocate storage for container of capacity bytes.
Definition: basic_string.hpp:2268
const CharT * cdata() const noexcept
Definition: basic_string.hpp:1928
C++ pmemobj transactions.
Convenience extensions for the resides on pmem property template.
reverse_iterator rend()
Return a reverse iterator to the end.
Definition: basic_string.hpp:1059
~basic_string()
Destructor.
Definition: basic_string.hpp:603
Functions for destroying arrays.
basic_string & erase(size_type index=0, size_type count=npos)
Remove characters from string starting at index transactionally.
Definition: basic_string.hpp:1322
void enable_sso()
Enable sso string.
Definition: basic_string.hpp:2473
Commonly used functionality.
void shrink_to_fit()
Remove unused capacity transactionally.
Definition: basic_string.hpp:2101
Iterators for pmem::obj::array.
void check_pmem() const
Definition: basic_string.hpp:2413
iterator end()
Return an iterator to past the end.
Definition: basic_string.hpp:981
void check_pmem_tx() const
Definition: basic_string.hpp:2436
T * data()
Returns raw pointer to the underlying data and adds entire array to a transaction.
Definition: array.hpp:265
pointer assign_large_data(InputIt first, InputIt last)
Initialize non_sso.data - call constructor of non_sso.data.
Definition: basic_string.hpp:2347
bool empty() const noexcept
Definition: basic_string.hpp:2136
reference operator[](size_type n)
Access element at specific index and snapshot it if there is an active transaction.
Definition: basic_string.hpp:1168
Array container with std::array compatible interface.
slice< pointer > range(size_type start, size_type n)
Returns slice and snapshots requested range.
Definition: array.hpp:483
void clear()
Remove all characters from the string transactionally.
Definition: basic_string.hpp:2126
Custom transaction error class.
Definition: pexceptions.hpp:63
CharT & back()
Access last element and snapshot it if there is an active transaction.
Definition: basic_string.hpp:1241
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:2172
basic_string & operator=(const basic_string &other)
Copy assignment operator.
Definition: basic_string.hpp:620
Type trait to determine if a given parameter type satisfies requirements of InputIterator.
Definition: iterator_traits.hpp:75
const_reference const_at(size_type n) const
Access element at specific index with bounds checking.
Definition: basic_string.hpp:1145
basic_string & append(size_type count, CharT ch)
Append count copies of character ch to the string transactionally.
Definition: basic_string.hpp:1430
void resize(size_type count, CharT ch)
Resize the string to count characters transactionally.
Definition: basic_string.hpp:2004
pmem::obj::experimental::array< T, N >::iterator end(pmem::obj::experimental::array< T, N > &a)
Non-member end.
Definition: array.hpp:837
void set_sso_size(size_type new_size)
Set size for sso.
Definition: basic_string.hpp:2495
const CharT & cback() const
Access last element.
Definition: basic_string.hpp:1268
const CharT & cfront() const
Access first element.
Definition: basic_string.hpp:1225
bool operator<=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less or equal operator.
Definition: array.hpp:767
Vector container with std::vector compatible interface.
int compare(const basic_string &other) const
Compares this string to other.
Definition: basic_string.hpp:1756
Persistent smart pointer.
bool operator>(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater than operator.
Definition: array.hpp:747
Iterface to access sequence of objects.
reverse_iterator rbegin()
Return a reverse iterator to the beginning.
Definition: basic_string.hpp:1020
size_type max_size() const noexcept
Definition: basic_string.hpp:1968
const_reverse_iterator crbegin() const noexcept
Return a const reverse iterator to the beginning.
Definition: basic_string.hpp:1046
bool operator<(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less than operator.
Definition: array.hpp:736
pointer replace(Args &&... args)
Generic function which replaces current content based on provided parameters.
Definition: basic_string.hpp:2213
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:516
pmem::obj::experimental::array< T, N >::const_iterator cbegin(const pmem::obj::experimental::array< T, N > &a)
Non-member cbegin.
Definition: array.hpp:777
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:1105
void snapshot_sso() const
Snapshot sso data.
Definition: basic_string.hpp:2447
pointer assign_sso_data(InputIt first, InputIt last)
Initialize sso data.
Definition: basic_string.hpp:2295
pool_base get_pool() const
Return pool_base instance and assert that object is on pmem.
Definition: basic_string.hpp:2400
iterator begin()
Return an iterator to the beginning.
Definition: basic_string.hpp:943
static void run(pool_base &pool, std::function< void()> tx, Locks &... locks)
Execute a closure-like transaction and lock locks.
Definition: transaction.hpp:398
const_iterator cend() const noexcept
Return const iterator to past the end.
Definition: basic_string.hpp:1007