GCC Code Coverage Report


Directory: ./
File: include/CXXIter/src/op/Sorter.h
Date: 2023-01-04 16:32:12
Exec Total Coverage
Lines: 20 20 100.0%
Functions: 56 56 100.0%
Branches: 10 16 62.5%

Line Branch Exec Source
1 #pragma once
2
3 #include <cstdlib>
4 #include <optional>
5
6 #include "../Common.h"
7 #include "../sources/ContainerSources.h"
8 #include "../util/TraitImpl.h"
9
10 namespace CXXIter {
11
12 // ################################################################################################
13 // SORTER
14 // ################################################################################################
15 namespace op {
16 /** @private */
17 template<typename TChainInput, typename TCompareFn, bool STABLE>
18 class [[nodiscard(CXXITER_CHAINER_NODISCARD_WARNING)]] Sorter : public IterApi<Sorter<TChainInput, TCompareFn, STABLE>> {
19 friend struct trait::Iterator<Sorter<TChainInput, TCompareFn, STABLE>>;
20 friend struct trait::DoubleEndedIterator<Sorter<TChainInput, TCompareFn, STABLE>>;
21 friend struct trait::ExactSizeIterator<Sorter<TChainInput, TCompareFn, STABLE>>;
22 private:
23 using OwnedInputItem = typename TChainInput::ItemOwned;
24 using SortCache = SrcMov<std::vector<OwnedInputItem>>;
25
26 TChainInput input;
27 TCompareFn compareFn;
28 std::optional<SortCache> sortCache;
29 public:
30 43 constexpr Sorter(TChainInput&& input, TCompareFn compareFn) : input(std::move(input)), compareFn(compareFn) {}
31 };
32 }
33 // ------------------------------------------------------------------------------------------------
34 /** @private */
35 template<typename TChainInput, typename TCompareFn, bool STABLE>
36 struct trait::Iterator<op::Sorter<TChainInput, TCompareFn, STABLE>> {
37 using ChainInputIterator = trait::Iterator<TChainInput>;
38 using InputItem = typename TChainInput::Item;
39 using OwnedInputItem = typename TChainInput::ItemOwned;
40 // CXXIter Interface
41 using Self = op::Sorter<TChainInput, TCompareFn, STABLE>;
42 using Item = OwnedInputItem;
43
44 23 static constexpr inline void initSortCache(Self& self) {
45 // drain input iterator into sortCache
46 23 std::vector<OwnedInputItem> sortCache;
47 113 while(true) {
48
1/2
✓ Branch 1 taken 71 times.
✗ Branch 2 not taken.
136 auto item = ChainInputIterator::next(self.input);
49
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 59 times.
136 if(!item.has_value()) [[unlikely]] { break; }
50
2/4
✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 59 times.
✗ Branch 6 not taken.
113 sortCache.push_back(std::forward<InputItem>( item.value() ));
51 }
52 // sort the cache
53 if constexpr(STABLE) {
54
1/2
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
4 std::stable_sort(sortCache.begin(), sortCache.end(), self.compareFn);
55 } else {
56
1/2
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
19 std::sort(sortCache.begin(), sortCache.end(), self.compareFn);
57 }
58
1/2
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
23 self.sortCache.emplace(std::move(sortCache));
59 23 }
60
61 104 static constexpr inline IterValue<Item> next(Self& self) {
62
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 47 times.
104 if(!self.sortCache.has_value()) [[unlikely]] { initSortCache(self); }
63
64 using SortCacheIterator = trait::Iterator<typename Self::SortCache>;
65 104 typename Self::SortCache& sortedItems = self.sortCache.value();
66 104 return SortCacheIterator::next(sortedItems);
67 }
68 31 static constexpr inline SizeHint sizeHint(const Self& self) { return ChainInputIterator::sizeHint(self.input); }
69 static constexpr inline size_t advanceBy(Self& self, size_t n) { return util::advanceByPull(self, n); }
70 };
71 /** @private */
72 template<CXXIterDoubleEndedIterator TChainInput, typename TCompareFn, bool STABLE>
73 struct trait::DoubleEndedIterator<op::Sorter<TChainInput, TCompareFn, STABLE>> {
74 using ChainInputIterator = trait::Iterator<TChainInput>;
75 using InputItem = typename TChainInput::Item;
76 using OwnedInputItem = typename TChainInput::ItemOwned;
77 // CXXIter Interface
78 using Self = op::Sorter<TChainInput, TCompareFn, STABLE>;
79 using Item = OwnedInputItem;
80
81 20 static constexpr inline IterValue<Item> nextBack(Self& self) {
82 20 if(!self.sortCache.has_value()) [[unlikely]] { trait::Iterator<Self>::initSortCache(self); }
83
84 using SortCacheIterator = trait::DoubleEndedIterator<typename Self::SortCache>;
85 20 typename Self::SortCache& sortedItems = self.sortCache.value();
86 20 return SortCacheIterator::nextBack(sortedItems);
87 }
88 };
89 /** @private */
90 template<CXXIterExactSizeIterator TChainInput, typename TCompareFn, bool STABLE>
91 struct trait::ExactSizeIterator<op::Sorter<TChainInput, TCompareFn, STABLE>> {
92 static constexpr inline size_t size(const op::Sorter<TChainInput, TCompareFn, STABLE>& self) {
93 return trait::ExactSizeIterator<TChainInput>::size(self.input);
94 }
95 };
96
97 }
98