]>
git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSShared/GenLinkedList.c
1 /* -*- Mode: C; tab-width: 4 -*-
3 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 Contains: implementation of generic linked lists.
24 Change History (most recent first):
26 $Log: GenLinkedList.c,v $
27 Revision 1.4 2006/08/14 23:24:56 cheshire
28 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
30 Revision 1.3 2004/04/22 21:14:42 cheshire
31 Fix comment spelling mistake
33 Revision 1.2 2004/02/05 07:41:08 cheshire
38 #include "GenLinkedList.h"
41 // Return the link pointer contained within element e at offset o.
42 #define GETLINK( e, o) ( *(void**)((char*) (e) + (o)) )
44 // Assign the link pointer l to element e at offset o.
45 #define ASSIGNLINK( e, l, o) ( *((void**)((char*) (e) + (o))) = (l))
48 // GenLinkedList /////////////////////////////////////////////////////////////
50 void InitLinkedList( GenLinkedList
*pList
, size_t linkOffset
)
51 /* Initialize the block of memory pointed to by pList as a linked list. */
55 pList
->LinkOffset
= linkOffset
;
59 void AddToTail( GenLinkedList
*pList
, void *elem
)
60 /* Add a linked list element to the tail of the list. */
63 ASSIGNLINK( pList
->Tail
, elem
, pList
->LinkOffset
);
66 ASSIGNLINK( elem
, NULL
, pList
->LinkOffset
);
72 void AddToHead( GenLinkedList
*pList
, void *elem
)
73 /* Add a linked list element to the head of the list. */
75 ASSIGNLINK( elem
, pList
->Head
, pList
->LinkOffset
);
76 if ( pList
->Tail
== NULL
)
83 int RemoveFromList( GenLinkedList
*pList
, void *elem
)
84 /* Remove a linked list element from the list. Return 0 if it was not found. */
85 /* If the element is removed, its link will be set to NULL. */
87 void *iElem
, *lastElem
;
89 for ( iElem
= pList
->Head
, lastElem
= NULL
; iElem
; iElem
= GETLINK( iElem
, pList
->LinkOffset
)) {
91 if ( lastElem
) { // somewhere past the head
92 ASSIGNLINK( lastElem
, GETLINK( elem
, pList
->LinkOffset
), pList
->LinkOffset
);
93 } else { // at the head
94 pList
->Head
= GETLINK( elem
, pList
->LinkOffset
);
96 if ( pList
->Tail
== elem
)
97 pList
->Tail
= lastElem
? lastElem
: NULL
;
98 ASSIGNLINK( elem
, NULL
, pList
->LinkOffset
); // maybe catch a stale reference bug.
108 int ReplaceElem( GenLinkedList
*pList
, void *elemInList
, void *newElem
)
109 /* Replace an element in the list with a new element, in the same position. */
111 void *iElem
, *lastElem
;
113 if ( elemInList
== NULL
|| newElem
== NULL
)
116 for ( iElem
= pList
->Head
, lastElem
= NULL
; iElem
; iElem
= GETLINK( iElem
, pList
->LinkOffset
))
118 if ( iElem
== elemInList
)
120 ASSIGNLINK( newElem
, GETLINK( elemInList
, pList
->LinkOffset
), pList
->LinkOffset
);
121 if ( lastElem
) // somewhere past the head
123 ASSIGNLINK( lastElem
, newElem
, pList
->LinkOffset
);
127 pList
->Head
= newElem
;
129 if ( pList
->Tail
== elemInList
)
130 pList
->Tail
= newElem
;
140 // GenDoubleLinkedList /////////////////////////////////////////////////////////
142 void InitDoubleLinkedList( GenDoubleLinkedList
*pList
, size_t fwdLinkOffset
,
143 size_t backLinkOffset
)
144 /* Initialize the block of memory pointed to by pList as a double linked list. */
148 pList
->FwdLinkOffset
= fwdLinkOffset
;
149 pList
->BackLinkOffset
= backLinkOffset
;
153 void DLLAddToHead( GenDoubleLinkedList
*pList
, void *elem
)
154 /* Add a linked list element to the head of the list. */
160 // fix up the forward links
161 ASSIGNLINK( elem
, pList
->Head
, pList
->FwdLinkOffset
);
164 // fix up the backward links
166 ASSIGNLINK( pNext
, elem
, pList
->BackLinkOffset
);
169 ASSIGNLINK( elem
, NULL
, pList
->BackLinkOffset
);
173 void DLLRemoveFromList( GenDoubleLinkedList
*pList
, void *elem
)
174 /* Remove a linked list element from the list. */
175 /* When the element is removed, its link will be set to NULL. */
179 pNext
= GETLINK( elem
, pList
->FwdLinkOffset
);
180 pPrev
= GETLINK( elem
, pList
->BackLinkOffset
);
182 // fix up the forward links
184 ASSIGNLINK( pPrev
, pNext
, pList
->FwdLinkOffset
);
188 // fix up the backward links
190 ASSIGNLINK( pNext
, pPrev
, pList
->BackLinkOffset
);
194 ASSIGNLINK( elem
, NULL
, pList
->FwdLinkOffset
);
195 ASSIGNLINK( elem
, NULL
, pList
->BackLinkOffset
);
199 // GenLinkedOffsetList /////////////////////////////////////////////////////
201 // Extract the Next offset from element
202 #define GETOFFSET( e, o) ( *(size_t*)((char*) (e) + (o)) )
204 static void AssignOffsetLink( void *elem
, void *link
, size_t linkOffset
);
207 static void AssignOffsetLink( void *elem
, void *link
, size_t linkOffset
)
208 // Assign link to elem as an offset from elem. Assign 0 to elem if link is NULL.
210 GETOFFSET( elem
, linkOffset
) = link
? (size_t) link
- (size_t) elem
: 0;
214 void *GetHeadPtr( GenLinkedOffsetList
*pList
)
215 /* Return a pointer to the head element of a list, or NULL if none. */
217 return pList
->Head
? ( (char*) (pList
) + pList
->Head
) : NULL
;
221 void *GetTailPtr( GenLinkedOffsetList
*pList
)
222 /* Return a pointer to the tail element of a list, or NULL if none. */
224 return pList
->Tail
? ( (char*) (pList
) + pList
->Tail
) : NULL
;
228 void *GetOffsetLink( GenLinkedOffsetList
*pList
, void *elem
)
229 /* Return the link pointer contained within element e for pList, or NULL if it is 0. */
233 nextOffset
= GETOFFSET( elem
, pList
->LinkOffset
);
235 return nextOffset
? (char*) elem
+ nextOffset
: NULL
;
239 void InitLinkedOffsetList( GenLinkedOffsetList
*pList
, size_t linkOffset
)
240 /* Initialize the block of memory pointed to by pList as a linked list. */
244 pList
->LinkOffset
= linkOffset
;
248 void OffsetAddToTail( GenLinkedOffsetList
*pList
, void *elem
)
249 /* Add a linked list element to the tail of the list. */
252 AssignOffsetLink( GetTailPtr( pList
), elem
, pList
->LinkOffset
);
254 pList
->Head
= (size_t) elem
- (size_t) pList
;
255 AssignOffsetLink( elem
, NULL
, pList
->LinkOffset
);
257 pList
->Tail
= (size_t) elem
- (size_t) pList
;
261 void OffsetAddToHead( GenLinkedOffsetList
*pList
, void *elem
)
262 /* Add a linked list element to the head of the list. */
264 AssignOffsetLink( elem
, GetHeadPtr( pList
), pList
->LinkOffset
);
265 if ( pList
->Tail
== 0)
266 pList
->Tail
= (size_t) elem
- (size_t) pList
;
268 pList
->Head
= (size_t) elem
- (size_t) pList
;
272 int OffsetRemoveFromList( GenLinkedOffsetList
*pList
, void *elem
)
273 /* Remove a linked list element from the list. Return 0 if it was not found. */
274 /* If the element is removed, its link will be set to NULL. */
276 void *iElem
, *lastElem
;
278 for ( iElem
= GetHeadPtr( pList
), lastElem
= NULL
; iElem
;
279 iElem
= GetOffsetLink( pList
, iElem
))
281 if ( iElem
== elem
) {
282 if ( lastElem
) { // somewhere past the head
283 AssignOffsetLink( lastElem
, GetOffsetLink( pList
, elem
), pList
->LinkOffset
);
284 } else { // at the head
285 iElem
= GetOffsetLink( pList
, elem
);
286 pList
->Head
= iElem
? (size_t) iElem
- (size_t) pList
: 0;
288 if ( GetTailPtr( pList
) == elem
)
289 pList
->Tail
= lastElem
? (size_t) lastElem
- (size_t) pList
: 0;
290 AssignOffsetLink( elem
, NULL
, pList
->LinkOffset
); // maybe catch a stale reference bug.
300 int OffsetReplaceElem( GenLinkedOffsetList
*pList
, void *elemInList
, void *newElem
)
301 /* Replace an element in the list with a new element, in the same position. */
303 void *iElem
, *lastElem
;
305 if ( elemInList
== NULL
|| newElem
== NULL
)
308 for ( iElem
= GetHeadPtr( pList
), lastElem
= NULL
; iElem
;
309 iElem
= GetOffsetLink( pList
, iElem
))
311 if ( iElem
== elemInList
)
313 AssignOffsetLink( newElem
, GetOffsetLink( pList
, elemInList
), pList
->LinkOffset
);
314 if ( lastElem
) // somewhere past the head
316 AssignOffsetLink( lastElem
, newElem
, pList
->LinkOffset
);
320 pList
->Head
= (size_t) newElem
- (size_t) pList
;
322 if ( GetTailPtr( pList
) == elemInList
)
323 pList
->Tail
= (size_t) newElem
- (size_t) pList
;