Skip to content

Commit a604541

Browse files
author
Michal Tichák
committed
iterators in the middle of work
1 parent c77cc97 commit a604541

File tree

2 files changed

+115
-2
lines changed

2 files changed

+115
-2
lines changed

Framework/include/QualityControl/Data.h

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,14 @@
1414
/// \author Michal Tichak
1515
///
1616

17+
#ifndef QC_CORE_DATA_H
18+
#define QC_CORE_DATA_H
19+
1720
#include <any>
1821
#include <concepts>
22+
#include <functional>
1923
#include <iostream>
24+
#include <iterator>
2025
#include <map>
2126
#include <memory>
2227
#include <optional>
@@ -31,7 +36,77 @@ class MonitorObject;
3136

3237
class Data
3338
{
39+
// change this for boost::flat_map? or do a magic and split by different keys?
40+
using InternalContainer = std::map<std::string, std::any, std::less<>>;
41+
using InternalContainerConstIterator = InternalContainer::const_iterator;
42+
3443
public:
44+
template <typename T>
45+
class Iterator
46+
{
47+
public:
48+
using value_type = std::pair<std::reference_wrapper<const std::string>, std::reference_wrapper<const T>>;
49+
using difference_type = std::ptrdiff_t;
50+
using iterator_category = std::forward_iterator_tag;
51+
using reference = const value_type&;
52+
using pointer = const value_type*;
53+
54+
Iterator() = default;
55+
Iterator(InternalContainerConstIterator it, InternalContainerConstIterator end)
56+
: mIt{ it }, mEnd{ end }, val{ std::nullopt }
57+
{
58+
seek_next_valid(mIt);
59+
}
60+
61+
reference operator*() const
62+
{
63+
return val.value();
64+
}
65+
66+
pointer operator->() const
67+
{
68+
return &val.value();
69+
}
70+
71+
Iterator& operator++()
72+
{
73+
// can this be optimised out?
74+
if (mIt != mEnd) {
75+
seek_next_valid(++mIt);
76+
}
77+
return *this;
78+
}
79+
80+
Iterator operator++(int)
81+
{
82+
auto tmp = *this;
83+
++*this;
84+
return tmp;
85+
}
86+
87+
bool operator==(const Iterator& other) const
88+
{
89+
return mIt == other.mIt;
90+
}
91+
92+
private:
93+
InternalContainerConstIterator mIt;
94+
InternalContainerConstIterator mEnd;
95+
std::optional<value_type> val;
96+
97+
void seek_next_valid(InternalContainerConstIterator startingIt)
98+
{
99+
for (auto it = startingIt; it != mEnd; ++it) {
100+
if (auto* casted = std::any_cast<T>(&it->second); casted != nullptr) {
101+
val.emplace(it->first, *casted);
102+
break;
103+
}
104+
}
105+
}
106+
};
107+
108+
static_assert(std::forward_iterator<Iterator<int>>);
109+
35110
Data() = default;
36111
Data(const std::map<std::string, std::shared_ptr<MonitorObject>>& moMap);
37112

@@ -49,7 +124,6 @@ class Data
49124
template <typename StoreType>
50125
void insert(std::string_view key, const StoreType& value)
51126
{
52-
// std::cout << "inserting value: " << value << ", of type: " << typeid(StoreType).name() << "\n";
53127
mObjects.insert({ std::string{ key }, value });
54128
}
55129

@@ -79,8 +153,22 @@ class Data
79153
return result;
80154
}
81155

156+
template <typename T>
157+
Iterator<T> begin()
158+
{
159+
return { mObjects.begin(), mObjects.end() };
160+
}
161+
162+
template <typename T>
163+
Iterator<T> end()
164+
{
165+
return { mObjects.end(), mObjects.end() };
166+
}
167+
82168
private:
83-
std::map<std::string, std::any, std::less<>> mObjects;
169+
InternalContainer mObjects;
84170
};
85171

86172
} // namespace o2::quality_control::core
173+
174+
#endif

Framework/test/testData.cxx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,28 @@ TEST_CASE("Data getAllOfTypeIf", "[Data]")
7777
auto filtered = data.getAllOfTypeIf<named<int>>([](const auto& val) { return val.name == "1"; });
7878
REQUIRE(filtered.size() == 1);
7979
}
80+
81+
TEST_CASE("Data iterator", "[Data]")
82+
{
83+
Data data;
84+
data.insert("testint1", 1);
85+
data.insert("teststr1", std::string{ "1" });
86+
data.insert("testint2", 2);
87+
data.insert("teststr2", std::string{ "2" });
88+
89+
auto intIt = data.begin<int>();
90+
REQUIRE(intIt != data.end<int>());
91+
REQUIRE(intIt->first.get() == "testint1");
92+
REQUIRE(intIt->second.get() == 1);
93+
intIt++;
94+
REQUIRE(intIt->first.get() == "testint2");
95+
REQUIRE(intIt->second.get() == 2);
96+
97+
auto strIt = data.begin<std::string>();
98+
REQUIRE(strIt != data.end<std::string>());
99+
REQUIRE(strIt->first.get() == "teststr1");
100+
REQUIRE(strIt->second.get() == "1");
101+
++strIt;
102+
REQUIRE(strIt->first.get() == "teststr2");
103+
REQUIRE(strIt->second.get() == "2");
104+
}

0 commit comments

Comments
 (0)