PMDK C++ bindings  1.13.0-git23.gf49772ac
This is the C++ bindings documentation for PMDK's libpmemobj.
inline_string.hpp
Go to the documentation of this file.
1 // SPDX-License-Identifier: BSD-3-Clause
2 /* Copyright 2020-2021, Intel Corporation */
3 
9 #ifndef LIBPMEMOBJ_CPP_INLINE_STRING_HPP
10 #define LIBPMEMOBJ_CPP_INLINE_STRING_HPP
11 
14 #include <libpmemobj++/slice.hpp>
17 
18 #include <string>
19 
20 namespace pmem
21 {
22 
23 namespace obj
24 {
25 
26 namespace experimental
27 {
28 
29 template <typename CharT, typename Traits = std::char_traits<CharT>>
30 class basic_inline_string_base {
31 public:
32  using traits_type = Traits;
33  using value_type = CharT;
34  using size_type = std::size_t;
35  using difference_type = std::ptrdiff_t;
36  using reference = value_type &;
37  using const_reference = const value_type &;
38  using pointer = value_type *;
39  using const_pointer = const value_type *;
40 
41  basic_inline_string_base(basic_string_view<CharT, Traits> v);
42  basic_inline_string_base(size_type capacity);
43  basic_inline_string_base(const basic_inline_string_base &rhs);
44 
45  basic_inline_string_base &
46  operator=(const basic_inline_string_base &rhs);
47 
48  basic_inline_string_base &
49  operator=(basic_string_view<CharT, Traits> rhs);
50 
51  basic_inline_string_base(basic_inline_string_base<CharT> &&) = delete;
52 
53  basic_inline_string_base &
54  operator=(basic_inline_string_base &&) = delete;
55  operator basic_string_view<CharT, Traits>() const;
56 
57  size_type size() const noexcept;
58  size_type capacity() const noexcept;
59 
60  pointer data();
61  const_pointer data() const noexcept;
62  const_pointer cdata() const noexcept;
63 
64  int compare(basic_string_view<CharT, Traits> rhs) const noexcept;
65 
66  reference operator[](size_type p);
67  const_reference operator[](size_type p) const noexcept;
68 
69  reference at(size_type p);
70  const_reference at(size_type p) const;
71 
72  slice<pointer> range(size_type p, size_type count);
73 
74  basic_inline_string_base &assign(basic_string_view<CharT, Traits> rhs);
75 
76 protected:
77  pointer snapshotted_data(size_t p, size_t n);
78 
79  obj::p<uint64_t> size_;
80  obj::p<uint64_t> capacity_;
81 };
82 
100 template <typename CharT, typename Traits = std::char_traits<CharT>>
102  : public basic_inline_string_base<CharT, Traits> {
103 public:
104  using traits_type = Traits;
105  using value_type = CharT;
106  using size_type = std::size_t;
107  using difference_type = std::ptrdiff_t;
108  using reference = value_type &;
109  using const_reference = const value_type &;
110  using pointer = value_type *;
111  using const_pointer = const value_type *;
112  using basic_inline_string_base<CharT, Traits>::operator=;
113 
115  : basic_inline_string_base<CharT, Traits>(v)
116  {
117  }
118 
119  basic_dram_inline_string(size_type capacity)
120  : basic_inline_string_base<CharT, Traits>(capacity)
121  {
122  }
124  : basic_inline_string_base<CharT, Traits>(rhs)
125  {
126  }
127 
129  operator=(const basic_dram_inline_string &rhs)
130  {
131  return static_cast<basic_dram_inline_string &>(this->operator=(
132  static_cast<const basic_inline_string_base<
133  CharT, Traits> &>(rhs)));
134  }
135 };
136 
153 template <typename CharT, typename Traits = std::char_traits<CharT>>
154 class basic_inline_string : public basic_inline_string_base<CharT, Traits> {
155 public:
156  using traits_type = Traits;
157  using value_type = CharT;
158  using size_type = std::size_t;
159  using difference_type = std::ptrdiff_t;
160  using reference = value_type &;
161  using const_reference = const value_type &;
162  using pointer = value_type *;
163  using const_pointer = const value_type *;
164  using basic_inline_string_base<CharT, Traits>::operator=;
165 
170  : basic_inline_string_base<CharT, Traits>(check_forward(v))
171  {
172  }
173 
177  basic_inline_string(size_type capacity)
178  : basic_inline_string_base<CharT, Traits>(check_forward(capacity))
179  {
180  }
181 
186  : basic_inline_string_base<CharT, Traits>(check_forward(rhs))
187  {
188  }
189 
191  operator=(const basic_inline_string &rhs)
192  {
193  return static_cast<basic_inline_string &>(this->operator=(
194  static_cast<const basic_inline_string_base<
195  CharT, Traits> &>(rhs)));
196  }
197 
198 private:
199  template <typename T>
200  T &&
201  check_forward(T &&t)
202  {
203  if (nullptr == pmemobj_pool_by_ptr(this))
204  throw pmem::pool_error("Invalid pool handle.");
205  return std::forward<T>(t);
206  }
207 };
208 
209 using dram_inline_string = basic_dram_inline_string<char>;
210 using dram_inline_wstring = basic_dram_inline_string<wchar_t>;
211 using dram_inline_u16string = basic_dram_inline_string<char16_t>;
212 using dram_inline_u32string = basic_dram_inline_string<char32_t>;
213 
214 using inline_string = basic_inline_string<char>;
215 using inline_wstring = basic_inline_string<wchar_t>;
216 using inline_u16string = basic_inline_string<char16_t>;
217 using inline_u32string = basic_inline_string<char32_t>;
218 
222 template <typename CharT, typename Traits>
223 basic_inline_string_base<CharT, Traits>::basic_inline_string_base(
224  basic_string_view<CharT, Traits> v)
225  : size_(v.size()), capacity_(v.size())
226 {
227  std::copy(v.data(), v.data() + static_cast<ptrdiff_t>(size_), data());
228 
229  data()[static_cast<ptrdiff_t>(size_)] = '\0';
230 }
231 
235 template <typename CharT, typename Traits>
236 basic_inline_string_base<CharT, Traits>::basic_inline_string_base(
237  size_type capacity)
238  : size_(0), capacity_(capacity)
239 {
240  data()[static_cast<ptrdiff_t>(size_)] = '\0';
241 }
242 
246 template <typename CharT, typename Traits>
247 basic_inline_string_base<CharT, Traits>::basic_inline_string_base(
248  const basic_inline_string_base &rhs)
249  : size_(rhs.size()), capacity_(rhs.capacity())
250 {
251  std::copy(rhs.data(), rhs.data() + static_cast<ptrdiff_t>(size_),
252  data());
253 
254  data()[static_cast<ptrdiff_t>(size_)] = '\0';
255 }
256 
260 template <typename CharT, typename Traits>
261 basic_inline_string_base<CharT, Traits> &
262 basic_inline_string_base<CharT, Traits>::operator=(
263  const basic_inline_string_base &rhs)
264 {
265  if (this == &rhs)
266  return *this;
267 
268  return assign(rhs);
269 }
270 
274 template <typename CharT, typename Traits>
275 basic_inline_string_base<CharT, Traits> &
276 basic_inline_string_base<CharT, Traits>::operator=(
277  basic_string_view<CharT, Traits> rhs)
278 {
279  return assign(rhs);
280 }
281 
283 template <typename CharT, typename Traits>
284 basic_inline_string_base<CharT, Traits>::operator basic_string_view<
285  CharT, Traits>() const
286 {
287  return {data(), size()};
288 }
289 
291 template <typename CharT, typename Traits>
292 typename basic_inline_string_base<CharT, Traits>::size_type
293 basic_inline_string_base<CharT, Traits>::size() const noexcept
294 {
295  return size_;
296 }
297 
305 template <typename CharT, typename Traits>
306 typename basic_inline_string_base<CharT, Traits>::size_type
307 basic_inline_string_base<CharT, Traits>::capacity() const noexcept
308 {
309  return capacity_;
310 }
311 
321 template <typename CharT, typename Traits>
322 typename basic_inline_string_base<CharT, Traits>::pointer
323 basic_inline_string_base<CharT, Traits>::data()
324 {
325  return snapshotted_data(0, size_);
326 }
327 
329 template <typename CharT, typename Traits>
330 typename basic_inline_string_base<CharT, Traits>::const_pointer
331 basic_inline_string_base<CharT, Traits>::data() const noexcept
332 {
333  return cdata();
334 }
335 
343 template <typename CharT, typename Traits>
344 typename basic_inline_string_base<CharT, Traits>::const_pointer
345 basic_inline_string_base<CharT, Traits>::cdata() const noexcept
346 {
347  return reinterpret_cast<const CharT *>(this + 1);
348 }
349 
358 template <typename CharT, typename Traits>
359 int
360 basic_inline_string_base<CharT, Traits>::compare(
361  basic_string_view<CharT, Traits> rhs) const noexcept
362 {
363  return basic_string_view<CharT, Traits>(data(), size()).compare(rhs);
364 }
365 
374 template <typename CharT, typename Traits>
375 typename basic_inline_string_base<CharT, Traits>::reference
376  basic_inline_string_base<CharT, Traits>::operator[](size_type p)
377 {
378  return snapshotted_data(p, 1)[0];
379 }
380 
387 template <typename CharT, typename Traits>
388 typename basic_inline_string_base<CharT, Traits>::const_reference
389  basic_inline_string_base<CharT, Traits>::operator[](size_type p) const
390  noexcept
391 {
392  return cdata()[p];
393 }
394 
404 template <typename CharT, typename Traits>
405 typename basic_inline_string_base<CharT, Traits>::reference
406 basic_inline_string_base<CharT, Traits>::at(size_type p)
407 {
408  if (p >= size())
409  throw std::out_of_range("basic_inline_string_base::at");
410 
411  return snapshotted_data(p, 1)[0];
412 }
413 
422 template <typename CharT, typename Traits>
423 typename basic_inline_string_base<CharT, Traits>::const_reference
424 basic_inline_string_base<CharT, Traits>::at(size_type p) const
425 {
426  if (p >= size())
427  throw std::out_of_range("basic_inline_string_base::at");
428 
429  return cdata()[p];
430 }
431 
445 template <typename CharT, typename Traits>
446 slice<typename basic_inline_string_base<CharT, Traits>::pointer>
447 basic_inline_string_base<CharT, Traits>::range(size_type start, size_type n)
448 {
449  if (start + n > size())
450  throw std::out_of_range("basic_inline_string_base::range");
451 
452  auto data = snapshotted_data(start, n);
453 
454  return {data, data + n};
455 }
456 
461 template <typename CharT, typename Traits>
462 typename basic_inline_string_base<CharT, Traits>::pointer
463 basic_inline_string_base<CharT, Traits>::snapshotted_data(size_t p, size_t n)
464 {
465  assert(p + n <= size());
466 
467  detail::conditional_add_to_tx(reinterpret_cast<CharT *>(this + 1) + p,
468  n, POBJ_XADD_ASSUME_INITIALIZED);
469 
470  return reinterpret_cast<CharT *>(this + 1) + p;
471 }
472 
479 template <typename CharT, typename Traits>
480 basic_inline_string_base<CharT, Traits> &
481 basic_inline_string_base<CharT, Traits>::assign(
482  basic_string_view<CharT, Traits> rhs)
483 {
484  auto cpop = pmemobj_pool_by_ptr(this);
485  if (nullptr == cpop)
486  throw pmem::pool_error("Invalid pool handle.");
487 
488  auto pop = pool_base(cpop);
489 
490  if (rhs.size() > capacity())
491  throw std::out_of_range("inline_string capacity exceeded.");
492 
493  auto initialized_mem =
494  (std::min)(rhs.size(), size()) + 1 /* sizeof('\0') */;
495 
496  obj::flat_transaction::run(pop, [&] {
497  detail::conditional_add_to_tx(data(), initialized_mem);
498 
499  if (rhs.size() > size())
500  detail::conditional_add_to_tx(
501  data() + initialized_mem,
502  rhs.size() - initialized_mem + 1,
503  POBJ_XADD_NO_SNAPSHOT);
504 
505  std::copy(rhs.data(),
506  rhs.data() + static_cast<ptrdiff_t>(rhs.size()),
507  data());
508  size_ = rhs.size();
509 
510  data()[static_cast<ptrdiff_t>(size_)] = '\0';
511  });
512 
513  return *this;
514 }
515 
522 template <typename T>
523 struct total_sizeof {
524  template <typename... Args>
525  static size_t
526  value(const Args &... args)
527  {
528  return sizeof(T);
529  }
530 };
531 
539 template <typename CharT, typename Traits>
540 struct total_sizeof<basic_inline_string<CharT, Traits>> {
541  static size_t
542  value(const basic_string_view<CharT, Traits> &s)
543  {
544  return sizeof(basic_inline_string_base<CharT, Traits>) +
545  (s.size() + 1 /* '\0' */) * sizeof(CharT);
546  }
547 };
548 
556 template <typename CharT, typename Traits>
557 struct total_sizeof<basic_dram_inline_string<CharT, Traits>> {
558  static size_t
559  value(const basic_string_view<CharT, Traits> &s)
560  {
562  (s.size() + 1 /* '\0' */) * sizeof(CharT);
563  }
564 };
565 } /* namespace experimental */
566 } /* namespace obj */
567 
568 namespace detail
569 {
570 /* Check if type is pmem::obj::basic_inline_string or
571  * pmem::obj::basic_dram_inline_string */
572 template <typename>
573 struct is_inline_string : std::false_type {
574 };
575 
576 template <typename CharT, typename Traits>
577 struct is_inline_string<obj::experimental::basic_inline_string<CharT, Traits>>
578  : std::true_type {
579 };
580 
581 template <typename CharT, typename Traits>
582 struct is_inline_string<
583  obj::experimental::basic_dram_inline_string<CharT, Traits>>
584  : std::true_type {
585 };
586 
587 } /* namespace detail */
588 
589 } /* namespace pmem */
590 
591 #endif /* LIBPMEMOBJ_CPP_INLINE_STRING_HPP */
constexpr size_type size() const noexcept
Returns count of characters stored in this pmem::obj::string_view data.
Definition: string_view.hpp:334
This class serves similar purpose to pmem::obj::string, but keeps the data within the same allocation...
Definition: inline_string.hpp:102
This class serves similar purpose to pmem::obj::string, but keeps the data within the same allocation...
Definition: inline_string.hpp:154
basic_inline_string(basic_string_view< CharT, Traits > v)
Definition: inline_string.hpp:169
basic_inline_string(const basic_inline_string &rhs)
Definition: inline_string.hpp:185
basic_inline_string(size_type capacity)
Definition: inline_string.hpp:177
Volatile residing on pmem class.
Definition: v.hpp:42
static void run(obj::pool_base &pool, std::function< void()> tx, Locks &... locks)
Execute a closure-like transaction and lock locks.
Definition: transaction.hpp:823
Custom pool error class.
Definition: pexceptions.hpp:45
Persistent_ptr transactional allocation functions for objects.
Persistent memory namespace.
Definition: allocation_flag.hpp:15
Persistent smart pointer.
Interface to access sequence of objects.
Our partial std::string_view implementation.
A helper trait which calculates required memory capacity (in bytes) for a type.
Definition: inline_string.hpp:523
C++ pmemobj transactions.