diff --git a/src/core/common/array.hpp b/src/core/common/array.hpp index a9d5c52d9..eb6da8740 100644 --- a/src/core/common/array.hpp +++ b/src/core/common/array.hpp @@ -491,6 +491,34 @@ public: return FindMatching(aIndicator) != nullptr; } + /** + * Counts the number of elements 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 The number of elements in the array matching @p aIndicator. + */ + template SizeType CountMatching(const Indicator &aIndicator) const + { + SizeType count = 0; + + for (const Type &element : *this) + { + if (element.Matches(aIndicator)) + { + count++; + } + } + + return count; + } + /** * Removes the first element in the array matching a given indicator. * @@ -572,17 +600,17 @@ public: } /** - * Indicates whether a given entry pointer is from the array buffer. + * Indicates whether a given pointer is from the array buffer. * * Does not check the current length of array and only checks that @p aEntry is pointing to an address * contained within underlying C array buffer. * - * @param[in] aEntry A pointer to an entry to check. + * @param[in] aEntry A pointer to check. * * @retval TRUE The @p aEntry is from the array. * @retval FALSE The @p aEntry is not from the array. */ - bool IsInArrayBuffer(const Type *aEntry) const + bool IsInArrayBuffer(const void *aEntry) const { return (&mElements[0] <= aEntry) && (aEntry < GetArrayEnd(mElements)); } diff --git a/src/core/thread/child_table.cpp b/src/core/thread/child_table.cpp index d95c10dc5..35ec5b7e7 100644 --- a/src/core/thread/child_table.cpp +++ b/src/core/thread/child_table.cpp @@ -54,7 +54,7 @@ void ChildTable::Iterator::Reset(void) { mItem = &Get().mChildren[0]; - if (!mItem->MatchesFilter(mFilter)) + if (!mItem->Matches(mFilter)) { Advance(); } @@ -67,8 +67,8 @@ void ChildTable::Iterator::Advance(void) do { mItem++; - VerifyOrExit(mItem < &Get().mChildren[Get().mMaxChildrenAllowed], mItem = nullptr); - } while (!mItem->MatchesFilter(mFilter)); + VerifyOrExit(mItem < Get().mChildren.end(), mItem = nullptr); + } while (!mItem->Matches(mFilter)); exit: return; @@ -83,8 +83,9 @@ ChildTable::ChildTable(Instance &aInstance) , mMaxChildIpAddresses(0) #endif , mNextChildId(Mle::kMaxChildId) - , mMaxChildrenAllowed(kMaxChildren) { + mChildren.SetLength(kMaxChildren); + for (Child &child : mChildren) { child.Init(aInstance); @@ -100,16 +101,7 @@ void ChildTable::Clear(void) } } -Child *ChildTable::GetChildAtIndex(uint16_t aChildIndex) -{ - Child *child = nullptr; - - VerifyOrExit(aChildIndex < mMaxChildrenAllowed); - child = &mChildren[aChildIndex]; - -exit: - return child; -} +Child *ChildTable::GetChildAtIndex(uint16_t aChildIndex) { return mChildren.At(aChildIndex); } Child *ChildTable::GetNewChild(void) { @@ -144,20 +136,7 @@ uint16_t ChildTable::AllocateNewChildRloc16(void) const Child *ChildTable::FindChild(const Child::AddressMatcher &aMatcher) const { - const Child *child = mChildren; - - for (uint16_t num = mMaxChildrenAllowed; num != 0; num--, child++) - { - if (child->Matches(aMatcher)) - { - ExitNow(); - } - } - - child = nullptr; - -exit: - return child; + return mChildren.FindMatching(aMatcher); } Child *ChildTable::FindChild(uint16_t aRloc16, Child::StateFilter aFilter) @@ -177,24 +156,10 @@ Child *ChildTable::FindChild(const Mac::Address &aMacAddress, Child::StateFilter bool ChildTable::HasChildren(Child::StateFilter aFilter) const { - return (FindChild(Child::AddressMatcher(aFilter)) != nullptr); + return mChildren.ContainsMatching(Child::AddressMatcher(aFilter)); } -uint16_t ChildTable::GetNumChildren(Child::StateFilter aFilter) const -{ - uint16_t numChildren = 0; - const Child *child = mChildren; - - for (uint16_t num = mMaxChildrenAllowed; num != 0; num--, child++) - { - if (child->MatchesFilter(aFilter)) - { - numChildren++; - } - } - - return numChildren; -} +uint16_t ChildTable::GetNumChildren(Child::StateFilter aFilter) const { return mChildren.CountMatching(aFilter); } Error ChildTable::SetMaxChildrenAllowed(uint16_t aMaxChildren) { @@ -203,7 +168,7 @@ Error ChildTable::SetMaxChildrenAllowed(uint16_t aMaxChildren) VerifyOrExit(aMaxChildren > 0 && aMaxChildren <= kMaxChildren, error = kErrorInvalidArgs); VerifyOrExit(!HasChildren(Child::kInStateAnyExceptInvalid), error = kErrorInvalidState); - mMaxChildrenAllowed = aMaxChildren; + mChildren.SetLength(aMaxChildren); exit: return error; @@ -325,18 +290,16 @@ Error ChildTable::StoreChild(const Child &aChild) void ChildTable::RefreshStoredChildren(void) { - const Child *child = &mChildren[0]; - Get().DeleteAllChildInfo(); - for (uint16_t num = mMaxChildrenAllowed; num != 0; num--, child++) + for (const Child &child : mChildren) { - if (child->IsStateInvalid()) + if (child.IsStateInvalid()) { continue; } - SuccessOrExit(StoreChild(*child)); + SuccessOrExit(StoreChild(child)); } exit: @@ -361,12 +324,11 @@ exit: bool ChildTable::HasSleepyChildWithAddress(const Ip6::Address &aIp6Address) const { - bool hasChild = false; - const Child *child = &mChildren[0]; + bool hasChild = false; - for (uint16_t num = mMaxChildrenAllowed; num != 0; num--, child++) + for (const Child &child : mChildren) { - if (child->IsStateValidOrRestoring() && !child->IsRxOnWhenIdle() && child->HasIp6Address(aIp6Address)) + if (child.IsStateValidOrRestoring() && !child.IsRxOnWhenIdle() && child.HasIp6Address(aIp6Address)) { hasChild = true; break; diff --git a/src/core/thread/child_table.hpp b/src/core/thread/child_table.hpp index ac2d547ee..af64f2da6 100644 --- a/src/core/thread/child_table.hpp +++ b/src/core/thread/child_table.hpp @@ -38,6 +38,7 @@ #if OPENTHREAD_FTD +#include "common/array.hpp" #include "common/const_cast.hpp" #include "common/iterator_utils.hpp" #include "common/locator.hpp" @@ -115,7 +116,7 @@ public: * * @returns The index corresponding to @p aChild. */ - uint16_t GetChildIndex(const Child &aChild) const { return static_cast(&aChild - mChildren); } + uint16_t GetChildIndex(const Child &aChild) const { return mChildren.IndexOf(aChild); } /** * Returns a pointer to a `Child` entry at a given index, or `nullptr` if the index is out of bounds, @@ -207,7 +208,7 @@ public: * * @returns The maximum number of children allowed. */ - uint16_t GetMaxChildrenAllowed(void) const { return mMaxChildrenAllowed; } + uint16_t GetMaxChildrenAllowed(void) const { return mChildren.GetLength(); } /** * Sets the maximum number of children allowed. @@ -306,12 +307,7 @@ public: * @retval TRUE if @p aNeighbor is a `Child` in the child table. * @retval FALSE if @p aNeighbor is not a `Child` in the child table. */ - bool Contains(const Neighbor &aNeighbor) const - { - const void *child = &aNeighbor; - - return (mChildren <= child) && (child < GetArrayEnd(mChildren)); - } + bool Contains(const Neighbor &aNeighbor) const { return mChildren.IsInArrayBuffer(&aNeighbor); } /** * Gets the maximum number of IP addresses that each MTD child may register with this device as parent. @@ -376,9 +372,8 @@ private: #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE uint8_t mMaxChildIpAddresses; #endif - uint16_t mNextChildId; - uint16_t mMaxChildrenAllowed; - Child mChildren[kMaxChildren]; + Array mChildren; + uint16_t mNextChildId; }; } // namespace ot diff --git a/src/core/thread/neighbor.cpp b/src/core/thread/neighbor.cpp index 9fceb275d..77c7b1a9c 100644 --- a/src/core/thread/neighbor.cpp +++ b/src/core/thread/neighbor.cpp @@ -60,7 +60,7 @@ bool Neighbor::AddressMatcher::Matches(const Neighbor &aNeighbor) const { bool matches = false; - VerifyOrExit(aNeighbor.MatchesFilter(mStateFilter)); + VerifyOrExit(aNeighbor.Matches(mStateFilter)); if (mShortAddress != Mac::kShortAddrInvalid) { @@ -130,7 +130,7 @@ bool Neighbor::IsStateValidOrAttaching(void) const return rval; } -bool Neighbor::MatchesFilter(StateFilter aFilter) const +bool Neighbor::Matches(StateFilter aFilter) const { bool matches = false; diff --git a/src/core/thread/neighbor.hpp b/src/core/thread/neighbor.hpp index 2d9b8b9de..5e621b448 100644 --- a/src/core/thread/neighbor.hpp +++ b/src/core/thread/neighbor.hpp @@ -289,7 +289,7 @@ public: * * @returns TRUE if the neighbor state matches the filter, FALSE otherwise. */ - bool MatchesFilter(StateFilter aFilter) const; + bool Matches(StateFilter aFilter) const; /** * Indicates whether neighbor matches a given `AddressMatcher`. diff --git a/src/core/thread/peer_table.cpp b/src/core/thread/peer_table.cpp index f4b19d645..bdda52224 100644 --- a/src/core/thread/peer_table.cpp +++ b/src/core/thread/peer_table.cpp @@ -51,7 +51,7 @@ void PeerTable::Iterator::Reset(void) { mItem = &Get().mPeers[0]; - if (!mItem->MatchesFilter(mFilter)) + if (!mItem->Matches(mFilter)) { Advance(); } @@ -65,7 +65,7 @@ void PeerTable::Iterator::Advance(void) { mItem++; VerifyOrExit(mItem < &Get().mPeers[Get().kMaxPeers], mItem = nullptr); - } while (!mItem->MatchesFilter(mFilter)); + } while (!mItem->Matches(mFilter)); exit: return; diff --git a/src/core/thread/router_table.hpp b/src/core/thread/router_table.hpp index 502690108..824c92f6d 100644 --- a/src/core/thread/router_table.hpp +++ b/src/core/thread/router_table.hpp @@ -277,10 +277,7 @@ public: * @retval FALSE if @p aNeighbor is not a `Router` in the router table * (i.e. it can be the parent or parent candidate, or a `Child` of the child table). */ - bool Contains(const Neighbor &aNeighbor) const - { - return mRouters.IsInArrayBuffer(&static_cast(aNeighbor)); - } + bool Contains(const Neighbor &aNeighbor) const { return mRouters.IsInArrayBuffer(&aNeighbor); } /** * Retains diagnostic information for a given router.