VLC 4.0.0-dev
Loading...
Searching...
No Matches
vlc_list.hpp
Go to the documentation of this file.
1/******************************************************************************
2 * vlc_list.hpp: C++ wrappers on top of vlc_list
3 ******************************************************************************
4 * Copyright © 2024 Videolabs
5 *
6 * Authors: Alexandre Janniaux <ajanni@videolabs.io>
7 * Pierre Lamot <pierre@videolabs.io>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
23
24#ifndef VLC_LIST_HPP
25#define VLC_LIST_HPP 1
26
27#include <vlc_list.h>
28
29#include <iterator>
30#include <type_traits>
31
32namespace vlc
33{
34
35/**
36 * \defgroup cpp_list Linked lists (C++ wrappers)
37 * \ingroup cext
38 * @{
39 * \file
40 * This provides convenience helpers for using the C linked lists extension
41 * from C++ files.
42 *
43 * A list wrapper should be used on an existing list:
44 *
45 * \code
46 * struct item {
47 * // ...
48 * vlc_list node;
49 * }
50 *
51 * struct vlc_list c_list;
52 * vlc_list_init(&c_list);
53 * // ...
54 * auto list = vlc::from(&list, &item::node);
55 * \endcode
56 *
57 * Using `vlc::from` will automatically select the correct variant for
58 * the list depending on the constness of the `vlc_list` list, and it
59 * can allow only iteration if the list is const.
60 *
61 * Iteration includes standard iterators and for range-based loops, as well
62 * as reversed list.
63 *
64 * \code
65 * for (auto it = list.begin(); it != list.end(); ++it)
66 * {
67 * // (*it) is of type `struct item`
68 * }
69 *
70 * for (auto &elem : vlc::from(&c_list, &item::node))
71 * {
72 * // `elem` type is `struct item`
73 * // ...
74 * }
75 *
76 * for (auto &elem : vlc::from(&c_list, &item::node).as_reverse())
77 * {
78 * // `elem` type is `struct item`
79 * // ...
80 * }
81 * \endcode
82 *
83 */
84
85/**
86 * Compare two vlc_list node and check whether they represent the same element.
87 * If the element is not in a list itself, or is not a list itself, then the
88 * result is undefined.
89 *
90 * \param a some node belonging to a vlc_list
91 * \param b some node belonging to a vlc_list
92 * \return true if they represent the same element or the same list,
93 * false otherwise
94 **/
95bool operator==(const ::vlc_list& a, const ::vlc_list& b)
96{
97 return a.prev == b.prev && a.next == b.next;
98}
99
100/**
101 * Compare two vlc_list node and check whether they representthe same element.
102 * If the element is not in a list itself, or is not a list itself, then the
103 * result is undefined.
104 *
105 * \param a some node belonging to a vlc_list
106 * \param b some node belonging to a vlc_list
107 * \return false if they represent the same element or the same list,
108 * true otherwise
109 **/
110bool operator!=(const ::vlc_list& a, const ::vlc_list& b)
111{
112 return !(a == b);
113}
114
115/**
116 * Base class for iterators on the vlc::list's vlc_list wrapper.
117 *
118 * The base class c
119 *
120 * \tparam NodeType the type of each node from the list
121 * \tparam ListType either vlc_list or const vlc_list
122 */
123template <typename NodeType, typename ListType>
125protected:
126 ListType* _current, *_next, *_prev;
127 vlc_list NodeType::* _node_ptr;
128
129 constexpr std::ptrdiff_t offset() const {
130 return reinterpret_cast<std::ptrdiff_t>(
131 &(static_cast<NodeType const volatile*>(NULL)->*_node_ptr)
132 );
133 }
134
135 static constexpr bool is_const = std::is_const<ListType>::value;
136
137public:
138 using iterator_category = std::bidirectional_iterator_tag;
139 using value_type = std::conditional_t<is_const, const NodeType, NodeType>;
140 using pointer = std::conditional_t<is_const, const NodeType*, NodeType*>;
141 using reference = std::conditional_t<is_const, const NodeType&, NodeType&>;
142 using difference_type = std::ptrdiff_t;
143
145
146 list_iterator_base(ListType& list, vlc_list NodeType::* node_ptr)
147 : _current{&list}, _next{list.next}, _prev{list.prev}, _node_ptr{node_ptr} {}
148
150 {
151 using char_pointer = std::conditional_t<is_const, const char*, char*>;
152 return *reinterpret_cast<pointer>(
153 reinterpret_cast<char_pointer>(this->_current) - this->offset());
154 }
155
157 {
158 return &operator*();
159 }
160
162 {
163 _prev = _next->prev;
164 _current = _next;
165 _next = _next->next;
166 return *this;
167 }
168
170 {
171 return iterator_type {*_next, _node_ptr};
172 }
173
175 {
176 _next = _prev->next;
177 _current = _prev;
178 _prev = _prev->prev;
179 return *this;
180 }
181
183 {
184 return iterator_type {*_prev, _node_ptr};
185 }
186
187 friend bool operator==(const iterator_type& a, const iterator_type& b)
188 {
189 return a._current == b._current;
190 }
191
192 friend bool operator!=(const iterator_type& a, const iterator_type& b)
193 {
194 return a._current != b._current;
195 }
196};
197
198/**
199 * Iterator on vlc_list with mutable capabilities.
200 */
201template <typename NodeType>
203
204/**
205 * Iterator on vlc_list with immutable capabilities.
206 */
207template <typename NodeType>
209
210template <typename NodeType, typename ListType>
212 : public std::reverse_iterator<list_iterator_base<NodeType, ListType>>
213{
214 using iterator = std::reverse_iterator<list_iterator_base<NodeType, ListType>>;
215 using inner_iterator = typename iterator::iterator_type;
216public:
217 list_reverse_iterator(ListType &list, vlc_list NodeType::* node_ptr)
218 : iterator {++inner_iterator{list, node_ptr}} {}
219
220 list_reverse_iterator(iterator other)
221 : iterator{other.base()} {}
222};
223
224/**
225 * Wrapper around any type matching with vlc_list, exposing C++ iterator operations.
226 *
227 * Users should use the vlc::list and vlc::const_list types instead,
228 * and initialize them from the vlc::from function.
229 *
230 * \code
231 * struct item {
232 * // ...
233 * vlc_list node;
234 * }
235 *
236 * struct vlc_list c_list;
237 * vlc_list_init(&c_list);
238 * // ...
239 * auto list = vlc::from(&list, &item::node);
240 * \endcode
241 *
242 * \tparam NodeType the type of each node from the list
243 * \tparam ListType either vlc_list or const vlc_list
244 * \tparam Iterator the iterator type returned by vlc::list_base::begin()
245 * and vlc::list_base::end()
246 * \tparam ConstIterator the iterator type returned by vlc::list_base::cbegin()
247 * and vlc::list_base::cend()
248 */
249template <
250 typename NodeType,
251 typename ListType,
252 typename Iterator,
253 typename ConstIterator
254>
256{
257 /* We use some kind of offsetof, which will only be valid on
258 * standard layout types since non-standard might have a variable
259 * layout and still be pointer-compatible. */
260 static_assert(std::is_standard_layout<NodeType>::value,
261 "list can only iterate standard layout types");
262
263protected:
264 ListType& _list;
265 vlc_list NodeType::* _node_ptr;
266
267 static bool constexpr is_reverse = !std::is_same<
269
270public:
271 list_base(ListType &list, vlc_list NodeType::* node_ptr)
272 : _list{list}, _node_ptr{node_ptr} {}
273
275
276 using iterator = Iterator;
277 using const_iterator = ConstIterator;
278 using reverse_iterator = std::conditional_t<is_reverse,
281 using const_reverse_iterator = std::conditional_t<is_reverse,
284
285 using reverse_list = list_base<NodeType, ListType,
287
292
294 {
295 return ++iterator{_list, _node_ptr};
296 }
297
298 iterator end() const
299 {
300 return iterator{_list, _node_ptr};
301 }
302
304 {
305 return ++const_iterator{_list, _node_ptr};
306 }
307
309 {
311 }
312
317
322
327
332
333 friend bool operator==(const list_type& a, const list_type& b)
334 {
335 return a._list == b._list;
336 }
337
338 friend bool operator!=(const list_type& a, const list_type& b)
339 {
340 return a._list != b._list;
341 }
342
343 bool empty() const
344 {
345 return vlc_list_is_empty(_list);
346 }
347};
348
349/**
350 * Public type-safe wrapper around const vlc_list, providing const iterator
351 * and iteration functions.
352 *
353 * It is advised to use ::vlc::list::from() to get the correct
354 * wrapper directly in an inferenced way.
355 *
356 * \tparam NodeType the type of each node from the list
357 **/
358template <typename NodeType>
359struct const_list : public list_base<
360 NodeType,
361 const vlc_list,
362 list_const_iterator<NodeType>,
363 list_const_iterator<NodeType>
364>{
365public:
368
369 const_list(const vlc_list &l, vlc_list NodeType::* node_ptr)
370 : list_base<
371 NodeType, const vlc_list, iterator, const_iterator
372 >(l, node_ptr) {};
373};
374
375/**
376 * Public type-safe wrapper around mutable vlc_list, providing iterators,
377 * iteration functions and mutation on the list itself.
378 *
379 * \tparam NodeType the type of each node from the list
380 **/
381template <typename NodeType>
382struct list : public list_base<
383 NodeType,
384 vlc_list,
385 list_iterator<NodeType>,
386 list_const_iterator<NodeType>
387>{
388
389public:
392
393 /**
394 * Construct a ::vlc::list from an existing vlc_list.
395 *
396 * It is advised to use ::vlc::list::from() to get the correct
397 * wrapper directly in an inferenced way.
398 **/
399 list(vlc_list &l, vlc_list NodeType::* node_ptr)
400 : list_base<
402 >(l, node_ptr) {};
403
404 template <typename IteratorType>
405 IteratorType erase(IteratorType it)
406 {
407 vlc_list_remove(&((*it).*(this->_node_ptr)));
408 return it;
409 }
410
411 void push_front(NodeType &item)
412 {
413 struct vlc_list *node = &(item.*(this->_node_ptr));
414 vlc_list_prepend(node, &this->_list);
415 }
416
417 void push_back(NodeType &item)
418 {
419 struct vlc_list *node = &(item.*(this->_node_ptr));
420 vlc_list_append(node, &this->_list);
421 }
422};
423
424/**
425 * Construct a vlc::list (mutable list) object from a mutable
426 * vlc_list reference
427 *
428 * \tparam NodeType the type of each node from the list
429 *
430 * \param list the vlc_list object to wrap around
431 * \param node_ptr a pointer to the intrusive vlc_list member from the
432 * type being stored in the list.
433 * \return a vlc::list instance
434 * */
435template <typename NodeType>
437{
438 return ::vlc::list<NodeType>{list, node_ptr};
439}
440
441/**
442 * Construct a vlc::const_list (immutable list) object from a const
443 * vlc_list reference
444 *
445 * \tparam NodeType the type of each node from the list
446 *
447 * \param list the vlc_list object to wrap around
448 * \param node_ptr a pointer to the intrusive vlc_list member from the
449 * type being stored in the list.
450 * \return a vlc::const_list instance which cannot modify the vlc_list
451 * */
452template <typename NodeType>
454{
455 return ::vlc::const_list<NodeType>{list, node_ptr};
456}
457
458/** @} */
459}
460
461#endif /* VLC_LIST_HPP */
Wrapper around any type matching with vlc_list, exposing C++ iterator operations.
Definition vlc_list.hpp:256
ListType & _list
Definition vlc_list.hpp:264
std::conditional_t< is_reverse, list_reverse_iterator< NodeType, ListType >, list_iterator_base< NodeType, ListType > > reverse_iterator
Definition vlc_list.hpp:280
static bool constexpr is_reverse
Definition vlc_list.hpp:267
std::conditional_t< is_reverse, list_reverse_iterator< NodeType, const ListType >, list_iterator_base< NodeType, const ListType > > const_reverse_iterator
Definition vlc_list.hpp:283
friend bool operator==(const list_type &a, const list_type &b)
Definition vlc_list.hpp:333
bool empty() const
Definition vlc_list.hpp:343
iterator end() const
Definition vlc_list.hpp:298
const_reverse_iterator crend() const
Definition vlc_list.hpp:328
list_base(ListType &list, vlc_list NodeType::*node_ptr)
Definition vlc_list.hpp:271
reverse_list as_reverse()
Definition vlc_list.hpp:288
iterator begin() const
Definition vlc_list.hpp:293
friend bool operator!=(const list_type &a, const list_type &b)
Definition vlc_list.hpp:338
reverse_iterator rbegin()
Definition vlc_list.hpp:313
const_iterator cbegin() const
Definition vlc_list.hpp:303
Iterator iterator
Definition vlc_list.hpp:276
ConstIterator const_iterator
Definition vlc_list.hpp:277
const_reverse_iterator crbegin() const
Definition vlc_list.hpp:323
reverse_iterator rend()
Definition vlc_list.hpp:318
vlc_list NodeType::* _node_ptr
Definition vlc_list.hpp:265
const_iterator cend() const
Definition vlc_list.hpp:308
Base class for iterators on the vlc::list's vlc_list wrapper.
Definition vlc_list.hpp:124
constexpr std::ptrdiff_t offset() const
Definition vlc_list.hpp:129
std::conditional_t< is_const, const NodeType *, NodeType * > pointer
Definition vlc_list.hpp:140
ListType * _prev
Definition vlc_list.hpp:126
std::conditional_t< is_const, const NodeType &, NodeType & > reference
Definition vlc_list.hpp:141
vlc_list NodeType::* _node_ptr
Definition vlc_list.hpp:127
friend bool operator!=(const iterator_type &a, const iterator_type &b)
Definition vlc_list.hpp:192
static constexpr bool is_const
Definition vlc_list.hpp:135
friend bool operator==(const iterator_type &a, const iterator_type &b)
Definition vlc_list.hpp:187
std::conditional_t< is_const, const NodeType, NodeType > value_type
Definition vlc_list.hpp:139
std::bidirectional_iterator_tag iterator_category
Definition vlc_list.hpp:138
iterator_type & operator--()
Definition vlc_list.hpp:174
reference operator*() const
Definition vlc_list.hpp:149
list_iterator_base(ListType &list, vlc_list NodeType::*node_ptr)
Definition vlc_list.hpp:146
std::ptrdiff_t difference_type
Definition vlc_list.hpp:142
iterator_type operator--(int)
Definition vlc_list.hpp:182
ListType * _next
Definition vlc_list.hpp:126
iterator_type operator++(int)
Definition vlc_list.hpp:169
iterator_type operator++()
Definition vlc_list.hpp:161
pointer operator->() const
Definition vlc_list.hpp:156
ListType * _current
Definition vlc_list.hpp:126
Definition vlc_list.hpp:213
list_reverse_iterator(iterator other)
Definition vlc_list.hpp:220
list_reverse_iterator(ListType &list, vlc_list NodeType::*node_ptr)
Definition vlc_list.hpp:217
struct vlc_param ** list
Definition core.c:402
bool operator==(const ::vlc_list &a, const ::vlc_list &b)
Compare two vlc_list node and check whether they represent the same element.
Definition vlc_list.hpp:95
bool operator!=(const ::vlc_list &a, const ::vlc_list &b)
Compare two vlc_list node and check whether they representthe same element.
Definition vlc_list.hpp:110
::vlc::list< NodeType > from(vlc_list &list, vlc_list NodeType::*node_ptr)
Construct a vlc::list (mutable list) object from a mutable vlc_list reference.
Definition vlc_list.hpp:436
static void vlc_list_append(struct vlc_list *restrict node, struct vlc_list *head)
Appends an element into a list.
Definition vlc_list.h:110
static void vlc_list_prepend(struct vlc_list *restrict node, struct vlc_list *head)
Prepends an element into a list.
Definition vlc_list.h:122
static bool vlc_list_is_empty(const struct vlc_list *head)
Checks if a list is empty.
Definition vlc_list.h:167
static void vlc_list_remove(struct vlc_list *restrict node)
Removes an element from a list.
Definition vlc_list.h:135
Definition vlc_cxx_helpers.hpp:46
Public type-safe wrapper around const vlc_list, providing const iterator and iteration functions.
Definition vlc_list.hpp:364
const_list(const vlc_list &l, vlc_list NodeType::*node_ptr)
Definition vlc_list.hpp:369
Public type-safe wrapper around mutable vlc_list, providing iterators, iteration functions and mutati...
Definition vlc_list.hpp:387
void push_back(NodeType &item)
Definition vlc_list.hpp:417
IteratorType erase(IteratorType it)
Definition vlc_list.hpp:405
list(vlc_list &l, vlc_list NodeType::*node_ptr)
Construct a vlc::list from an existing vlc_list.
Definition vlc_list.hpp:399
void push_front(NodeType &item)
Definition vlc_list.hpp:411
Doubly-linked list node.
Definition vlc_list.h:44
This provides convenience helpers for linked lists.