19#include <fmt/format.h>
36std::string
join(ConcreteDataTypeMatcher
const& matcher, std::string
const& sep =
"_")
42using namespace data_matcher;
74 if (
auto concrete = std::get_if<ConcreteDataMatcher>(&spec.
matcher)) {
75 return join(*concrete,
"/");
76 }
else if (
auto matcher = std::get_if<DataDescriptorMatcher>(&spec.
matcher)) {
77 std::ostringstream ss;
78 ss <<
"<matcher query: " << *matcher <<
">";
86 return std::visit([](
auto const& concrete) {
87 return join(concrete,
"/");
94 return join(matcher,
"/");
97template <HasMatcher T>
102 return fmt::format_to_n(
buffer,
size - 1,
"{:.4}/{:.16}/{}", concrete.origin.str, concrete.description.str, concrete.subSpec);
105 return fmt::format_to_n(
buffer,
size - 1,
"<matcher query: {}/{}>", concrete.origin, concrete.description);
108 std::ostringstream ss;
109 ss <<
"<matcher query: " << matcher <<
">";
110 return fmt::format_to_n(
buffer,
size - 1,
"{}", ss.str());
112 [](...) -> fmt::format_to_n_result<char*> {
throw std::runtime_error(
"Unsupported Input / Output Spec"); }},
123 if (
auto concrete = std::get_if<ConcreteDataMatcher>(&spec.
matcher)) {
124 return join(*concrete,
"_");
125 }
else if (
auto matcher = std::get_if<DataDescriptorMatcher>(&spec.
matcher)) {
126 std::ostringstream ss;
128 std::hash<std::string> hash_fn;
140 return std::visit(
overloaded{[](
auto const& matcher) {
141 return join(matcher,
"_");
148 if (
auto concrete = std::get_if<ConcreteDataMatcher>(&spec.
matcher)) {
149 return std::string(
"/") + join(*concrete,
"/");
157 if (
auto concrete = std::get_if<ConcreteDataMatcher>(&spec.
matcher)) {
158 concrete->subSpec = subSpec;
170 concrete.subSpec = subSpec;
175 dataType.description,
184 using namespace header;
188 if (
auto concrete = std::get_if<ConcreteDataMatcher>(&spec.
matcher)) {
199 using namespace header;
224 return matcher.match(concreteExample, context);
231 if (
auto concrete = std::get_if<ConcreteDataMatcher>(&spec.
matcher)) {
232 return *concrete ==
target;
233 }
else if (
auto matcher = std::get_if<DataDescriptorMatcher>(&spec.
matcher)) {
235 return matcher->match(
target, context);
245 return concrete ==
target;
248 return concrete.origin ==
target.origin &&
249 concrete.description ==
target.description;
256 if (
auto leftConcrete = std::get_if<ConcreteDataMatcher>(&
left.matcher)) {
258 }
else if (
auto rightConcrete = std::get_if<ConcreteDataMatcher>(&
right.matcher)) {
270 return std::visit([&input](
auto const& concrete) ->
bool {
279 return dataType.origin ==
origin;
309 bool hasOrigin =
false;
310 bool hasDescription =
false;
311 bool hasSubSpec =
false;
312 bool hasUniqueOrigin =
false;
313 bool hasUniqueDescription =
false;
314 bool hasUniqueSubSpec =
false;
315 bool hasError =
false;
320 using namespace data_matcher;
326 if (
state.hasError) {
331 if (action.node->getOp() == ops::Or || action.node->getOp() == ops::Xor) {
332 state.hasError =
true;
335 if (action.node->getOp() == ops::Just ||
336 action.node->getOp() == ops::Not) {
350 if (
state.hasOrigin) {
351 state.hasError =
false;
354 state.hasOrigin =
true;
357 [&
state](std::string
const& s) {
358 strncpy(
state.origin.str, s.data(), 4);
359 state.hasUniqueOrigin =
true;
361 [&
state](
auto) {
state.hasUniqueOrigin =
false; }});
364 if (
state.hasDescription) {
365 state.hasError =
true;
368 state.hasDescription =
true;
370 [&
state](std::string
const& s) {
371 strncpy(
state.description.str, s.data(), 16);
372 state.hasUniqueDescription =
true;
374 [&
state](
auto) {
state.hasUniqueDescription =
false; }});
377 if (
state.hasSubSpec) {
378 state.hasError =
true;
381 state.hasSubSpec =
true;
385 state.hasUniqueSubSpec =
true;
387 [&
state](
auto) {
state.hasUniqueSubSpec =
false; }});
401 if (info.hasOrigin && info.hasUniqueOrigin &&
402 info.hasDescription && info.hasDescription &&
403 info.hasSubSpec && info.hasUniqueSubSpec) {
406 throw std::runtime_error(
"Cannot convert " +
binding +
" to ConcreteDataMatcher");
413 return std::get<ConcreteDataMatcher>(spec.
matcher);
420 return std::optional<ConcreteDataMatcher>{concrete};
425 [](
auto const&) {
return std::optional<ConcreteDataMatcher>{std::nullopt}; }},
431 return std::visit([](
auto const& concrete) {
440 [](
auto const& concrete) {
445 if (
state.hasUniqueOrigin &&
state.hasUniqueDescription) {
448 throw runtime_error(
"Could not extract data type from query");
456 [](
auto const& concrete) {
457 return concrete.origin;
461 if (
state.hasUniqueOrigin) {
464 throw runtime_error(
"Could not extract data type from query");
472 [](
auto const& concrete) {
473 return concrete.description;
477 if (
state.hasUniqueDescription) {
478 return state.description;
480 throw runtime_error(
"Could not extract data type from query");
493 if (
state.hasUniqueOrigin &&
state.hasUniqueDescription &&
state.hasUniqueSubSpec) {
495 }
else if (
state.hasUniqueOrigin &&
state.hasUniqueDescription) {
499 throw runtime_error_f(
"Could not extract neither ConcreteDataMatcher nor ConcreteDataTypeMatcher from query %s",
describe(spec).c_str());
507 DataDescriptorMatcher::Op::And,
509 std::make_unique<DataDescriptorMatcher>(
510 DataDescriptorMatcher::Op::And,
512 std::make_unique<DataDescriptorMatcher>(
513 DataDescriptorMatcher::Op::And,
515 std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just,
517 return matchEverything;
522 auto timeDescriptionMatcher = std::make_unique<DataDescriptorMatcher>(
523 DataDescriptorMatcher::Op::And,
525 std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just,
528 DataDescriptorMatcher::Op::And,
530 std::move(timeDescriptionMatcher));
535 char buf[5] = {0, 0, 0, 0, 0};
538 DataDescriptorMatcher::Op::And,
540 std::make_unique<DataDescriptorMatcher>(
541 DataDescriptorMatcher::Op::And,
543 std::make_unique<DataDescriptorMatcher>(
544 DataDescriptorMatcher::Op::And,
546 std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just,
548 return matchOnlyOrigin;
553 char buf[17] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
556 DataDescriptorMatcher::Op::And,
558 std::make_unique<DataDescriptorMatcher>(
559 DataDescriptorMatcher::Op::And,
561 std::make_unique<DataDescriptorMatcher>(
562 DataDescriptorMatcher::Op::And,
564 std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just,
566 return matchOnlyOrigin;
571 using namespace data_matcher;
577 if (
state.hasError) {
582 if (action.node->getOp() == ops::Just) {
584 }
else if (action.node->getOp() == ops::And) {
589 state.hasError =
true;
597 if (
state.hasOrigin) {
598 state.hasUniqueOrigin =
false;
601 state.hasOrigin =
true;
604 [&
state](std::string
const& s) {
605 strncpy(
state.origin.str, s.data(), 4);
606 state.hasUniqueOrigin =
true;
608 [&
state](
auto) {
state.hasUniqueOrigin =
false; }});
611 if (
state.hasDescription) {
612 state.hasUniqueDescription =
false;
615 state.hasDescription =
true;
617 [&
state](std::string
const& s) {
618 strncpy(
state.description.str, s.data(), 16);
619 state.hasUniqueDescription =
true;
621 [&
state](
auto) {
state.hasUniqueDescription =
false; }});
624 if (
state.hasSubSpec) {
625 state.hasUniqueSubSpec =
false;
628 state.hasSubSpec =
true;
632 state.hasUniqueSubSpec =
true;
634 [&
state](
auto) {
state.hasUniqueSubSpec =
false; }});
638 if (
state.hasError ==
false &&
state.hasUniqueOrigin &&
state.hasUniqueDescription &&
state.hasUniqueSubSpec) {
651 concrete.description,
667 std::regex word_regex(
"(\\w+)");
668 auto words = std::sregex_iterator(s.begin(), s.end(), word_regex);
669 if (std::distance(words, std::sregex_iterator()) != 4) {
672 std::array<std::string, 4>
data;
674 for (
auto i = words;
i != std::sregex_iterator(); ++
i) {
688 std::regex word_regex(
"(\\w+)");
689 auto words = std::sregex_iterator(s.begin(), s.end(), word_regex);
690 if (std::distance(words, std::sregex_iterator()) != 3) {
693 std::array<std::string, 3>
data;
695 for (
auto i = words;
i != std::sregex_iterator(); ++
i) {
712 return std::make_optional(concrete.origin);
716 if (
state.hasUniqueOrigin) {
717 return std::make_optional(
state.origin);
718 }
else if (
state.hasError) {
731 return std::make_optional(concrete.description);
735 if (
state.hasUniqueDescription) {
736 return std::make_optional(
state.description);
737 }
else if (
state.hasError) {
738 throw runtime_error(
"Could not extract description from query");
748 [](
ConcreteDataMatcher const& concrete) -> std::optional<header::DataHeader::SubSpecificationType> {
749 return std::make_optional(concrete.subSpec);
761 [](
ConcreteDataMatcher const& concrete) -> std::optional<header::DataHeader::SubSpecificationType> {
762 return std::make_optional(concrete.subSpec);
764 [](
DataDescriptorMatcher const& matcher) -> std::optional<header::DataHeader::SubSpecificationType> {
766 if (
state.hasUniqueSubSpec) {
767 return std::make_optional(
state.subSpec);
768 }
else if (
state.hasError) {
788 return rightInfo.hasUniqueOrigin && rightInfo.origin == leftMatcher.origin &&
789 rightInfo.hasUniqueDescription && rightInfo.description == leftMatcher.description &&
790 rightInfo.hasUniqueSubSpec && rightInfo.subSpec == leftMatcher.subSpec;
794 return (!leftInfo.hasOrigin || (rightInfo.hasOrigin && leftInfo.origin == rightInfo.origin)) &&
795 (!leftInfo.hasDescription || (rightInfo.hasDescription && leftInfo.description == rightInfo.description)) &&
796 (!leftInfo.hasSubSpec || (rightInfo.hasSubSpec && leftInfo.subSpec == rightInfo.subSpec));
805 auto locate = std::find(
list.begin(),
list.end(), input);
806 if (locate !=
list.end()) {
808 auto& entryMetadata = locate->metadata;
809 entryMetadata.insert(entryMetadata.end(), input.metadata.begin(), input.metadata.end());
811 auto new_end = std::unique(entryMetadata.begin(), entryMetadata.end(), [](
ConfigParamSpec const&
a,
ConfigParamSpec const&
b) { return a.name == b.name; });
812 entryMetadata.erase(new_end, entryMetadata.end());
815 list.emplace_back(std::move(input));
821 auto locate = std::find(
list.begin(),
list.end(), spec);
822 if (locate !=
list.end()) {
824 auto& entryMetadata = locate->metadata;
825 entryMetadata.insert(entryMetadata.end(), spec.metadata.begin(), spec.metadata.end());
827 auto new_end = std::unique(entryMetadata.begin(), entryMetadata.end(), [](
ConfigParamSpec const&
a,
ConfigParamSpec const&
b) { return a.name == b.name; });
828 entryMetadata.erase(new_end, entryMetadata.end());
831 list.emplace_back(std::move(spec));
header::DataOrigin origin
header::DataDescription description
Something which can be matched against a header::DataDescription.
Something which can be matched against a header::DataOrigin.
Matcher on actual time, as reported in the DataProcessingHeader.
Something which can be matched against a header::SubSpecificationType.
GLdouble GLdouble GLdouble GLdouble top
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
GLenum GLuint GLenum GLsizei const GLchar * buf
constexpr o2::header::DataDescription gDataDescriptionInvalid
constexpr o2::header::DataOrigin gDataOriginInvalid
constexpr framework::ConcreteDataMatcher matcher()
Defining PrimaryVertex explicitly as messageable.
RuntimeErrorRef runtime_error(const char *)
MatcherInfo extractMatcherInfo(DataDescriptorMatcher const &top)
RuntimeErrorRef runtime_error_f(const char *,...)
constexpr auto join(Ts const &... t)
std::string to_string(gsl::span< T, Size > span)
header::DataDescription description
header::DataHeader::SubSpecificationType subSpec
header::DataOrigin origin
header::DataOrigin origin
header::DataDescription description
static std::optional< ConcreteDataMatcher > asOptionalConcreteDataMatcher(OutputSpec const &spec)
static bool partialMatch(InputSpec const &spec, o2::header::DataOrigin const &origin)
static InputSpec fromMetadataString(std::string s)
Create an InputSpec from metadata string.
static std::string describe(InputSpec const &spec)
static void updateOutputList(std::vector< OutputSpec > &list, OutputSpec &&input)
Updates list of OutputSpecs by merging metadata (or adding output).
static ConcreteDataTypeMatcher asConcreteDataTypeMatcher(OutputSpec const &spec)
static bool validate(InputSpec const &input)
static ConcreteDataMatcher asConcreteDataMatcher(InputSpec const &input)
static std::optional< header::DataHeader::SubSpecificationType > getOptionalSubSpec(OutputSpec const &spec)
Get the subspec, if available.
static InputSpec matchingInput(OutputSpec const &spec)
static data_matcher::DataDescriptorMatcher dataDescriptorMatcherFrom(ConcreteDataMatcher const &concrete)
Build a DataDescriptMatcher which does not care about the subSpec.
static ConcreteDataMatcher fromString(std::string s)
Create a concrete data matcher from serialized string.
static std::optional< framework::ConcreteDataMatcher > optionalConcreteDataMatcherFrom(data_matcher::DataDescriptorMatcher const &matcher)
static std::string restEndpoint(InputSpec const &spec)
static std::optional< header::DataDescription > getOptionalDescription(InputSpec const &spec)
Get the description, if available.
static std::optional< header::DataOrigin > getOptionalOrigin(InputSpec const &spec)
Get the origin, if available.
static void updateMatchingSubspec(InputSpec &in, header::DataHeader::SubSpecificationType subSpec)
static bool includes(const InputSpec &left, const InputSpec &right)
Checks if left includes right (or is equal to)
static header::DataOrigin asConcreteOrigin(InputSpec const &spec)
static void updateInputList(std::vector< InputSpec > &list, InputSpec &&input)
Updates list of InputSpecs by merging metadata.
static header::DataDescription asConcreteDataDescription(InputSpec const &spec)
static std::string label(InputSpec const &spec)
static OutputSpec asOutputSpec(InputSpec const &spec)
static bool match(InputSpec const &spec, ConcreteDataMatcher const &target)
std::variant< ConcreteDataMatcher, ConcreteDataTypeMatcher > matcher
A typesafe reference to an element of the context.
static void walk(DataDescriptorMatcher const &top, EDGEWALKER edgeWalker, LEAFWALKER leafWalker)
From https://en.cppreference.com/w/cpp/utility/variant/visit.