add first draft of tr_bitfieldFindTrue() courtesy of erdgeist
This commit is contained in:
parent
041561f232
commit
e212eeceb7
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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* );
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue