make list less error-prone by changing the API s.t. we're guaranteed to update the list's pointer correctly.

This commit is contained in:
Charles Kerr 2007-08-14 14:18:54 +00:00
parent 8f8100e4d8
commit 26dabf816e
6 changed files with 80 additions and 39 deletions

View File

@ -29,44 +29,70 @@ node_free( tr_list_t* node )
***/
void
tr_list_free( tr_list_t* list )
tr_list_free( tr_list_t** list )
{
while( list )
while( *list )
{
tr_list_t * node = list;
list = list->next;
tr_list_t * node = *list;
*list = (*list)->next;
node_free( node );
}
}
tr_list_t*
tr_list_prepend( tr_list_t * list, void * data )
void
tr_list_prepend( tr_list_t ** list, void * data )
{
tr_list_t * node = node_alloc ();
node->data = data;
node->next = list;
if( list )
list->prev = node;
return node;
node->next = *list;
if( *list )
(*list)->prev = node;
*list = node;
}
tr_list_t*
tr_list_append( tr_list_t * list, void * data )
void
tr_list_append( tr_list_t ** list, void * data )
{
tr_list_t * node = node_alloc( );
node->data = data;
if( !list )
return node;
if( !*list )
*list = node;
else {
tr_list_t * l = list;
tr_list_t * l = *list;
while( l->next )
l = l->next;
l->next = node;
node->prev = l;
return list;
}
}
void
tr_list_insert_sorted( tr_list_t ** list,
void * data,
int compare(const void*,const void*) )
{
/* find l, the node that we'll insert this data before */
tr_list_t * l;
for( l=*list; l!=NULL; l=l->next ) {
const int c = (compare)( data, l->data );
if( c <= 0 )
break;
}
if( l == NULL)
tr_list_append( list, data );
else if( l == *list )
tr_list_prepend( list, data );
else {
tr_list_t * node = node_alloc( );
node->data = data;
if( l->prev ) { node->prev = l->prev; node->prev->next = node; }
node->next = l;
l->prev = node;
}
}
tr_list_t*
tr_list_find_data ( tr_list_t * list, const void * data )
{
@ -77,21 +103,20 @@ tr_list_find_data ( tr_list_t * list, const void * data )
return NULL;
}
tr_list_t*
tr_list_remove_data ( tr_list_t * list, const void * data )
void
tr_list_remove_data ( tr_list_t ** list, const void * data )
{
tr_list_t * node = tr_list_find_data( list, data );
tr_list_t * node = tr_list_find_data( *list, data );
tr_list_t * prev = node ? node->prev : NULL;
tr_list_t * next = node ? node->next : NULL;
if( prev ) prev->next = next;
if( next ) next->prev = prev;
if( list == node ) list = next;
if( *list == node ) *list = next;
node_free( node );
return list;
}
tr_list_t*
tr_list_find ( tr_list_t * list , TrListCompareFunc func, const void * b )
tr_list_find ( tr_list_t * list , const void * b, TrListCompareFunc func )
{
for( ; list; list=list->next )
if( !func( list->data, b ) )

View File

@ -19,17 +19,33 @@ typedef struct tr_list_s
}
tr_list_t;
void tr_list_free ( tr_list_t* );
tr_list_t* tr_list_append ( tr_list_t*, void * data );
tr_list_t* tr_list_prepend ( tr_list_t*, void * data );
tr_list_t* tr_list_remove_data ( tr_list_t*, const void * data );
typedef int (*TrListCompareFunc)(const void * a, const void * b);
tr_list_t* tr_list_find ( tr_list_t*, TrListCompareFunc func, const void * b );
tr_list_t* tr_list_find_data ( tr_list_t*, const void * data );
typedef void (*TrListForeachFunc)(void *);
void tr_list_foreach ( tr_list_t*, TrListForeachFunc func );
void tr_list_free ( tr_list_t ** list );
void tr_list_append ( tr_list_t ** list,
void * data );
void tr_list_prepend ( tr_list_t ** list,
void * data );
void tr_list_remove_data ( tr_list_t ** list,
const void * data );
void tr_list_insert_sorted ( tr_list_t ** list,
void * data,
TrListCompareFunc compare_func );
tr_list_t* tr_list_find ( tr_list_t * list,
const void * b,
TrListCompareFunc compare_func );
tr_list_t* tr_list_find_data ( tr_list_t * list,
const void * data );
void tr_list_foreach ( tr_list_t * list,
TrListForeachFunc foreach_func );
#endif /* TR_LIST_H */

View File

@ -313,7 +313,7 @@ void tr_peerDestroy( tr_peer_t * peer )
tr_bitfieldFree( peer->banfield );
tr_bitfieldFree( peer->reqfield );
tr_list_foreach( peer->outRequests, tr_free );
tr_list_free( peer->outRequests );
tr_list_free( &peer->outRequests );
tr_free( peer->inRequests );
tr_free( peer->buf );
tr_free( peer->outMessages );

View File

@ -123,7 +123,7 @@ blockPending( tr_torrent_t * tor,
r = (tr_request_t*) peer->outRequests->data;
assert( r != NULL );
peer->outRequests = tr_list_remove_data( peer->outRequests, r );
tr_list_remove_data( &peer->outRequests, r );
if( !tr_cpPieceIsComplete( tor->completion, r->index ) ) /* sanity clause */
{
@ -226,7 +226,7 @@ static void sendChoke( tr_peer_t * peer, int yes )
{
/* Drop older requests from the last time it was unchoked, if any */
tr_list_foreach( peer->outRequests, tr_free );
tr_list_free( peer->outRequests );
tr_list_free( &peer->outRequests );
peer->outRequests = NULL;
}

View File

@ -244,7 +244,7 @@ static int parseRequest( tr_torrent_t * tor, tr_peer_t * peer,
r->index = index;
r->begin = begin;
r->length = length;
peer->outRequests = tr_list_append( peer->outRequests, r );
tr_list_append( &peer->outRequests, r );
return TR_OK;
}
@ -418,9 +418,9 @@ static int parseCancel( tr_torrent_t * tor, tr_peer_t * peer,
req.index = index;
req.begin = begin;
req.length = length;
while(( l = tr_list_find( peer->outRequests, reqCompare, &req ) )) {
while(( l = tr_list_find( peer->outRequests, &req, reqCompare ) )) {
tr_request_t * r = (tr_request_t *) l->data;
peer->outRequests = tr_list_remove_data( peer->outRequests, r );
tr_list_remove_data( &peer->outRequests, r );
tr_free( r );
}

View File

@ -270,7 +270,7 @@ tr_loadTorrents ( tr_handle_t * h,
tr_buildPath( path, sizeof(path), torrentDir, d->d_name, NULL );
tor = tr_torrentInit( h, path, destination, flags, NULL );
if( tor != NULL ) {
list = tr_list_append( list, tor );
tr_list_append( &list, tor );
//fprintf (stderr, "#%d - %s\n", n, tor->info.name );
n++;
}
@ -284,7 +284,7 @@ tr_loadTorrents ( tr_handle_t * h,
torrents[i++] = (tr_torrent_t*) l->data;
assert( i==n );
tr_list_free( list );
tr_list_free( &list );
*setmeCount = n;
tr_inf( "Loaded %d torrents from disk", *setmeCount );