From c808a8356bcdc32fcf625ef3347d84f8a9677a4d Mon Sep 17 00:00:00 2001 From: Martin Jobst Date: Thu, 21 Mar 2024 17:03:16 +0100 Subject: [PATCH] Support EQ and NE for array and struct --- src/core/datatypes/forte_array.cpp | 17 --------- src/core/datatypes/forte_array.h | 26 ++++++++++++-- src/core/datatypes/forte_array_common.h | 19 +++++++++- src/core/datatypes/forte_struct.h | 10 ++++++ src/core/iec61131_functions.h | 8 +++-- tests/core/iec61131_functionstests.cpp | 47 +++++++++++++++++++++++++ 6 files changed, 105 insertions(+), 22 deletions(-) diff --git a/src/core/datatypes/forte_array.cpp b/src/core/datatypes/forte_array.cpp index 5eba2cda..cb04edef 100644 --- a/src/core/datatypes/forte_array.cpp +++ b/src/core/datatypes/forte_array.cpp @@ -40,23 +40,6 @@ void CIEC_ARRAY::setValue(const CIEC_ANY &paValue) { } } -bool CIEC_ARRAY::equals(const CIEC_ANY &paOther) const { - if (paOther.getDataTypeID() == CIEC_ANY::e_ARRAY) { - auto &otherArray = static_cast(paOther); - if (getLowerBound() != otherArray.getLowerBound() || getUpperBound() != otherArray.getUpperBound()) { - return false; - } - - for (intmax_t i = getLowerBound(), end = getUpperBound(); i <= end; ++i) { - if (!operator[](i).equals(otherArray[i])) { - return false; - } - } - return true; - } - return false; -} - int CIEC_ARRAY::toString(char *paValue, size_t paBufferSize) const { int nBytesUsed = -1; diff --git a/src/core/datatypes/forte_array.h b/src/core/datatypes/forte_array.h index 900355e2..90eb3ba1 100644 --- a/src/core/datatypes/forte_array.h +++ b/src/core/datatypes/forte_array.h @@ -27,7 +27,24 @@ /** \brief A common supertype for all CIEC_ARRAY variants, providing the minimal interface an array must provide */ class CIEC_ARRAY : public CIEC_ANY_DERIVED { -public: + friend bool operator==(const CIEC_ARRAY &paLeft, const CIEC_ARRAY &paRight) { + if (paLeft.getLowerBound() != paRight.getLowerBound() || paLeft.getUpperBound() != paRight.getUpperBound()) { + return false; + } + + for (intmax_t i = paLeft.getLowerBound(), end = paLeft.getUpperBound(); i <= end; ++i) { + if (!paLeft[i].equals(paRight[i])) { + return false; + } + } + return true; + } + + friend bool operator!=(const CIEC_ARRAY &paLeft, const CIEC_ARRAY &paRight) { + return !(paLeft == paRight); + } + + public: using value_type = CIEC_ANY; using pointer = value_type *; using const_pointer = const value_type *; @@ -93,7 +110,12 @@ class CIEC_ARRAY : public CIEC_ANY_DERIVED { void setValue(const CIEC_ANY &paValue) override; - [[nodiscard]] bool equals(const CIEC_ANY &paOther) const override; + [[nodiscard]] bool equals(const CIEC_ANY &paOther) const override { + if (paOther.getDataTypeID() == CIEC_ANY::e_ARRAY) { + return *this == static_cast(paOther); + } + return false; + } [[nodiscard]] int toString(char *paValue, size_t paBufferSize) const override; diff --git a/src/core/datatypes/forte_array_common.h b/src/core/datatypes/forte_array_common.h index 09e8dd01..786a03b1 100644 --- a/src/core/datatypes/forte_array_common.h +++ b/src/core/datatypes/forte_array_common.h @@ -29,7 +29,24 @@ */ template class CIEC_ARRAY_COMMON : public CIEC_ARRAY { -public: + friend bool operator==(const CIEC_ARRAY_COMMON &paLeft, const CIEC_ARRAY_COMMON &paRight) { + if (paLeft.getLowerBound() != paRight.getLowerBound() || paLeft.getUpperBound() != paRight.getUpperBound()) { + return false; + } + + for (intmax_t i = paLeft.getLowerBound(), end = paLeft.getUpperBound(); i <= end; ++i) { + if (!func_EQ(paLeft[i], paRight[i])) { + return false; + } + } + return true; + } + + friend bool operator!=(const CIEC_ARRAY_COMMON &paLeft, const CIEC_ARRAY_COMMON &paRight) { + return !(paLeft == paRight); + } + + public: using value_type = T; using pointer = value_type *; using const_pointer = const value_type *; diff --git a/src/core/datatypes/forte_struct.h b/src/core/datatypes/forte_struct.h index 6a4e3809..874d25ac 100644 --- a/src/core/datatypes/forte_struct.h +++ b/src/core/datatypes/forte_struct.h @@ -20,6 +20,16 @@ #include "forte_any_derived.h" class CIEC_STRUCT : public CIEC_ANY_DERIVED{ + template , int> = 0> + friend bool operator==(const T &paLeft, const T &paRight) { + return paLeft.equals(paRight); + } + + template , int> = 0> + friend bool operator!=(const T &paLeft, const T &paRight) { + return !(paLeft == paRight); + } + public: //! Indicator for invalid array member index positions static constexpr size_t csmNIndex = -1; diff --git a/src/core/iec61131_functions.h b/src/core/iec61131_functions.h index 6080e3a8..b2511b8e 100644 --- a/src/core/iec61131_functions.h +++ b/src/core/iec61131_functions.h @@ -425,7 +425,9 @@ CIEC_BOOL func_EQ(const T &paIn1, const U &paIn2, const Args& ... args) { template CIEC_BOOL func_EQ(const T &paIN1, const U &paIN2) { - if constexpr (forte::core::mpl::are_of_subtype_v) { //ANY_BITs can be also partial accesses + if constexpr (forte::core::mpl::has_equality_v) { + return CIEC_BOOL(paIN1 == paIN2); + } else if constexpr (forte::core::mpl::are_of_subtype_v) { //ANY_BITs can be also partial accesses using tTClass = typename forte::core::mpl::get_equivalent_CIEC_class_t; using tUClass = typename forte::core::mpl::get_equivalent_CIEC_class_t; using tImplicitCastType = typename forte::core::mpl::get_castable_type_t; @@ -539,7 +541,9 @@ CIEC_BOOL func_LT(const T &paIN1, const T &paIN2) { template CIEC_BOOL func_NE(const T &paIN1, const U &paIN2) { - if constexpr (forte::core::mpl::are_of_subtype_v) { //ANY_BITs can be also partial accesses + if constexpr (forte::core::mpl::has_equality_v) { + return CIEC_BOOL(paIN1 != paIN2); + } else if constexpr (forte::core::mpl::are_of_subtype_v) { //ANY_BITs can be also partial accesses using tTClass = typename forte::core::mpl::get_equivalent_CIEC_class_t; using tUClass = typename forte::core::mpl::get_equivalent_CIEC_class_t; using tImplicitCastType = typename forte::core::mpl::get_castable_type_t; diff --git a/tests/core/iec61131_functionstests.cpp b/tests/core/iec61131_functionstests.cpp index 5190d4fc..05a63bdc 100644 --- a/tests/core/iec61131_functionstests.cpp +++ b/tests/core/iec61131_functionstests.cpp @@ -52,6 +52,9 @@ class CIEC_EndianessTestStruct : public CIEC_STRUCT { CIEC_EndianessTestStruct() = default; + CIEC_EndianessTestStruct(CIEC_BOOL paVar1, CIEC_DINT paVar2, CIEC_LWORD paVar3) + : Var1(paVar1), Var2(paVar2), Var3(paVar3) {} + size_t getStructSize() const override { return 3; } @@ -438,6 +441,28 @@ BOOST_AUTO_TEST_CASE(eq_false_variadic_4) BOOST_TEST(func_EQ(number1, number2, number3, number4) == false); } +BOOST_AUTO_TEST_CASE(eq_array_fixed) +{ + CIEC_ARRAY_FIXED array1 = {17_INT, 4_INT}; + CIEC_ARRAY_FIXED array2 = {17_INT, 4_INT}; + CIEC_ARRAY_FIXED array3 = {21_INT, 42_INT}; + CIEC_ARRAY_FIXED array4 = {17_INT, 4_INT, 21_INT}; + CIEC_ARRAY_FIXED array5 = {17_DINT, 4_DINT}; + BOOST_TEST(func_EQ(array1, array2) == true); + BOOST_TEST(func_EQ(array1, array3) == false); + BOOST_TEST(func_EQ(array1, array4) == false); + BOOST_TEST(func_EQ(array1, array5) == false); +} + +BOOST_AUTO_TEST_CASE(eq_struct) +{ + CIEC_EndianessTestStruct struct1(true_BOOL, 17_DINT, 4_LWORD); + CIEC_EndianessTestStruct struct2(true_BOOL, 17_DINT, 4_LWORD); + CIEC_EndianessTestStruct struct3(true_BOOL, 21_DINT, 42_LWORD); + BOOST_TEST(func_EQ(struct1, struct2) == true); + BOOST_TEST(func_EQ(struct1, struct3) == false); +} + BOOST_AUTO_TEST_CASE(gt_true) { BOOST_TEST(func_GT(100_SINT, 90_INT) == true); } @@ -580,6 +605,28 @@ BOOST_AUTO_TEST_CASE(ne_false_mixed_types) BOOST_TEST(func_NE(nLint1, nInt2) == true); } +BOOST_AUTO_TEST_CASE(ne_array_fixed) +{ + CIEC_ARRAY_FIXED array1 = {17_INT, 4_INT}; + CIEC_ARRAY_FIXED array2 = {17_INT, 4_INT}; + CIEC_ARRAY_FIXED array3 = {21_INT, 42_INT}; + CIEC_ARRAY_FIXED array4 = {17_INT, 4_INT, 21_INT}; + CIEC_ARRAY_FIXED array5 = {17_DINT, 4_DINT}; + BOOST_TEST(func_NE(array1, array2) == false); + BOOST_TEST(func_NE(array1, array3) == true); + BOOST_TEST(func_NE(array1, array4) == true); + BOOST_TEST(func_NE(array1, array5) == true); +} + +BOOST_AUTO_TEST_CASE(ne_struct) +{ + CIEC_EndianessTestStruct struct1(true_BOOL, 17_DINT, 4_LWORD); + CIEC_EndianessTestStruct struct2(true_BOOL, 17_DINT, 4_LWORD); + CIEC_EndianessTestStruct struct3(true_BOOL, 21_DINT, 42_LWORD); + BOOST_TEST(func_NE(struct1, struct2) == false); + BOOST_TEST(func_NE(struct1, struct3) == true); +} + BOOST_AUTO_TEST_CASE(implicit_bool_casts) { bool bSame = std::is_same::type>::value;