PMDK C++ bindings  1.7.1
This is the C++ bindings documentation for PMDK's libpmemobj.
basic_string.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2019, 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  sso._size = 0;
327 
328  allocate(0);
329  initialize(0U, value_type('\0'));
330 }
331 
346 template <typename CharT, typename Traits>
348 {
349  check_pmem_tx();
350  sso._size = 0;
351 
352  allocate(count);
353  initialize(count, ch);
354 }
355 
373 template <typename CharT, typename Traits>
375  size_type pos, size_type count)
376 {
377  check_pmem_tx();
378  sso._size = 0;
379 
380  if (pos > other.size())
381  throw std::out_of_range("Index out of range.");
382 
383  if (count == npos || pos + count > other.size())
384  count = other.size() - pos;
385 
386  auto first = static_cast<difference_type>(pos);
387  auto last = first + static_cast<difference_type>(count);
388 
389  allocate(count);
390  initialize(other.cbegin() + first, other.cbegin() + last);
391 }
392 
411 template <typename CharT, typename Traits>
412 basic_string<CharT, Traits>::basic_string(const std::basic_string<CharT> &other,
413  size_type pos, size_type count)
414 {
415  check_pmem_tx();
416  sso._size = 0;
417 
418  if (pos > other.size())
419  throw std::out_of_range("Index out of range.");
420 
421  if (count == npos || pos + count > other.size())
422  count = other.size() - pos;
423 
424  auto first = static_cast<difference_type>(pos);
425  auto last = first + static_cast<difference_type>(count);
426 
427  allocate(count);
428  initialize(other.cbegin() + first, other.cbegin() + last);
429 }
430 
446 template <typename CharT, typename Traits>
447 basic_string<CharT, Traits>::basic_string(const CharT *s, size_type count)
448 {
449  check_pmem_tx();
450  sso._size = 0;
451 
452  allocate(count);
453  initialize(s, s + count);
454 }
455 
469 template <typename CharT, typename Traits>
471 {
472  check_pmem_tx();
473  sso._size = 0;
474 
475  auto length = traits_type::length(s);
476 
477  allocate(length);
478  initialize(s, s + length);
479 }
480 
497 template <typename CharT, typename Traits>
498 template <typename InputIt, typename Enable>
499 basic_string<CharT, Traits>::basic_string(InputIt first, InputIt last)
500 {
501  auto len = std::distance(first, last);
502  assert(len >= 0);
503 
504  check_pmem_tx();
505  sso._size = 0;
506 
507  allocate(static_cast<size_type>(len));
508  initialize(first, last);
509 }
510 
525 template <typename CharT, typename Traits>
527 {
528  check_pmem_tx();
529  sso._size = 0;
530 
531  allocate(other.size());
532  initialize(other.cbegin(), other.cend());
533 }
534 
550 template <typename CharT, typename Traits>
551 basic_string<CharT, Traits>::basic_string(const std::basic_string<CharT> &other)
552  : basic_string(other.cbegin(), other.cend())
553 {
554 }
555 
570 template <typename CharT, typename Traits>
572 {
573  check_pmem_tx();
574  sso._size = 0;
575 
576  allocate(other.size());
577  initialize(std::move(other));
578 
579  if (other.is_sso_used())
580  other.initialize(0U, value_type('\0'));
581 }
582 
597 template <typename CharT, typename Traits>
598 basic_string<CharT, Traits>::basic_string(std::initializer_list<CharT> ilist)
599 {
600  check_pmem_tx();
601  sso._size = 0;
602 
603  allocate(ilist.size());
604  initialize(ilist.begin(), ilist.end());
605 }
606 
612 template <typename CharT, typename Traits>
614 {
615  if (!is_sso_used())
616  detail::destroy<non_sso_type>(non_sso.data);
617 }
618 
628 template <typename CharT, typename Traits>
631 {
632  return assign(other);
633 }
634 
645 template <typename CharT, typename Traits>
647 basic_string<CharT, Traits>::operator=(const std::basic_string<CharT> &other)
648 {
649  return assign(other);
650 }
651 
661 template <typename CharT, typename Traits>
664 {
665  return assign(std::move(other));
666 }
667 
676 template <typename CharT, typename Traits>
679 {
680  return assign(s);
681 }
682 
691 template <typename CharT, typename Traits>
694 {
695  return assign(1, ch);
696 }
697 
707 template <typename CharT, typename Traits>
709 basic_string<CharT, Traits>::operator=(std::initializer_list<CharT> ilist)
710 {
711  return assign(ilist);
712 }
713 
724 template <typename CharT, typename Traits>
726 basic_string<CharT, Traits>::assign(size_type count, CharT ch)
727 {
728  auto pop = get_pool();
729 
730  transaction::run(pop, [&] { replace(count, ch); });
731 
732  return *this;
733 }
734 
744 template <typename CharT, typename Traits>
747 {
748  if (&other == this)
749  return *this;
750 
751  auto pop = get_pool();
752 
753  transaction::run(pop, [&] { replace(other.cbegin(), other.cend()); });
754 
755  return *this;
756 }
757 
768 template <typename CharT, typename Traits>
770 basic_string<CharT, Traits>::assign(const std::basic_string<CharT> &other)
771 {
772  return assign(other.cbegin(), other.cend());
773 }
774 
787 template <typename CharT, typename Traits>
790  size_type count)
791 {
792  if (pos > other.size())
793  throw std::out_of_range("Index out of range.");
794 
795  if (count == npos || pos + count > other.size())
796  count = other.size() - pos;
797 
798  auto pop = get_pool();
799  auto first = static_cast<difference_type>(pos);
800  auto last = first + static_cast<difference_type>(count);
801 
802  transaction::run(pop, [&] {
803  replace(other.cbegin() + first, other.cbegin() + last);
804  });
805 
806  return *this;
807 }
808 
823 template <typename CharT, typename Traits>
825 basic_string<CharT, Traits>::assign(const std::basic_string<CharT> &other,
826  size_type pos, size_type count)
827 {
828  if (pos > other.size())
829  throw std::out_of_range("Index out of range.");
830 
831  if (count == npos || pos + count > other.size())
832  count = other.size() - pos;
833 
834  return assign(other.c_str() + pos, count);
835 }
836 
847 template <typename CharT, typename Traits>
849 basic_string<CharT, Traits>::assign(const CharT *s, size_type count)
850 {
851  auto pop = get_pool();
852 
853  transaction::run(pop, [&] { replace(s, s + count); });
854 
855  return *this;
856 }
857 
866 template <typename CharT, typename Traits>
869 {
870  auto pop = get_pool();
871 
872  auto length = traits_type::length(s);
873 
874  transaction::run(pop, [&] { replace(s, s + length); });
875 
876  return *this;
877 }
878 
890 template <typename CharT, typename Traits>
891 template <typename InputIt, typename Enable>
893 basic_string<CharT, Traits>::assign(InputIt first, InputIt last)
894 {
895  auto pop = get_pool();
896 
897  transaction::run(pop, [&] { replace(first, last); });
898 
899  return *this;
900 }
901 
911 template <typename CharT, typename Traits>
914 {
915  if (&other == this)
916  return *this;
917 
918  auto pop = get_pool();
919 
920  transaction::run(pop, [&] {
921  replace(std::move(other));
922 
923  if (other.is_sso_used())
924  other.initialize(0U, value_type('\0'));
925  });
926 
927  return *this;
928 }
929 
939 template <typename CharT, typename Traits>
941 basic_string<CharT, Traits>::assign(std::initializer_list<CharT> ilist)
942 {
943  return assign(ilist.begin(), ilist.end());
944 }
945 
951 template <typename CharT, typename Traits>
954 {
955  return is_sso_used() ? iterator(&*sso.data.begin())
956  : iterator(&*non_sso.data.begin());
957 }
958 
964 template <typename CharT, typename Traits>
965 typename basic_string<CharT, Traits>::const_iterator
967 {
968  return cbegin();
969 }
970 
976 template <typename CharT, typename Traits>
977 typename basic_string<CharT, Traits>::const_iterator
979 {
980  return is_sso_used() ? const_iterator(&*sso.data.cbegin())
981  : const_iterator(&*non_sso.data.cbegin());
982 }
983 
989 template <typename CharT, typename Traits>
992 {
993  return begin() + static_cast<difference_type>(size());
994 }
995 
1002 template <typename CharT, typename Traits>
1003 typename basic_string<CharT, Traits>::const_iterator
1005 {
1006  return cbegin() + static_cast<difference_type>(size());
1007 }
1008 
1015 template <typename CharT, typename Traits>
1016 typename basic_string<CharT, Traits>::const_iterator
1018 {
1019  return cbegin() + static_cast<difference_type>(size());
1020 }
1021 
1028 template <typename CharT, typename Traits>
1029 typename basic_string<CharT, Traits>::reverse_iterator
1031 {
1032  return reverse_iterator(end());
1033 }
1034 
1041 template <typename CharT, typename Traits>
1042 typename basic_string<CharT, Traits>::const_reverse_iterator
1044 {
1045  return crbegin();
1046 }
1047 
1054 template <typename CharT, typename Traits>
1055 typename basic_string<CharT, Traits>::const_reverse_iterator
1057 {
1058  return const_reverse_iterator(cend());
1059 }
1060 
1067 template <typename CharT, typename Traits>
1068 typename basic_string<CharT, Traits>::reverse_iterator
1070 {
1071  return reverse_iterator(begin());
1072 }
1073 
1080 template <typename CharT, typename Traits>
1081 typename basic_string<CharT, Traits>::const_reverse_iterator
1083 {
1084  return crend();
1085 }
1086 
1093 template <typename CharT, typename Traits>
1094 typename basic_string<CharT, Traits>::const_reverse_iterator
1096 {
1097  return const_reverse_iterator(cbegin());
1098 }
1099 
1113 template <typename CharT, typename Traits>
1114 typename basic_string<CharT, Traits>::reference
1116 {
1117  if (n >= size())
1118  throw std::out_of_range("string::at");
1119 
1120  return is_sso_used() ? sso.data[n] : non_sso.data[n];
1121 }
1122 
1133 template <typename CharT, typename Traits>
1134 typename basic_string<CharT, Traits>::const_reference
1136 {
1137  return const_at(n);
1138 }
1139 
1153 template <typename CharT, typename Traits>
1154 typename basic_string<CharT, Traits>::const_reference
1156 {
1157  if (n >= size())
1158  throw std::out_of_range("string::const_at");
1159 
1160  return is_sso_used()
1161  ? static_cast<const sso_type &>(sso.data)[n]
1162  : static_cast<const non_sso_type &>(non_sso.data)[n];
1163 }
1164 
1176 template <typename CharT, typename Traits>
1177 typename basic_string<CharT, Traits>::reference basic_string<CharT, Traits>::
1178 operator[](size_type n)
1179 {
1180  return is_sso_used() ? sso.data[n] : non_sso.data[n];
1181 }
1182 
1190 template <typename CharT, typename Traits>
1191 typename basic_string<CharT, Traits>::const_reference
1193 {
1194  return is_sso_used() ? sso.data[n] : non_sso.data[n];
1195 }
1196 
1206 template <typename CharT, typename Traits>
1207 CharT &
1209 {
1210  return (*this)[0];
1211 }
1212 
1218 template <typename CharT, typename Traits>
1219 const CharT &
1221 {
1222  return cfront();
1223 }
1224 
1233 template <typename CharT, typename Traits>
1234 const CharT &
1236 {
1237  return static_cast<const basic_string &>(*this)[0];
1238 }
1239 
1249 template <typename CharT, typename Traits>
1250 CharT &
1252 {
1253  return (*this)[size() - 1];
1254 }
1255 
1261 template <typename CharT, typename Traits>
1262 const CharT &
1264 {
1265  return cback();
1266 }
1267 
1276 template <typename CharT, typename Traits>
1277 const CharT &
1279 {
1280  return static_cast<const basic_string &>(*this)[size() - 1];
1281 }
1282 
1286 template <typename CharT, typename Traits>
1287 typename basic_string<CharT, Traits>::size_type
1289 {
1290  if (is_sso_used())
1291  return get_sso_size();
1292  else if (non_sso.data.size() == 0)
1293  return 0;
1294  else
1295  return non_sso.data.size() - 1;
1296 }
1297 
1304 template <typename CharT, typename Traits>
1305 CharT *
1307 {
1308  return is_sso_used() ? sso.data.range(0, get_sso_size() + 1).begin()
1309  : non_sso.data.data();
1310 }
1311 
1330 template <typename CharT, typename Traits>
1331 basic_string<CharT, Traits> &
1332 basic_string<CharT, Traits>::erase(size_type index, size_type count)
1333 {
1334  auto sz = size();
1335 
1336  if (index > sz)
1337  throw std::out_of_range("Index exceeds size.");
1338 
1339  count = (std::min)(count, sz - index);
1340 
1341  auto pop = get_pool();
1342 
1343  auto first = begin() + static_cast<difference_type>(index);
1344  auto last = first + static_cast<difference_type>(count);
1345 
1346  if (is_sso_used()) {
1347  transaction::run(pop, [&] {
1348  auto move_len = sz - index - count;
1349 
1350  auto dest = sso.data.range(index, move_len + 1).begin();
1351 
1352  traits_type::move(dest, &*last, move_len);
1353 
1354  auto new_size = sz - count;
1355  set_sso_size(new_size);
1356  sso.data[new_size] = value_type('\0');
1357  });
1358  } else {
1359  non_sso.data.erase(first, last);
1360  }
1361 
1362  return *this;
1363 };
1364 
1381 template <typename CharT, typename Traits>
1384 {
1385  return erase(pos, pos + 1);
1386 };
1387 
1406 template <typename CharT, typename Traits>
1408 basic_string<CharT, Traits>::erase(const_iterator first, const_iterator last)
1409 {
1410  size_type index =
1411  static_cast<size_type>(std::distance(cbegin(), first));
1412  size_type len = static_cast<size_type>(std::distance(first, last));
1413 
1414  erase(index, len);
1415 
1416  return begin() + static_cast<difference_type>(index);
1417 };
1418 
1438 template <typename CharT, typename Traits>
1440 basic_string<CharT, Traits>::append(size_type count, CharT ch)
1441 {
1442  auto sz = size();
1443  auto new_size = sz + count;
1444 
1445  if (new_size > max_size())
1446  throw std::length_error("Size exceeds max size.");
1447 
1448  if (is_sso_used()) {
1449  auto pop = get_pool();
1450 
1451  transaction::run(pop, [&] {
1452  if (new_size > sso_capacity) {
1453  sso_to_large(new_size);
1454 
1455  non_sso.data.insert(
1456  non_sso.data.cbegin() +
1457  static_cast<difference_type>(
1458  sz),
1459  count, ch);
1460  } else {
1461  /*
1462  * XXX: There is no necessity to snapshot
1463  * uninitialized data. However, we need
1464  * libpmemobj support for that, because right
1465  * now pmemcheck will report an error
1466  * (uninitialized part of data not added to tx).
1467  *
1468  * XXX: future optimization: we don't have to
1469  * snapshot data which we will not overwrite. We
1470  * should snapshot terminating null character
1471  * only.
1472  */
1473  snapshot_sso();
1474  auto dest =
1475  sso.data.range(sz, count + 1).begin();
1476  traits_type::assign(dest, count, ch);
1477 
1478  set_sso_size(new_size);
1479  sso.data[new_size] = value_type('\0');
1480  }
1481  });
1482  } else {
1483  non_sso.data.insert(non_sso.data.cbegin() +
1484  static_cast<difference_type>(sz),
1485  count, ch);
1486  }
1487 
1488  return *this;
1489 }
1490 
1509 template <typename CharT, typename Traits>
1512 {
1513  return append(str.data(), str.size());
1514 }
1515 
1541 template <typename CharT, typename Traits>
1544  size_type count)
1545 {
1546  auto sz = str.size();
1547 
1548  if (pos > sz)
1549  throw std::out_of_range("Index out of range.");
1550 
1551  count = (std::min)(count, sz - pos);
1552 
1553  append(str.data() + pos, count);
1554 
1555  return *this;
1556 }
1557 
1577 template <typename CharT, typename Traits>
1579 basic_string<CharT, Traits>::append(const CharT *s, size_type count)
1580 {
1581  return append(s, s + count);
1582 }
1583 
1603 template <typename CharT, typename Traits>
1606 {
1607  return append(s, traits_type::length(s));
1608 }
1609 
1631 template <typename CharT, typename Traits>
1632 template <typename InputIt, typename Enable>
1634 basic_string<CharT, Traits>::append(InputIt first, InputIt last)
1635 {
1636  auto sz = size();
1637  auto count = static_cast<size_type>(std::distance(first, last));
1638  auto new_size = sz + count;
1639 
1640  if (new_size > max_size())
1641  throw std::length_error("Size exceeds max size.");
1642 
1643  if (is_sso_used()) {
1644  auto pop = get_pool();
1645 
1646  transaction::run(pop, [&] {
1647  if (new_size > sso_capacity) {
1648  /* 1) Cache C-style string in case of
1649  * self-append, because it will be destroyed
1650  * when switching from sso to large string.
1651  *
1652  * 2) We cache in std::vector instead of
1653  * std::string because of overload deduction
1654  * ambiguity on Windows
1655  */
1656  std::vector<value_type> str(first, last);
1657 
1658  sso_to_large(new_size);
1659  non_sso.data.insert(
1660  non_sso.data.cbegin() +
1661  static_cast<difference_type>(
1662  sz),
1663  str.begin(), str.end());
1664  } else {
1665  /*
1666  * XXX: future optimization: we don't have to
1667  * snapshot data which we will not overwrite. We
1668  * should snapshot terminating null character
1669  * only.
1670  */
1671  snapshot_sso();
1672  auto dest =
1673  sso.data.range(sz, count + 1).begin();
1674  std::copy(first, last, dest);
1675 
1676  set_sso_size(new_size);
1677  sso.data[new_size] = value_type('\0');
1678  }
1679  });
1680  } else {
1681  non_sso.data.insert(non_sso.data.cbegin() +
1682  static_cast<difference_type>(sz),
1683  first, last);
1684  }
1685 
1686  return *this;
1687 }
1688 
1707 template <typename CharT, typename Traits>
1709 basic_string<CharT, Traits>::append(std::initializer_list<CharT> ilist)
1710 {
1711  return append(ilist.begin(), ilist.end());
1712 }
1713 
1731 template <typename CharT, typename Traits>
1732 int
1733 basic_string<CharT, Traits>::compare(size_type pos, size_type count1,
1734  const CharT *s, size_type count2) const
1735 {
1736  if (pos > size())
1737  throw std::out_of_range("Index out of range.");
1738 
1739  if (count1 > size() - pos)
1740  count1 = size() - pos;
1741 
1742  auto ret = traits_type::compare(cdata() + pos, s,
1743  std::min<size_type>(count1, count2));
1744 
1745  if (ret != 0)
1746  return ret;
1747 
1748  if (count1 < count2)
1749  return -1;
1750  else if (count1 == count2)
1751  return 0;
1752  else
1753  return 1;
1754 }
1755 
1764 template <typename CharT, typename Traits>
1765 int
1767 {
1768  return compare(0, size(), other.cdata(), other.size());
1769 }
1770 
1779 template <typename CharT, typename Traits>
1780 int
1782  const std::basic_string<CharT> &other) const
1783 {
1784  return compare(0, size(), other.data(), other.size());
1785 }
1786 
1800 template <typename CharT, typename Traits>
1801 int
1802 basic_string<CharT, Traits>::compare(size_type pos, size_type count,
1803  const basic_string &other) const
1804 {
1805  return compare(pos, count, other.cdata(), other.size());
1806 }
1807 
1822 template <typename CharT, typename Traits>
1823 int
1825  size_type pos, size_type count,
1826  const std::basic_string<CharT> &other) const
1827 {
1828  return compare(pos, count, other.data(), other.size());
1829 }
1830 
1849 template <typename CharT, typename Traits>
1850 int
1851 basic_string<CharT, Traits>::compare(size_type pos1, size_type count1,
1852  const basic_string &other, size_type pos2,
1853  size_type count2) const
1854 {
1855  if (pos2 > other.size())
1856  throw std::out_of_range("Index out of range.");
1857 
1858  if (count2 > other.size() - pos2)
1859  count2 = other.size() - pos2;
1860 
1861  return compare(pos1, count1, other.cdata() + pos2, count2);
1862 }
1863 
1882 template <typename CharT, typename Traits>
1883 int
1884 basic_string<CharT, Traits>::compare(size_type pos1, size_type count1,
1885  const std::basic_string<CharT> &other,
1886  size_type pos2, size_type count2) const
1887 {
1888  if (pos2 > other.size())
1889  throw std::out_of_range("Index out of range.");
1890 
1891  if (count2 > other.size() - pos2)
1892  count2 = other.size() - pos2;
1893 
1894  return compare(pos1, count1, other.data() + pos2, count2);
1895 }
1896 
1905 template <typename CharT, typename Traits>
1906 int
1908 {
1909  return compare(0, size(), s, traits_type::length(s));
1910 }
1911 
1925 template <typename CharT, typename Traits>
1926 int
1927 basic_string<CharT, Traits>::compare(size_type pos, size_type count,
1928  const CharT *s) const
1929 {
1930  return compare(pos, count, s, traits_type::length(s));
1931 }
1932 
1936 template <typename CharT, typename Traits>
1937 const CharT *
1939 {
1940  return is_sso_used() ? sso.data.cdata() : non_sso.data.cdata();
1941 }
1942 
1946 template <typename CharT, typename Traits>
1947 const CharT *
1948 basic_string<CharT, Traits>::data() const noexcept
1949 {
1950  return cdata();
1951 }
1952 
1956 template <typename CharT, typename Traits>
1957 const CharT *
1959 {
1960  return cdata();
1961 }
1962 
1966 template <typename CharT, typename Traits>
1967 typename basic_string<CharT, Traits>::size_type
1969 {
1970  return size();
1971 }
1972 
1976 template <typename CharT, typename Traits>
1977 typename basic_string<CharT, Traits>::size_type
1979 {
1980  return PMEMOBJ_MAX_ALLOC_SIZE / sizeof(CharT) - 1;
1981 }
1982 
1987 template <typename CharT, typename Traits>
1988 typename basic_string<CharT, Traits>::size_type
1990 {
1991  return is_sso_used() ? sso_capacity : non_sso.data.capacity() - 1;
1992 }
1993 
2012 template <typename CharT, typename Traits>
2013 void
2014 basic_string<CharT, Traits>::resize(size_type count, CharT ch)
2015 {
2016  if (count > max_size())
2017  throw std::length_error("Count exceeds max size.");
2018 
2019  auto sz = size();
2020 
2021  auto pop = get_pool();
2022 
2023  transaction::run(pop, [&] {
2024  if (count > sz) {
2025  append(count - sz, ch);
2026  } else if (is_sso_used()) {
2027  set_sso_size(count);
2028  sso.data[count] = value_type('\0');
2029  } else {
2030  non_sso.data.resize(count + 1, ch);
2031  non_sso.data.back() = value_type('\0');
2032  }
2033  });
2034 }
2035 
2053 template <typename CharT, typename Traits>
2054 void
2056 {
2057  resize(count, CharT());
2058 }
2059 
2078 template <typename CharT, typename Traits>
2079 void
2081 {
2082  if (new_cap > max_size())
2083  throw std::length_error("New capacity exceeds max size.");
2084 
2085  if (new_cap < capacity() || new_cap <= sso_capacity)
2086  return;
2087 
2088  if (is_sso_used()) {
2089  auto pop = get_pool();
2090 
2091  transaction::run(pop, [&] { sso_to_large(new_cap); });
2092  } else {
2093  non_sso.data.reserve(new_cap + 1);
2094  }
2095 }
2096 
2109 template <typename CharT, typename Traits>
2110 void
2112 {
2113  if (is_sso_used())
2114  return;
2115 
2116  if (size() <= sso_capacity) {
2117  auto pop = get_pool();
2118 
2119  transaction::run(pop, [&] { large_to_sso(); });
2120  } else {
2121  non_sso.data.shrink_to_fit();
2122  }
2123 }
2124 
2134 template <typename CharT, typename Traits>
2135 void
2137 {
2138  erase(begin(), end());
2139 }
2140 
2144 template <typename CharT, typename Traits>
2145 bool
2147 {
2148  return size() == 0;
2149 }
2150 
2151 template <typename CharT, typename Traits>
2152 bool
2154 {
2155  return sso._size & _sso_mask;
2156 }
2157 
2158 template <typename CharT, typename Traits>
2159 void
2160 basic_string<CharT, Traits>::destroy_data()
2161 {
2162  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2163 
2164  if (is_sso_used()) {
2165  snapshot_sso();
2166  /* sso.data destructor does not have to be called */
2167  } else {
2168  non_sso.data.free_data();
2169  detail::destroy<decltype(non_sso.data)>(non_sso.data);
2170  }
2171 }
2172 
2179 template <typename CharT, typename Traits>
2180 template <typename InputIt, typename Enable>
2181 typename basic_string<CharT, Traits>::size_type
2182 basic_string<CharT, Traits>::get_size(InputIt first, InputIt last) const
2183 {
2184  return static_cast<size_type>(std::distance(first, last));
2185 }
2186 
2193 template <typename CharT, typename Traits>
2194 typename basic_string<CharT, Traits>::size_type
2195 basic_string<CharT, Traits>::get_size(size_type count, value_type ch) const
2196 {
2197  return count;
2198 }
2199 
2206 template <typename CharT, typename Traits>
2207 typename basic_string<CharT, Traits>::size_type
2209 {
2210  return other.size();
2211 }
2212 
2220 template <typename CharT, typename Traits>
2221 template <typename... Args>
2222 typename basic_string<CharT, Traits>::pointer
2224 {
2225  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2226 
2227  auto new_size = get_size(std::forward<Args>(args)...);
2228 
2229  /* If non_sso.data is used and there is enough capacity */
2230  if (!is_sso_used() && new_size <= capacity())
2231  return assign_large_data(std::forward<Args>(args)...);
2232 
2233  destroy_data();
2234 
2235  allocate(new_size);
2236  return initialize(std::forward<Args>(args)...);
2237 }
2238 
2250 template <typename CharT, typename Traits>
2251 template <typename... Args>
2252 typename basic_string<CharT, Traits>::pointer
2254 {
2255  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2256 
2257  auto size = get_size(std::forward<Args>(args)...);
2258 
2259  if (is_sso_used()) {
2260  set_sso_size(size);
2261  return assign_sso_data(std::forward<Args>(args)...);
2262  } else {
2263  return assign_large_data(std::forward<Args>(args)...);
2264  }
2265 }
2266 
2276 template <typename CharT, typename Traits>
2277 void
2279 {
2280  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2281 
2282  if (capacity <= sso_capacity) {
2283  enable_sso();
2284  } else {
2285  disable_sso();
2286  }
2287 
2288  /*
2289  * array is aggregate type so it's not required to call
2290  * a constructor.
2291  */
2292  if (!is_sso_used()) {
2293  detail::conditional_add_to_tx(&non_sso.data);
2294  detail::create<decltype(non_sso.data)>(&non_sso.data);
2295  non_sso.data.reserve(capacity + sizeof('\0'));
2296  }
2297 }
2298 
2302 template <typename CharT, typename Traits>
2303 template <typename InputIt, typename Enable>
2304 typename basic_string<CharT, Traits>::pointer
2306 {
2307  auto size = static_cast<size_type>(std::distance(first, last));
2308 
2309  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2310  assert(size <= sso_capacity);
2311 
2312  auto dest = sso.data.range(0, size + 1).begin();
2313  std::copy(first, last, dest);
2314 
2315  dest[size] = value_type('\0');
2316 
2317  return dest;
2318 }
2319 
2323 template <typename CharT, typename Traits>
2324 typename basic_string<CharT, Traits>::pointer
2325 basic_string<CharT, Traits>::assign_sso_data(size_type count, value_type ch)
2326 {
2327  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2328  assert(count <= sso_capacity);
2329 
2330  auto dest = sso.data.range(0, count + 1).begin();
2331  traits_type::assign(dest, count, ch);
2332 
2333  dest[count] = value_type('\0');
2334 
2335  return dest;
2336 }
2337 
2341 template <typename CharT, typename Traits>
2342 typename basic_string<CharT, Traits>::pointer
2344 {
2345  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2346 
2347  return assign_sso_data(other.cbegin(), other.cend());
2348 }
2349 
2354 template <typename CharT, typename Traits>
2355 template <typename InputIt, typename Enable>
2356 typename basic_string<CharT, Traits>::pointer
2358 {
2359  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2360 
2361  auto size = static_cast<size_type>(std::distance(first, last));
2362 
2363  non_sso.data.reserve(size + 1);
2364  non_sso.data.assign(first, last);
2365  non_sso.data.push_back(value_type('\0'));
2366 
2367  return non_sso.data.data();
2368 }
2369 
2374 template <typename CharT, typename Traits>
2375 typename basic_string<CharT, Traits>::pointer
2376 basic_string<CharT, Traits>::assign_large_data(size_type count, value_type ch)
2377 {
2378  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2379 
2380  non_sso.data.reserve(count + 1);
2381  non_sso.data.assign(count, ch);
2382  non_sso.data.push_back(value_type('\0'));
2383 
2384  return non_sso.data.data();
2385 }
2386 
2391 template <typename CharT, typename Traits>
2392 typename basic_string<CharT, Traits>::pointer
2394 {
2395  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2396 
2397  if (other.is_sso_used())
2398  return assign_large_data(other.cbegin(), other.cend());
2399 
2400  non_sso.data = std::move(other.non_sso.data);
2401 
2402  return non_sso.data.data();
2403 }
2404 
2408 template <typename CharT, typename Traits>
2409 pool_base
2411 {
2412  auto pop = pmemobj_pool_by_ptr(this);
2413  assert(pop != nullptr);
2414 
2415  return pool_base(pop);
2416 }
2417 
2421 template <typename CharT, typename Traits>
2422 void
2424 {
2425  if (pmemobj_pool_by_ptr(this) == nullptr)
2426  throw pool_error("Object is not on pmem.");
2427 }
2428 
2432 template <typename CharT, typename Traits>
2433 void
2435 {
2436  if (pmemobj_tx_stage() != TX_STAGE_WORK)
2437  throw transaction_error("Call made out of transaction scope.");
2438 }
2439 
2444 template <typename CharT, typename Traits>
2445 void
2447 {
2448  check_pmem();
2449  check_tx_stage_work();
2450 }
2451 
2455 template <typename CharT, typename Traits>
2456 void
2458 {
2459 /*
2460  * XXX: this can be optimized - only snapshot length() elements.
2461  */
2462 #if LIBPMEMOBJ_CPP_VG_MEMCHECK_ENABLED
2463  VALGRIND_MAKE_MEM_DEFINED(&sso.data, sizeof(sso.data));
2464 #endif
2465  sso.data.data();
2466 };
2467 
2471 template <typename CharT, typename Traits>
2472 typename basic_string<CharT, Traits>::size_type
2474 {
2475  return sso._size & ~_sso_mask;
2476 }
2477 
2481 template <typename CharT, typename Traits>
2482 void
2484 {
2485  /* temporary size_type must be created to avoid undefined reference
2486  * linker error */
2487  sso._size |= (size_type)(_sso_mask);
2488 }
2489 
2493 template <typename CharT, typename Traits>
2494 void
2496 {
2497  sso._size &= ~_sso_mask;
2498 }
2499 
2503 template <typename CharT, typename Traits>
2504 void
2506 {
2507  sso._size = new_size | _sso_mask;
2508 }
2509 
2521 template <typename CharT, typename Traits>
2522 void
2524 {
2525  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2526  assert(new_capacity > sso_capacity);
2527 
2528  auto sz = size();
2529 
2530  sso_type tmp;
2531  std::copy(cbegin(), cend(), tmp.data());
2532  tmp[sz] = value_type('\0');
2533 
2534  destroy_data();
2535  allocate(new_capacity);
2536 
2537  auto begin = tmp.cbegin();
2538  auto end = begin + sz;
2539 
2540  initialize(begin, end);
2541 
2542  assert(!is_sso_used());
2543 };
2544 
2554 template <typename CharT, typename Traits>
2555 void
2557 {
2558  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2559 
2560  auto sz = size();
2561 
2562  assert(sz <= sso_capacity);
2563 
2564  sso_type tmp;
2565  std::copy(cbegin(), cbegin() + sz, tmp.data());
2566  tmp[sz] = value_type('\0');
2567 
2568  destroy_data();
2569  allocate(sz);
2570 
2571  auto begin = tmp.cbegin();
2572  auto end = begin + sz;
2573 
2574  initialize(begin, end);
2575 
2576  assert(is_sso_used());
2577 };
2578 
2583 template <typename CharT, typename Traits>
2584 template <typename T, typename Enable>
2587 {
2588  return erase(static_cast<size_type>(param));
2589 }
2590 
2595 template <typename CharT, typename Traits>
2596 template <typename T, typename Enable>
2599 {
2600  return erase(static_cast<const_iterator>(param));
2601 }
2602 
2606 template <class CharT, class Traits>
2607 bool
2609  const basic_string<CharT, Traits> &rhs)
2610 {
2611  return lhs.compare(rhs) == 0;
2612 }
2613 
2617 template <class CharT, class Traits>
2618 bool
2620  const basic_string<CharT, Traits> &rhs)
2621 {
2622  return lhs.compare(rhs) != 0;
2623 }
2624 
2628 template <class CharT, class Traits>
2629 bool
2631  const basic_string<CharT, Traits> &rhs)
2632 {
2633  return lhs.compare(rhs) < 0;
2634 }
2635 
2639 template <class CharT, class Traits>
2640 bool
2642  const basic_string<CharT, Traits> &rhs)
2643 {
2644  return lhs.compare(rhs) <= 0;
2645 }
2646 
2650 template <class CharT, class Traits>
2651 bool
2653  const basic_string<CharT, Traits> &rhs)
2654 {
2655  return lhs.compare(rhs) > 0;
2656 }
2657 
2661 template <class CharT, class Traits>
2662 bool
2664  const basic_string<CharT, Traits> &rhs)
2665 {
2666  return lhs.compare(rhs) >= 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 CharT *lhs, const basic_string<CharT, Traits> &rhs)
2725 {
2726  return rhs.compare(lhs) <= 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 basic_string<CharT, Traits> &lhs, const CharT *rhs)
2785 {
2786  return lhs.compare(rhs) >= 0;
2787 }
2788 
2792 template <class CharT, class Traits>
2793 bool
2794 operator==(const std::basic_string<CharT, Traits> &lhs,
2795  const basic_string<CharT, Traits> &rhs)
2796 {
2797  return rhs.compare(lhs) == 0;
2798 }
2799 
2803 template <class CharT, class Traits>
2804 bool
2805 operator!=(const std::basic_string<CharT, Traits> &lhs,
2806  const basic_string<CharT, Traits> &rhs)
2807 {
2808  return rhs.compare(lhs) != 0;
2809 }
2810 
2814 template <class CharT, class Traits>
2815 bool
2816 operator<(const std::basic_string<CharT, Traits> &lhs,
2817  const basic_string<CharT, Traits> &rhs)
2818 {
2819  return rhs.compare(lhs) > 0;
2820 }
2821 
2825 template <class CharT, class Traits>
2826 bool
2827 operator<=(const std::basic_string<CharT, Traits> &lhs,
2828  const basic_string<CharT, Traits> &rhs)
2829 {
2830  return rhs.compare(lhs) >= 0;
2831 }
2832 
2836 template <class CharT, class Traits>
2837 bool
2838 operator>(const std::basic_string<CharT, Traits> &lhs,
2839  const basic_string<CharT, Traits> &rhs)
2840 {
2841  return rhs.compare(lhs) < 0;
2842 }
2843 
2847 template <class CharT, class Traits>
2848 bool
2849 operator>=(const std::basic_string<CharT, Traits> &lhs,
2850  const basic_string<CharT, Traits> &rhs)
2851 {
2852  return rhs.compare(lhs) <= 0;
2853 }
2854 
2858 template <class CharT, class Traits>
2859 bool
2861  const std::basic_string<CharT, Traits> &rhs)
2862 {
2863  return lhs.compare(rhs) == 0;
2864 }
2865 
2869 template <class CharT, class Traits>
2870 bool
2872  const std::basic_string<CharT, Traits> &rhs)
2873 {
2874  return lhs.compare(rhs) != 0;
2875 }
2876 
2880 template <class CharT, class Traits>
2881 bool
2883  const std::basic_string<CharT, Traits> &rhs)
2884 {
2885  return lhs.compare(rhs) < 0;
2886 }
2887 
2891 template <class CharT, class Traits>
2892 bool
2894  const std::basic_string<CharT, Traits> &rhs)
2895 {
2896  return lhs.compare(rhs) <= 0;
2897 }
2898 
2902 template <class CharT, class Traits>
2903 bool
2905  const std::basic_string<CharT, Traits> &rhs)
2906 {
2907  return lhs.compare(rhs) > 0;
2908 }
2909 
2913 template <class CharT, class Traits>
2914 bool
2916  const std::basic_string<CharT, Traits> &rhs)
2917 {
2918  return lhs.compare(rhs) >= 0;
2919 }
2920 
2921 } /* namespace experimental */
2922 
2923 } /* namespace obj */
2924 
2925 } /* namespace pmem */
2926 
2927 #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:2080
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:726
size_type size() const noexcept
Definition: basic_string.hpp:1288
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:2556
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:2434
const_reverse_iterator crend() const noexcept
Return a const reverse iterator to the end.
Definition: basic_string.hpp:1095
size_type capacity() const noexcept
Definition: basic_string.hpp:1989
const_iterator cbegin() const noexcept
Return const iterator to the beginning.
Definition: basic_string.hpp:978
Common iterator traits.
void disable_sso()
Disable sso string.
Definition: basic_string.hpp:2495
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:1208
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:2473
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:2253
void sso_to_large(size_t new_capacity)
Resize sso string to large string.
Definition: basic_string.hpp:2523
const CharT * c_str() const noexcept
Definition: basic_string.hpp:1958
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:1968
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:2278
const CharT * cdata() const noexcept
Definition: basic_string.hpp:1938
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:1069
~basic_string()
Destructor.
Definition: basic_string.hpp:613
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:1332
void enable_sso()
Enable sso string.
Definition: basic_string.hpp:2483
Commonly used functionality.
void shrink_to_fit()
Remove unused capacity transactionally.
Definition: basic_string.hpp:2111
Iterators for pmem::obj::array.
void check_pmem() const
Definition: basic_string.hpp:2423
iterator end()
Return an iterator to past the end.
Definition: basic_string.hpp:991
void check_pmem_tx() const
Definition: basic_string.hpp:2446
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:2357
bool empty() const noexcept
Definition: basic_string.hpp:2146
reference operator[](size_type n)
Access element at specific index and snapshot it if there is an active transaction.
Definition: basic_string.hpp:1178
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:2136
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:1251
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:2182
basic_string & operator=(const basic_string &other)
Copy assignment operator.
Definition: basic_string.hpp:630
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:1155
basic_string & append(size_type count, CharT ch)
Append count copies of character ch to the string transactionally.
Definition: basic_string.hpp:1440
void resize(size_type count, CharT ch)
Resize the string to count characters transactionally.
Definition: basic_string.hpp:2014
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:2505
const CharT & cback() const
Access last element.
Definition: basic_string.hpp:1278
const CharT & cfront() const
Access first element.
Definition: basic_string.hpp:1235
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:1766
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:1030
size_type max_size() const noexcept
Definition: basic_string.hpp:1978
const_reverse_iterator crbegin() const noexcept
Return a const reverse iterator to the beginning.
Definition: basic_string.hpp:1056
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:2223
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:1115
void snapshot_sso() const
Snapshot sso data.
Definition: basic_string.hpp:2457
pointer assign_sso_data(InputIt first, InputIt last)
Initialize sso data.
Definition: basic_string.hpp:2305
pool_base get_pool() const
Return pool_base instance and assert that object is on pmem.
Definition: basic_string.hpp:2410
iterator begin()
Return an iterator to the beginning.
Definition: basic_string.hpp:953
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:1017