From ba4a44713fb8ff6a1304a50cb990d14f98674275 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Thu, 29 Jul 2021 14:22:10 -0700 Subject: [PATCH] [array] add `FindMatching()` and `ContainsMatching()` (#6872) This commit adds template `Find/ContainsMatching()` methods which search in the array to find the first element matching a given indicator. Unit test `test_array` is also updated to check the behavior of newly added methods. --- src/core/common/array.hpp | 69 +++++++++++++++++++++++++++++++++++++++ tests/unit/test_array.cpp | 33 +++++++++++++++++-- 2 files changed, 100 insertions(+), 2 deletions(-) diff --git a/src/core/common/array.hpp b/src/core/common/array.hpp index dd485b299..112f3d4db 100644 --- a/src/core/common/array.hpp +++ b/src/core/common/array.hpp @@ -305,6 +305,75 @@ public: */ bool Contains(const Type &aEntry) const { return Find(aEntry) != nullptr; } + /** + * This template method finds the first element in the array matching a given indicator. + * + * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against elements + * in the array. To check that an element matches the given indicator, the `Matches()` method is invoked on each + * `Type` element in the array. The `Matches()` method should be provided by `Type` class accordingly: + * + * bool Type::Matches(const Indicator &aIndicator) const + * + * @param[in] aIndicator An indicator to match with elements in the array. + * + * @returns A pointer to the matched array element, or nullptr if a match could not be found. + * + */ + template Type *FindMatching(const Indicator &aIndicator) + { + return const_cast(const_cast(this)->FindMatching(aIndicator)); + } + + /** + * This template method finds the first element in the array matching a given indicator. + * + * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against elements + * in the array. To check that an element matches the given indicator, the `Matches()` method is invoked on each + * `Type` element in the array. The `Matches()` method should be provided by `Type` class accordingly: + * + * bool Type::Matches(const Indicator &aIndicator) const + * + * @param[in] aIndicator An indicator to match with elements in the array. + * + * @returns A pointer to the matched array element, or nullptr if a match could not be found. + * + */ + template const Type *FindMatching(const Indicator &aIndicator) const + { + const Type *matched = nullptr; + + for (const Type &element : *this) + { + if (element.Matches(aIndicator)) + { + matched = &element; + break; + } + } + + return matched; + } + + /** + * This template method indicates whether or not the array contains an element matching a given indicator. + * + * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against elements + * in the array. To check that an element matches the given indicator, the `Matches()` method is invoked on each + * `Type` element in the array. The `Matches()` method should be provided by `Type` class accordingly: + * + * bool Type::Matches(const Indicator &aIndicator) const + * + * @param[in] aIndicator An indicator to match with elements in the array. + * + * @retval TRUE The array contains a matching element with @p aIndicator. + * @retval FALSE The array does not contain a matching element with @p aIndicator. + * + */ + template bool ContainsMatching(const Indicator &aIndicator) const + { + return FindMatching(aIndicator) != nullptr; + } + /** * This method overloads assignment `=` operator to copy elements from another array into the array. * diff --git a/tests/unit/test_array.cpp b/tests/unit/test_array.cpp index 2f1b68dc4..5b1e12783 100644 --- a/tests/unit/test_array.cpp +++ b/tests/unit/test_array.cpp @@ -171,7 +171,7 @@ void TestArray(void) VerifyOrQuit(array.IsEmpty()); } -void TestArrayCopy(void) +void TestArrayCopyAndFindMatching(void) { constexpr uint16_t kMaxSize = 10; @@ -186,6 +186,8 @@ void TestArrayCopy(void) } bool operator==(const Entry &aOther) { return (mName == aOther.mName) && (mYear == aOther.mYear); } + bool Matches(const char *aName) const { return strcmp(aName, mName) == 0; } + bool Matches(uint16_t aYear) const { return aYear == mYear; } const char *mName; uint16_t mYear; @@ -243,6 +245,33 @@ void TestArrayCopy(void) VerifyOrQuit(array2[index] == array4[index]); } } + + SuccessOrQuit(array2.PushBack(ps5)); + VerifyOrQuit(array2.GetLength() == 5); + + for (const Entry &entry : array2) + { + Entry *match; + + printf("- Name:%-3s Year:%d\n", entry.mName, entry.mYear); + + match = array2.FindMatching(entry.mName); + VerifyOrQuit(match != nullptr); + VerifyOrQuit(match == &entry); + VerifyOrQuit(array2.ContainsMatching(entry.mName)); + + match = array2.FindMatching(entry.mYear); + VerifyOrQuit(match != nullptr); + VerifyOrQuit(match == &entry); + VerifyOrQuit(array2.ContainsMatching(entry.mYear)); + } + + VerifyOrQuit(array2.FindMatching("PS6") == nullptr); + VerifyOrQuit(!array2.ContainsMatching("PS6")); + VerifyOrQuit(array2.FindMatching(static_cast(2001)) == nullptr); + VerifyOrQuit(!array2.ContainsMatching(static_cast(2001))); + + printf("\n"); } void TestArrayIndexType(void) @@ -261,7 +290,7 @@ void TestArrayIndexType(void) int main(void) { ot::TestArray(); - ot::TestArrayCopy(); + ot::TestArrayCopyAndFindMatching(); ot::TestArrayIndexType(); printf("All tests passed\n");