1616#include < cstdint>
1717#include < string>
1818#include < variant>
19+ #include < vector>
1920
2021namespace o2
2122{
2223namespace framework
2324{
25+ namespace data_matcher
26+ {
27+
28+ // / Marks an empty item in the context
29+ struct None {
30+ };
31+
32+ // / A typesafe reference to an element of the context.
33+ struct ContextRef {
34+ size_t index;
35+ };
36+
37+ // / An element of the matching context. Context itself is really a vector of
38+ // / those. It's up to the matcher builder to build the vector in a suitable way.
39+ // / We do not have any float in the value, because AFAICT there is no need for
40+ // / it in the O2 DataHeader, however we could add it later on.
41+ struct ContextElement {
42+ std::string label; // / The name of the variable contained in this element.
43+ std::variant<uint64_t , std::string, None> value; // / The actual contents of the element.
44+ };
2445
2546// / Something which can be matched against a header::DataOrigin
2647class OriginValueMatcher
2748{
2849 public:
50+ // / Initialise the matcher with an actual value
2951 OriginValueMatcher (std::string const & s)
3052 : mValue { s }
3153 {
3254 }
3355
34- bool match (header::DataHeader const & header) const
56+ // / This means that the matcher will fill a variable in the context if
57+ // / the ref points to none or use the dereferenced value, if not.
58+ OriginValueMatcher (ContextRef variableId)
59+ : mValue { variableId }
3560 {
36- return strncmp (header.dataOrigin .str , mValue .c_str (), 4 ) == 0 ;
61+ }
62+
63+ bool match (header::DataHeader const & header, std::vector<ContextElement>& context) const
64+ {
65+ if (auto ref = std::get_if<ContextRef>(&mValue )) {
66+ auto & variable = context.at (ref->index );
67+ if (auto value = std::get_if<std::string>(&variable.value )) {
68+ return strncmp (header.dataOrigin .str , value->c_str (), 4 ) == 0 ;
69+ }
70+ auto maxSize = strnlen (header.dataOrigin .str , 4 );
71+ variable.value = std::string (header.dataOrigin .str , maxSize);
72+ return true ;
73+ } else if (auto s = std::get_if<std::string>(&mValue )) {
74+ return strncmp (header.dataOrigin .str , s->c_str (), 4 ) == 0 ;
75+ }
76+ throw std::runtime_error (" Mismatching type for variable" );
3777 }
3878
3979 private:
40- std::string mValue ;
80+ std::variant<std:: string, ContextRef> mValue ;
4181};
4282
4383// / Something which can be matched against a header::DataDescription
@@ -49,13 +89,31 @@ class DescriptionValueMatcher
4989 {
5090 }
5191
52- bool match (header::DataHeader const & header) const
92+ // / This means that the matcher will fill a variable in the context if
93+ // / the ref points to none or use the dereferenced value, if not.
94+ DescriptionValueMatcher (ContextRef ref)
95+ : mValue { ref }
96+ {
97+ }
98+
99+ bool match (header::DataHeader const & header, std::vector<ContextElement>& context) const
53100 {
54- return strncmp (header.dataDescription .str , mValue .c_str (), 8 ) == 0 ;
101+ if (auto ref = std::get_if<ContextRef>(&mValue )) {
102+ auto & variable = context.at (ref->index );
103+ if (auto value = std::get_if<std::string>(&variable.value )) {
104+ return strncmp (header.dataDescription .str , value->c_str (), 16 ) == 0 ;
105+ }
106+ auto maxSize = strnlen (header.dataDescription .str , 16 );
107+ variable.value = std::string (header.dataDescription .str , maxSize);
108+ return true ;
109+ } else if (auto s = std::get_if<std::string>(&mValue )) {
110+ return strncmp (header.dataDescription .str , s->c_str (), 16 ) == 0 ;
111+ }
112+ throw std::runtime_error (" Mismatching type for variable" );
55113 }
56114
57115 private:
58- std::string mValue ;
116+ std::variant<std:: string, ContextRef> mValue ;
59117};
60118
61119// / Something which can be matched against a header::SubSpecificationType
@@ -65,21 +123,40 @@ class SubSpecificationTypeValueMatcher
65123 // / The passed string @a s is the expected numerical value for
66124 // / the SubSpecification type.
67125 SubSpecificationTypeValueMatcher (std::string const & s)
126+ : SubSpecificationTypeValueMatcher(strtoull(s.c_str(), nullptr , 10 ))
68127 {
69- mValue = strtoull (s.c_str (), nullptr , 10 );
70128 }
71129
130+ // / This means that the matcher is looking for a constant.
72131 SubSpecificationTypeValueMatcher (uint64_t v)
132+ : mValue { v }
73133 {
74- mValue = v;
75134 }
76- bool match (header::DataHeader const & header) const
135+
136+ // / This means that the matcher will fill a variable in the context if
137+ // / the ref points to none or use the dereferenced value, if not.
138+ SubSpecificationTypeValueMatcher (ContextRef ref)
139+ : mValue { ref }
77140 {
78- return header.subSpecification == mValue ;
141+ }
142+
143+ bool match (header::DataHeader const & header, std::vector<ContextElement>& context) const
144+ {
145+ if (auto ref = std::get_if<ContextRef>(&mValue )) {
146+ auto & variable = context.at (ref->index );
147+ if (auto value = std::get_if<uint64_t >(&variable.value )) {
148+ return header.subSpecification == *value;
149+ }
150+ variable.value = header.subSpecification ;
151+ return true ;
152+ } else if (auto v = std::get_if<uint64_t >(&mValue )) {
153+ return header.subSpecification == *v;
154+ }
155+ throw std::runtime_error (" Mismatching type for variable" );
79156 }
80157
81158 private:
82- uint64_t mValue ;
159+ std::variant< uint64_t , ContextRef> mValue ;
83160};
84161
85162// / Something which can be matched against a header::SubSpecificationType
@@ -92,6 +169,7 @@ class ConstantValueMatcher
92169 {
93170 mValue = value;
94171 }
172+
95173 bool match (header::DataHeader const & header) const
96174 {
97175 return mValue ;
@@ -107,7 +185,7 @@ struct DescriptorMatcherTrait {
107185
108186template <>
109187struct DescriptorMatcherTrait <header::DataOrigin> {
110- using Matcher = framework:: OriginValueMatcher;
188+ using Matcher = OriginValueMatcher;
111189};
112190
113191template <>
@@ -147,33 +225,34 @@ class DataDescriptorMatcher
147225
148226 // / @return true if the (sub-)query associated to this matcher will
149227 // / match the provided @a spec, false otherwise.
150- bool match (InputSpec const & spec) const
228+ bool match (InputSpec const & spec, std::vector<ContextElement>& context ) const
151229 {
152230 header::DataHeader dh;
153231 dh.dataOrigin = spec.origin ;
154232 dh.dataDescription = spec.description ;
155233 dh.subSpecification = spec.subSpec ;
156234
157- return this ->match (dh);
235+ return this ->match (dh, context );
158236 }
159237
160- bool match (header::DataHeader const & d) const
238+ bool match (header::DataHeader const & d, std::vector<ContextElement>& context ) const
161239 {
162- auto eval = [&d](auto && arg) -> bool {
163- using T = std::decay_t <decltype (arg)>;
164- if constexpr (std::is_same_v<T, std::unique_ptr<DataDescriptorMatcher>>) {
165- return arg->match (d);
166- } else {
167- return arg.match (d);
168- }
169- };
170-
171240 bool leftValue = false , rightValue = false ;
172241
173242 // FIXME: Using std::visit is not API compatible due to a new
174243 // exception being thrown. This is the ABI compatible version.
175244 // Replace with:
176245 //
246+ // auto eval = [&d](auto&& arg) -> bool {
247+ // using T = std::decay_t<decltype(arg)>;
248+ // if constexpr (std::is_same_v<T, std::unique_ptr<DataDescriptorMatcher>>) {
249+ // return arg->match(d, context);
250+ // if constexpr (std::is_same_v<T, ConstantValueMatcher>) {
251+ // return arg->match(d);
252+ // } else {
253+ // return arg.match(d, context);
254+ // }
255+ // };
177256 // switch (mOp) {
178257 // case Op::Or:
179258 // return std::visit(eval, mLeft) || std::visit(eval, mRight);
@@ -185,29 +264,28 @@ class DataDescriptorMatcher
185264 // return std::visit(eval, mLeft);
186265 // }
187266 // When we drop support for macOS 10.13
188-
189267 if (auto pval0 = std::get_if<OriginValueMatcher>(&mLeft )) {
190- leftValue = pval0->match (d);
268+ leftValue = pval0->match (d, context );
191269 } else if (auto pval1 = std::get_if<DescriptionValueMatcher>(&mLeft )) {
192- leftValue = pval1->match (d);
270+ leftValue = pval1->match (d, context );
193271 } else if (auto pval2 = std::get_if<SubSpecificationTypeValueMatcher>(&mLeft )) {
194- leftValue = pval2->match (d);
272+ leftValue = pval2->match (d, context );
195273 } else if (auto pval3 = std::get_if<std::unique_ptr<DataDescriptorMatcher>>(&mLeft )) {
196- leftValue = (*pval3)->match (d);
274+ leftValue = (*pval3)->match (d, context );
197275 } else if (auto pval4 = std::get_if<ConstantValueMatcher>(&mLeft )) {
198276 leftValue = pval4->match (d);
199277 } else {
200278 throw std::runtime_error (" Bad parsing tree" );
201279 }
202280
203281 if (auto pval0 = std::get_if<OriginValueMatcher>(&mRight )) {
204- rightValue = pval0->match (d);
282+ rightValue = pval0->match (d, context );
205283 } else if (auto pval1 = std::get_if<DescriptionValueMatcher>(&mRight )) {
206- rightValue = pval1->match (d);
284+ rightValue = pval1->match (d, context );
207285 } else if (auto pval2 = std::get_if<SubSpecificationTypeValueMatcher>(&mRight )) {
208- rightValue = pval2->match (d);
286+ rightValue = pval2->match (d, context );
209287 } else if (auto pval3 = std::get_if<std::unique_ptr<DataDescriptorMatcher>>(&mRight )) {
210- rightValue = (*pval3)->match (d);
288+ rightValue = (*pval3)->match (d, context );
211289 } else if (auto pval4 = std::get_if<ConstantValueMatcher>(&mRight )) {
212290 rightValue = pval4->match (d);
213291 }
@@ -231,7 +309,8 @@ class DataDescriptorMatcher
231309 Node mRight ;
232310};
233311
234- } // naemspace framework
312+ } // namespace data_matcher
313+ } // namespace framework
235314} // namespace o2
236315
237316#endif // o2_framework_DataDescriptorMatcher_H_INCLUDED
0 commit comments