mCRL2
Loading...
Searching...
No Matches
embedded_list.h
Go to the documentation of this file.
1// Author(s): Jan Friso Groote
2// Copyright: see the accompanying file COPYING or copy at
3// https://github.com/mCRL2org/mCRL2/blob/master/COPYING
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8//
9/// \file lts/detail/embedded_list.h
10
11#ifndef MCRL2_LTS_DETAIL_EMBEDDED_LIST_H
12#define MCRL2_LTS_DETAIL_EMBEDDED_LIST_H
13
14#include <cassert>
15#include <vector>
16
17namespace mcrl2::lts::detail
18{
19
20// The list type below embeds a list in existing data structures.
21// For instance if elements are stored in a vector, and should also
22// be linked in a particular order in a list this data structure can be
23// used.
24//
25// For this purpose to each data structure that must be put in an embedded
26// list the embedded_list_node must be added to the data structure.
27//
28// From that point on the embedded_list data type can be used to construct
29// an embedded list. The data structure, once created will not require
30// extra memory.
31
32// prototype.
33template < class TYPE > class embedded_list;
34
35template <class TYPE>
37{
38
39 template < class T > friend class embedded_list;
40
41 protected:
42 TYPE* m_next; // Points to the next element in the list. The nullptr if it does not exist.
43 TYPE* m_prev; // Points to the current element in the list. The nullptr if it does not exist.
44};
45
46
47template < class TYPE >
49{
50 protected:
51 TYPE* m_first; // Points to the last element of the list. nulllptr if not valid.
52 TYPE* m_last; // Points to the first element of the list
53 std::size_t m_size = 0; // The number of elements in the list.
54
55 protected:
56
58 {
59 std::size_t count_up=0;
60 for(TYPE* walker=m_first; walker!=nullptr && count_up<=m_size ; walker=walker->m_next)
61 {
62 count_up++;
63 }
64
65 std::size_t count_down=0;
66 for(TYPE* walker=m_last; walker!=nullptr && count_down<=m_size ; walker=walker->m_prev)
67 {
68 count_down++;
69 }
70
71 return m_size==count_up && m_size==count_down;
72 }
73
74 bool check_presence(const TYPE& e) const
75 {
76 for(TYPE* walker=m_first; walker!=nullptr; walker=walker->m_next)
77 {
78 if (walker==&e)
79 {
80 return true;
81 }
82 }
83 return false;
84 }
85
86
87
88 public:
89
90 // Constructor.
92 : m_first(nullptr), m_last(nullptr)
93 {}
94
95 // Copy constructor.
96 embedded_list(const embedded_list& other) = default;
97
98 // Assignment.
99 embedded_list& operator=(const embedded_list& other) = default;
100
101 // get the size
102 std::size_t size() const
103 {
104 return m_size;
105 }
106
107 // Get the first element of the list.
108 TYPE& front()
109 {
110 assert(m_size>0);
111 return *m_first;
112 }
113
114 // Get the last element of the list.
115 TYPE& back()
116 {
117 assert(m_size>0);
118 return *m_last;
119 }
120
121 // Insert an element at the end of the list. Note that the element e is changed.
122 void push_back(TYPE& e)
123 {
124 if (m_first==nullptr)
125 {
126 assert(m_last==nullptr && m_size==0);
127 m_first= &e;
128 e.m_prev= nullptr;
129 }
130 else
131 {
132 assert(m_last!=nullptr && m_size>0);
133 e.m_prev=m_last;
134 m_last->m_next=&e;
135 }
136 e.m_next=nullptr;
137 m_last= &e;
138 m_size++;
140 }
141
142 // Insert an element at the begining of the list. Note that the element e is changed.
143 void push_front(TYPE& e)
144 {
145 if (m_last==nullptr)
146 {
147 assert(m_first==nullptr && m_size==0);
148 m_last= &e;
149 e.m_next= nullptr;
150 }
151 else
152 {
153 assert(m_first!=nullptr && m_size>0);
154 e.m_next=m_first;
155 m_first->m_prev=&e;
156 }
157 e.m_prev=nullptr;
158 m_first= &e;
159 m_size++;
161 }
162
163 // Erase this element from the list. The list is adapted such that it does not contain
164 // element e anymore. Postcondition: The previous and next pointer in e are invalid.
165 void erase(TYPE& e)
166 {
167 assert(check_presence(e));
168 if (e.m_next==nullptr)
169 {
170 assert(&e==m_last);
171 m_last=e.m_prev;
172 }
173 else
174 {
175 assert(e.m_next->m_prev!=nullptr);
176 e.m_next->m_prev = e.m_prev;
177 }
178
179 if (e.m_prev==nullptr)
180 {
181 assert(&e==m_first);
182 m_first=e.m_next;
183 }
184 else
185 {
186 assert(e.m_prev->m_next!=nullptr);
187 e.m_prev->m_next = e.m_next;
188 }
189
190 e.m_next= nullptr;
191 e.m_prev= nullptr;
192
193 m_size--;
194
196 }
197
198 void clear()
199 {
200 m_first=nullptr;
201 m_last=nullptr;
202 m_size=0;
203 }
204
205 /* Append the list l to the current list.
206 After this operation the list l is replaced by the empty list
207 to prevent unwanted sharing of lists. */
208
210 {
211 if (l.size()==0)
212 {
213 return;
214 }
215
216 if (m_size==0)
217 {
218 *this=l;
219 }
220 else
221 {
222 m_last->m_next=l.m_first;
223 l.m_first->m_prev=m_last;
224 m_last=l.m_last;
225 m_size=m_size+l.m_size;
226 }
227 // Explicitly invalidate l.
228 l.m_first=nullptr;
229 l.m_last=nullptr;
230 l.m_size=0;
231
233 }
234
236 {
237 protected:
238 TYPE* m_ptr;
239
240 public:
241
242 iterator(TYPE* p)
243 : m_ptr(p)
244 {}
245
246 // Prefix increment
248 {
249 iterator old=*this;
250 m_ptr=m_ptr->m_next;
251 return old;
252 }
253
254 // Postfix increment
256 {
257 m_ptr=m_ptr->m_next;
258 return *this;
259 }
260
261 // Dereference of the iterator.
262 TYPE& operator*()
263 {
264 return *m_ptr;
265 }
266
267 // Dereference of the iterator.
268 TYPE* operator->()
269 {
270 return m_ptr;
271 }
272
273 // Equality operator on iterators.
274 bool operator ==(const iterator& other) const
275 {
276 return m_ptr==other.m_ptr;
277 }
278 // Inequality operator on iterators.
279 bool operator !=(const iterator& other) const
280 {
281 return !(*this==other);
282 }
283
284 };
285
287 {
289 return m_first;
290 }
291
292 iterator end() const
293 {
294 return nullptr;
295 }
296
297};
298
299} // end namespace detail
300// end namespace lts
301// end namespace mcrl2
302#endif //MCRL2_LTS_DETAIL_EMBEDDED_LIST_H
bool operator==(const iterator &other) const
bool operator!=(const iterator &other) const
embedded_list(const embedded_list &other)=default
embedded_list & operator=(const embedded_list &other)=default
void append(embedded_list &l)
bool check_presence(const TYPE &e) const
The main LTS namespace.
std::size_t operator()(const std::vector< X > &v) const