1 /*
2  *  Copyright (c) 2021, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes definitions for a singly linked list which owns its entries and frees them upon destruction of
32  *   the list.
33  */
34 
35 #ifndef OWNING_LIST_HPP_
36 #define OWNING_LIST_HPP_
37 
38 #include "openthread-core-config.h"
39 
40 #include "common/linked_list.hpp"
41 #include "common/owned_ptr.hpp"
42 
43 namespace ot {
44 
45 /**
46  * Represents a singly linked list which owns its entries and frees them upon destruction of the
47  * list.
48  */
49 template <typename Type> class OwningList : public LinkedList<Type>
50 {
51     class Iterator;
52     class ConstIterator;
53 
54 public:
55     /**
56      * This is the default constructor for `OwningList`
57      */
58     OwningList(void) = default;
59 
60     /**
61      * This is the destructor for `OwningList`.
62      *
63      * On destruction, all existing entries in the list are freed.
64      */
~OwningList(void)65     ~OwningList(void) { Free(); }
66 
67     /**
68      * Clears the list and frees all existing entries in it.
69      */
Free(void)70     void Free(void)
71     {
72         while (!Pop().IsNull())
73         {
74         }
75     }
76 
77     /**
78      * Clears the list and frees all existing entries in it.
79      */
Clear(void)80     void Clear(void) { Free(); }
81 
82     /**
83      * Pops an entry from head of the linked list and return an `OwnedPtr` to it.
84      *
85      * @note This method does not change the popped entry itself, i.e., the popped entry next pointer stays as before.
86      *
87      * @returns An `OwnedPtr` to the entry that was popped (set to null if list of empty).
88      */
Pop(void)89     OwnedPtr<Type> Pop(void) { return OwnedPtr<Type>(LinkedList<Type>::Pop()); }
90 
91     /**
92      * Pops an entry after a given previous entry.
93      *
94      * @note This method does not change the popped entry itself, i.e., the popped entry next pointer stays as before.
95      *
96      * @param[in] aPrevEntry  A pointer to a previous entry. If it is not `nullptr` the entry after this will be popped,
97      *                        otherwise (if it is `nullptr`) the entry at the head of the list is popped.
98      *
99      * @returns An `OwnedPtr` to the entry that was popped (set to null if there is no entry to pop).
100      */
PopAfter(Type * aPrevEntry)101     OwnedPtr<Type> PopAfter(Type *aPrevEntry) { return OwnedPtr<Type>(LinkedList<Type>::PopAfter(aPrevEntry)); }
102 
103     /**
104      * Removes an entry matching a given set of conditions from the linked list.
105      *
106      * To check that an entry matches, the `Matches()` method is invoked on each `Type` entry in the list. The
107      * `Matches()` method with the same set of `Args` input types should be provided by the `Type` class accordingly:
108      *
109      *      bool Type::Matches(const Args &...) const
110      *
111      * @note This method does not change the removed entry itself (which is returned in case of success), i.e., the
112      * entry next pointer stays as before.
113      *
114      * @param[in]  aArgs       The args to pass to `Matches()`.
115      *
116      * @returns An `OwnedPtr` to the entry that was removed (set to null if there is no matching entry to remove).
117      */
RemoveMatching(const Args &...aArgs)118     template <typename... Args> OwnedPtr<Type> RemoveMatching(const Args &...aArgs)
119     {
120         return OwnedPtr<Type>(LinkedList<Type>::RemoveMatching(aArgs...));
121     }
122 
123     /**
124      * Removes all entries in the list matching given set of conditions from the list and adds them to a new list.
125      *
126      * To check that an entry matches, the `Matches()` method is invoked on each `Type` entry in the list. The
127      * `Matches()` method with the same set of `Args` input types should be provided by the `Type` class accordingly:
128      *
129      *      bool Type::Matches(const Args &...) const
130      *
131      * The ownership of the removed entries is transferred from the original list to the @p aRemovedList.
132      *
133      * @param[in] aRemovedList The list to add the removed entries to.
134      * @param[in] aArgs       The args to pass to `Matches()`.
135      */
RemoveAllMatching(OwningList & aRemovedList,const Args &...aArgs)136     template <typename... Args> void RemoveAllMatching(OwningList &aRemovedList, const Args &...aArgs)
137     {
138         LinkedList<Type>::RemoveAllMatching(aRemovedList, aArgs...);
139     }
140 
141     /**
142      * Removes and frees all entries in the list matching a given set of conditions.
143      *
144      * To check that an entry matches, the `Matches()` method is invoked on each `Type` entry in the list. The
145      * `Matches()` method with the same set of `Args` input types should be provided by the `Type` class accordingly:
146      *
147      *      bool Type::Matches(const Args &...) const
148      *
149      * @param[in] aArgs       The args to pass to `Matches()`.
150      *
151      * @retval TRUE    At least one matching entry was removed.
152      * @retval FALSE   No matching entry was found.
153      */
RemoveAndFreeAllMatching(const Args &...aArgs)154     template <typename... Args> bool RemoveAndFreeAllMatching(const Args &...aArgs)
155     {
156         OwningList removedList;
157 
158         RemoveAllMatching(removedList, aArgs...);
159         return !removedList.IsEmpty();
160     }
161 };
162 
163 } // namespace ot
164 
165 #endif // OWNING_LIST_HPP_
166