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,
188 if (
auto concrete = std::get_if<ConcreteDataMatcher>(&spec.
matcher)) {
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
std::vector< std::string > header
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error s
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 ITS Vertex 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.