pupnp (libupnp) snapshot from SourceForge: git clone git://pupnp.git.sourceforge...
[igd2-for-linux:pandonghui1211s-igd2-for-linux.git] / pupnp_branch-1.6.x / threadutil / src / LinkedList.c
1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000-2003 Intel Corporation 
4 // All rights reserved. 
5 //
6 // Redistribution and use in source and binary forms, with or without 
7 // modification, are permitted provided that the following conditions are met: 
8 //
9 // * Redistributions of source code must retain the above copyright notice, 
10 // this list of conditions and the following disclaimer. 
11 // * Redistributions in binary form must reproduce the above copyright notice, 
12 // this list of conditions and the following disclaimer in the documentation 
13 // and/or other materials provided with the distribution. 
14 // * Neither name of Intel Corporation nor the names of its contributors 
15 // may be used to endorse or promote products derived from this software 
16 // without specific prior written permission.
17 // 
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR 
22 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
23 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
24 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
25 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
26 // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
28 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 ///////////////////////////////////////////////////////////////////////////
31
32 #include "LinkedList.h"
33 #ifndef WIN32
34         #include <sys/param.h>
35 #endif
36 #if (defined(BSD) && BSD >= 199306) || defined(__OSX__) || defined(__APPLE__)
37         #include <stdlib.h>
38 #else
39         #include <malloc.h>
40 #endif
41 #include <assert.h>
42
43 static int
44 freeListNode( ListNode * node,
45               LinkedList * list )
46 {
47     assert( list != NULL );
48
49     return FreeListFree( &list->freeNodeList, node );
50 }
51
52 /****************************************************************************
53  * Function: CreateListNode
54  *
55  *  Description:
56  *      Creates a list node. Dynamically.
57  *      
58  *  Parameters:
59  *      void * item - the item to store
60  *  Returns:
61  *      The new node, NULL on failure.
62  *****************************************************************************/
63 static ListNode *
64 CreateListNode( void *item,
65                 LinkedList * list )
66 {
67
68     ListNode *temp = NULL;
69
70     assert( list != NULL );
71
72     temp = ( ListNode * ) FreeListAlloc( &list->freeNodeList );
73     if( temp ) {
74         temp->prev = NULL;
75         temp->next = NULL;
76         temp->item = item;
77     }
78     return temp;
79 }
80
81 /****************************************************************************
82  * Function: ListInit
83  *
84  *  Description:
85  *      Initializes LinkedList. Must be called first.
86  *      And only once for List.
87  *  Parameters:
88  *      list  - must be valid, non null, pointer to a linked list.
89  *      cmp_func - function used to compare items. (May be NULL)
90  *      free_func - function used to free items. (May be NULL)
91  *  Returns:
92  *      0 on success, EOUTOFMEM on failure.
93  *****************************************************************************/
94 int
95 ListInit( LinkedList * list,
96           cmp_routine cmp_func,
97           free_function free_func )
98 {
99
100     int retCode = 0;
101
102     assert( list != NULL );
103
104     if( list == NULL )
105         return EINVAL;
106
107     list->size = 0;
108     list->cmp_func = cmp_func;
109     list->free_func = free_func;
110
111     retCode =
112         FreeListInit( &list->freeNodeList, sizeof( ListNode ),
113                       FREELISTSIZE );
114
115     assert( retCode == 0 );
116
117     list->head.item = NULL;
118     list->head.next = &list->tail;
119     list->head.prev = NULL;
120
121     list->tail.item = NULL;
122     list->tail.prev = &list->head;
123     list->tail.next = NULL;
124
125     return 0;
126 }
127
128 /****************************************************************************
129  * Function: ListAddHead
130  *
131  *  Description:
132  *      Adds a node to the head of the list.
133  *      Node gets immediately after list.head.
134  *  Parameters:
135  *      LinkedList *list  - must be valid, non null, pointer to a linked list.
136  *      void * item - item to be added
137  *  Returns:
138  *      The pointer to the ListNode on success, NULL on failure.
139  *  Precondition:
140  *      The list has been initialized.
141  *****************************************************************************/
142 ListNode *
143 ListAddHead( LinkedList * list,
144              void *item )
145 {
146     assert( list != NULL );
147
148     if( list == NULL )
149         return NULL;
150
151     return ListAddAfter( list, item, &list->head );
152 }
153
154 /****************************************************************************
155  * Function: ListAddTail
156  *
157  *  Description:
158  *      Adds a node to the tail of the list.
159  *      Node gets added immediately before list.tail.
160  *  Parameters:
161  *      LinkedList *list  - must be valid, non null, pointer to a linked list.
162  *      void * item - item to be added
163  *  Returns:
164  *      The pointer to the ListNode on success, NULL on failure.
165  *  Precondition:
166  *      The list has been initialized.
167  *****************************************************************************/
168 ListNode *
169 ListAddTail( LinkedList * list,
170              void *item )
171 {
172     assert( list != NULL );
173
174     if( list == NULL )
175         return NULL;
176
177     return ListAddBefore( list, item, &list->tail );
178 }
179
180 /****************************************************************************
181  * Function: ListAddAfter
182  *
183  *  Description:
184  *      Adds a node after the specified node.
185  *      Node gets added immediately after bnode.
186  *  Parameters:
187  *      LinkedList *list  - must be valid, non null, pointer to a linked list.
188  *      void * item - item to be added
189  *      ListNode * bnode - node to add after
190  *  Returns:
191  *      The pointer to the ListNode on success, NULL on failure.
192  *  Precondition:
193  *      The list has been initialized.
194  *****************************************************************************/
195 ListNode *
196 ListAddAfter( LinkedList * list,
197               void *item,
198               ListNode * bnode )
199 {
200     ListNode *newNode = NULL;
201
202     assert( list != NULL );
203
204     if( ( list == NULL ) || ( bnode == NULL ) )
205         return NULL;
206
207     newNode = CreateListNode( item, list );
208     if( newNode ) {
209         ListNode *temp = bnode->next;
210
211         bnode->next = newNode;
212         newNode->prev = bnode;
213         newNode->next = temp;
214         temp->prev = newNode;
215         list->size++;
216         return newNode;
217     }
218     return NULL;
219 }
220
221 /****************************************************************************
222  * Function: ListAddBefore
223  *
224  *  Description:
225  *      Adds a node before the specified node.
226  *      Node gets added immediately before anode.
227  *  Parameters:
228  *      LinkedList *list  - must be valid, non null, pointer to a linked list.
229  *      ListNode * anode  - node to add the in front of.
230  *      void * item - item to be added
231  *  Returns:
232  *      The pointer to the ListNode on success, NULL on failure.
233  *  Precondition:
234  *      The list has been initialized.
235  *****************************************************************************/
236 ListNode *
237 ListAddBefore( LinkedList * list,
238                void *item,
239                ListNode * anode )
240 {
241     ListNode *newNode = NULL;
242
243     assert( list != NULL );
244
245     if( ( list == NULL ) || ( anode == NULL ) )
246         return NULL;
247
248     newNode = CreateListNode( item, list );
249
250     if( newNode ) {
251         ListNode *temp = anode->prev;
252
253         anode->prev = newNode;
254         newNode->next = anode;
255         newNode->prev = temp;
256         temp->next = newNode;
257         list->size++;
258         return newNode;
259     }
260     return NULL;
261 }
262
263 /****************************************************************************
264  * Function: ListDelNode
265  *
266  *  Description:
267  *      Removes a node from the list
268  *      The memory for the node is freed but the
269  *      the memory for the items are not.
270  *  Parameters:
271  *      LinkedList *list  - must be valid, non null, pointer to a linked list.
272  *      ListNode *dnode - done to delete.
273  *  Returns:
274  *      The pointer to the item stored in node on success, NULL on failure.
275  *  Precondition:
276  *      The list has been initialized.
277  *****************************************************************************/
278 void *
279 ListDelNode( LinkedList * list,
280              ListNode * dnode,
281              int freeItem )
282 {
283     void *temp;
284
285     assert( list != NULL );
286     assert( dnode != &list->head );
287     assert( dnode != &list->tail );
288
289     if( ( list == NULL ) ||
290         ( dnode == &list->head ) ||
291         ( dnode == &list->tail ) || ( dnode == NULL ) ) {
292         return NULL;
293     }
294
295     temp = dnode->item;
296     dnode->prev->next = dnode->next;
297     dnode->next->prev = dnode->prev;
298
299     freeListNode( dnode, list );
300     list->size--;
301
302     if( freeItem && list->free_func ) {
303         list->free_func( temp );
304         temp = NULL;
305     }
306
307     return temp;
308 }
309
310 /****************************************************************************
311  * Function: ListDestroy
312  *
313  *  Description:
314  *      Removes all memory associated with list nodes. 
315  *      Does not free LinkedList *list. 
316  *      Items stored in the list are not freed, only nodes are.
317  *  Parameters:
318  *      LinkedList *list  - must be valid, non null, pointer to a linked list.
319  *  Returns:
320  *      0 on success. Nonzero on failure.
321  *      Always returns 0.
322  *  Precondition:
323  *      The list has been initialized.
324  *****************************************************************************/
325 int
326 ListDestroy( LinkedList * list,
327              int freeItem )
328 {
329     ListNode *dnode = NULL;
330     ListNode *temp = NULL;
331
332     if( list == NULL )
333         return EINVAL;
334
335     for( dnode = list->head.next; dnode != &list->tail; ) {
336         temp = dnode->next;
337         ListDelNode( list, dnode, freeItem );
338         dnode = temp;
339     }
340
341     list->size = 0;
342     FreeListDestroy( &list->freeNodeList );
343     return 0;
344 }
345
346 /****************************************************************************
347  * Function: ListHead
348  *
349  *  Description:
350  *      Returns the head of the list.
351  *    
352  *  Parameters:
353  *      LinkedList *list  - must be valid, non null, pointer to a linked list.
354  *  
355  *  Returns:
356  *      The head of the list. NULL if list is empty.
357  *  Precondition:
358  *      The list has been initialized.
359  *****************************************************************************/
360 ListNode *
361 ListHead( LinkedList * list )
362 {
363     assert( list != NULL );
364
365     if( list == NULL )
366         return NULL;
367
368     if( list->size == 0 )
369         return NULL;
370     else
371         return list->head.next;
372 }
373
374 /****************************************************************************
375  * Function: ListTail
376  *
377  *  Description:
378  *      Returns the tail of the list.
379  *    
380  *  Parameters:
381  *      LinkedList *list  - must be valid, non null, pointer to a linked list.
382  *  
383  *  Returns:
384  *      The tail of the list. NULL if list is empty.
385  *  Precondition:
386  *      The list has been initialized.
387  *****************************************************************************/
388 ListNode *
389 ListTail( LinkedList * list )
390 {
391     assert( list != NULL );
392
393     if( list == NULL )
394         return NULL;
395
396     if( list->size == 0 )
397         return NULL;
398     else
399         return list->tail.prev;
400 }
401
402 /****************************************************************************
403  * Function: ListNext
404  *
405  *  Description:
406  *      Returns the next item in the list.
407  *    
408  *  Parameters:
409  *      LinkedList *list  - must be valid, non null, pointer to a linked list.
410  *  
411  *  Returns:
412  *      The next item in the list. NULL if there are no more items in list.
413  *  Precondition:
414  *      The list has been initialized.
415  *****************************************************************************/
416 ListNode *
417 ListNext( LinkedList * list,
418           ListNode * node )
419 {
420     assert( list != NULL );
421     assert( node != NULL );
422
423     if( ( list == NULL ) || ( node == NULL ) )
424         return NULL;
425
426     if( node->next == &list->tail )
427         return NULL;
428     else
429         return node->next;
430 }
431
432 /****************************************************************************
433  * Function: ListPrev
434  *
435  *  Description:
436  *      Returns the previous item in the list.
437  *    
438  *  Parameters:
439  *      LinkedList *list  - must be valid, non null, pointer to a linked list.
440  *  
441  *  Returns:
442  *      The previous item in the list. NULL if there are no more items in list.
443  *  Precondition:
444  *      The list has been initialized.
445  *****************************************************************************/
446 ListNode *
447 ListPrev( LinkedList * list,
448           ListNode * node )
449 {
450     assert( list != NULL );
451     assert( node != NULL );
452
453     if( ( list == NULL ) || ( node == NULL ) )
454         return NULL;
455
456     if( node->prev == &list->head )
457         return NULL;
458     else
459         return node->prev;
460 }
461
462 /****************************************************************************
463  * Function: ListFind
464  *
465  *  Description:
466  *      Finds the specified item in the list.
467  *      Uses the compare function specified in ListInit. If compare function
468  *      is NULL then compares items as pointers.
469  *  Parameters:
470  *      LinkedList *list  - must be valid, non null, pointer to a linked list.
471  *      ListNode *start - the node to start from, NULL if to start from 
472  *                        beginning.
473  *      void * item - the item to search for.
474  *  Returns:
475  *      The node containing the item. NULL if no node contains the item.
476  *  Precondition:
477  *      The list has been initialized.
478  *****************************************************************************/
479 ListNode *
480 ListFind( LinkedList * list,
481           ListNode * start,
482           void *item )
483 {
484
485     ListNode *finger = NULL;
486
487     if( list == NULL )
488         return NULL;
489
490     if( start == NULL )
491         start = &list->head;
492
493     assert( start );
494
495     finger = start->next;
496
497     assert( finger );
498
499     while( finger != &list->tail ) {
500         if( list->cmp_func ) {
501             if( list->cmp_func( item, finger->item ) )
502                 return finger;
503         } else {
504             if( item == finger->item )
505                 return finger;
506         }
507         finger = finger->next;
508     }
509
510     return NULL;
511
512 }
513
514 /****************************************************************************
515  * Function: ListSize
516  *
517  *  Description:
518  *     Returns the size of the list.
519  *  Parameters:
520  *      LinkedList *list  - must be valid, non null, pointer to a linked list.
521  
522  *  Returns:
523  *      The number of items in the list.
524  *  Precondition:
525  *      The list has been initialized.
526  *****************************************************************************/
527 int
528 ListSize( LinkedList * list )
529 {
530     assert( list != NULL );
531
532     if( list == NULL )
533         return EINVAL;
534
535     return list->size;
536 }
537