Skip to content

Commit fa2e0aa

Browse files
authored
DPL: add generic walker for DataDescriptorMatcher (#2220)
This introduces an helper which is able to do a deep first walk of a DataDescriptorMatcher tree. This also reimplements the operator<< for a DataDescriptorTree using such a walker. This will also allow us to customise the display of the matcher, or to properly serialise it using RapidJSON.
1 parent 0af8b08 commit fa2e0aa

2 files changed

Lines changed: 137 additions & 18 deletions

File tree

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// Copyright CERN and copyright holders of ALICE O2. This software is
2+
// distributed under the terms of the GNU General Public License v3 (GPL
3+
// Version 3), copied verbatim in the file "COPYING".
4+
//
5+
// See http://alice-o2.web.cern.ch/license for full licensing information.
6+
//
7+
// In applying this license CERN does not waive the privileges and immunities
8+
// granted to it by virtue of its status as an Intergovernmental Organization
9+
// or submit itself to any jurisdiction.
10+
#ifndef O2_FRAMEWORK_DATAMATCHERWALKER_H_
11+
#define O2_FRAMEWORK_DATAMATCHERWALKER_H_
12+
13+
#include "Framework/DataDescriptorMatcher.h"
14+
#include "Framework/VariantHelpers.h"
15+
16+
namespace o2::framework::data_matcher
17+
{
18+
19+
struct EdgeActions {
20+
struct EnterNode {
21+
DataDescriptorMatcher const* node;
22+
};
23+
struct ExitNode {
24+
DataDescriptorMatcher const* node;
25+
};
26+
struct EnterLeft {
27+
};
28+
struct ExitLeft {
29+
};
30+
struct EnterRight {
31+
};
32+
struct ExitRight {
33+
};
34+
};
35+
36+
enum ChildAction : int {
37+
VisitNone = 0,
38+
VisitLeft = 1,
39+
VisitRight = 2,
40+
VisitBoth = 3
41+
};
42+
43+
using EdgeAction = std::variant<EdgeActions::EnterNode, EdgeActions::ExitNode>;
44+
45+
/// Helper class which holds methods which are useful
46+
/// to navigate a DataDescriptorMatcher hierarchy
47+
struct DataMatcherWalker {
48+
49+
// Deep-first algorithm
50+
// @a top is the toplevel node in the tree.
51+
// @a edgeWalker is a visitor for an EdgeAction
52+
// @a leafWalker is a visitor for the DataDescriptorMatcher node
53+
template <typename EDGEWALKER, typename LEAFWALKER>
54+
static void walk(DataDescriptorMatcher const& top,
55+
EDGEWALKER edgeWalker,
56+
LEAFWALKER leafWalker)
57+
{
58+
std::vector<EdgeAction> matchers;
59+
matchers.push_back(EdgeActions::EnterNode{ &top });
60+
61+
while (matchers.empty() == false) {
62+
EdgeAction action = matchers.back();
63+
matchers.pop_back();
64+
ChildAction childrenVisitor = std::visit(overloaded{
65+
[&matchers, &edgeWalker](EdgeActions::EnterNode action) {
66+
matchers.push_back(EdgeActions::ExitNode{ action.node });
67+
return edgeWalker(action);
68+
},
69+
[&edgeWalker](EdgeActions::ExitNode action) {
70+
edgeWalker(action);
71+
return ChildAction::VisitNone;
72+
} },
73+
action);
74+
75+
if (childrenVisitor & ChildAction::VisitRight) {
76+
auto node = std::visit([](auto action) { return action.node; }, action);
77+
78+
std::visit(overloaded{
79+
[&matchers](std::unique_ptr<DataDescriptorMatcher> const& matcher) {
80+
matchers.push_back(EdgeActions::EnterNode{ matcher.get() });
81+
},
82+
[edgeWalker, leafWalker](auto const& leaf) {
83+
edgeWalker(EdgeActions::EnterRight{});
84+
leafWalker(leaf);
85+
edgeWalker(EdgeActions::ExitRight{});
86+
} },
87+
node->getRight());
88+
}
89+
90+
if (childrenVisitor & ChildAction::VisitLeft) {
91+
auto node = std::visit([](auto action) { return action.node; }, action);
92+
93+
std::visit(overloaded{
94+
[&matchers](std::unique_ptr<DataDescriptorMatcher> const& matcher) {
95+
matchers.push_back(EdgeActions::EnterNode{ matcher.get() });
96+
},
97+
[edgeWalker, leafWalker](auto const& leaf) {
98+
edgeWalker(EdgeActions::EnterLeft{});
99+
leafWalker(leaf);
100+
edgeWalker(EdgeActions::ExitLeft{});
101+
} },
102+
node->getLeft());
103+
}
104+
}
105+
}
106+
};
107+
108+
} // namespace o2::framework::data_matcher
109+
110+
#endif // O2_FRAMEWORK_DATAMATCHERWALKER_H_

Framework/Core/src/DataDescriptorMatcher.cxx

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010

1111
#include "Framework/CompilerBuiltins.h"
1212
#include "Framework/DataDescriptorMatcher.h"
13+
#include "Framework/DataMatcherWalker.h"
1314
#include "Framework/DataProcessingHeader.h"
15+
#include "Framework/VariantHelpers.h"
1416
#include <iostream>
1517

1618
namespace o2
@@ -413,25 +415,32 @@ bool DataDescriptorMatcher::operator==(DataDescriptorMatcher const& other) const
413415

414416
std::ostream& operator<<(std::ostream& os, DataDescriptorMatcher const& matcher)
415417
{
416-
auto printer = [&os](decltype(&matcher.mLeft) v) -> void {
417-
if (auto left = std::get_if<std::unique_ptr<DataDescriptorMatcher>>(v)) {
418-
os << **left;
419-
} else if (auto originMatcher = std::get_if<OriginValueMatcher>(v)) {
420-
os << "origin:" << *originMatcher;
421-
} else if (auto descriptionMatcher = std::get_if<DescriptionValueMatcher>(v)) {
422-
os << "description:" << *descriptionMatcher;
423-
} else if (auto subSpecMatcher = std::get_if<SubSpecificationTypeValueMatcher>(v)) {
424-
os << "subSpec:" << *subSpecMatcher;
425-
} else if (auto startTimeMatcher = std::get_if<StartTimeValueMatcher>(v)) {
426-
os << "startTime:" << *startTimeMatcher;
427-
}
418+
auto edgeWalker = overloaded{
419+
[&os](EdgeActions::EnterNode action) {
420+
os << "(" << action.node->mOp;
421+
if (action.node->mOp == DataDescriptorMatcher::Op::Just) {
422+
return ChildAction::VisitLeft;
423+
}
424+
return ChildAction::VisitBoth;
425+
},
426+
[&os](EdgeActions::EnterLeft) { os << " "; },
427+
[&os](EdgeActions::ExitLeft) { os << " "; },
428+
[&os](EdgeActions::EnterRight) { os << " "; },
429+
[&os](EdgeActions::ExitRight) { os << " "; },
430+
[&os](EdgeActions::ExitNode) { os << ")"; },
431+
[&os](auto) {}
428432
};
429-
430-
os << "(" << matcher.mOp << " ";
431-
printer(&matcher.mLeft);
432-
os << " ";
433-
printer(&matcher.mRight);
434-
os << ")";
433+
auto leafWalker = overloaded{
434+
[&os](OriginValueMatcher const& origin) { os << "origin:" << origin; },
435+
[&os](DescriptionValueMatcher const& description) { os << "description:" << description; },
436+
[&os](SubSpecificationTypeValueMatcher const& subSpec) { os << "subSpec:" << subSpec; },
437+
[&os](StartTimeValueMatcher const& startTime) { os << "startTime:" << startTime; },
438+
[&os](ConstantValueMatcher const& constant) {},
439+
[&os](auto t) { os << "not implemented " << typeid(decltype(t)).name(); }
440+
};
441+
DataMatcherWalker::walk(matcher,
442+
edgeWalker,
443+
leafWalker);
435444

436445
return os;
437446
}

0 commit comments

Comments
 (0)