[array] add Remove() and RemoveMatching() (#7817)

This commit adds `Remove/RemoveMatching()` in `Array` class which
remove a given or a matched element from the array. To remove the
element, it is replaced by the last element from array, so the order
of items in the array can change after call to these method.

This commit also updated unit test `test_array` to verify the behavior
of newly added methods.
This commit is contained in:
Abtin Keshavarzian
2022-06-16 21:26:03 -07:00
committed by Jonathan Hui
parent a5d39c3ec3
commit aad14e9f2f
2 changed files with 95 additions and 2 deletions
+47
View File
@@ -310,6 +310,27 @@ public:
*/
IndexType IndexOf(const Type &aElement) const { return static_cast<IndexType>(&aElement - &mElements[0]); }
/**
* This method removes an element from the array.
*
* The @p aElement MUST be from the array, otherwise the behavior of this method is undefined.
*
* To remove @p aElement, it is replaced by the last element in array, so the order of items in the array can
* change after a call to this method.
*
* The method uses assignment `=` operator on `Type` to copy the last element in place of @p aElement.
*
*/
void Remove(Type &aElement)
{
Type *lastElement = PopBack();
if (lastElement != &aElement)
{
aElement = *lastElement;
}
}
/**
* This method finds the first match of a given entry in the array.
*
@@ -430,6 +451,32 @@ public:
return FindMatching(aIndicator) != nullptr;
}
/**
* This template method removes the first element in the array matching a given indicator.
*
* This method behaves similar to `Remove()`, i.e., the matched element (if found) is replaced with the last element
* in the array (using `=` operator on `Type`). So the order of items in the array can change after a call to this
* method.
*
* 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.
*
*/
template <typename Indicator> void RemoveMatching(const Indicator &aIndicator)
{
Type *entry = FindMatching(aIndicator);
if (entry != nullptr)
{
Remove(*entry);
}
}
/**
* This method overloads assignment `=` operator to copy elements from another array into the array.
*
+48 -2
View File
@@ -35,6 +35,7 @@
#include "common/array.hpp"
#include "common/debug.hpp"
#include "common/equatable.hpp"
#include "common/instance.hpp"
#include "common/type_traits.hpp"
@@ -175,7 +176,7 @@ void TestArrayCopyAndFindMatching(void)
{
constexpr uint16_t kMaxSize = 10;
struct Entry
struct Entry : public Unequatable<Entry>
{
Entry(void) = default;
@@ -185,7 +186,7 @@ void TestArrayCopyAndFindMatching(void)
{
}
bool operator==(const Entry &aOther) { return (mName == aOther.mName) && (mYear == aOther.mYear); }
bool operator==(const Entry &aOther) const { 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; }
@@ -271,6 +272,51 @@ void TestArrayCopyAndFindMatching(void)
VerifyOrQuit(array2.FindMatching(static_cast<uint16_t>(2001)) == nullptr);
VerifyOrQuit(!array2.ContainsMatching(static_cast<uint16_t>(2001)));
// Test removing of entries at every index.
array1 = array2;
for (const Entry &entryToRemove : array1)
{
Entry *match;
// Test `Remove()`
array2 = array1;
match = array2.Find(entryToRemove);
VerifyOrQuit(match != nullptr);
array2.Remove(*match);
VerifyOrQuit(array2.GetLength() == array1.GetLength() - 1);
for (const Entry &entry : array2)
{
VerifyOrQuit(entry != entryToRemove);
VerifyOrQuit(array1.Contains(entry));
}
// Test `RemoveMatching()`
array2 = array1;
array2.RemoveMatching(entryToRemove.mName);
printf("\nArray after `RemoveMatching()` on entry %s\n", entryToRemove.mName);
VerifyOrQuit(array2.GetLength() == array1.GetLength() - 1);
for (const Entry &entry : array2)
{
printf("- Name:%-3s Year:%d\n", entry.mName, entry.mYear);
VerifyOrQuit(entry != entryToRemove);
VerifyOrQuit(array1.Contains(entry));
}
// Test `RemoveMatchin()` with a non-existing match
array2.RemoveMatching(entryToRemove.mName);
VerifyOrQuit(array2.GetLength() == array1.GetLength() - 1);
}
printf("\n");
}