@@ -32,6 +32,11 @@ struct None {
3232// / A typesafe reference to an element of the context.
3333struct ContextRef {
3434 size_t index;
35+
36+ bool operator ==(ContextRef const & other) const
37+ {
38+ return index == other.index ;
39+ }
3540};
3641
3742// / An element of the matching context. Context itself is really a vector of
@@ -43,23 +48,59 @@ struct ContextElement {
4348 std::variant<uint64_t , std::string, None> value; // / The actual contents of the element.
4449};
4550
46- // / Something which can be matched against a header::DataOrigin
47- class OriginValueMatcher
51+ // / Can hold either an actual value of type T or a reference to
52+ // / a variable of the same type in the Context.
53+ template <typename T>
54+ class ValueHolder
4855{
4956 public:
50- // / Initialise the matcher with an actual value
51- OriginValueMatcher (std::string const & s)
57+ ValueHolder (T const & s)
5258 : mValue { s }
5359 {
5460 }
55-
5661 // / This means that the matcher will fill a variable in the context if
5762 // / the ref points to none or use the dereferenced value, if not.
58- OriginValueMatcher (ContextRef variableId)
63+ ValueHolder (ContextRef variableId)
5964 : mValue { variableId }
6065 {
6166 }
6267
68+ bool operator ==(ValueHolder<T> const & other) const
69+ {
70+ auto s1 = std::get_if<T>(&mValue );
71+ auto s2 = std::get_if<T>(&other.mValue );
72+
73+ if (s1 && s2) {
74+ return *s1 == *s2;
75+ }
76+
77+ auto c1 = std::get_if<ContextRef>(&mValue );
78+ auto c2 = std::get_if<ContextRef>(&other.mValue );
79+ if (c1 && c2) {
80+ return *c1 == *c2;
81+ }
82+
83+ return false ;
84+ }
85+
86+ protected:
87+ std::variant<T, ContextRef> mValue ;
88+ };
89+
90+ // / Something which can be matched against a header::DataOrigin
91+ class OriginValueMatcher : public ValueHolder <std::string>
92+ {
93+ public:
94+ OriginValueMatcher (std::string const & s)
95+ : ValueHolder{ s }
96+ {
97+ }
98+
99+ OriginValueMatcher (ContextRef variableId)
100+ : ValueHolder{ variableId }
101+ {
102+ }
103+
63104 bool match (header::DataHeader const & header, std::vector<ContextElement>& context) const
64105 {
65106 if (auto ref = std::get_if<ContextRef>(&mValue )) {
@@ -75,24 +116,19 @@ class OriginValueMatcher
75116 }
76117 throw std::runtime_error (" Mismatching type for variable" );
77118 }
78-
79- private:
80- std::variant<std::string, ContextRef> mValue ;
81119};
82120
83121// / Something which can be matched against a header::DataDescription
84- class DescriptionValueMatcher
122+ class DescriptionValueMatcher : public ValueHolder <std::string>
85123{
86124 public:
87125 DescriptionValueMatcher (std::string const & s)
88- : mValue { s }
126+ : ValueHolder { s }
89127 {
90128 }
91129
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 }
130+ DescriptionValueMatcher (ContextRef variableId)
131+ : ValueHolder{ variableId }
96132 {
97133 }
98134
@@ -106,37 +142,32 @@ class DescriptionValueMatcher
106142 auto maxSize = strnlen (header.dataDescription .str , 16 );
107143 variable.value = std::string (header.dataDescription .str , maxSize);
108144 return true ;
109- } else if (auto s = std::get_if<std::string>(&mValue )) {
145+ } else if (auto s = std::get_if<std::string>(&this -> mValue )) {
110146 return strncmp (header.dataDescription .str , s->c_str (), 16 ) == 0 ;
111147 }
112148 throw std::runtime_error (" Mismatching type for variable" );
113149 }
114-
115- private:
116- std::variant<std::string, ContextRef> mValue ;
117150};
118151
119152// / Something which can be matched against a header::SubSpecificationType
120- class SubSpecificationTypeValueMatcher
153+ class SubSpecificationTypeValueMatcher : public ValueHolder < uint64_t >
121154{
122155 public:
156+ SubSpecificationTypeValueMatcher (ContextRef variableId)
157+ : ValueHolder{ variableId }
158+ {
159+ }
160+
123161 // / The passed string @a s is the expected numerical value for
124162 // / the SubSpecification type.
125163 SubSpecificationTypeValueMatcher (std::string const & s)
126- : SubSpecificationTypeValueMatcher( strtoull(s.c_str(), nullptr , 10 ))
164+ : ValueHolder< uint64_t >{ strtoull (s.c_str (), nullptr , 10 ) }
127165 {
128166 }
129167
130168 // / This means that the matcher is looking for a constant.
131169 SubSpecificationTypeValueMatcher (uint64_t v)
132- : mValue { v }
133- {
134- }
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 }
170+ : ValueHolder<uint64_t >{ v }
140171 {
141172 }
142173
@@ -154,9 +185,6 @@ class SubSpecificationTypeValueMatcher
154185 }
155186 throw std::runtime_error (" Mismatching type for variable" );
156187 }
157-
158- private:
159- std::variant<uint64_t , ContextRef> mValue ;
160188};
161189
162190// / Something which can be matched against a header::SubSpecificationType
@@ -175,6 +203,11 @@ class ConstantValueMatcher
175203 return mValue ;
176204 }
177205
206+ bool operator ==(ConstantValueMatcher const & other) const
207+ {
208+ return mValue == other.mValue ;
209+ }
210+
178211 private:
179212 bool mValue ;
180213};
@@ -217,9 +250,9 @@ class DataDescriptorMatcher
217250 // / contents mLeft and mRight into a new unique_ptr, if
218251 // / needed.
219252 DataDescriptorMatcher (DataDescriptorMatcher const & other)
220- : mOp {other.mOp },
221- mLeft {ConstantValueMatcher{false } },
222- mRight {ConstantValueMatcher{false } }
253+ : mOp { other.mOp },
254+ mLeft { ConstantValueMatcher{ false } },
255+ mRight { ConstantValueMatcher{ false } }
223256 {
224257 if (auto pval0 = std::get_if<OriginValueMatcher>(&other.mLeft )) {
225258 mLeft = *pval0;
@@ -346,6 +379,106 @@ class DataDescriptorMatcher
346379 }
347380 };
348381
382+ bool operator ==(DataDescriptorMatcher const & other) const
383+ {
384+ if (mOp != this ->mOp ) {
385+ return false ;
386+ }
387+
388+ bool leftValue = false ;
389+ bool rightValue = false ;
390+
391+ {
392+ auto v1 = std::get_if<OriginValueMatcher>(&this ->mLeft );
393+ auto v2 = std::get_if<OriginValueMatcher>(&other.mLeft );
394+ if (v1 && v2 && *v1 == *v2) {
395+ leftValue = true ;
396+ }
397+ }
398+
399+ {
400+ auto v1 = std::get_if<DescriptionValueMatcher>(&this ->mLeft );
401+ auto v2 = std::get_if<DescriptionValueMatcher>(&other.mLeft );
402+ if (v1 && v2 && *v1 == *v2) {
403+ leftValue = true ;
404+ }
405+ }
406+
407+ {
408+ auto v1 = std::get_if<SubSpecificationTypeValueMatcher>(&this ->mLeft );
409+ auto v2 = std::get_if<SubSpecificationTypeValueMatcher>(&other.mLeft );
410+ if (v1 && v2 && *v1 == *v2) {
411+ leftValue = true ;
412+ }
413+ }
414+
415+ {
416+ auto v1 = std::get_if<ConstantValueMatcher>(&this ->mLeft );
417+ auto v2 = std::get_if<ConstantValueMatcher>(&other.mLeft );
418+ if (v1 && v2 && *v1 == *v2) {
419+ leftValue = true ;
420+ }
421+ }
422+
423+ {
424+ auto v1 = std::get_if<std::unique_ptr<DataDescriptorMatcher>>(&this ->mLeft );
425+ auto v2 = std::get_if<std::unique_ptr<DataDescriptorMatcher>>(&other.mLeft );
426+ if (v1 && v2 && v1->get () && v2->get () && (**v1 == **v2)) {
427+ leftValue = true ;
428+ }
429+ }
430+
431+ // Shortcut the fact that the left side is different.
432+ if (leftValue == false ) {
433+ return false ;
434+ }
435+
436+ if (mOp == Op::Just) {
437+ return true ;
438+ }
439+
440+ {
441+ auto v1 = std::get_if<OriginValueMatcher>(&this ->mRight );
442+ auto v2 = std::get_if<OriginValueMatcher>(&other.mRight );
443+ if (v1 && v2 && *v1 == *v2) {
444+ return true ;
445+ }
446+ }
447+
448+ {
449+ auto v1 = std::get_if<DescriptionValueMatcher>(&this ->mRight );
450+ auto v2 = std::get_if<DescriptionValueMatcher>(&other.mRight );
451+ if (v1 && v2 && *v1 == *v2) {
452+ return true ;
453+ }
454+ }
455+
456+ {
457+ auto v1 = std::get_if<SubSpecificationTypeValueMatcher>(&this ->mRight );
458+ auto v2 = std::get_if<SubSpecificationTypeValueMatcher>(&other.mRight );
459+ if (v1 && v2 && *v1 == *v2) {
460+ return true ;
461+ }
462+ }
463+
464+ {
465+ auto v1 = std::get_if<ConstantValueMatcher>(&this ->mRight );
466+ auto v2 = std::get_if<ConstantValueMatcher>(&other.mRight );
467+ if (v1 && v2 && *v1 == *v2) {
468+ return true ;
469+ }
470+ }
471+
472+ {
473+ auto v1 = std::get_if<std::unique_ptr<DataDescriptorMatcher>>(&this ->mRight );
474+ auto v2 = std::get_if<std::unique_ptr<DataDescriptorMatcher>>(&other.mRight );
475+ if (v1 && v2 && v1->get () && v2->get () && (**v1 == **v2)) {
476+ return true ;
477+ }
478+ }
479+ // We alredy know the left side is true.
480+ return false ;
481+ }
349482 Node const & getLeft () const { return mLeft ; };
350483 Node const & getRight () const { return mRight ; };
351484 Op getOp () const { return mOp ; };
0 commit comments