ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
bidilist.hpp
Go to the documentation of this file.
1/** ************************************************************************************************
2 * \file
3 * This header file is part of the \aliblong. It does not belong to an \alibmod and is
4 * included in any \alibdist.
5 *
6 * \emoji :copyright: 2013-2024 A-Worx GmbH, Germany.
7 * Published under \ref mainpage_license "Boost Software License".
8 **************************************************************************************************/
9#ifndef HPP_ALIB_LANG_BIDILIST
10#define HPP_ALIB_LANG_BIDILIST 1
11
12#if !defined(HPP_ALIB_LANG_SIDILIST)
13# include "alib/lang/sidilist.hpp"
14#endif
15
16#if !defined(HPP_ALIB_LANG_TMP) && !defined(ALIB_DOX)
17# include "alib/lang/tmp.hpp"
18#endif
19
20namespace alib::lang {
21
22/** ************************************************************************************************
23 * This is a generic base type that represents a node of a doubly (bidirectional) linked lists.
24 * The effective (instantiated) nodes of the list are to be derived from this type with specifying
25 * their very own type name as template parameter \p{TElement}. For more information on this
26 * design, see explanations of parent type \alib{lang::SidiNodeBase}.
27 *
28 * By being derived from aforementioned type, instances of \p{TElement} may also be added
29 * to single-linked lists of type \alib{lang::SidiListHelper}). This is for example
30 * used by types \alib{monomem;List} and \alib{monomem;HashTable} to collect erased list elements
31 * for recycling.
32 *
33 * \see Types \alib{lang::SidiNodeBase},<br>
34 * \alib{lang::SidiListHelper} and<br>
35 * \alib{lang::BidiListHelper}.
36 *
37 * @tparam TElement The "final" node type, containing custom data fields, that is to be derived from
38 * this struct.
39 **************************************************************************************************/
40template<typename TElement>
41struct BidiNodeBase : public SidiNodeBase<TElement>
42{
43 /** Alias name for the an instantiation of the base template. */
45
46 /** A pointer to the previous element in the list.
47 * \attention
48 * If this is the first node in the list, this object will point to the list hook, which is
49 * an instance of this type instead of template type \p{TElement}. */
50 TElement* pprev;
51
52 /** Default constructor. (Does not initialize the pointer!) */
53 BidiNodeBase() noexcept = default;
54
55 /** Deleted copy constructor. This is deleted because it is dangerous, respectively often
56 * not possible and also mostly not wanted to be able to create copies of derived type
57 * \p{TElement} */
58 BidiNodeBase( const BidiNodeBase& ) = delete;
59
60 /** Defaulted move constructor. */
61 BidiNodeBase( BidiNodeBase&& ) noexcept = default;
62
63 /** Deleted copy assignment operator. This is deleted because it is dangerous, respectively
64 * often not possible and also mostly not wanted to created copies of derived type
65 * \p{TElement}
66 * @return Not defined.*/
67 BidiNodeBase& operator=( const BidiNodeBase& ) = delete;
68
69 /** Defaulted move assignment operator.
70 * @return A reference to this object.*/
71
72 BidiNodeBase& operator=( BidiNodeBase&& ) noexcept = default;
73
74 /** Constructor accepting a pointer to the next and previous elements.
75 * @param next Pointer to the next element. Assigned to inherited field
76 * \alib{lang::SidiNodeBase::pnext}.
77 * @param prev Pointer to the next element. Assigned to field #pprev. */
78 BidiNodeBase( TElement* next, TElement* prev ) noexcept
79 : SidiNodeBase<TElement>(next)
80 , pprev (prev)
81 {}
82
83 /** Returns the backward pointer of this node.
84 * @return Pointer to the previous element. */
85 TElement* prev() const { return pprev; }
86
87 /** Sets the backward pointer of this node.
88 * @param newPrev Pointer to the previous element. */
89 void prev(BidiNodeBase* newPrev) { pprev = static_cast<TElement*>(newPrev); }
90
91 /** Hooks the given element before this node.
92 * @param elem The element to add. */
93 void addBefore( TElement* elem )
94 {
95 elem->next( this );
96 elem->prev( prev() );
97 prev()->next(elem);
98 prev(elem);
99 }
100
101 /** Hooks the given element behind this node.
102 * @param elem The element to add. */
103 void addBehind( TElement* elem )
104 {
105 elem->next( FWDNode::next() );
106 elem->prev( this );
107 FWDNode::next()->prev( elem );
108 FWDNode::next( elem );
109 }
110
111 /** Unhooks this node from a list. */
112 void remove()
113 {
114 FWDNode::next()->prev(prev());
115 prev()->next( FWDNode::next());
116 }
117
118 /** Unhooks the range of nodes starting with this node and ending with \p{last} a list.
119 * @param last The last element of the range to remove. */
120 void remove( TElement* last )
121 {
122 last->next()->prev( prev() );
123 prev()->next( last->next() );
124 }
125
126}; // struct BidiNodeBase
127
128/** ************************************************************************************************
129 * This struct, together with sibling struct \alib{lang::BidiNodeBase} provide the tools to
130 * implement a doubly linked list of \p{TElement} instances.<br>
131 *
132 * Template type \p{TElement} have to extend struct BidiNodeBase<TElement>.
133 *
134 * \see Types \alib{lang::SidiNodeBase},<br>
135 * \alib{lang::SidiListHelper} and<br>
136 * \alib{lang::BidiNodeBase}.
137 *
138 * @tparam TElement The "final" custom type that (by contract) is derived from
139 * \alib{lang::BidiNodeBase}.
140 **************************************************************************************************/
141template<typename TElement>
143{
144 /** An alias for the base type of the node type of this list. */
146
147 /** An alias for the node type of this list. */
149
150 /** The root node. Points twice to itself when list is empty. */
152
153 /** Default constructor. Initializes this list to be empty. */
154 BidiListHelper() noexcept
155 {
156 hook.next(&hook);
157 hook.prev(&hook);
158 }
159
160 /** Deleted copy constructor. */
161 BidiListHelper( const BidiListHelper& ) = delete;
162
163 /** Move constructor. Takes elements of \p move and sets \p move to empty.
164 * @param move The list to move.
165 */
167 {
168 if( !move.isEmpty() )
169 {
170 hook.next( move.hook.next() );
171 hook.prev(move.hook.prev());
172 move.reset();
173 }
174 else
175 reset();
176 }
177
178 /** Deleted copy assignment operator.
179 * @return A reference to this list object. */
181
182 /** Defaulted move assignment operator.
183 * @return A reference to this list object. */
184 BidiListHelper& operator= ( BidiListHelper&&) noexcept = default;
185
186 /** Constructor accepting a pointer to the first element.
187 * @param first The element to use as the first element of this list. */
189 {
190 hook.next( first );
191 hook.prev( first );
192 first->next( &hook );
193 first->prev( &hook );
194 }
195
196 /** Constructor accepting a pointer to the first and last element.
197 * @param first The element to use as the first element of this list.
198 * @param last The element to use as the last element of this list. */
199 BidiListHelper( TElement* first, TElement* last )
200 {
201 hook.next( first );
202 hook.prev( last );
203 first->prev( &hook );
204 last->next( &hook );
205 }
206
207 /** Tests if this list is empty.
208 * @return \c false if the list is empty, \c true otherwise. */
209 bool isEmpty() const
210 {
211 return hook.pointsTo( &hook );
212 }
213
214 /** Resets this list to zero elements. */
215 void reset()
216 {
217 hook.next(&hook);
218 hook.prev(&hook);
219 }
220
221 /** Returns a pointer to the #hook node casted to a pointer to a mutable element.
222 * This method must only be used in cases where such conversion is allowed, i.e. with
223 * iterator types that use this pointer exclusively for pointer value comparison, but do not
224 * allow (by contract) to dereference or otherwise use this pointer.
225 * @return The first element of this list. */
226 TElement* end() const
227 {
228 return static_cast<TElement*>( &const_cast<BidiListHelper*>(this)->hook );
229 }
230
231
232 /** Returns the first element of this list.
233 * @return The first element of this list. */
234 TElement* first() const
235 {
236 return hook.next();
237 }
238
239 /** Returns the last element of this list.
240 * @return The last element of this list. */
241 TElement* last() const
242 {
243 return hook.prev();
244 }
245
246 /** Tests if given \p{elem} is the first element of this list.
247 * @param elem The element to test for being the first.
248 * @return \c true if \p{elem} is the first element of this list, \c false otherwise. */
249 bool isFirst( const TElement* elem ) const
250 {
251 return first() == elem;
252 }
253
254 /** Tests if given \p{elem} is the last element of this list.
255 * @param elem The element to test for being the last.
256 * @return \c true if \p{elem} is the last element of this list, \c false otherwise. */
257 bool isLast( const TElement* elem ) const
258 {
259 return last() == elem;
260 }
261
262 /** Hooks the given element to the beginning of this list.
263 * @param elem The element to insert to at the start. */
264 void pushFront( TElement* elem )
265 {
266 hook.addBehind( elem );
267 }
268
269 /** Hooks the given range of elements to the front of this list.
270 * @param first The first element of the range to insert.
271 * @param last The last element of the range to insert. */
272 void pushFront( TElement* first, TElement* last )
273 {
275 }
276
277 /** Hooks the given element to the end of this list.
278 * @param elem The element to insert to at the start. */
279 void pushEnd( TElement* elem )
280 {
281 hook.addBefore( elem );
282 }
283
284 /** Hooks the given range of elements to the end of this list.
285 * @param first The first element of the range to insert.
286 * @param last The last element of the range to insert. */
287 void pushEnd( TElement* first, TElement* last )
288 {
290 }
291
292 /** Removes and returns the first element from this list.
293 * Must not be invoked on empty lists.
294 * @return A pointer to the first element (which was removed). */
295 TElement* popFront()
296 {
297 TElement* first= hook.next();
298 first->remove();
299 return first;
300 }
301
302 /** Removes and returns the last element from this list.
303 * Must not be invoked on empty lists.
304 * @return A pointer to the last element (which was removed). */
305 TElement* popEnd()
306 {
307 TElement* last= hook.prev();
308 last->remove();
309 return last;
310 }
311
312 /** Counts the number of elements found in the range starting with this list's first element and
313 * ending with the element before \p{end}.
314 * @param end The element after the last one to count.
315 * Defaults to a \c nullptr marking the end of the list.
316 * @return The number of elements in the range. */
317 integer count( const TNode* end= nullptr ) const
318 {
319 if( end == nullptr )
320 end= &hook;
321
322 integer count= 0;
323 const TNode* node= hook.next();
324 while( node != end )
325 {
326 node= node->next();
327 ++count;
328 }
329 return count;
330 }
331}; // struct BidiListHelper
332
333
334} // namespace [alib::detail]
335
336
337#endif // HPP_ALIB_LANG_BIDILIST
platform_specific integer
Definition integers.hpp:50
bool isFirst(const TElement *elem) const
Definition bidilist.hpp:249
void pushFront(TElement *elem)
Definition bidilist.hpp:264
BidiListHelper & operator=(const BidiListHelper &)=delete
TElement * end() const
Definition bidilist.hpp:226
integer count(const TNode *end=nullptr) const
Definition bidilist.hpp:317
BidiListHelper(TElement *first, TElement *last)
Definition bidilist.hpp:199
BidiListHelper(const BidiListHelper &)=delete
BidiListHelper(BidiListHelper &&move) noexcept
Definition bidilist.hpp:166
void pushEnd(TElement *first, TElement *last)
Definition bidilist.hpp:287
TElement * last() const
Definition bidilist.hpp:241
TElement * first() const
Definition bidilist.hpp:234
void pushEnd(TElement *elem)
Definition bidilist.hpp:279
bool isLast(const TElement *elem) const
Definition bidilist.hpp:257
void pushFront(TElement *first, TElement *last)
Definition bidilist.hpp:272
void remove(TElement *last)
Definition bidilist.hpp:120
void addBefore(TElement *elem)
Definition bidilist.hpp:93
TElement * prev() const
Definition bidilist.hpp:85
void prev(BidiNodeBase *newPrev)
Definition bidilist.hpp:89
BidiNodeBase() noexcept=default
void addBehind(TElement *elem)
Definition bidilist.hpp:103
TElement * next() const
Definition sidilist.hpp:112
void next(SidiNodeBase *p)
Definition sidilist.hpp:107
bool pointsTo(const SidiNodeBase *elem) const
Definition sidilist.hpp:121