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  */
50 template <typename Type> class OwningList : public LinkedList<Type>
51 {
52     class Iterator;
53     class ConstIterator;
54 
55 public:
56     /**
57      * This is the default constructor for `OwningList`
58      *
59      */
60     OwningList(void) = default;
61 
62     /**
63      * This is the destructor for `OwningList`.
64      *
65      * On destruction, all existing entries in the list are freed.
66      *
67      */
~OwningList(void)68     ~OwningList(void) { Free(); }
69 
70     /**
71      * Clears the list and frees all existing entries in it.
72      *
73      */
Free(void)74     void Free(void)
75     {
76         while (!Pop().IsNull())
77         {
78         }
79     }
80 
81     /**
82      * Clears the list and frees all existing entries in it.
83      *
84      */
Clear(void)85     void Clear(void) { Free(); }
86 
87     /**
88      * Pops an entry from head of the linked list and return an `OwnedPtr` to it.
89      *
90      * @note This method does not change the popped entry itself, i.e., the popped entry next pointer stays as before.
91      *
92      * @returns An `OwnedPtr` to the entry that was popped (set to null if list of empty).
93      *
94      */
Pop(void)95     OwnedPtr<Type> Pop(void) { return OwnedPtr<Type>(LinkedList<Type>::Pop()); }
96 
97     /**
98      * Pops an entry after a given previous entry.
99      *
100      * @note This method does not change the popped entry itself, i.e., the popped entry next pointer stays as before.
101      *
102      * @param[in] aPrevEntry  A pointer to a previous entry. If it is not `nullptr` the entry after this will be popped,
103      *                        otherwise (if it is `nullptr`) the entry at the head of the list is popped.
104      *
105      * @returns An `OwnedPtr` to the entry that was popped (set to null if there is no entry to pop).
106      *
107      */
PopAfter(Type * aPrevEntry)108     OwnedPtr<Type> PopAfter(Type *aPrevEntry) { return OwnedPtr<Type>(LinkedList<Type>::PopAfter(aPrevEntry)); }
109 
110     /**
111      * Removes an entry matching a given entry indicator from the linked list.
112      *
113      * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against entries
114      * in the list. To check that an entry matches the given indicator, the `Matches()` method is invoked on each
115      * `Type` entry in the list. The `Matches()` method should be provided by `Type` class accordingly:
116      *
117      *     bool Type::Matches(const Indicator &aIndicator) const
118      *
119      * @note This method does not change the removed entry itself (which is returned in case of success), i.e., the
120      * entry next pointer stays as before.
121      *
122      * @param[in] aIndicator   An entry indicator to match against entries in the list.
123      *
124      * @returns An `OwnedPtr` to the entry that was removed (set to null if there is no matching entry to remove).
125      *
126      */
RemoveMatching(const Indicator & aIndicator)127     template <typename Indicator> OwnedPtr<Type> RemoveMatching(const Indicator &aIndicator)
128     {
129         return OwnedPtr<Type>(LinkedList<Type>::RemoveMatching(aIndicator));
130     }
131 
132     /**
133      * Removes all entries in the list matching a given entry indicator from the list and adds
134      * them to a new list.
135      *
136      * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against entries
137      * in the list. To check that an entry matches the given indicator, the `Matches()` method is invoked on each
138      * `Type` entry in the list. The `Matches()` method should be provided by `Type` class accordingly:
139      *
140      *     bool Type::Matches(const Indicator &aIndicator) const
141      *
142      * The ownership of the removed entries is transferred from the original list to the @p aRemovedList.
143      *
144      * @param[in] aIndicator   An entry indicator to match against entries in the list.
145      * @param[in] aRemovedList The list to add the removed entries to.
146      *
147      */
RemoveAllMatching(const Indicator & aIndicator,OwningList & aRemovedList)148     template <typename Indicator> void RemoveAllMatching(const Indicator &aIndicator, OwningList &aRemovedList)
149     {
150         LinkedList<Type>::RemoveAllMatching(aIndicator, aRemovedList);
151     }
152 
153     /**
154      * Removes and frees all entries in the list matching a given entry indicator.
155      *
156      * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against entries
157      * in the list. To check that an entry matches the given indicator, the `Matches()` method is invoked on each
158      * `Type` entry in the list. The `Matches()` method should be provided by `Type` class accordingly:
159      *
160      *     bool Type::Matches(const Indicator &aIndicator) const
161      *
162      * @param[in] aIndicator   An entry indicator to match against entries in the list.
163      *
164      * @retval TRUE    At least one matching entry was removed.
165      * @retval FALSE   No matching entry was found.
166      *
167      */
RemoveAndFreeAllMatching(const Indicator & aIndicator)168     template <typename Indicator> bool RemoveAndFreeAllMatching(const Indicator &aIndicator)
169     {
170         OwningList removedList;
171 
172         RemoveAllMatching(aIndicator, removedList);
173         return !removedList.IsEmpty();
174     }
175 };
176 
177 } // namespace ot
178 
179 #endif // OWNING_LIST_HPP_
180