GCC Code Coverage Report


Directory: gridformat/
File: gridformat/common/enumerated_range.hpp
Date: 2024-11-10 16:24:00
Exec Total Coverage
Lines: 23 23 100.0%
Functions: 99 99 100.0%
Branches: 5 10 50.0%

Line Branch Exec Source
1 // SPDX-FileCopyrightText: 2022-2023 Dennis Gläser <dennis.glaeser@iws.uni-stuttgart.de>
2 // SPDX-License-Identifier: MIT
3 /*!
4 * \file
5 * \ingroup Common
6 * \copydoc GridFormat::EnumeratedRange
7 */
8 #ifndef GRIDFORMAT_COMMON_ENUMERATED_RANGE_HPP_
9 #define GRIDFORMAT_COMMON_ENUMERATED_RANGE_HPP_
10
11 #include <ranges>
12 #include <cassert>
13 #include <utility>
14 #include <concepts>
15 #include <iterator>
16 #include <type_traits>
17
18 #include <gridformat/common/iterator_facades.hpp>
19 #include <gridformat/common/type_traits.hpp>
20
21
22 namespace GridFormat {
23
24 #ifndef DOXYGEN
25 namespace EnumeratedRangeDetail {
26
27 template<typename IT, typename Index>
28 using ValueType = std::pair<Index, typename std::iterator_traits<IT>::reference>;
29
30 template<typename IT, typename Sentinel, typename Index>
31 class Iterator : public ForwardIteratorFacade<Iterator<IT, Sentinel, Index>,
32 ValueType<IT, Index>,
33 ValueType<IT, Index>> {
34 public:
35 Iterator() = default;
36 2258 explicit Iterator(IT it, Sentinel sentinel, Index offset)
37 2258 : _it{it}
38
1/2
✓ Branch 1 taken 1440 times.
✗ Branch 2 not taken.
2254 , _sentinel{sentinel}
39 2258 , _counter{offset}
40 2258 {}
41
42 17100 friend bool operator==(const Iterator& self,
43 const std::default_sentinel_t&) noexcept {
44 17100 return self._it == self._sentinel;
45 }
46
47 friend bool operator==(const std::default_sentinel_t& s,
48 const Iterator& self) noexcept {
49 return self == s;
50 }
51
52 private:
53 friend IteratorAccess;
54
55 4990 ValueType<IT, Index> _dereference() const {
56
1/2
✓ Branch 1 taken 4380 times.
✗ Branch 2 not taken.
4990 return {_counter, *_it};
57 }
58
59 14830 void _increment() {
60 14830 ++_it;
61 14830 ++_counter;
62 14830 }
63
64 bool _is_equal(const Iterator& other) const {
65 return _it == other._it;
66 }
67
68 IT _it;
69 Sentinel _sentinel;
70 Index _counter{0};
71 };
72
73 template<typename IT, typename S, typename I>
74 Iterator(IT&&, S&&, I&&) -> Iterator<std::remove_cvref_t<IT>, std::remove_cvref_t<S>, std::remove_cvref_t<I>>;
75
76 } // namespace EnumeratedRangeDetail
77 #endif // DOXYGEN
78
79 /*!
80 * \ingroup Common
81 * \brief Wraps a range to yield value-index pairs.
82 */
83 template<std::ranges::forward_range R, typename Index = std::size_t>
84 class EnumeratedRange {
85 using StoredRange = LVReferenceOrValue<R>;
86
87 static constexpr bool is_const = std::is_const_v<std::remove_reference_t<R>>;
88
89 public:
90 template<typename _R>
91 requires(std::convertible_to<_R, StoredRange>)
92 2250 explicit EnumeratedRange(_R&& range)
93 2250 : _range{std::forward<_R>(range)}
94 2250 {}
95
96 2258 auto begin() {
97 return EnumeratedRangeDetail::Iterator{
98
1/2
✓ Branch 1 taken 1440 times.
✗ Branch 2 not taken.
3698 std::ranges::begin(_range),
99
1/2
✓ Branch 1 taken 1440 times.
✗ Branch 2 not taken.
3698 std::ranges::end(_range),
100 Index{0}
101
1/2
✓ Branch 1 taken 1440 times.
✗ Branch 2 not taken.
3698 };
102 }
103 auto begin() const {
104 return EnumeratedRangeDetail::Iterator{
105 std::ranges::cbegin(_range),
106 std::ranges::cend(_range),
107 Index{0}
108 };
109 }
110
111 2258 auto end() { return std::default_sentinel_t{}; }
112 auto end() const { return std::default_sentinel_t{}; }
113
114 private:
115 StoredRange _range;
116 };
117
118 template<std::ranges::range R>
119 EnumeratedRange(R&&) -> EnumeratedRange<R>;
120
121 namespace Ranges {
122
123 template<std::ranges::range R>
124 1845 auto enumerated(R&& range) {
125 1845 return EnumeratedRange{std::forward<R>(range)};
126 }
127
128 } // namespace Ranges
129 } // namespace GridFormat
130
131 #endif // GRIDFORMAT_COMMON_ENUMERATED_RANGE_HPP_
132