VirtualBox

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

Last change on this file since 34066 was 32445, checked in by vboxsync, 14 years ago

iprt/list.h: Added RTListForEachSafe and RTListForEachReverseSafe.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.8 KB
Line 
1/** @file
2 * IPRT - Generic Doubly Linked List.
3 */
4
5/*
6 * Copyright (C) 2010 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 list node pointer. */
57typedef PRTLISTNODE *PPRTLISTNODE;
58
59/**
60 * Initialize a list.
61 *
62 * @param pList Pointer to an unitialised list.
63 */
64DECLINLINE(void) RTListInit(PRTLISTNODE pList)
65{
66 pList->pNext = pList;
67 pList->pPrev = pList;
68}
69
70/**
71 * Append a node to the end of the list.
72 *
73 * @param pList The list to append the node to.
74 * @param pNode The node to append.
75 */
76DECLINLINE(void) RTListAppend(PRTLISTNODE pList, PRTLISTNODE pNode)
77{
78 pList->pPrev->pNext = pNode;
79 pNode->pPrev = pList->pPrev;
80 pNode->pNext = pList;
81 pList->pPrev = pNode;
82}
83
84/**
85 * Add a node as the first element of the list.
86 *
87 * @param pList The list to prepend the node to.
88 * @param pNode The node to prepend.
89 */
90DECLINLINE(void) RTListPrepend(PRTLISTNODE pList, PRTLISTNODE pNode)
91{
92 pList->pNext->pPrev = pNode;
93 pNode->pNext = pList->pNext;
94 pNode->pPrev = pList;
95 pList->pNext = pNode;
96}
97
98/**
99 * Remove a node from a list.
100 *
101 * @param pNode The node to remove.
102 */
103DECLINLINE(void) RTListNodeRemove(PRTLISTNODE pNode)
104{
105 PRTLISTNODE pPrev = pNode->pPrev;
106 PRTLISTNODE pNext = pNode->pNext;
107
108 pPrev->pNext = pNext;
109 pNext->pPrev = pPrev;
110
111 /* poison */
112 pNode->pNext = NULL;
113 pNode->pPrev = NULL;
114}
115
116/**
117 * Checks if a node is the last element in the list.
118 *
119 * @retval @c true if the node is the last element in the list.
120 * @retval @c false otherwise
121 *
122 * @param pList The list.
123 * @param pNode The node to check.
124 */
125#define RTListNodeIsLast(pList, pNode) ((pNode)->pNext == (pList))
126
127/**
128 * Checks if a node is the first element in the list.
129 *
130 * @retval @c true if the node is the first element in the list.
131 * @retval @c false otherwise.
132 *
133 * @param pList The list.
134 * @param pNode The node to check.
135 */
136#define RTListNodeIsFirst(pList, pNode) ((pNode)->pPrev == (pList))
137
138/**
139 * Checks if a type converted node is actually the dummy element (@a pList).
140 *
141 * @retval @c true if the node is the dummy element in the list.
142 * @retval @c false otherwise.
143 *
144 * @param pList The list.
145 * @param pNodeStruct The node structure to check. Typically
146 * something obtained from RTListNodeGetNext() or
147 * RTListNodeGetPrev(). This is NOT a PRTLISTNODE
148 * but something that contains a RTLISTNODE member!
149 * @param Type Structure the list node is a member of.
150 * @param Member The list node member.
151 */
152#define RTListNodeIsDummy(pList, pNode, Type, Member) \
153 ( (pNode) == RT_FROM_MEMBER((pList), Type, Member) )
154
155/**
156 * Checks if a list is empty.
157 *
158 * @retval @c true if the list is empty.
159 * @retval @c false otherwise.
160 *
161 * @param pList The list to check.
162 */
163#define RTListIsEmpty(pList) ((pList)->pPrev == (pList))
164
165/**
166 * Returns the next node in the list.
167 *
168 * @returns The next node.
169 *
170 * @param pCurNode The current node.
171 * @param Type Structure the list node is a member of.
172 * @param Member The list node member.
173 */
174#define RTListNodeGetNext(pCurNode, Type, Member) \
175 RT_FROM_MEMBER((pCurNode)->pNext, Type, Member)
176
177/**
178 * Returns the previous node in the list.
179 *
180 * @returns The previous node.
181 *
182 * @param pCurNode The current node.
183 * @param Type Structure the list node is a member of.
184 * @param Member The list node member.
185 */
186#define RTListNodeGetPrev(pCurNode, Type, Member) \
187 RT_FROM_MEMBER((pCurNode)->pPrev, Type, Member)
188
189/**
190 * Returns the first element in the list (checks for empty list).
191 *
192 * @retval Pointer to the first list element.
193 * @retval NULL if the list is empty.
194 *
195 * @param pList List to get the first element from.
196 * @param Type Structure the list node is a member of.
197 * @param Member The list node member.
198 */
199#define RTListNodeGetFirst(pList, Type, Member) \
200 (!RTListIsEmpty(pList) ? RTListNodeGetNext(pList, Type, Member) : NULL)
201
202/**
203 * Returns the last element in the list (checks for empty list).
204 *
205 * @retval Pointer to the last list element.
206 * @retval NULL if the list is empty.
207 *
208 * @param pList List to get the last element from.
209 * @param Type Structure the list node is a member of.
210 * @param Member The list node member.
211 */
212#define RTListNodeGetLast(pList, Type, Member) \
213 (!RTListIsEmpty(pList) ? RTListNodeGetPrev(pList, Type, Member) : NULL)
214
215/**
216 * Enumerate the list in head to tail order.
217 *
218 * @param pList List to enumerate.
219 * @param pIterator The iterator variable name.
220 * @param Type Structure the list node is a member of.
221 * @param Member The list node member name.
222 */
223#define RTListForEach(pList, pIterator, Type, Member) \
224 for (pIterator = RTListNodeGetNext(pList, Type, Member); \
225 !RTListNodeIsDummy(pList, pIterator, Type, Member); \
226 pIterator = RT_FROM_MEMBER((pIterator)->Member.pNext, Type, Member) )
227
228
229/**
230 * Enumerate the list in head to tail order, safe against removal of the
231 * current node.
232 *
233 * @param pList List to enumerate.
234 * @param pIterator The iterator variable name.
235 * @param pIterNext The name of the variable saving the pointer to
236 * the next element.
237 * @param Type Structure the list node is a member of.
238 * @param Member The list node member name.
239 */
240#define RTListForEachSafe(pList, pIterator, pIterNext, Type, Member) \
241 for (pIterator = RTListNodeGetNext(pList, Type, Member), \
242 pIterNext = RT_FROM_MEMBER((pIterator)->Member.pNext, Type, Member); \
243 !RTListNodeIsDummy(pList, pIterator, Type, Member); \
244 pIterator = pIterNext, \
245 pIterNext = RT_FROM_MEMBER((pIterator)->Member.pNext, Type, Member) )
246
247
248/**
249 * Enumerate the list in reverse order (tail to head).
250 *
251 * @param pList List to enumerate.
252 * @param pIterator The iterator variable name.
253 * @param Type Structure the list node is a member of.
254 * @param Member The list node member name.
255 */
256#define RTListForEachReverse(pList, pIterator, Type, Member) \
257 for (pIterator = RTListNodeGetPrev(pList, Type, Member); \
258 !RTListNodeIsDummy(pList, pIterator, Type, Member); \
259 pIterator = RT_FROM_MEMBER((pIterator)->Member.pPrev, Type, Member) )
260
261
262/**
263 * Enumerate the list in reverse order (tail to head).
264 *
265 * @param pList List to enumerate.
266 * @param pIterator The iterator variable name.
267 * @param pIterPrev The name of the variable saving the pointer to
268 * the previous element.
269 * @param Type Structure the list node is a member of.
270 * @param Member The list node member name.
271 */
272#define RTListForEachReverseSafe(pList, pIterator, pIterPrev, Type, Member) \
273 for (pIterator = RTListNodeGetPrev(pList, Type, Member), \
274 pIterPrev = RT_FROM_MEMBER((pIterator)->Member.pPrev, Type, Member); \
275 !RTListNodeIsDummy(pList, pIterator, Type, Member); \
276 pIterator = pIterPrev, \
277 pIterPrev = RT_FROM_MEMBER((pIterator)->Member.pPrev, Type, Member) )
278
279
280/**
281 * Move the given list to a new list header.
282 *
283 * @param pListDst The new list.
284 * @param pListSrc The list to move.
285 */
286DECLINLINE(void) RTListMove(PRTLISTNODE pListDst, PRTLISTNODE pListSrc)
287{
288 if (!RTListIsEmpty(pListSrc))
289 {
290 pListDst->pNext = pListSrc->pNext;
291 pListDst->pPrev = pListSrc->pPrev;
292
293 /* Adjust the first and last element links */
294 pListDst->pNext->pPrev = pListDst;
295 pListDst->pPrev->pNext = pListDst;
296
297 /* Finally remove the elements from the source list */
298 RTListInit(pListSrc);
299 }
300}
301
302RT_C_DECLS_END
303
304/** @} */
305
306#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