19#include <fmt/format.h>
36std::string
join(ConcreteDataTypeMatcher
const& matcher, std::string
const& sep =
"_")
38 return matcher.origin.as<std::string>() + sep + matcher.description.as<std::string>();
42using namespace data_matcher;
61 return dataType.
origin == origin &&
63 matcher.subSpec == subSpec;
66 return dataType.
origin == origin &&
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,
"/");
92template <HasMatcher T>
97 return fmt::format_to_n(
buffer,
size - 1,
"{:.4}/{:.16}/{}", concrete.origin.str, concrete.description.str, concrete.subSpec);
100 return fmt::format_to_n(
buffer,
size - 1,
"<matcher query: {}/{}>", concrete.origin, concrete.description);
103 std::ostringstream ss;
104 ss <<
"<matcher query: " << matcher <<
">";
105 return fmt::format_to_n(
buffer,
size - 1,
"{}", ss.str());
107 [](...) -> fmt::format_to_n_result<char*> {
throw std::runtime_error(
"Unsupported Input / Output Spec"); }},
118 if (
auto concrete = std::get_if<ConcreteDataMatcher>(&spec.
matcher)) {
119 return join(*concrete,
"_");
120 }
else if (
auto matcher = std::get_if<DataDescriptorMatcher>(&spec.
matcher)) {
121 std::ostringstream ss;
123 std::hash<std::string> hash_fn;
135 return std::visit(
overloaded{[](
auto const& matcher) {
136 return join(matcher,
"_");
143 if (
auto concrete = std::get_if<ConcreteDataMatcher>(&spec.
matcher)) {
144 return std::string(
"/") + join(*concrete,
"/");
152 if (
auto concrete = std::get_if<ConcreteDataMatcher>(&spec.
matcher)) {
153 concrete->subSpec = subSpec;
165 concrete.subSpec = subSpec;
170 dataType.description,
179 using namespace header;
183 if (
auto concrete = std::get_if<ConcreteDataMatcher>(&spec.
matcher)) {
194 using namespace header;
219 return matcher.match(concreteExample, context);
226 if (
auto concrete = std::get_if<ConcreteDataMatcher>(&spec.
matcher)) {
227 return *concrete ==
target;
228 }
else if (
auto matcher = std::get_if<DataDescriptorMatcher>(&spec.
matcher)) {
230 return matcher->match(
target, context);
240 return concrete ==
target;
243 return concrete.origin ==
target.origin &&
244 concrete.description ==
target.description;
251 if (
auto leftConcrete = std::get_if<ConcreteDataMatcher>(&
left.matcher)) {
253 }
else if (
auto rightConcrete = std::get_if<ConcreteDataMatcher>(&
right.matcher)) {
265 return std::visit([&input](
auto const& concrete) ->
bool {
274 return dataType.origin == origin;
304 bool hasOrigin =
false;
305 bool hasDescription =
false;
306 bool hasSubSpec =
false;
307 bool hasUniqueOrigin =
false;
308 bool hasUniqueDescription =
false;
309 bool hasUniqueSubSpec =
false;
310 bool hasError =
false;
315 using namespace data_matcher;
321 if (
state.hasError) {
326 if (action.node->getOp() == ops::Or || action.node->getOp() == ops::Xor) {
327 state.hasError =
true;
330 if (action.node->getOp() == ops::Just ||
331 action.node->getOp() == ops::Not) {
345 if (
state.hasOrigin) {
346 state.hasError =
false;
349 state.hasOrigin =
true;
352 [&
state](std::string
const& s) {
353 strncpy(
state.origin.str, s.data(), 4);
354 state.hasUniqueOrigin =
true;
356 [&
state](
auto) {
state.hasUniqueOrigin =
false; }});
359 if (
state.hasDescription) {
360 state.hasError =
true;
363 state.hasDescription =
true;
365 [&
state](std::string
const& s) {
366 strncpy(
state.description.str, s.data(), 16);
367 state.hasUniqueDescription =
true;
369 [&
state](
auto) {
state.hasUniqueDescription =
false; }});
372 if (
state.hasSubSpec) {
373 state.hasError =
true;
376 state.hasSubSpec =
true;
380 state.hasUniqueSubSpec =
true;
382 [&
state](
auto) {
state.hasUniqueSubSpec =
false; }});
396 if (info.hasOrigin && info.hasUniqueOrigin &&
397 info.hasDescription && info.hasDescription &&
398 info.hasSubSpec && info.hasUniqueSubSpec) {
401 throw std::runtime_error(
"Cannot convert " + binding +
" to ConcreteDataMatcher");
408 return std::get<ConcreteDataMatcher>(spec.
matcher);
415 return std::optional<ConcreteDataMatcher>{concrete};
420 [](
auto const&) {
return std::optional<ConcreteDataMatcher>{std::nullopt}; }},
426 return std::visit([](
auto const& concrete) {
435 [](
auto const& concrete) {
440 if (
state.hasUniqueOrigin &&
state.hasUniqueDescription) {
443 throw runtime_error(
"Could not extract data type from query");
451 [](
auto const& concrete) {
452 return concrete.origin;
456 if (
state.hasUniqueOrigin) {
459 throw runtime_error(
"Could not extract data type from query");
467 [](
auto const& concrete) {
468 return concrete.description;
472 if (
state.hasUniqueDescription) {
473 return state.description;
475 throw runtime_error(
"Could not extract data type from query");
488 if (
state.hasUniqueOrigin &&
state.hasUniqueDescription &&
state.hasUniqueSubSpec) {
490 }
else if (
state.hasUniqueOrigin &&
state.hasUniqueDescription) {
494 throw runtime_error_f(
"Could not extract neither ConcreteDataMatcher nor ConcreteDataTypeMatcher from query %s",
describe(spec).c_str());
502 DataDescriptorMatcher::Op::And,
504 std::make_unique<DataDescriptorMatcher>(
505 DataDescriptorMatcher::Op::And,
507 std::make_unique<DataDescriptorMatcher>(
508 DataDescriptorMatcher::Op::And,
510 std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just,
512 return matchEverything;
517 auto timeDescriptionMatcher = std::make_unique<DataDescriptorMatcher>(
518 DataDescriptorMatcher::Op::And,
520 std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just,
523 DataDescriptorMatcher::Op::And,
525 std::move(timeDescriptionMatcher));
530 char buf[5] = {0, 0, 0, 0, 0};
531 strncpy(
buf, origin.
str, 4);
533 DataDescriptorMatcher::Op::And,
535 std::make_unique<DataDescriptorMatcher>(
536 DataDescriptorMatcher::Op::And,
538 std::make_unique<DataDescriptorMatcher>(
539 DataDescriptorMatcher::Op::And,
541 std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just,
543 return matchOnlyOrigin;
548 char buf[17] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
549 strncpy(
buf, description.
str, 16);
551 DataDescriptorMatcher::Op::And,
553 std::make_unique<DataDescriptorMatcher>(
554 DataDescriptorMatcher::Op::And,
556 std::make_unique<DataDescriptorMatcher>(
557 DataDescriptorMatcher::Op::And,
559 std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just,
561 return matchOnlyOrigin;
566 using namespace data_matcher;
572 if (
state.hasError) {
577 if (action.node->getOp() == ops::Just) {
579 }
else if (action.node->getOp() == ops::And) {
584 state.hasError =
true;
592 if (
state.hasOrigin) {
593 state.hasUniqueOrigin =
false;
596 state.hasOrigin =
true;
599 [&
state](std::string
const& s) {
600 strncpy(
state.origin.str, s.data(), 4);
601 state.hasUniqueOrigin =
true;
603 [&
state](
auto) {
state.hasUniqueOrigin =
false; }});
606 if (
state.hasDescription) {
607 state.hasUniqueDescription =
false;
610 state.hasDescription =
true;
612 [&
state](std::string
const& s) {
613 strncpy(
state.description.str, s.data(), 16);
614 state.hasUniqueDescription =
true;
616 [&
state](
auto) {
state.hasUniqueDescription =
false; }});
619 if (
state.hasSubSpec) {
620 state.hasUniqueSubSpec =
false;
623 state.hasSubSpec =
true;
627 state.hasUniqueSubSpec =
true;
629 [&
state](
auto) {
state.hasUniqueSubSpec =
false; }});
633 if (
state.hasError ==
false &&
state.hasUniqueOrigin &&
state.hasUniqueDescription &&
state.hasUniqueSubSpec) {
646 concrete.description,
662 std::regex word_regex(
"(\\w+)");
663 auto words = std::sregex_iterator(s.begin(), s.end(), word_regex);
664 if (std::distance(words, std::sregex_iterator()) != 4) {
667 std::vector<std::string>
data;
668 for (
auto i = words;
i != std::sregex_iterator(); ++
i) {
669 data.emplace_back(
i->str());
672 char description[16];
673 std::memcpy(&origin,
data[1].c_str(), 4);
674 std::memcpy(&description,
data[2].c_str(), 16);
684 return std::make_optional(concrete.origin);
688 if (
state.hasUniqueOrigin) {
689 return std::make_optional(
state.origin);
690 }
else if (
state.hasError) {
703 return std::make_optional(concrete.description);
707 if (
state.hasUniqueDescription) {
708 return std::make_optional(
state.description);
709 }
else if (
state.hasError) {
710 throw runtime_error(
"Could not extract description from query");
720 [](
ConcreteDataMatcher const& concrete) -> std::optional<header::DataHeader::SubSpecificationType> {
721 return std::make_optional(concrete.subSpec);
733 [](
ConcreteDataMatcher const& concrete) -> std::optional<header::DataHeader::SubSpecificationType> {
734 return std::make_optional(concrete.subSpec);
736 [](
DataDescriptorMatcher const& matcher) -> std::optional<header::DataHeader::SubSpecificationType> {
738 if (
state.hasUniqueSubSpec) {
739 return std::make_optional(
state.subSpec);
740 }
else if (
state.hasError) {
760 return rightInfo.hasUniqueOrigin && rightInfo.origin == leftMatcher.origin &&
761 rightInfo.hasUniqueDescription && rightInfo.description == leftMatcher.description &&
762 rightInfo.hasUniqueSubSpec && rightInfo.subSpec == leftMatcher.subSpec;
766 return (!leftInfo.hasOrigin || (rightInfo.hasOrigin && leftInfo.origin == rightInfo.origin)) &&
767 (!leftInfo.hasDescription || (rightInfo.hasDescription && leftInfo.description == rightInfo.description)) &&
768 (!leftInfo.hasSubSpec || (rightInfo.hasSubSpec && leftInfo.subSpec == rightInfo.subSpec));
777 auto locate = std::find(
list.begin(),
list.end(), input);
778 if (locate !=
list.end()) {
780 auto& entryMetadata = locate->metadata;
781 entryMetadata.insert(entryMetadata.end(), input.metadata.begin(), input.metadata.end());
783 auto new_end = std::unique(entryMetadata.begin(), entryMetadata.end(), [](
ConfigParamSpec const&
a,
ConfigParamSpec const&
b) { return a.name == b.name; });
784 entryMetadata.erase(new_end, entryMetadata.end());
787 list.emplace_back(std::move(input));
793 auto locate = std::find(
list.begin(),
list.end(), spec);
794 if (locate !=
list.end()) {
796 auto& entryMetadata = locate->metadata;
797 entryMetadata.insert(entryMetadata.end(), spec.metadata.begin(), spec.metadata.end());
799 auto new_end = std::unique(entryMetadata.begin(), entryMetadata.end(), [](
ConfigParamSpec const&
a,
ConfigParamSpec const&
b) { return a.name == b.name; });
800 entryMetadata.erase(new_end, entryMetadata.end());
803 list.emplace_back(std::move(spec));
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
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 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.