19 #ifndef PSTORE_ADT_SPARSE_ARRAY_HPP 20 #define PSTORE_ADT_SPARSE_ARRAY_HPP 23 #include <type_traits> 37 template <
typename Iterator,
typename Accessor>
39 using return_type =
typename std::result_of<Accessor (Iterator)>::type;
40 static_assert (std::is_reference<return_type>::value,
41 "return type from Accessor must be a reference");
44 using value_type =
typename std::remove_reference<return_type>::type;
45 using pointer = value_type *;
46 using const_pointer = value_type
const *;
47 using reference = value_type &;
48 using const_reference = value_type
const &;
50 using difference_type =
typename std::iterator_traits<Iterator>::difference_type;
51 using iterator_category =
typename std::iterator_traits<Iterator>::iterator_category;
55 , acc_{std::move (acc)} {}
67 return it_ - other.it_;
92 return it_ == other.it_ && acc_ == other.acc_;
96 const_reference operator* ()
const {
100 const_pointer operator-> ()
const {
120 template <
size_t I,
typename Iterator>
121 constexpr decltype (
auto) get_accessor () noexcept {
122 return [] (Iterator it)
123 -> std::tuple_element_t<
124 I,
typename std::iterator_traits<Iterator>::value_type>
const & {
125 return std::get<I> (*it);
133 template <std::u
intmax_t V,
typename Enable =
void>
135 template <std::u
intmax_t V>
137 using type = std::uint8_t;
139 template <std::u
intmax_t V>
141 using type = std::uint16_t;
143 template <std::u
intmax_t V>
145 using type = std::uint32_t;
147 template <std::u
intmax_t V>
149 using type = std::uint64_t;
152 template <std::u
intmax_t V>
166 template <
typename ValueType,
typename BitmapType = std::u
int64_t>
168 template <
typename V,
typename B>
172 using bitmap_type = BitmapType;
174 using value_type = ValueType;
175 using size_type = std::size_t;
176 using reference = value_type &;
177 using const_reference = value_type
const &;
178 using iterator = ValueType *;
179 using const_iterator = ValueType
const *;
180 using reverse_iterator = std::reverse_iterator<iterator>;
181 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
188 template <
typename IteratorIdx,
typename IteratorV>
189 sparse_array (IteratorIdx first_index, IteratorIdx last_index, IteratorV first_value,
190 IteratorV last_value);
194 template <
typename IteratorIdx>
195 sparse_array (IteratorIdx first_index, IteratorIdx last_index);
209 template <
typename IteratorIdx,
typename IteratorV>
210 static auto make_unique (IteratorIdx first_index, IteratorIdx last_index,
211 IteratorV first_value, IteratorV last_value)
212 -> std::unique_ptr<sparse_array>;
214 template <
typename IteratorIdx>
215 static auto make_unique (IteratorIdx first_index, IteratorIdx last_index,
216 std::initializer_list<ValueType> values)
217 -> std::unique_ptr<sparse_array>;
219 template <
typename Iterator>
220 static auto make_unique (Iterator
begin, Iterator end) -> std::unique_ptr<sparse_array>;
222 static auto make_unique (std::initializer_list<size_type>
indices,
223 std::initializer_list<ValueType> values = {})
224 -> std::unique_ptr<sparse_array>;
226 static auto make_unique (std::initializer_list<std::pair<size_type, ValueType>> v)
227 -> std::unique_ptr<sparse_array> {
228 return make_unique (std::begin (v), std::end (v));
233 constexpr
bool empty ()
const noexcept {
return bitmap_ == 0U; }
234 constexpr size_type size ()
const noexcept {
return bit_count::pop_count (bitmap_); }
238 static constexpr size_type
max_size () noexcept {
return sizeof (BitmapType) * 8; }
241 constexpr
bool has_index (size_type pos)
const noexcept {
242 return pos < max_size () ? (bitmap_ & (BitmapType{1U} << pos)) != 0U :
false;
249 iterator begin () {
return data (); }
250 const_iterator begin ()
const {
return data (); }
251 const_iterator cbegin ()
const {
return begin (); }
253 iterator end () {
return begin () + size (); }
254 const_iterator end ()
const {
return begin () + size (); }
255 const_iterator cend ()
const {
return end (); }
257 reverse_iterator rbegin () {
return reverse_iterator{end ()}; }
258 const_reverse_iterator rbegin ()
const {
return const_reverse_iterator{end ()}; }
259 const_reverse_iterator crbegin ()
const {
return rbegin (); }
261 reverse_iterator rend () {
return reverse_iterator{begin ()}; }
262 const_reverse_iterator rend ()
const {
return const_reverse_iterator{begin ()}; }
263 const_reverse_iterator crend ()
const {
return rend (); }
269 using iterator_category = std::forward_iterator_tag;
270 using value_type = std::size_t;
271 using difference_type = std::ptrdiff_t;
272 using pointer = value_type
const *;
273 using reference = value_type
const &;
280 constexpr
bool operator== (
const_iterator const & rhs)
const noexcept {
281 return bitmap_ == rhs.bitmap_;
283 constexpr
bool operator!= (
const_iterator const & rhs)
const noexcept {
284 return !operator== (rhs);
287 constexpr reference operator* ()
const noexcept {
return pos_; }
288 constexpr pointer operator-> ()
const noexcept {
return pos_; }
305 std::advance (result, x);
310 void next () noexcept {
311 for (; bitmap_ != 0U && (bitmap_ & 1U) == 0U; bitmap_ >>= 1U) {
316 std::size_t pos_ = 0;
318 constexpr
explicit indices (
sparse_array const & arr) noexcept
319 : bitmap_{arr.bitmap_} {}
323 constexpr
bool empty ()
const noexcept {
return bitmap_ == 0U; }
327 constexpr
unsigned front () const noexcept {
328 PSTORE_ASSERT (!empty ());
329 return bit_count::ctz (bitmap_);
334 constexpr
unsigned back () const noexcept {
335 PSTORE_ASSERT (!empty ());
336 return sizeof (bitmap_) * 8U - bit_count::clz (bitmap_) - 1U;
340 BitmapType
const bitmap_;
343 indices get_indices ()
const noexcept {
return indices{*
this}; }
350 ValueType * data () noexcept {
return &elements_[0]; }
351 ValueType
const * data ()
const noexcept {
return &elements_[0]; }
353 reference operator[] (size_type pos) noexcept {
354 return sparse_array::index_impl (*
this, pos);
356 const_reference operator[] (size_type pos)
const noexcept {
357 return sparse_array::index_impl (*
this, pos);
360 reference at (size_type pos) {
return sparse_array::at_impl (*
this, pos); }
361 const_reference at (size_type pos)
const {
return sparse_array::at_impl (*
this, pos); }
366 PSTORE_ASSERT (!empty ());
367 return (*
this)[get_indices ().front ()];
371 constexpr const_reference
front ()
const {
372 PSTORE_ASSERT (!empty ());
373 return (*
this)[get_indices ().front ()];
378 PSTORE_ASSERT (!empty ());
379 return (*
this)[get_indices ().back ()];
383 constexpr const_reference
back ()
const {
384 PSTORE_ASSERT (!empty ());
385 return (*
this)[get_indices ().back ()];
390 void fill (ValueType
const & value) { std::fill_n (begin (), size (), value); }
392 constexpr std::size_t size_bytes ()
const {
393 return sparse_array::size_bytes (this->size ());
395 static constexpr std::size_t size_bytes (std::size_t
const num_entries) noexcept {
396 static_assert (
sizeof (elements_) /
sizeof (ValueType) == 1U,
397 "Expected elements_ to be an array of 1 ValueType");
399 (std::max (std::size_t{1}, num_entries) - 1U) *
sizeof (ValueType);
402 void *
operator new (std::size_t
const ,
void *
const ptr) {
return ptr; }
403 void operator delete (
void *
const ,
void *
const ) {}
404 void operator delete (
void *
const p) { ::operator
delete (p); }
417 template <
typename InputIterator>
418 static std::size_t required_bytes (std::size_t
const count, InputIterator
const first,
419 InputIterator
const last) {
422 static_assert (
sizeof (elements_) /
sizeof (ValueType) == 1U,
423 "Expected elements_ to be an array of 1 ValueType");
424 auto const elements = std::max (bit_count::pop_count (bitmap (first, last)), 1U);
425 return count -
sizeof (elements_) + elements *
sizeof (ValueType);
435 template <
typename InputIterator>
436 void *
operator new (std::size_t count, InputIterator indices_first,
437 InputIterator indices_last) {
438 return ::operator
new (
439 sparse_array::required_bytes (count, indices_first, indices_last));
444 template <
typename InputIterator>
445 void operator delete (
void *
const p, InputIterator
const ,
446 InputIterator
const ) {
447 return ::operator
delete (p);
450 BitmapType
const bitmap_;
451 ValueType elements_[1];
455 template <
typename InputIterator,
456 typename =
typename std::enable_if_t<std::is_unsigned<
457 typename std::iterator_traits<InputIterator>::value_type>::value>>
458 static BitmapType bitmap (InputIterator first, InputIterator last);
461 template <
typename SparseArray,
463 static ResultType & index_impl (SparseArray && sa, size_type pos) noexcept;
466 template <
typename SparseArray,
468 static ResultType & at_impl (SparseArray && sa, size_type pos);
473 template <
typename ValueType,
typename BitmapType>
474 template <
typename IteratorIdx,
typename IteratorV>
476 IteratorIdx last_index,
477 IteratorV first_value, IteratorV last_value)
478 : bitmap_{bitmap (first_index, last_index)} {
483 if (first_index != last_index) {
484 if (first_value != last_value) {
485 elements_[0] = *(first_value++);
490 auto out = &elements_[1];
494 for (; first_index != last_index && first_value != last_value;
495 ++first_index, ++first_value, ++out) {
496 new (out) ValueType (*first_value);
499 for (; first_index != last_index; ++first_index, ++out) {
500 new (out) ValueType ();
504 template <
typename ValueType,
typename BitmapType>
505 template <
typename IteratorIdx>
507 IteratorIdx last_index)
510 if (first_index != last_index) {
513 auto * out = &elements_[1];
515 for (; first_index != last_index; ++first_index, ++out) {
516 new (out) ValueType ();
522 template <
typename ValueType,
typename BitmapType>
524 auto const elements = size ();
526 for (
auto it = &elements_[1], end = &elements_[0] + elements; it != end; ++it) {
534 template <
typename ValueType,
typename BitmapType>
535 template <
typename Iterator>
537 -> std::unique_ptr<sparse_array> {
539 using details::get_accessor;
542 auto const accessor0 = get_accessor<0U, Iterator> ();
543 auto const accessor1 = get_accessor<1U, Iterator> ();
546 auto const begin0 = pair_field_iterator<Iterator, decltype (accessor0)>{begin, accessor0};
547 auto const end0 = pair_field_iterator<Iterator, decltype (accessor0)>{end, accessor0};
548 auto const begin1 = pair_field_iterator<Iterator, decltype (accessor1)>{begin, accessor1};
549 auto const end1 = pair_field_iterator<Iterator, decltype (accessor1)>{end, accessor1};
551 return std::unique_ptr<sparse_array<ValueType, BitmapType>>{
555 template <
typename ValueType,
typename BitmapType>
556 template <
typename IteratorIdx,
typename IteratorV>
558 IteratorIdx last_index,
559 IteratorV first_value,
560 IteratorV last_value)
561 -> std::unique_ptr<sparse_array> {
563 return std::unique_ptr<sparse_array<ValueType, BitmapType>>{
565 first_index, last_index, first_value, last_value)};
568 template <
typename ValueType,
typename BitmapType>
570 std::initializer_list<ValueType> values)
571 -> std::unique_ptr<sparse_array> {
573 return make_unique (std::begin (indices), std::end (indices), std::begin (values),
577 template <
typename ValueType,
typename BitmapType>
578 template <
typename IteratorIdx>
580 IteratorIdx last_index,
581 std::initializer_list<ValueType> values)
582 -> std::unique_ptr<sparse_array> {
584 return std::unique_ptr<sparse_array<ValueType, BitmapType>>{
586 first_index, last_index, std::begin (values), std::end (values))};
591 template <
typename ValueType,
typename BitmapType>
592 template <
typename InputIterator,
typename>
594 InputIterator last) {
595 return std::accumulate (
596 first, last, BitmapType{0U},
597 [] (BitmapType
const mm,
typename std::iterator_traits<InputIterator>::value_type
const idx) {
598 PSTORE_ASSERT (idx < max_size ());
599 auto const mask = BitmapType{1U} << idx;
600 PSTORE_ASSERT ((mm & mask) == 0U &&
601 "The same index must not appear more than once in the " 602 "collection of sparse indices");
603 return static_cast<BitmapType
> (mm | mask);
609 template <
typename ValueType,
typename BitmapType>
610 template <
typename SparseArray,
typename ResultType>
612 size_type pos) noexcept {
613 PSTORE_ASSERT (pos < max_size ());
614 auto mask = BitmapType{1U} << pos;
615 PSTORE_ASSERT ((sa.bitmap_ & mask) != 0U);
617 return sa.elements_[bit_count::pop_count (static_cast<BitmapType> (sa.bitmap_ & mask))];
622 template <
typename ValueType,
typename BitmapType>
623 template <
typename SparseArray,
typename ResultType>
625 if (pos < max_size ()) {
626 auto const bit_position = BitmapType{1} << pos;
627 if ((sa.bitmap_ & bit_position) != 0) {
628 return sa.elements_[bit_count::pop_count (sa.bitmap_ & (bit_position - 1U))];
631 raise_exception (std::out_of_range (
"spare array index out of range"));
637 template <
typename ValueType,
typename BitmapType>
640 return lhs.bitmap_ == rhs.bitmap_ &&
641 std::equal (std::begin (lhs), std::end (lhs), std::begin (rhs));
646 template <
typename ValueType,
typename BitmapType>
649 return !(lhs == rhs);
654 template <std::
size_t Ip,
typename ValueType,
typename BitmapType>
657 "Index out of bounds in std::get<> (sparse_array)");
661 template <std::
size_t Ip,
typename ValueType,
typename BitmapType>
664 "Index out of bounds in std::get<> (const sparse_array)");
670 #endif // PSTORE_ADT_SPARSE_ARRAY_HPP A sparse array type.
Definition: sparse_array.hpp:167
constexpr reference back()
Returns a reference to the last element in the container.
Definition: sparse_array.hpp:377
static constexpr size_type max_size() noexcept
Returns the maximum number of indices that could be contained by an instance of this sparse_array typ...
Definition: sparse_array.hpp:238
Definition: sparse_array.hpp:38
Definition: chunked_sequence.hpp:607
transaction< transaction_lock > begin(database &db, transaction_lock &lock)
Creates a new transaction. Every operation performed on a transaction instance can be potentially und...
Definition: transaction.hpp:311
constexpr bool has_index(size_type pos) const noexcept
Returns true if the sparse array has an index 'pos'.
Definition: sparse_array.hpp:241
constexpr reference front()
Returns a reference to the first element in the container.
Definition: sparse_array.hpp:365
constexpr unsigned back() const noexcept
Returns the index of the last element in the container.
Definition: sparse_array.hpp:334
constexpr unsigned front() const noexcept
Returns the index of the first element in the container.
Definition: sparse_array.hpp:327
sparse_array(IteratorIdx first_index, IteratorIdx last_index, IteratorV first_value, IteratorV last_value)
Constructs a sparse array whose available indices are defined by the iterator range from [first_index...
Definition: sparse_array.hpp:475
Definition: sparse_array.hpp:265
Definition: nonpod2.cpp:40
Derives the correct type for the bitmap field of a sparse_array<> given the maximum index value...
Definition: sparse_array.hpp:134
Implements portable functions for bit twiddling operations including counting leading and trailing ze...
constexpr const_reference back() const
Returns a reference to the last element in the container.
Definition: sparse_array.hpp:383
Provides an pstore-specific error codes and a suitable error category for them.
Definition: sparse_array.hpp:267
constexpr const_reference front() const
Returns a reference to the first element in the container.
Definition: sparse_array.hpp:371
typename std::conditional< std::is_const< typename std::remove_reference< T >::type >::value, RC, R >::type type
If T is const, R const otherwise R.
Definition: inherit_const.hpp:112