VirtualBox

source: vbox/trunk/include/iprt/list.h@ 56378

Last change on this file since 56378 was 56291, checked in by vboxsync, 9 years ago

include: Updated (C) year.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.3 KB
Line 
1/** @file
2 * IPRT - Generic Doubly Linked List.
3 */
4
5/*
6 * Copyright (C) 2010-2015 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 */
25
26#ifndef ___iprt_list_h
27#define ___iprt_list_h
28
29#include <iprt/types.h>
30
31/** @defgroup grp_rt_list RTList - Generic Doubly Linked List
32 * @ingroup grp_rt
33 *
34 * The list implementation is circular without any type wise distintion between
35 * the list and its nodes. This can be confusing since the list head usually
36 * resides in a different structure than the nodes, so care must be taken when
37 * walking the list.
38 *
39 * @{
40 */
41
42RT_C_DECLS_BEGIN
43
44/**
45 * A list node of a doubly linked list.
46 */
47typedef struct RTLISTNODE
48{
49 /** Pointer to the next list node. */
50 struct RTLISTNODE *pNext;
51 /** Pointer to the previous list node. */
52 struct RTLISTNODE *pPrev;
53} RTLISTNODE;
54/** Pointer to a list node. */
55typedef RTLISTNODE *PRTLISTNODE;
56/** Pointer to a const list node. */
57typedef RTLISTNODE const *PCRTLISTNODE;
58/** Pointer to a list node pointer. */
59typedef PRTLISTNODE *PPRTLISTNODE;
60
61/** The anchor (head/tail) of a doubly linked list.
62 *
63 * @remarks Please use this instead of RTLISTNODE to indicate a list
64 * head/tail. It makes the code so much easier to read. Also,
65 * always mention the actual list node type(s) in the comment. */
66typedef RTLISTNODE RTLISTANCHOR;
67/** Pointer to a doubly linked list anchor. */
68typedef RTLISTANCHOR *PRTLISTANCHOR;
69/** Pointer to a const doubly linked list anchor. */
70typedef RTLISTANCHOR const *PCRTLISTANCHOR;
71
72
73/**
74 * Initialize a list.
75 *
76 * @param pList Pointer to an unitialised list.
77 */
78DECLINLINE(void) RTListInit(PRTLISTNODE pList)
79{
80 pList->pNext = pList;
81 pList->pPrev = pList;
82}
83
84/**
85 * Append a node to the end of the list.
86 *
87 * @param pList The list to append the node to.
88 * @param pNode The node to append.
89 */
90DECLINLINE(void) RTListAppend(PRTLISTNODE pList, PRTLISTNODE pNode)
91{
92 pList->pPrev->pNext = pNode;
93 pNode->pPrev = pList->pPrev;
94 pNode->pNext = pList;
95 pList->pPrev = pNode;
96}
97
98/**
99 * Add a node as the first element of the list.
100 *
101 * @param pList The list to prepend the node to.
102 * @param pNode The node to prepend.
103 */
104DECLINLINE(void) RTListPrepend(PRTLISTNODE pList, PRTLISTNODE pNode)
105{
106 pList->pNext->pPrev = pNode;
107 pNode->pNext = pList->pNext;
108 pNode->pPrev = pList;
109 pList->pNext = pNode;
110}
111
112/**
113 * Inserts a node after the specified one.
114 *
115 * @param pCurNode The current node.
116 * @param pNewNode The node to insert.
117 */
118DECLINLINE(void) RTListNodeInsertAfter(PRTLISTNODE pCurNode, PRTLISTNODE pNewNode)
119{
120 RTListPrepend(pCurNode, pNewNode);
121}
122
123/**
124 * Inserts a node before the specified one.
125 *
126 * @param pCurNode The current node.
127 * @param pNewNode The node to insert.
128 */
129DECLINLINE(void) RTListNodeInsertBefore(PRTLISTNODE pCurNode, PRTLISTNODE pNewNode)
130{
131 RTListAppend(pCurNode, pNewNode);
132}
133
134/**
135 * Remove a node from a list.
136 *
137 * @param pNode The node to remove.
138 */
139DECLINLINE(void) RTListNodeRemove(PRTLISTNODE pNode)
140{
141 PRTLISTNODE pPrev = pNode->pPrev;
142 PRTLISTNODE pNext = pNode->pNext;
143
144 pPrev->pNext = pNext;
145 pNext->pPrev = pPrev;
146
147 /* poison */
148 pNode->pNext = NULL;
149 pNode->pPrev = NULL;
150}
151
152/**
153 * Checks if a node is the last element in the list.
154 *
155 * @retval @c true if the node is the last element in the list.
156 * @retval @c false otherwise
157 *
158 * @param pList The list.
159 * @param pNode The node to check.
160 */
161#define RTListNodeIsLast(pList, pNode) ((pNode)->pNext == (pList))
162
163/**
164 * Checks if a node is the first element in the list.
165 *
166 * @retval @c true if the node is the first element in the list.
167 * @retval @c false otherwise.
168 *
169 * @param pList The list.
170 * @param pNode The node to check.
171 */
172#define RTListNodeIsFirst(pList, pNode) ((pNode)->pPrev == (pList))
173
174/**
175 * Checks if a type converted node is actually the dummy element (@a pList).
176 *
177 * @retval @c true if the node is the dummy element in the list.
178 * @retval @c false otherwise.
179 *
180 * @param pList The list.
181 * @param pNodeStruct The node structure to check. Typically
182 * something obtained from RTListNodeGetNext() or
183 * RTListNodeGetPrev(). This is NOT a PRTLISTNODE
184 * but something that contains a RTLISTNODE member!
185 * @param Type Structure the list node is a member of.
186 * @param Member The list node member.
187 */
188#define RTListNodeIsDummy(pList, pNode, Type, Member) \
189 ( (pNode) == RT_FROM_MEMBER((pList), Type, Member) )
190/** @copydoc RTListNodeIsDummy */
191#define RTListNodeIsDummyCpp(pList, pNode, Type, Member) \
192 ( (pNode) == RT_FROM_CPP_MEMBER((pList), Type, Member) )
193
194/**
195 * Checks if a list is empty.
196 *
197 * @retval @c true if the list is empty.
198 * @retval @c false otherwise.
199 *
200 * @param pList The list to check.
201 */
202#define RTListIsEmpty(pList) ((pList)->pPrev == (pList))
203
204/**
205 * Returns the next node in the list.
206 *
207 * @returns The next node.
208 *
209 * @param pCurNode The current node.
210 * @param Type Structure the list node is a member of.
211 * @param Member The list node member.
212 */
213#define RTListNodeGetNext(pCurNode, Type, Member) \
214 RT_FROM_MEMBER((pCurNode)->pNext, Type, Member)
215/** @copydoc RTListNodeGetNext */
216#define RTListNodeGetNextCpp(pCurNode, Type, Member) \
217 RT_FROM_CPP_MEMBER((pCurNode)->pNext, Type, Member)
218
219/**
220 * Returns the previous node in the list.
221 *
222 * @returns The previous node.
223 *
224 * @param pCurNode The current node.
225 * @param Type Structure the list node is a member of.
226 * @param Member The list node member.
227 */
228#define RTListNodeGetPrev(pCurNode, Type, Member) \
229 RT_FROM_MEMBER((pCurNode)->pPrev, Type, Member)
230/** @copydoc RTListNodeGetPrev */
231#define RTListNodeGetPrevCpp(pCurNode, Type, Member) \
232 RT_FROM_CPP_MEMBER((pCurNode)->pPrev, Type, Member)
233
234/**
235 * Returns the first element in the list (checks for empty list).
236 *
237 * @retval Pointer to the first list element.
238 * @retval NULL if the list is empty.
239 *
240 * @param pList List to get the first element from.
241 * @param Type Structure the list node is a member of.
242 * @param Member The list node member.
243 */
244#define RTListGetFirst(pList, Type, Member) \
245 (!RTListIsEmpty(pList) ? RTListNodeGetNext(pList, Type, Member) : NULL)
246/** @copydoc RTListGetFirst */
247#define RTListGetFirstCpp(pList, Type, Member) \
248 (!RTListIsEmpty(pList) ? RTListNodeGetNextCpp(pList, Type, Member) : NULL)
249
250/**
251 * Returns the last element in the list (checks for empty list).
252 *
253 * @retval Pointer to the last list element.
254 * @retval NULL if the list is empty.
255 *
256 * @param pList List to get the last element from.
257 * @param Type Structure the list node is a member of.
258 * @param Member The list node member.
259 */
260#define RTListGetLast(pList, Type, Member) \
261 (!RTListIsEmpty(pList) ? RTListNodeGetPrev(pList, Type, Member) : NULL)
262/** @copydoc RTListGetLast */
263#define RTListGetLastCpp(pList, Type, Member) \
264 (!RTListIsEmpty(pList) ? RTListNodeGetPrevCpp(pList, Type, Member) : NULL)
265
266/**
267 * Returns the next node in the list or NULL if the end has been reached.
268 *
269 * @returns The next node or NULL.
270 *
271 * @param pList The list @a pCurNode is linked on.
272 * @param pCurNode The current node, of type @a Type.
273 * @param Type Structure the list node is a member of.
274 * @param Member The list node member.
275 */
276#define RTListGetNext(pList, pCurNode, Type, Member) \
277 ( (pCurNode)->Member.pNext != (pList) ? RT_FROM_MEMBER((pCurNode)->Member.pNext, Type, Member) : NULL )
278/** @copydoc RTListGetNext */
279#define RTListGetNextCpp(pList, pCurNode, Type, Member) \
280 ( (pCurNode)->Member.pNext != (pList) ? RT_FROM_CPP_MEMBER((pCurNode)->Member.pNext, Type, Member) : NULL )
281
282/**
283 * Returns the previous node in the list or NULL if the start has been reached.
284 *
285 * @returns The previous node or NULL.
286 *
287 * @param pList The list @a pCurNode is linked on.
288 * @param pCurNode The current node, of type @a Type.
289 * @param Type Structure the list node is a member of.
290 * @param Member The list node member.
291 */
292#define RTListGetPrev(pList, pCurNode, Type, Member) \
293 ( (pCurNode)->Member.pPrev != (pList) ? RT_FROM_MEMBER((pCurNode)->Member.pPrev, Type, Member) : NULL )
294/** @copydoc RTListGetPrev */
295#define RTListGetPrevCpp(pList, pCurNode, Type, Member) \
296 ( (pCurNode)->Member.pPrev != (pList) ? RT_FROM_CPP_MEMBER((pCurNode)->Member.pPrev, Type, Member) : NULL )
297
298/**
299 * Enumerate the list in head to tail order.
300 *
301 * @param pList List to enumerate.
302 * @param pIterator The iterator variable name.
303 * @param Type Structure the list node is a member of.
304 * @param Member The list node member name.
305 */
306#define RTListForEach(pList, pIterator, Type, Member) \
307 for (pIterator = RTListNodeGetNext(pList, Type, Member); \
308 !RTListNodeIsDummy(pList, pIterator, Type, Member); \
309 pIterator = RT_FROM_MEMBER((pIterator)->Member.pNext, Type, Member) )
310/** @copydoc RTListForEach */
311#define RTListForEachCpp(pList, pIterator, Type, Member) \
312 for (pIterator = RTListNodeGetNextCpp(pList, Type, Member); \
313 !RTListNodeIsDummyCpp(pList, pIterator, Type, Member); \
314 pIterator = RT_FROM_CPP_MEMBER((pIterator)->Member.pNext, Type, Member) )
315
316
317/**
318 * Enumerate the list in head to tail order, safe against removal of the
319 * current node.
320 *
321 * @param pList List to enumerate.
322 * @param pIterator The iterator variable name.
323 * @param pIterNext The name of the variable saving the pointer to
324 * the next element.
325 * @param Type Structure the list node is a member of.
326 * @param Member The list node member name.
327 */
328#define RTListForEachSafe(pList, pIterator, pIterNext, Type, Member) \
329 for (pIterator = RTListNodeGetNext(pList, Type, Member), \
330 pIterNext = RT_FROM_MEMBER((pIterator)->Member.pNext, Type, Member); \
331 !RTListNodeIsDummy(pList, pIterator, Type, Member); \
332 pIterator = pIterNext, \
333 pIterNext = RT_FROM_MEMBER((pIterator)->Member.pNext, Type, Member) )
334/** @copydoc RTListForEachSafe */
335#define RTListForEachSafeCpp(pList, pIterator, pIterNext, Type, Member) \
336 for (pIterator = RTListNodeGetNextCpp(pList, Type, Member), \
337 pIterNext = RT_FROM_CPP_MEMBER((pIterator)->Member.pNext, Type, Member); \
338 !RTListNodeIsDummyCpp(pList, pIterator, Type, Member); \
339 pIterator = pIterNext, \
340 pIterNext = RT_FROM_CPP_MEMBER((pIterator)->Member.pNext, Type, Member) )
341
342
343/**
344 * Enumerate the list in reverse order (tail to head).
345 *
346 * @param pList List to enumerate.
347 * @param pIterator The iterator variable name.
348 * @param Type Structure the list node is a member of.
349 * @param Member The list node member name.
350 */
351#define RTListForEachReverse(pList, pIterator, Type, Member) \
352 for (pIterator = RTListNodeGetPrev(pList, Type, Member); \
353 !RTListNodeIsDummy(pList, pIterator, Type, Member); \
354 pIterator = RT_FROM_MEMBER((pIterator)->Member.pPrev, Type, Member) )
355/** @copydoc RTListForEachReverse */
356#define RTListForEachReverseCpp(pList, pIterator, Type, Member) \
357 for (pIterator = RTListNodeGetPrevCpp(pList, Type, Member); \
358 !RTListNodeIsDummyCpp(pList, pIterator, Type, Member); \
359 pIterator = RT_FROM_CPP_MEMBER((pIterator)->Member.pPrev, Type, Member) )
360
361
362/**
363 * Enumerate the list in reverse order (tail to head).
364 *
365 * @param pList List to enumerate.
366 * @param pIterator The iterator variable name.
367 * @param pIterPrev The name of the variable saving the pointer to
368 * the previous element.
369 * @param Type Structure the list node is a member of.
370 * @param Member The list node member name.
371 */
372#define RTListForEachReverseSafe(pList, pIterator, pIterPrev, Type, Member) \
373 for (pIterator = RTListNodeGetPrev(pList, Type, Member), \
374 pIterPrev = RT_FROM_MEMBER((pIterator)->Member.pPrev, Type, Member); \
375 !RTListNodeIsDummy(pList, pIterator, Type, Member); \
376 pIterator = pIterPrev, \
377 pIterPrev = RT_FROM_MEMBER((pIterator)->Member.pPrev, Type, Member) )
378/** @copydoc RTListForEachReverseSafe */
379#define RTListForEachReverseSafeCpp(pList, pIterator, pIterPrev, Type, Member) \
380 for (pIterator = RTListNodeGetPrevCpp(pList, Type, Member), \
381 pIterPrev = RT_FROM_CPP_MEMBER((pIterator)->Member.pPrev, Type, Member); \
382 !RTListNodeIsDummyCpp(pList, pIterator, Type, Member); \
383 pIterator = pIterPrev, \
384 pIterPrev = RT_FROM_CPP_MEMBER((pIterator)->Member.pPrev, Type, Member) )
385
386
387/**
388 * Move the given list to a new list header.
389 *
390 * @param pListDst The new list.
391 * @param pListSrc The list to move.
392 */
393DECLINLINE(void) RTListMove(PRTLISTNODE pListDst, PRTLISTNODE pListSrc)
394{
395 if (!RTListIsEmpty(pListSrc))
396 {
397 pListDst->pNext = pListSrc->pNext;
398 pListDst->pPrev = pListSrc->pPrev;
399
400 /* Adjust the first and last element links */
401 pListDst->pNext->pPrev = pListDst;
402 pListDst->pPrev->pNext = pListDst;
403
404 /* Finally remove the elements from the source list */
405 RTListInit(pListSrc);
406 }
407}
408
409/**
410 * List concatenation.
411 *
412 * @returns nothing.
413 * @param pListDst The destination list.
414 * @param pListSrc The source list to concatenate.
415 */
416DECLINLINE(void) RTListConcatenate(PRTLISTANCHOR pListDst, PRTLISTANCHOR pListSrc)
417{
418 if (!RTListIsEmpty(pListSrc))
419 {
420 PRTLISTNODE pFirst = pListSrc->pNext;
421 PRTLISTNODE pLast = pListSrc->pPrev;
422
423 pListDst->pPrev->pNext = pFirst;
424 pFirst->pPrev = pListDst->pPrev;
425 pLast->pNext = pListDst;
426 pListDst->pPrev = pLast;
427
428 /* Finally remove the elements from the source list */
429 RTListInit(pListSrc);
430 }
431}
432
433RT_C_DECLS_END
434
435/** @} */
436
437#endif
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette