From b9e025a6dd499b8eca478bd56c824fc023c7df1e Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 3 Jul 2020 20:52:21 -0700 Subject: [PATCH] Value::compareType() -> Value::equalType() --- src/data.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++++ src/pvxs/data.h | 12 ++++++++---- test/testdata.cpp | 13 ++++++++----- 3 files changed, 63 insertions(+), 9 deletions(-) diff --git a/src/data.cpp b/src/data.cpp index ddddba7..cb783a2 100644 --- a/src/data.cpp +++ b/src/data.cpp @@ -284,6 +284,53 @@ bool Value::idStartsWith(const std::string& prefix) const return ID.size()>=prefix.size() && prefix==ID.substr(0u, prefix.size()); } +bool Value::_equal(const impl::FieldDesc* A, const impl::FieldDesc* B) +{ + if(A==B) { + return true; + + } else if(!A ^ !B) { + return false; + + } else if(!A) { // !A && !B + return true; + + } else if(A->size()!=B->size()) { + return false; + } + + for(auto i : range(A->size())) { + if(A[i].code!=B[i].code) + return false; + + if(A[i].code==TypeCode::StructA || A[i].code==TypeCode::UnionA) { + if(!_equal(&A[i].members[0], &B[i].members[0])) + return false; + + } else if(A[i].code==TypeCode::Struct || A[i].code==TypeCode::Union) { + auto it = A[i].mlookup.begin(); + auto end= A[i].mlookup.end(); + auto it2= B[i].mlookup.begin(); + + for(;it!=end; ++it, ++it2) { + if(it->first!=it2->first) { + return false; // different field name + + } else if(it->second!=it2->second) { + return false; // different field order + + } else if(A[i].code==TypeCode::Union) { + if(!_equal(&A[i].members[it->second], &B[i].members[it2->second])) + return false; + + } // else if A[i] is Struct, outer loop will reach members + } + } + } + + return true; +} + const std::string &Value::nameOf(const Value& descendant) const { if(!store || !descendant.store) diff --git a/src/pvxs/data.h b/src/pvxs/data.h index ca23688..d1be4a0 100644 --- a/src/pvxs/data.h +++ b/src/pvxs/data.h @@ -528,10 +528,14 @@ public: //! Test prefix of Type ID string (Struct or Union only) bool idStartsWith(const std::string& prefix) const; - //! test for instance equality. - inline bool compareInst(const Value& o) const { return store==o.store; } -// int compareValue(const Value&) const; - inline int compareType(const Value& o) const { return desc==o.desc; } +private: + static + bool _equal(const impl::FieldDesc* A, const impl::FieldDesc* B); +public: + //! Test for instance equality. aka. this==this + inline bool equalInst(const Value& o) const { return store==o.store; } + //! Test for equality of type only (including field names) + inline bool equalType(const Value& o) const { return _equal(desc, o.desc); } /** Return our name for a descendant field. * @code diff --git a/test/testdata.cpp b/test/testdata.cpp index fef98f8..1e6a88b 100644 --- a/test/testdata.cpp +++ b/test/testdata.cpp @@ -29,15 +29,18 @@ void testTraverse() { auto top2 = top["value<"]; - testOk1(top.compareType(top2)); - testOk1(top.compareInst(top2)); + testOk1(top.equalType(top2)); + testOk1(top.equalInst(top2)); } { auto sevr1 = top["alarm.severity"]; auto sevr2 = top["value