/* * This file Copyright (C) 2007-2009 Charles Kerr * * This file is licensed by the GPL version 2. Works owned by the * Transmission project are granted a special exemption to clause 2(b) * so that the bulk of its code can remain under the MIT license. * This exemption does not extend to derived works not owned by * the Transmission project. * * $Id:$ */ #include #include "transmission.h" #include "request-list.h" #include "utils.h" static int compareRequests( const struct peer_request * a, const struct peer_request * b ) { if( a->index != b->index ) return a->index < b->index ? -1 : 1; if( a->offset != b->offset ) return a->offset < b->offset ? -1 : 1; return 0; } const struct request_list REQUEST_LIST_INIT = { 0, 0, NULL, NULL }; static const int GROW = 8; static void reqListReserve( struct request_list * list, size_t max ) { if( list->max < max ) { list->max = max + GROW; list->fifo = tr_renew( struct peer_request, list->fifo, list->max ); list->sort = tr_renew( struct peer_request, list->sort, list->max ); } } void reqListClear( struct request_list * list ) { tr_free( list->fifo ); tr_free( list->sort ); *list = REQUEST_LIST_INIT; } void reqListCopy( struct request_list * dest, const struct request_list * src ) { dest->len = dest->max = src->len; dest->fifo = tr_memdup( src->fifo, dest->len * sizeof( struct peer_request ) ); dest->sort = tr_memdup( src->sort, dest->len * sizeof( struct peer_request ) ); } typedef int (*compareFunc)(const void * a, const void * b ); static int reqListSortPos( const struct request_list * list, const struct peer_request * req, tr_bool * exactMatch ) { return tr_lowerBound( req, list->sort, list->len, sizeof( struct peer_request ), (compareFunc)compareRequests, exactMatch ); } void reqListAppend( struct request_list * list, const struct peer_request * req ) { int low; reqListReserve( list, list->len + 8 ); /* append into list->fifo */ list->fifo[list->len] = *req; /* insert into list->sort */ low = reqListSortPos( list, req, NULL ); memmove( &list->sort[low+1], &list->sort[low], (list->len-low)*sizeof(struct peer_request) ); list->sort[low] = *req; ++list->len; } static tr_bool reqListRemoveFromSorted( struct request_list * list, const struct peer_request * key ) { tr_bool found; const int low = reqListSortPos( list, key, &found ); if( found ) memmove( &list->sort[low], &list->sort[low+1], (list->len-low-1)*sizeof(struct peer_request)); return found; } static void reqListRemoveNthFromFifo( struct request_list * list, int n ) { memmove( &list->fifo[n], &list->fifo[n+1], (list->len-n-1)*sizeof(struct peer_request)); } tr_bool reqListPop( struct request_list * list, struct peer_request * setme ) { tr_bool success; if( !list->len ) { success = FALSE; } else { *setme = list->fifo[0]; reqListRemoveNthFromFifo( list, 0 ); reqListRemoveFromSorted( list, setme ); --list->len; success = TRUE; } return success; } tr_bool reqListHas( const struct request_list * list, const struct peer_request * key ) { tr_bool exactMatch; reqListSortPos( list, key, &exactMatch ); return exactMatch; } tr_bool reqListRemove( struct request_list * list, const struct peer_request * key ) { tr_bool found = reqListRemoveFromSorted( list, key ); if( found ) { size_t i; for( i=0; ilen; ++i ) if( !compareRequests( &list->fifo[i], key ) ) break; assert( i < list->len ); reqListRemoveNthFromFifo( list, i ); --list->len; } return found; }