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