PMDK C++ bindings  1.13.0-git107.g7e59f08f
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 
104 template <typename CharT, typename Traits = std::char_traits<CharT>>
106  : public basic_inline_string_base<CharT, Traits> {
107 public:
108  using traits_type = Traits;
109  using value_type = CharT;
110  using size_type = std::size_t;
111  using difference_type = std::ptrdiff_t;
112  using reference = value_type &;
113  using const_reference = const value_type &;
114  using pointer = value_type *;
115  using const_pointer = const value_type *;
116  using basic_inline_string_base<CharT, Traits>::operator=;
117 
119  : basic_inline_string_base<CharT, Traits>(v)
120  {
121  }
122 
123  basic_dram_inline_string(size_type capacity)
124  : basic_inline_string_base<CharT, Traits>(capacity)
125  {
126  }
128  : basic_inline_string_base<CharT, Traits>(rhs)
129  {
130  }
131 
133  operator=(const basic_dram_inline_string &rhs)
134  {
135  return static_cast<basic_dram_inline_string &>(this->operator=(
136  static_cast<const basic_inline_string_base<
137  CharT, Traits> &>(rhs)));
138  }
139 };
140 
161 template <typename CharT, typename Traits = std::char_traits<CharT>>
162 class basic_inline_string : public basic_inline_string_base<CharT, Traits> {
163 public:
164  using traits_type = Traits;
165  using value_type = CharT;
166  using size_type = std::size_t;
167  using difference_type = std::ptrdiff_t;
168  using reference = value_type &;
169  using const_reference = const value_type &;
170  using pointer = value_type *;
171  using const_pointer = const value_type *;
172  using basic_inline_string_base<CharT, Traits>::operator=;
173 
178  : basic_inline_string_base<CharT, Traits>(check_forward(v))
179  {
180  }
181 
185  basic_inline_string(size_type capacity)
186  : basic_inline_string_base<CharT, Traits>(check_forward(capacity))
187  {
188  }
189 
194  : basic_inline_string_base<CharT, Traits>(check_forward(rhs))
195  {
196  }
197 
199  operator=(const basic_inline_string &rhs)
200  {
201  return static_cast<basic_inline_string &>(this->operator=(
202  static_cast<const basic_inline_string_base<
203  CharT, Traits> &>(rhs)));
204  }
205 
206 private:
207  template <typename T>
208  T &&
209  check_forward(T &&t)
210  {
211  if (nullptr == pmemobj_pool_by_ptr(this))
212  throw pmem::pool_error("Invalid pool handle.");
213  return std::forward<T>(t);
214  }
215 };
216 
238 
260 
264 template <typename CharT, typename Traits>
265 basic_inline_string_base<CharT, Traits>::basic_inline_string_base(
267  : size_(v.size()), capacity_(v.size())
268 {
269  std::copy(v.data(), v.data() + static_cast<ptrdiff_t>(size_), data());
270 
271  data()[static_cast<ptrdiff_t>(size_)] = '\0';
272 }
273 
277 template <typename CharT, typename Traits>
278 basic_inline_string_base<CharT, Traits>::basic_inline_string_base(
279  size_type capacity)
280  : size_(0), capacity_(capacity)
281 {
282  data()[static_cast<ptrdiff_t>(size_)] = '\0';
283 }
284 
288 template <typename CharT, typename Traits>
289 basic_inline_string_base<CharT, Traits>::basic_inline_string_base(
290  const basic_inline_string_base &rhs)
291  : size_(rhs.size()), capacity_(rhs.capacity())
292 {
293  std::copy(rhs.data(), rhs.data() + static_cast<ptrdiff_t>(size_),
294  data());
295 
296  data()[static_cast<ptrdiff_t>(size_)] = '\0';
297 }
298 
302 template <typename CharT, typename Traits>
303 basic_inline_string_base<CharT, Traits> &
304 basic_inline_string_base<CharT, Traits>::operator=(
305  const basic_inline_string_base &rhs)
306 {
307  if (this == &rhs)
308  return *this;
309 
310  return assign(rhs);
311 }
312 
316 template <typename CharT, typename Traits>
317 basic_inline_string_base<CharT, Traits> &
318 basic_inline_string_base<CharT, Traits>::operator=(
319  basic_string_view<CharT, Traits> rhs)
320 {
321  return assign(rhs);
322 }
323 
325 template <typename CharT, typename Traits>
326 basic_inline_string_base<CharT, Traits>::operator basic_string_view<
327  CharT, Traits>() const
328 {
329  return {data(), size()};
330 }
331 
333 template <typename CharT, typename Traits>
334 typename basic_inline_string_base<CharT, Traits>::size_type
335 basic_inline_string_base<CharT, Traits>::size() const noexcept
336 {
337  return size_;
338 }
339 
347 template <typename CharT, typename Traits>
348 typename basic_inline_string_base<CharT, Traits>::size_type
349 basic_inline_string_base<CharT, Traits>::capacity() const noexcept
350 {
351  return capacity_;
352 }
353 
363 template <typename CharT, typename Traits>
364 typename basic_inline_string_base<CharT, Traits>::pointer
365 basic_inline_string_base<CharT, Traits>::data()
366 {
367  return snapshotted_data(0, size_);
368 }
369 
371 template <typename CharT, typename Traits>
372 typename basic_inline_string_base<CharT, Traits>::const_pointer
373 basic_inline_string_base<CharT, Traits>::data() const noexcept
374 {
375  return cdata();
376 }
377 
385 template <typename CharT, typename Traits>
386 typename basic_inline_string_base<CharT, Traits>::const_pointer
387 basic_inline_string_base<CharT, Traits>::cdata() const noexcept
388 {
389  return reinterpret_cast<const CharT *>(this + 1);
390 }
391 
400 template <typename CharT, typename Traits>
401 int
402 basic_inline_string_base<CharT, Traits>::compare(
403  basic_string_view<CharT, Traits> rhs) const noexcept
404 {
405  return basic_string_view<CharT, Traits>(data(), size()).compare(rhs);
406 }
407 
416 template <typename CharT, typename Traits>
417 typename basic_inline_string_base<CharT, Traits>::reference
418  basic_inline_string_base<CharT, Traits>::operator[](size_type p)
419 {
420  return snapshotted_data(p, 1)[0];
421 }
422 
429 template <typename CharT, typename Traits>
430 typename basic_inline_string_base<CharT, Traits>::const_reference
431  basic_inline_string_base<CharT, Traits>::operator[](size_type p) const
432  noexcept
433 {
434  return cdata()[p];
435 }
436 
446 template <typename CharT, typename Traits>
447 typename basic_inline_string_base<CharT, Traits>::reference
448 basic_inline_string_base<CharT, Traits>::at(size_type p)
449 {
450  if (p >= size())
451  throw std::out_of_range("basic_inline_string_base::at");
452 
453  return snapshotted_data(p, 1)[0];
454 }
455 
464 template <typename CharT, typename Traits>
465 typename basic_inline_string_base<CharT, Traits>::const_reference
466 basic_inline_string_base<CharT, Traits>::at(size_type p) const
467 {
468  if (p >= size())
469  throw std::out_of_range("basic_inline_string_base::at");
470 
471  return cdata()[p];
472 }
473 
487 template <typename CharT, typename Traits>
488 slice<typename basic_inline_string_base<CharT, Traits>::pointer>
489 basic_inline_string_base<CharT, Traits>::range(size_type start, size_type n)
490 {
491  if (start + n > size())
492  throw std::out_of_range("basic_inline_string_base::range");
493 
494  auto data = snapshotted_data(start, n);
495 
496  return {data, data + n};
497 }
498 
503 template <typename CharT, typename Traits>
504 typename basic_inline_string_base<CharT, Traits>::pointer
505 basic_inline_string_base<CharT, Traits>::snapshotted_data(size_t p, size_t n)
506 {
507  assert(p + n <= size());
508 
509  detail::conditional_add_to_tx(reinterpret_cast<CharT *>(this + 1) + p,
510  n, POBJ_XADD_ASSUME_INITIALIZED);
511 
512  return reinterpret_cast<CharT *>(this + 1) + p;
513 }
514 
521 template <typename CharT, typename Traits>
522 basic_inline_string_base<CharT, Traits> &
523 basic_inline_string_base<CharT, Traits>::assign(
524  basic_string_view<CharT, Traits> rhs)
525 {
526  auto cpop = pmemobj_pool_by_ptr(this);
527  if (nullptr == cpop)
528  throw pmem::pool_error("Invalid pool handle.");
529 
530  auto pop = pool_base(cpop);
531 
532  if (rhs.size() > capacity())
533  throw std::out_of_range("inline_string capacity exceeded.");
534 
535  auto initialized_mem =
536  (std::min)(rhs.size(), size()) + 1 /* sizeof('\0') */;
537 
538  obj::flat_transaction::run(pop, [&] {
539  detail::conditional_add_to_tx(data(), initialized_mem);
540 
541  if (rhs.size() > size())
543  data() + initialized_mem,
544  rhs.size() - initialized_mem + 1,
545  POBJ_XADD_NO_SNAPSHOT);
546 
547  std::copy(rhs.data(),
548  rhs.data() + static_cast<ptrdiff_t>(rhs.size()),
549  data());
550  size_ = rhs.size();
551 
552  data()[static_cast<ptrdiff_t>(size_)] = '\0';
553  });
554 
555  return *this;
556 }
557 
564 template <typename T>
565 struct total_sizeof {
566  template <typename... Args>
567  static size_t
568  value(const Args &... args)
569  {
570  return sizeof(T);
571  }
572 };
573 
581 template <typename CharT, typename Traits>
582 struct total_sizeof<basic_inline_string<CharT, Traits>> {
583  static size_t
584  value(const basic_string_view<CharT, Traits> &s)
585  {
586  return sizeof(basic_inline_string_base<CharT, Traits>) +
587  (s.size() + 1 /* '\0' */) * sizeof(CharT);
588  }
589 };
590 
598 template <typename CharT, typename Traits>
599 struct total_sizeof<basic_dram_inline_string<CharT, Traits>> {
600  static size_t
601  value(const basic_string_view<CharT, Traits> &s)
602  {
604  (s.size() + 1 /* '\0' */) * sizeof(CharT);
605  }
606 };
607 } /* namespace experimental */
608 } /* namespace obj */
609 
610 namespace detail
611 {
612 /* Check if type is pmem::obj::basic_inline_string or
613  * pmem::obj::basic_dram_inline_string */
614 template <typename>
615 struct is_inline_string : std::false_type {
616 };
617 
618 template <typename CharT, typename Traits>
619 struct is_inline_string<obj::experimental::basic_inline_string<CharT, Traits>>
620  : std::true_type {
621 };
622 
623 template <typename CharT, typename Traits>
624 struct is_inline_string<
625  obj::experimental::basic_dram_inline_string<CharT, Traits>>
626  : std::true_type {
627 };
628 
629 } /* namespace detail */
630 
631 } /* namespace pmem */
632 
633 #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:397
Pmem/DRAM variation of pmem::obj::string, where data is kept right next to the inline_string structur...
Definition: inline_string.hpp:106
Pmem-only variation of pmem::obj::string, where data is kept right next to the inline_string structur...
Definition: inline_string.hpp:162
basic_inline_string(basic_string_view< CharT, Traits > v)
Definition: inline_string.hpp:177
basic_inline_string(const basic_inline_string &rhs)
Definition: inline_string.hpp:193
basic_inline_string(size_type capacity)
Definition: inline_string.hpp:185
Volatile residing on pmem class.
Definition: v.hpp:43
static void run(obj::pool_base &pool, std::function< void()> tx, Locks &... locks)
Execute a closure-like transaction and lock locks.
Definition: transaction.hpp:810
Custom pool error class.
Definition: pexceptions.hpp:84
persistent_ptr transactional allocation functions for objects.
void conditional_add_to_tx(const T *that, std::size_t count=1, uint64_t flags=0)
Conditionally add 'count' objects to a transaction.
Definition: common.hpp:176
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:565
C++ pmemobj transactions.