diff --git a/Framework/Core/include/Framework/DataMatcherWalker.h b/Framework/Core/include/Framework/DataMatcherWalker.h new file mode 100644 index 0000000000000..28d4a23616713 --- /dev/null +++ b/Framework/Core/include/Framework/DataMatcherWalker.h @@ -0,0 +1,110 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#ifndef O2_FRAMEWORK_DATAMATCHERWALKER_H_ +#define O2_FRAMEWORK_DATAMATCHERWALKER_H_ + +#include "Framework/DataDescriptorMatcher.h" +#include "Framework/VariantHelpers.h" + +namespace o2::framework::data_matcher +{ + +struct EdgeActions { + struct EnterNode { + DataDescriptorMatcher const* node; + }; + struct ExitNode { + DataDescriptorMatcher const* node; + }; + struct EnterLeft { + }; + struct ExitLeft { + }; + struct EnterRight { + }; + struct ExitRight { + }; +}; + +enum ChildAction : int { + VisitNone = 0, + VisitLeft = 1, + VisitRight = 2, + VisitBoth = 3 +}; + +using EdgeAction = std::variant; + +/// Helper class which holds methods which are useful +/// to navigate a DataDescriptorMatcher hierarchy +struct DataMatcherWalker { + + // Deep-first algorithm + // @a top is the toplevel node in the tree. + // @a edgeWalker is a visitor for an EdgeAction + // @a leafWalker is a visitor for the DataDescriptorMatcher node + template + static void walk(DataDescriptorMatcher const& top, + EDGEWALKER edgeWalker, + LEAFWALKER leafWalker) + { + std::vector matchers; + matchers.push_back(EdgeActions::EnterNode{ &top }); + + while (matchers.empty() == false) { + EdgeAction action = matchers.back(); + matchers.pop_back(); + ChildAction childrenVisitor = std::visit(overloaded{ + [&matchers, &edgeWalker](EdgeActions::EnterNode action) { + matchers.push_back(EdgeActions::ExitNode{ action.node }); + return edgeWalker(action); + }, + [&edgeWalker](EdgeActions::ExitNode action) { + edgeWalker(action); + return ChildAction::VisitNone; + } }, + action); + + if (childrenVisitor & ChildAction::VisitRight) { + auto node = std::visit([](auto action) { return action.node; }, action); + + std::visit(overloaded{ + [&matchers](std::unique_ptr const& matcher) { + matchers.push_back(EdgeActions::EnterNode{ matcher.get() }); + }, + [edgeWalker, leafWalker](auto const& leaf) { + edgeWalker(EdgeActions::EnterRight{}); + leafWalker(leaf); + edgeWalker(EdgeActions::ExitRight{}); + } }, + node->getRight()); + } + + if (childrenVisitor & ChildAction::VisitLeft) { + auto node = std::visit([](auto action) { return action.node; }, action); + + std::visit(overloaded{ + [&matchers](std::unique_ptr const& matcher) { + matchers.push_back(EdgeActions::EnterNode{ matcher.get() }); + }, + [edgeWalker, leafWalker](auto const& leaf) { + edgeWalker(EdgeActions::EnterLeft{}); + leafWalker(leaf); + edgeWalker(EdgeActions::ExitLeft{}); + } }, + node->getLeft()); + } + } + } +}; + +} // namespace o2::framework::data_matcher + +#endif // O2_FRAMEWORK_DATAMATCHERWALKER_H_ diff --git a/Framework/Core/src/DataDescriptorMatcher.cxx b/Framework/Core/src/DataDescriptorMatcher.cxx index 67faddd6cfb27..6840df8e8279b 100644 --- a/Framework/Core/src/DataDescriptorMatcher.cxx +++ b/Framework/Core/src/DataDescriptorMatcher.cxx @@ -10,7 +10,9 @@ #include "Framework/CompilerBuiltins.h" #include "Framework/DataDescriptorMatcher.h" +#include "Framework/DataMatcherWalker.h" #include "Framework/DataProcessingHeader.h" +#include "Framework/VariantHelpers.h" #include namespace o2 @@ -413,25 +415,32 @@ bool DataDescriptorMatcher::operator==(DataDescriptorMatcher const& other) const std::ostream& operator<<(std::ostream& os, DataDescriptorMatcher const& matcher) { - auto printer = [&os](decltype(&matcher.mLeft) v) -> void { - if (auto left = std::get_if>(v)) { - os << **left; - } else if (auto originMatcher = std::get_if(v)) { - os << "origin:" << *originMatcher; - } else if (auto descriptionMatcher = std::get_if(v)) { - os << "description:" << *descriptionMatcher; - } else if (auto subSpecMatcher = std::get_if(v)) { - os << "subSpec:" << *subSpecMatcher; - } else if (auto startTimeMatcher = std::get_if(v)) { - os << "startTime:" << *startTimeMatcher; - } + auto edgeWalker = overloaded{ + [&os](EdgeActions::EnterNode action) { + os << "(" << action.node->mOp; + if (action.node->mOp == DataDescriptorMatcher::Op::Just) { + return ChildAction::VisitLeft; + } + return ChildAction::VisitBoth; + }, + [&os](EdgeActions::EnterLeft) { os << " "; }, + [&os](EdgeActions::ExitLeft) { os << " "; }, + [&os](EdgeActions::EnterRight) { os << " "; }, + [&os](EdgeActions::ExitRight) { os << " "; }, + [&os](EdgeActions::ExitNode) { os << ")"; }, + [&os](auto) {} }; - - os << "(" << matcher.mOp << " "; - printer(&matcher.mLeft); - os << " "; - printer(&matcher.mRight); - os << ")"; + auto leafWalker = overloaded{ + [&os](OriginValueMatcher const& origin) { os << "origin:" << origin; }, + [&os](DescriptionValueMatcher const& description) { os << "description:" << description; }, + [&os](SubSpecificationTypeValueMatcher const& subSpec) { os << "subSpec:" << subSpec; }, + [&os](StartTimeValueMatcher const& startTime) { os << "startTime:" << startTime; }, + [&os](ConstantValueMatcher const& constant) {}, + [&os](auto t) { os << "not implemented " << typeid(decltype(t)).name(); } + }; + DataMatcherWalker::walk(matcher, + edgeWalker, + leafWalker); return os; }