]>
git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSShared/GenLinkedList.c
2 * Copyright (c) 2003-2019 Apple Inc. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
14 * limitations under the License.
17 #include "GenLinkedList.h"
20 // Return the link pointer contained within element e at offset o.
21 #define GETLINK( e, o) ( *(void**)((char*) (e) + (o)) )
23 // Assign the link pointer l to element e at offset o.
24 #define ASSIGNLINK( e, l, o) ( *((void**)((char*) (e) + (o))) = (l))
27 // GenLinkedList /////////////////////////////////////////////////////////////
29 void InitLinkedList( GenLinkedList
*pList
, size_t linkOffset
)
30 /* Initialize the block of memory pointed to by pList as a linked list. */
34 pList
->LinkOffset
= linkOffset
;
38 void AddToTail( GenLinkedList
*pList
, void *elem
)
39 /* Add a linked list element to the tail of the list. */
42 ASSIGNLINK( pList
->Tail
, elem
, pList
->LinkOffset
);
45 ASSIGNLINK( elem
, NULL
, pList
->LinkOffset
);
51 void AddToHead( GenLinkedList
*pList
, void *elem
)
52 /* Add a linked list element to the head of the list. */
54 ASSIGNLINK( elem
, pList
->Head
, pList
->LinkOffset
);
55 if ( pList
->Tail
== NULL
)
62 int RemoveFromList( GenLinkedList
*pList
, void *elem
)
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. */
66 void *iElem
, *lastElem
;
68 for ( iElem
= pList
->Head
, lastElem
= NULL
; iElem
; iElem
= GETLINK( iElem
, pList
->LinkOffset
)) {
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
);
75 if ( pList
->Tail
== elem
)
76 pList
->Tail
= lastElem
? lastElem
: NULL
;
77 ASSIGNLINK( elem
, NULL
, pList
->LinkOffset
); // maybe catch a stale reference bug.
87 int ReplaceElem( GenLinkedList
*pList
, void *elemInList
, void *newElem
)
88 /* Replace an element in the list with a new element, in the same position. */
90 void *iElem
, *lastElem
;
92 if ( elemInList
== NULL
|| newElem
== NULL
)
95 for ( iElem
= pList
->Head
, lastElem
= NULL
; iElem
; iElem
= GETLINK( iElem
, pList
->LinkOffset
))
97 if ( iElem
== elemInList
)
99 ASSIGNLINK( newElem
, GETLINK( elemInList
, pList
->LinkOffset
), pList
->LinkOffset
);
100 if ( lastElem
) // somewhere past the head
102 ASSIGNLINK( lastElem
, newElem
, pList
->LinkOffset
);
106 pList
->Head
= newElem
;
108 if ( pList
->Tail
== elemInList
)
109 pList
->Tail
= newElem
;
119 // GenDoubleLinkedList /////////////////////////////////////////////////////////
121 void InitDoubleLinkedList( GenDoubleLinkedList
*pList
, size_t fwdLinkOffset
,
122 size_t backLinkOffset
)
123 /* Initialize the block of memory pointed to by pList as a double linked list. */
127 pList
->FwdLinkOffset
= fwdLinkOffset
;
128 pList
->BackLinkOffset
= backLinkOffset
;
132 void DLLAddToHead( GenDoubleLinkedList
*pList
, void *elem
)
133 /* Add a linked list element to the head of the list. */
139 // fix up the forward links
140 ASSIGNLINK( elem
, pList
->Head
, pList
->FwdLinkOffset
);
143 // fix up the backward links
145 ASSIGNLINK( pNext
, elem
, pList
->BackLinkOffset
);
148 ASSIGNLINK( elem
, NULL
, pList
->BackLinkOffset
);
152 void DLLRemoveFromList( GenDoubleLinkedList
*pList
, void *elem
)
153 /* Remove a linked list element from the list. */
154 /* When the element is removed, its link will be set to NULL. */
158 pNext
= GETLINK( elem
, pList
->FwdLinkOffset
);
159 pPrev
= GETLINK( elem
, pList
->BackLinkOffset
);
161 // fix up the forward links
163 ASSIGNLINK( pPrev
, pNext
, pList
->FwdLinkOffset
);
167 // fix up the backward links
169 ASSIGNLINK( pNext
, pPrev
, pList
->BackLinkOffset
);
173 ASSIGNLINK( elem
, NULL
, pList
->FwdLinkOffset
);
174 ASSIGNLINK( elem
, NULL
, pList
->BackLinkOffset
);
178 // GenLinkedOffsetList /////////////////////////////////////////////////////
180 // Extract the Next offset from element
181 #define GETOFFSET( e, o) ( *(size_t*)((char*) (e) + (o)) )
183 static void AssignOffsetLink( void *elem
, void *link
, size_t linkOffset
);
186 static void AssignOffsetLink( void *elem
, void *link
, size_t linkOffset
)
187 // Assign link to elem as an offset from elem. Assign 0 to elem if link is NULL.
189 GETOFFSET( elem
, linkOffset
) = link
? (size_t) link
- (size_t) elem
: 0;
193 void *GetHeadPtr( GenLinkedOffsetList
*pList
)
194 /* Return a pointer to the head element of a list, or NULL if none. */
196 return pList
->Head
? ( (char*) (pList
) + pList
->Head
) : NULL
;
200 void *GetTailPtr( GenLinkedOffsetList
*pList
)
201 /* Return a pointer to the tail element of a list, or NULL if none. */
203 return pList
->Tail
? ( (char*) (pList
) + pList
->Tail
) : NULL
;
207 void *GetOffsetLink( GenLinkedOffsetList
*pList
, void *elem
)
208 /* Return the link pointer contained within element e for pList, or NULL if it is 0. */
212 nextOffset
= GETOFFSET( elem
, pList
->LinkOffset
);
214 return nextOffset
? (char*) elem
+ nextOffset
: NULL
;
218 void InitLinkedOffsetList( GenLinkedOffsetList
*pList
, size_t linkOffset
)
219 /* Initialize the block of memory pointed to by pList as a linked list. */
223 pList
->LinkOffset
= linkOffset
;
227 void OffsetAddToTail( GenLinkedOffsetList
*pList
, void *elem
)
228 /* Add a linked list element to the tail of the list. */
231 AssignOffsetLink( GetTailPtr( pList
), elem
, pList
->LinkOffset
);
233 pList
->Head
= (size_t) elem
- (size_t) pList
;
234 AssignOffsetLink( elem
, NULL
, pList
->LinkOffset
);
236 pList
->Tail
= (size_t) elem
- (size_t) pList
;
240 void OffsetAddToHead( GenLinkedOffsetList
*pList
, void *elem
)
241 /* Add a linked list element to the head of the list. */
243 AssignOffsetLink( elem
, GetHeadPtr( pList
), pList
->LinkOffset
);
244 if ( pList
->Tail
== 0)
245 pList
->Tail
= (size_t) elem
- (size_t) pList
;
247 pList
->Head
= (size_t) elem
- (size_t) pList
;
251 int OffsetRemoveFromList( GenLinkedOffsetList
*pList
, void *elem
)
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. */
255 void *iElem
, *lastElem
;
260 for ( iElem
= GetHeadPtr( pList
), lastElem
= NULL
; iElem
;
261 iElem
= GetOffsetLink( pList
, iElem
))
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;
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.
282 int OffsetReplaceElem( GenLinkedOffsetList
*pList
, void *elemInList
, void *newElem
)
283 /* Replace an element in the list with a new element, in the same position. */
285 void *iElem
, *lastElem
;
287 if ( elemInList
== NULL
|| newElem
== NULL
)
290 for ( iElem
= GetHeadPtr( pList
), lastElem
= NULL
; iElem
;
291 iElem
= GetOffsetLink( pList
, iElem
))
293 if ( iElem
== elemInList
)
295 AssignOffsetLink( newElem
, GetOffsetLink( pList
, elemInList
), pList
->LinkOffset
);
296 if ( lastElem
) // somewhere past the head
298 AssignOffsetLink( lastElem
, newElem
, pList
->LinkOffset
);
302 pList
->Head
= (size_t) newElem
- (size_t) pList
;
304 if ( GetTailPtr( pList
) == elemInList
)
305 pList
->Tail
= (size_t) newElem
- (size_t) pList
;