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