add first draft of tr_bitfieldFindTrue() courtesy of erdgeist

This commit is contained in:
Charles Kerr 2008-06-07 14:41:31 +00:00
parent 041561f232
commit e212eeceb7
7 changed files with 92 additions and 4 deletions

View File

@ -179,6 +179,14 @@ tr_cpPieceRem( tr_completion * cp, tr_piece_index_t piece )
tr_bitfieldRem( cp->pieceBitfield, piece );
}
int
tr_cpBlockFindComplete( const tr_completion * cp,
size_t startPos,
size_t * foundPos )
{
return tr_bitfieldFindTrue( cp->blockBitfield, startPos, foundPos );
}
int
tr_cpBlockIsComplete( const tr_completion * cp, tr_block_index_t block )
{
@ -232,9 +240,9 @@ tr_cpBlockBitfieldSet( tr_completion * cp, tr_bitfield * bitfield )
return TR_ERROR_ASSERT;
tr_cpReset( cp );
for( i=0; i < cp->tor->blockCount; ++i )
if( tr_bitfieldHas( bitfield, i ) )
tr_cpBlockAdd( cp, i );
i = 0;
while( tr_bitfieldFindTrue( bitfield, i, &i ) )
tr_cpBlockAdd( cp, i++ );
return 0;
}

View File

@ -53,9 +53,12 @@ void tr_cpPieceRem( tr_completion *, tr_piece_index_t piece );
/* Blocks */
int tr_cpBlockIsComplete( const tr_completion *, tr_block_index_t block );
int tr_cpBlockFindComplete( const tr_completion * cp,
size_t startPos, size_t* foundPos );
void tr_cpBlockAdd( tr_completion *, tr_block_index_t block );
tr_errno tr_cpBlockBitfieldSet( tr_completion *, struct tr_bitfield * );
int tr_cpMissingBlocksInPiece( const tr_completion * cp, tr_piece_index_t piece );
int tr_cpMissingBlocksInPiece( const tr_completion * cp,
tr_piece_index_t piece );
const struct tr_bitfield * tr_cpPieceBitfield( const tr_completion* );

View File

@ -430,6 +430,7 @@ parseProgress( tr_torrent * tor,
/* get the completion bitfield */
memset( &bitfield, 0, sizeof bitfield );
bitfield.byteCount = FR_BLOCK_BITFIELD_LEN( tor );
bitfield.bitCount = bitfield.byteCount * 8;
bitfield.bits = (uint8_t*) walk;
if( !tr_cpBlockBitfieldSet( tor->completion, &bitfield ) )
ret = TR_FR_PROGRESS;

View File

@ -320,6 +320,7 @@ loadProgress( tr_benc * dict, tr_torrent * tor )
{
tr_bitfield tmp;
tmp.byteCount = b->val.s.i;
tmp.bitCount = tmp.byteCount * 8;
tmp.bits = (uint8_t*) b->val.s.s;
if( tr_cpBlockBitfieldSet( tor->completion, &tmp ) ) {
tr_torrentUncheck( tor );

View File

@ -33,6 +33,7 @@ test_bitfields( void )
{
int i;
int bitcount = 5000000;
size_t pos;
tr_bitfield * field = tr_bitfieldNew( bitcount );
/* make every seventh one true */
@ -44,6 +45,27 @@ test_bitfields( void )
for( i=0; i<bitcount; ++i )
check( tr_bitfieldHas( field, i ) == (!(i%7)) );
/* testing the "find next" function */
check( tr_bitfieldFindTrue( field, 0, &pos ) );
check( pos == 0 );
check( tr_bitfieldFindTrue( field, 1, &pos ) );
check( pos == 7 );
check( tr_bitfieldFindTrue( field, 2, &pos ) );
check( pos == 7 );
check( tr_bitfieldFindTrue( field, 7, &pos ) );
check( pos == 7 );
check( tr_bitfieldFindTrue( field, 8, &pos ) );
check( pos == 14 );
check( tr_bitfieldFindTrue( field, 13, &pos ) );
check( pos == 14 );
check( tr_bitfieldFindTrue( field, 14, &pos ) );
check( pos == 14 );
check( tr_bitfieldFindTrue( field, 15, &pos ) );
check( pos == 21 );
check( tr_bitfieldFindTrue( field, 16, &pos ) );
check( pos == 21 );
tr_bitfieldFree( field );
return 0;
}

View File

@ -732,6 +732,51 @@ tr_bitfieldHas( const tr_bitfield * bitfield, size_t nth )
&& ( tr_bitfieldHasFast( bitfield, nth ) );
}
static int
find_top_bit( uint8_t val )
{
int pos = 0;
if ( val & 0xF0U ) pos |= 4, val >>= 4;
if ( val & 0xCU ) pos |= 2, val >>= 2;
if ( val & 0x2 ) pos |= 1;
return 7 - pos;
}
int
tr_bitfieldFindTrue( const tr_bitfield * bitfield,
size_t startBit,
size_t * setmePos )
{
if( bitfield && bitfield->bits && startBit < bitfield->bitCount )
{
const uint8_t * b = bitfield->bits + startBit/8;
const uint8_t * end = bitfield->bits + bitfield->byteCount;
/* If first byte already contains a set bit after startBit*/
if( *b & ( 0xff >> (startBit&7) ) ) {
*setmePos = 8 * ( b - bitfield->bits );
*setmePos += find_top_bit( *b & ( 0xff >> (startBit&7) ) );
return 1;
}
/* Test bitfield for first non zero byte */
++b;
while( (b < end) && !*b )
++b;
/* If we hit the end of our bitfield, no set bit was found */
if( b == end )
return 0;
/* New bitposition is byteoff*8 */
*setmePos = 8 * ( b - bitfield->bits ) + find_top_bit( *b );
return 1;
}
return 0;
}
int
tr_bitfieldAdd( tr_bitfield * bitfield, size_t nth )
{

View File

@ -263,6 +263,14 @@ size_t tr_bitfieldCountTrueBits( const tr_bitfield* );
tr_bitfield* tr_bitfieldOr( tr_bitfield*, const tr_bitfield* );
/** @brief finds the first true bit in the bitfield, starting at `startPos'
@param setmePos the position of the true bit, if found, is set here.
@return nonzero if a true bit was found */
int tr_bitfieldFindTrue( const tr_bitfield * bitfield,
size_t startPos,
size_t * setmePos );
/** A stripped-down version of bitfieldHas to be used
for speed when you're looping quickly. This version
has none of tr_bitfieldHas()'s safety checks, so you