]> git.saurik.com Git - apple/mdnsresponder.git/blame - mDNSShared/GenLinkedList.c
mDNSResponder-1310.80.1.tar.gz
[apple/mdnsresponder.git] / mDNSShared / GenLinkedList.c
CommitLineData
f0cc3e7b
A
1/*
2 * Copyright (c) 2003-2019 Apple Inc. All rights reserved.
8e92c31c 3 *
67c8f8a1
A
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
83fb1e36 7 *
67c8f8a1 8 * http://www.apache.org/licenses/LICENSE-2.0
83fb1e36 9 *
67c8f8a1
A
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
8e92c31c 14 * limitations under the License.
263eeeab 15 */
8e92c31c
A
16
17#include "GenLinkedList.h"
18
19
20// Return the link pointer contained within element e at offset o.
83fb1e36 21#define GETLINK( e, o) ( *(void**)((char*) (e) + (o)) )
8e92c31c
A
22
23// Assign the link pointer l to element e at offset o.
83fb1e36 24#define ASSIGNLINK( e, l, o) ( *((void**)((char*) (e) + (o))) = (l))
8e92c31c
A
25
26
27// GenLinkedList /////////////////////////////////////////////////////////////
28
83fb1e36 29void InitLinkedList( GenLinkedList *pList, size_t linkOffset)
8e92c31c
A
30/* Initialize the block of memory pointed to by pList as a linked list. */
31{
83fb1e36
A
32 pList->Head = NULL;
33 pList->Tail = NULL;
34 pList->LinkOffset = linkOffset;
8e92c31c
A
35}
36
37
83fb1e36 38void AddToTail( GenLinkedList *pList, void *elem)
8e92c31c
A
39/* Add a linked list element to the tail of the list. */
40{
83fb1e36
A
41 if ( pList->Tail) {
42 ASSIGNLINK( pList->Tail, elem, pList->LinkOffset);
43 } else
44 pList->Head = elem;
45 ASSIGNLINK( elem, NULL, pList->LinkOffset);
8e92c31c 46
83fb1e36 47 pList->Tail = elem;
8e92c31c
A
48}
49
50
83fb1e36 51void AddToHead( GenLinkedList *pList, void *elem)
8e92c31c
A
52/* Add a linked list element to the head of the list. */
53{
83fb1e36
A
54 ASSIGNLINK( elem, pList->Head, pList->LinkOffset);
55 if ( pList->Tail == NULL)
56 pList->Tail = elem;
8e92c31c 57
83fb1e36 58 pList->Head = elem;
8e92c31c
A
59}
60
61
83fb1e36 62int RemoveFromList( GenLinkedList *pList, void *elem)
8e92c31c
A
63/* Remove a linked list element from the list. Return 0 if it was not found. */
64/* If the element is removed, its link will be set to NULL. */
65{
83fb1e36
A
66 void *iElem, *lastElem;
67
68 for ( iElem = pList->Head, lastElem = NULL; iElem; iElem = GETLINK( iElem, pList->LinkOffset)) {
69 if ( iElem == elem) {
70 if ( lastElem) { // somewhere past the head
71 ASSIGNLINK( lastElem, GETLINK( elem, pList->LinkOffset), pList->LinkOffset);
72 } else { // at the head
73 pList->Head = GETLINK( elem, pList->LinkOffset);
74 }
75 if ( pList->Tail == elem)
76 pList->Tail = lastElem ? lastElem : NULL;
77 ASSIGNLINK( elem, NULL, pList->LinkOffset); // maybe catch a stale reference bug.
78 return 1;
79 }
80 lastElem = iElem;
81 }
82
83 return 0;
8e92c31c
A
84}
85
86
83fb1e36 87int ReplaceElem( GenLinkedList *pList, void *elemInList, void *newElem)
8e92c31c
A
88/* Replace an element in the list with a new element, in the same position. */
89{
83fb1e36
A
90 void *iElem, *lastElem;
91
92 if ( elemInList == NULL || newElem == NULL)
93 return 0;
94
95 for ( iElem = pList->Head, lastElem = NULL; iElem; iElem = GETLINK( iElem, pList->LinkOffset))
96 {
97 if ( iElem == elemInList)
98 {
99 ASSIGNLINK( newElem, GETLINK( elemInList, pList->LinkOffset), pList->LinkOffset);
100 if ( lastElem) // somewhere past the head
101 {
102 ASSIGNLINK( lastElem, newElem, pList->LinkOffset);
103 }
104 else // at the head
105 {
106 pList->Head = newElem;
107 }
108 if ( pList->Tail == elemInList)
109 pList->Tail = newElem;
110 return 1;
111 }
112 lastElem = iElem;
113 }
114
115 return 0;
8e92c31c
A
116}
117
118
119// GenDoubleLinkedList /////////////////////////////////////////////////////////
120
83fb1e36
A
121void InitDoubleLinkedList( GenDoubleLinkedList *pList, size_t fwdLinkOffset,
122 size_t backLinkOffset)
8e92c31c
A
123/* Initialize the block of memory pointed to by pList as a double linked list. */
124{
83fb1e36
A
125 pList->Head = NULL;
126 pList->Tail = NULL;
127 pList->FwdLinkOffset = fwdLinkOffset;
128 pList->BackLinkOffset = backLinkOffset;
8e92c31c
A
129}
130
131
83fb1e36 132void DLLAddToHead( GenDoubleLinkedList *pList, void *elem)
8e92c31c
A
133/* Add a linked list element to the head of the list. */
134{
83fb1e36 135 void *pNext;
8e92c31c 136
83fb1e36 137 pNext = pList->Head;
8e92c31c 138
83fb1e36
A
139 // fix up the forward links
140 ASSIGNLINK( elem, pList->Head, pList->FwdLinkOffset);
141 pList->Head = elem;
8e92c31c 142
83fb1e36
A
143 // fix up the backward links
144 if ( pNext) {
145 ASSIGNLINK( pNext, elem, pList->BackLinkOffset);
146 } else
147 pList->Tail = elem;
148 ASSIGNLINK( elem, NULL, pList->BackLinkOffset);
8e92c31c
A
149}
150
151
83fb1e36 152void DLLRemoveFromList( GenDoubleLinkedList *pList, void *elem)
8e92c31c
A
153/* Remove a linked list element from the list. */
154/* When the element is removed, its link will be set to NULL. */
155{
83fb1e36
A
156 void *pNext, *pPrev;
157
158 pNext = GETLINK( elem, pList->FwdLinkOffset);
159 pPrev = GETLINK( elem, pList->BackLinkOffset);
160
161 // fix up the forward links
162 if ( pPrev)
163 ASSIGNLINK( pPrev, pNext, pList->FwdLinkOffset);
164 else
165 pList->Head = pNext;
166
167 // fix up the backward links
168 if ( pNext)
169 ASSIGNLINK( pNext, pPrev, pList->BackLinkOffset);
170 else
171 pList->Tail = pPrev;
172
173 ASSIGNLINK( elem, NULL, pList->FwdLinkOffset);
174 ASSIGNLINK( elem, NULL, pList->BackLinkOffset);
8e92c31c
A
175}
176
177
178// GenLinkedOffsetList /////////////////////////////////////////////////////
179
180// Extract the Next offset from element
83fb1e36 181#define GETOFFSET( e, o) ( *(size_t*)((char*) (e) + (o)) )
8e92c31c 182
83fb1e36 183static void AssignOffsetLink( void *elem, void *link, size_t linkOffset);
8e92c31c
A
184
185
83fb1e36 186static void AssignOffsetLink( void *elem, void *link, size_t linkOffset)
8e92c31c
A
187// Assign link to elem as an offset from elem. Assign 0 to elem if link is NULL.
188{
83fb1e36 189 GETOFFSET( elem, linkOffset) = link ? (size_t) link - (size_t) elem : 0;
8e92c31c
A
190}
191
192
83fb1e36 193void *GetHeadPtr( GenLinkedOffsetList *pList)
8e92c31c
A
194/* Return a pointer to the head element of a list, or NULL if none. */
195{
83fb1e36 196 return pList->Head ? ( (char*) (pList) + pList->Head) : NULL;
8e92c31c
A
197}
198
199
83fb1e36 200void *GetTailPtr( GenLinkedOffsetList *pList)
8e92c31c
A
201/* Return a pointer to the tail element of a list, or NULL if none. */
202{
83fb1e36 203 return pList->Tail ? ( (char*) (pList) + pList->Tail) : NULL;
8e92c31c
A
204}
205
206
83fb1e36 207void *GetOffsetLink( GenLinkedOffsetList *pList, void *elem)
8e92c31c
A
208/* Return the link pointer contained within element e for pList, or NULL if it is 0. */
209{
83fb1e36 210 size_t nextOffset;
8e92c31c 211
83fb1e36 212 nextOffset = GETOFFSET( elem, pList->LinkOffset);
8e92c31c 213
83fb1e36 214 return nextOffset ? (char*) elem + nextOffset : NULL;
8e92c31c
A
215}
216
217
83fb1e36 218void InitLinkedOffsetList( GenLinkedOffsetList *pList, size_t linkOffset)
8e92c31c
A
219/* Initialize the block of memory pointed to by pList as a linked list. */
220{
83fb1e36
A
221 pList->Head = 0;
222 pList->Tail = 0;
223 pList->LinkOffset = linkOffset;
8e92c31c
A
224}
225
226
83fb1e36 227void OffsetAddToTail( GenLinkedOffsetList *pList, void *elem)
8e92c31c
A
228/* Add a linked list element to the tail of the list. */
229{
83fb1e36
A
230 if ( pList->Tail) {
231 AssignOffsetLink( GetTailPtr( pList), elem, pList->LinkOffset);
232 } else
233 pList->Head = (size_t) elem - (size_t) pList;
234 AssignOffsetLink( elem, NULL, pList->LinkOffset);
8e92c31c 235
83fb1e36 236 pList->Tail = (size_t) elem - (size_t) pList;
8e92c31c
A
237}
238
239
83fb1e36 240void OffsetAddToHead( GenLinkedOffsetList *pList, void *elem)
8e92c31c
A
241/* Add a linked list element to the head of the list. */
242{
83fb1e36
A
243 AssignOffsetLink( elem, GetHeadPtr( pList), pList->LinkOffset);
244 if ( pList->Tail == 0)
245 pList->Tail = (size_t) elem - (size_t) pList;
8e92c31c 246
83fb1e36 247 pList->Head = (size_t) elem - (size_t) pList;
8e92c31c
A
248}
249
250
83fb1e36 251int OffsetRemoveFromList( GenLinkedOffsetList *pList, void *elem)
8e92c31c
A
252/* Remove a linked list element from the list. Return 0 if it was not found. */
253/* If the element is removed, its link will be set to NULL. */
254{
83fb1e36
A
255 void *iElem, *lastElem;
256
f0cc3e7b
A
257 if (elem == NULL) {
258 return 0;
259 }
83fb1e36
A
260 for ( iElem = GetHeadPtr( pList), lastElem = NULL; iElem;
261 iElem = GetOffsetLink( pList, iElem))
262 {
263 if ( iElem == elem) {
264 if ( lastElem) { // somewhere past the head
265 AssignOffsetLink( lastElem, GetOffsetLink( pList, elem), pList->LinkOffset);
266 } else { // at the head
267 iElem = GetOffsetLink( pList, elem);
268 pList->Head = iElem ? (size_t) iElem - (size_t) pList : 0;
269 }
270 if ( GetTailPtr( pList) == elem)
271 pList->Tail = lastElem ? (size_t) lastElem - (size_t) pList : 0;
272 AssignOffsetLink( elem, NULL, pList->LinkOffset); // maybe catch a stale reference bug.
273 return 1;
274 }
275 lastElem = iElem;
276 }
277
278 return 0;
8e92c31c
A
279}
280
281
83fb1e36 282int OffsetReplaceElem( GenLinkedOffsetList *pList, void *elemInList, void *newElem)
8e92c31c
A
283/* Replace an element in the list with a new element, in the same position. */
284{
83fb1e36
A
285 void *iElem, *lastElem;
286
287 if ( elemInList == NULL || newElem == NULL)
288 return 0;
289
290 for ( iElem = GetHeadPtr( pList), lastElem = NULL; iElem;
291 iElem = GetOffsetLink( pList, iElem))
292 {
293 if ( iElem == elemInList)
294 {
295 AssignOffsetLink( newElem, GetOffsetLink( pList, elemInList), pList->LinkOffset);
296 if ( lastElem) // somewhere past the head
297 {
298 AssignOffsetLink( lastElem, newElem, pList->LinkOffset);
299 }
300 else // at the head
301 {
302 pList->Head = (size_t) newElem - (size_t) pList;
303 }
304 if ( GetTailPtr( pList) == elemInList)
305 pList->Tail = (size_t) newElem - (size_t) pList;
306 return 1;
307 }
308 lastElem = iElem;
309 }
310
311 return 0;
8e92c31c
A
312}
313
314