source: trunk/libtransmission/list.c @ 7658

Last change on this file since 7658 was 7658, checked in by charles, 12 years ago

(trunk) update the GPL code's copyright dates

  • Property svn:keywords set to Date Rev Author Id
File size: 4.4 KB
Line 
1/*
2 * This file Copyright (C) 2007-2009 Charles Kerr <charles@transmissionbt.com>
3 *
4 * This file is licensed by the GPL version 2.  Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id: list.c 7658 2009-01-10 23:09:07Z charles $
11 */
12
13#include "transmission.h"
14#include "list.h"
15#include "utils.h"
16
17/***
18****
19***/
20
21static tr_list * _unusedNodes = NULL;
22
23static const tr_list TR_LIST_INIT = { NULL, NULL, NULL };
24
25static tr_list*
26node_alloc( void )
27{
28    tr_list * node;
29
30    if( _unusedNodes == NULL )
31        node = tr_new( tr_list, 1 );
32    else {
33        node = _unusedNodes;
34        _unusedNodes = node->next;
35    }
36
37    *node = TR_LIST_INIT;
38    return node;
39}
40
41static void
42node_free( tr_list* node )
43{
44    if( node )
45    {
46        *node = TR_LIST_INIT;
47        node->next = _unusedNodes;
48        _unusedNodes = node;
49    }
50}
51
52/***
53****
54***/
55
56void
57tr_list_free( tr_list**         list,
58              TrListForeachFunc data_free_func )
59{
60    while( *list )
61    {
62        tr_list *node = *list;
63        *list = ( *list )->next;
64        if( data_free_func )
65            data_free_func( node->data );
66        node_free( node );
67    }
68}
69
70void
71tr_list_prepend( tr_list ** list,
72                 void *     data )
73{
74    tr_list * node = node_alloc ( );
75
76    node->data = data;
77    node->next = *list;
78    if( *list )
79        ( *list )->prev = node;
80    *list = node;
81}
82
83void
84tr_list_append( tr_list ** list,
85                void *     data )
86{
87    tr_list * node = node_alloc( );
88
89    node->data = data;
90    if( !*list )
91        *list = node;
92    else
93    {
94        tr_list * l = *list;
95        while( l->next )
96            l = l->next;
97
98        l->next = node;
99        node->prev = l;
100    }
101}
102
103static tr_list*
104tr_list_find_data( tr_list *    list,
105                   const void * data )
106{
107    for( ; list; list = list->next )
108        if( list->data == data )
109            return list;
110
111    return NULL;
112}
113
114static void*
115tr_list_remove_node( tr_list ** list,
116                     tr_list *  node )
117{
118    void *    data;
119    tr_list * prev = node ? node->prev : NULL;
120    tr_list * next = node ? node->next : NULL;
121
122    if( prev ) prev->next = next;
123    if( next ) next->prev = prev;
124    if( *list == node ) *list = next;
125    data = node ? node->data : NULL;
126    node_free( node );
127    return data;
128}
129
130void*
131tr_list_pop_front( tr_list ** list )
132{
133    void * ret = NULL;
134
135    if( *list )
136    {
137        ret = ( *list )->data;
138        tr_list_remove_node( list, *list );
139    }
140    return ret;
141}
142
143void*
144tr_list_remove_data( tr_list **   list,
145                     const void * data )
146{
147    return tr_list_remove_node( list, tr_list_find_data( *list, data ) );
148}
149
150void*
151tr_list_remove( tr_list **        list,
152                const void *      b,
153                TrListCompareFunc compare_func )
154{
155    return tr_list_remove_node( list, tr_list_find( *list, b, compare_func ) );
156}
157
158tr_list*
159tr_list_find( tr_list *         list,
160              const void *      b,
161              TrListCompareFunc func )
162{
163    for( ; list; list = list->next )
164        if( !func( list->data, b ) )
165            return list;
166
167    return NULL;
168}
169
170int
171tr_list_size( const tr_list * list )
172{
173    int size = 0;
174
175    while( list )
176    {
177        ++size;
178        list = list->next;
179    }
180
181    return size;
182}
183
184
185
186/*
187 * Double-linked list with easy memory management and fast
188 * insert/remove operations
189 */
190
191void
192__tr_list_init( struct __tr_list * head )
193{
194    head->next = head;
195    head->prev = head;
196}
197
198void
199__tr_list_insert( struct __tr_list * list,
200                  struct __tr_list * prev,
201                  struct __tr_list * next)
202{
203    next->prev = list;
204    list->next = next;
205    list->prev = prev;
206    prev->next = list;
207}
208
209void
210__tr_list_splice( struct __tr_list * prev,
211                  struct __tr_list * next)
212{
213    next->prev = prev;
214    prev->next = next;
215}
216
217 
218void
219__tr_list_append( struct __tr_list * head,
220                  struct __tr_list * list)
221{
222    __tr_list_insert( list, head->prev, head );
223}
224
225void
226__tr_list_remove( struct __tr_list * head )
227{
228    __tr_list_splice( head->prev, head->next );
229    head->next = head->prev = NULL;
230}
231
232void
233__tr_list_destroy( struct __tr_list * head,
234                   __tr_list_free_t   func)
235{
236    while ( head->next != head )
237    {
238        struct __tr_list * list = head->next;
239        __tr_list_splice( list->prev, list->next );
240
241        func( list );
242    }
243}
Note: See TracBrowser for help on using the repository browser.