18#include <fmt/format.h>
34std::string
join(ConcreteDataTypeMatcher
const& matcher, std::string
const& sep =
"_")
36 return matcher.origin.as<std::string>() + sep + matcher.description.as<std::string>();
40using namespace data_matcher;
59 return dataType.
origin == origin &&
61 matcher.subSpec == subSpec;
64 return dataType.
origin == origin &&
72 if (
auto concrete = std::get_if<ConcreteDataMatcher>(&spec.
matcher)) {
73 return join(*concrete,
"/");
74 }
else if (
auto matcher = std::get_if<DataDescriptorMatcher>(&spec.
matcher)) {
75 std::ostringstream ss;
76 ss <<
"<matcher query: " << *matcher <<
">";
84 return std::visit([](
auto const& concrete) {
85 return join(concrete,
"/");
92 if (
auto concrete = std::get_if<ConcreteDataMatcher>(&spec.
matcher)) {
97 snprintf(
buffer,
size,
"%s/%s/%" PRIu32, (strncpy(origin, concrete->origin.
str, 4), origin),
98 (strncpy(description, concrete->description.str, 16), description), concrete->subSpec);
99 }
else if (
auto matcher = std::get_if<DataDescriptorMatcher>(&spec.
matcher)) {
100 std::ostringstream ss;
101 ss <<
"<matcher query: " << *matcher <<
">";
110 if (
auto concrete = std::get_if<ConcreteDataMatcher>(&spec.
matcher)) {
113 char description[17];
115 snprintf(
buffer,
size,
"%s/%s/%" PRIu32, (strncpy(origin, concrete->origin.
str, 4), origin),
116 (strncpy(description, concrete->description.str, 16), description), concrete->subSpec);
117 }
else if (
auto concrete = std::get_if<ConcreteDataTypeMatcher>(&spec.
matcher)) {
118 fmt::format_to(
buffer,
"<matcher query: {}/{}>", concrete->origin, concrete->description);
126 if (
auto concrete = std::get_if<ConcreteDataMatcher>(&spec.
matcher)) {
127 return join(*concrete,
"_");
128 }
else if (
auto matcher = std::get_if<DataDescriptorMatcher>(&spec.
matcher)) {
129 std::ostringstream ss;
131 std::hash<std::string> hash_fn;
143 return std::visit(
overloaded{[](
auto const& matcher) {
144 return join(matcher,
"_");
151 if (
auto concrete = std::get_if<ConcreteDataMatcher>(&spec.
matcher)) {
152 return std::string(
"/") + join(*concrete,
"/");
160 if (
auto concrete = std::get_if<ConcreteDataMatcher>(&spec.
matcher)) {
161 concrete->subSpec = subSpec;
173 concrete.subSpec = subSpec;
178 dataType.description,
187 using namespace header;
191 if (
auto concrete = std::get_if<ConcreteDataMatcher>(&spec.
matcher)) {
202 using namespace header;
227 return matcher.match(concreteExample, context);
234 if (
auto concrete = std::get_if<ConcreteDataMatcher>(&spec.
matcher)) {
235 return *concrete ==
target;
236 }
else if (
auto matcher = std::get_if<DataDescriptorMatcher>(&spec.
matcher)) {
238 return matcher->match(
target, context);
248 return concrete ==
target;
251 return concrete.origin ==
target.origin &&
252 concrete.description ==
target.description;
259 if (
auto leftConcrete = std::get_if<ConcreteDataMatcher>(&
left.matcher)) {
261 }
else if (
auto rightConcrete = std::get_if<ConcreteDataMatcher>(&
right.matcher)) {
273 return std::visit([&input](
auto const& concrete) ->
bool {
282 return dataType.origin == origin;
323 using namespace data_matcher;
329 if (
state.hasError) {
334 if (action.node->getOp() == ops::Or || action.node->getOp() == ops::Xor) {
335 state.hasError =
true;
338 if (action.node->getOp() == ops::Just ||
339 action.node->getOp() == ops::Not) {
353 if (
state.hasOrigin) {
354 state.hasError =
false;
357 state.hasOrigin =
true;
360 [&
state](std::string
const& s) {
361 strncpy(
state.origin.str, s.data(), 4);
362 state.hasUniqueOrigin =
true;
364 [&
state](
auto) {
state.hasUniqueOrigin =
false; }});
367 if (
state.hasDescription) {
368 state.hasError =
true;
371 state.hasDescription =
true;
373 [&
state](std::string
const& s) {
374 strncpy(
state.description.str, s.data(), 16);
375 state.hasUniqueDescription =
true;
377 [&
state](
auto) {
state.hasUniqueDescription =
false; }});
380 if (
state.hasSubSpec) {
381 state.hasError =
true;
384 state.hasSubSpec =
true;
388 state.hasUniqueSubSpec =
true;
390 [&
state](
auto) {
state.hasUniqueSubSpec =
false; }});
404 if (info.hasOrigin && info.hasUniqueOrigin &&
405 info.hasDescription && info.hasDescription &&
406 info.hasSubSpec && info.hasUniqueSubSpec) {
409 throw std::runtime_error(
"Cannot convert " + binding +
" to ConcreteDataMatcher");
416 return std::get<ConcreteDataMatcher>(spec.
matcher);
423 return std::optional<ConcreteDataMatcher>{concrete};
428 [](
auto const&) {
return std::optional<ConcreteDataMatcher>{std::nullopt}; }},
434 return std::visit([](
auto const& concrete) {
443 [](
auto const& concrete) {
448 if (
state.hasUniqueOrigin &&
state.hasUniqueDescription) {
451 throw runtime_error(
"Could not extract data type from query");
459 [](
auto const& concrete) {
460 return concrete.origin;
464 if (
state.hasUniqueOrigin) {
467 throw runtime_error(
"Could not extract data type from query");
475 [](
auto const& concrete) {
476 return concrete.description;
480 if (
state.hasUniqueDescription) {
481 return state.description;
483 throw runtime_error(
"Could not extract data type from query");
496 if (
state.hasUniqueOrigin &&
state.hasUniqueDescription &&
state.hasUniqueSubSpec) {
498 }
else if (
state.hasUniqueOrigin &&
state.hasUniqueDescription) {
502 throw runtime_error_f(
"Could not extract neither ConcreteDataMatcher nor ConcreteDataTypeMatcher from query %s",
describe(spec).c_str());
510 DataDescriptorMatcher::Op::And,
512 std::make_unique<DataDescriptorMatcher>(
513 DataDescriptorMatcher::Op::And,
515 std::make_unique<DataDescriptorMatcher>(
516 DataDescriptorMatcher::Op::And,
518 std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just,
520 return matchEverything;
525 auto timeDescriptionMatcher = std::make_unique<DataDescriptorMatcher>(
526 DataDescriptorMatcher::Op::And,
528 std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just,
531 DataDescriptorMatcher::Op::And,
533 std::move(timeDescriptionMatcher));
538 char buf[5] = {0, 0, 0, 0, 0};
539 strncpy(
buf, origin.
str, 4);
541 DataDescriptorMatcher::Op::And,
543 std::make_unique<DataDescriptorMatcher>(
544 DataDescriptorMatcher::Op::And,
546 std::make_unique<DataDescriptorMatcher>(
547 DataDescriptorMatcher::Op::And,
549 std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just,
551 return matchOnlyOrigin;
556 char buf[17] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
557 strncpy(
buf, description.
str, 16);
559 DataDescriptorMatcher::Op::And,
561 std::make_unique<DataDescriptorMatcher>(
562 DataDescriptorMatcher::Op::And,
564 std::make_unique<DataDescriptorMatcher>(
565 DataDescriptorMatcher::Op::And,
567 std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just,
569 return matchOnlyOrigin;
574 using namespace data_matcher;
580 if (
state.hasError) {
585 if (action.node->getOp() == ops::Just) {
587 }
else if (action.node->getOp() == ops::And) {
592 state.hasError =
true;
600 if (
state.hasOrigin) {
601 state.hasUniqueOrigin =
false;
604 state.hasOrigin =
true;
607 [&
state](std::string
const& s) {
608 strncpy(
state.origin.str, s.data(), 4);
609 state.hasUniqueOrigin =
true;
611 [&
state](
auto) {
state.hasUniqueOrigin =
false; }});
614 if (
state.hasDescription) {
615 state.hasUniqueDescription =
false;
618 state.hasDescription =
true;
620 [&
state](std::string
const& s) {
621 strncpy(
state.description.str, s.data(), 16);
622 state.hasUniqueDescription =
true;
624 [&
state](
auto) {
state.hasUniqueDescription =
false; }});
627 if (
state.hasSubSpec) {
628 state.hasUniqueSubSpec =
false;
631 state.hasSubSpec =
true;
635 state.hasUniqueSubSpec =
true;
637 [&
state](
auto) {
state.hasUniqueSubSpec =
false; }});
641 if (
state.hasError ==
false &&
state.hasUniqueOrigin &&
state.hasUniqueDescription &&
state.hasUniqueSubSpec) {
654 concrete.description,
670 std::regex word_regex(
"(\\w+)");
671 auto words = std::sregex_iterator(s.begin(), s.end(), word_regex);
672 if (std::distance(words, std::sregex_iterator()) != 4) {
675 std::vector<std::string>
data;
676 for (
auto i = words;
i != std::sregex_iterator(); ++
i) {
677 data.emplace_back(
i->str());
680 char description[16];
681 std::memcpy(&origin,
data[1].c_str(), 4);
682 std::memcpy(&description,
data[2].c_str(), 16);
692 return std::make_optional(concrete.origin);
696 if (
state.hasUniqueOrigin) {
697 return std::make_optional(
state.origin);
698 }
else if (
state.hasError) {
711 return std::make_optional(concrete.description);
715 if (
state.hasUniqueDescription) {
716 return std::make_optional(
state.description);
717 }
else if (
state.hasError) {
718 throw runtime_error(
"Could not extract description from query");
728 [](
ConcreteDataMatcher const& concrete) -> std::optional<header::DataHeader::SubSpecificationType> {
729 return std::make_optional(concrete.subSpec);
741 [](
ConcreteDataMatcher const& concrete) -> std::optional<header::DataHeader::SubSpecificationType> {
742 return std::make_optional(concrete.subSpec);
744 [](
DataDescriptorMatcher const& matcher) -> std::optional<header::DataHeader::SubSpecificationType> {
746 if (
state.hasUniqueSubSpec) {
747 return std::make_optional(
state.subSpec);
748 }
else if (
state.hasError) {
768 return rightInfo.hasUniqueOrigin && rightInfo.origin == leftMatcher.origin &&
769 rightInfo.hasUniqueDescription && rightInfo.description == leftMatcher.description &&
770 rightInfo.hasUniqueSubSpec && rightInfo.subSpec == leftMatcher.subSpec;
774 return (!leftInfo.hasOrigin || (rightInfo.hasOrigin && leftInfo.origin == rightInfo.origin)) &&
775 (!leftInfo.hasDescription || (rightInfo.hasDescription && leftInfo.description == rightInfo.description)) &&
776 (!leftInfo.hasSubSpec || (rightInfo.hasSubSpec && leftInfo.subSpec == rightInfo.subSpec));
785 auto locate = std::find(
list.begin(),
list.end(), input);
786 if (locate !=
list.end()) {
788 auto& entryMetadata = locate->metadata;
789 entryMetadata.insert(entryMetadata.end(), input.metadata.begin(), input.metadata.end());
791 auto new_end = std::unique(entryMetadata.begin(), entryMetadata.end(), [](
ConfigParamSpec const&
a,
ConfigParamSpec const&
b) { return a.name == b.name; });
792 entryMetadata.erase(new_end, entryMetadata.end());
795 list.emplace_back(std::move(input));
801 auto locate = std::find(
list.begin(),
list.end(), spec);
802 if (locate !=
list.end()) {
804 auto& entryMetadata = locate->metadata;
805 entryMetadata.insert(entryMetadata.end(), spec.metadata.begin(), spec.metadata.end());
807 auto new_end = std::unique(entryMetadata.begin(), entryMetadata.end(), [](
ConfigParamSpec const&
a,
ConfigParamSpec const&
b) { return a.name == b.name; });
808 entryMetadata.erase(new_end, entryMetadata.end());
811 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)
header::DataOrigin origin
header::DataDescription description
header::DataHeader::SubSpecificationType subSpec
bool hasUniqueDescription
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.