diff --git a/libtransmission/utils-test.c b/libtransmission/utils-test.c index eed24edb6..97bdf7a5e 100644 --- a/libtransmission/utils-test.c +++ b/libtransmission/utils-test.c @@ -227,6 +227,44 @@ test_numbers( void ) return 0; } +static int +compareInts( const void * va, const void * vb ) +{ + const int a = *(const int *)va; + const int b = *(const int*)vb; + return a - b; +} + +static int +test_lowerbound( void ) +{ + int i; + const int A[] = { 1, 2, 3, 3, 3, 5, 8 }; + const int expected_pos[] = { 0, 1, 2, 5, 5, 6, 6, 6, 7, 7 }; + const int expected_exact[] = { TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE }; + const int N = sizeof(A) / sizeof(A[0]); + + for( i=1; i<=10; ++i ) + { + tr_bool exact; + const int pos = tr_lowerBound( &i, A, N, sizeof(int), compareInts, &exact ); + +#if 0 + fprintf( stderr, "searching for %d. ", i ); + fprintf( stderr, "result: index = %d, ", pos ); + if( pos != N ) + fprintf( stderr, "A[%d] == %d\n", pos, A[pos] ); + else + fprintf( stderr, "which is off the end.\n" ); +#endif + check( pos == expected_pos[i-1] ) + check( exact == expected_exact[i-1] ) + + } + + return 0; +} + static int test_memmem( void ) { @@ -270,6 +308,8 @@ main( void ) tr_free( in ); tr_free( out ); + if( ( i = test_lowerbound( ) ) ) + return i; if( ( i = test_strstrip( ) ) ) return i; if( ( i = test_buildpath( ) ) ) diff --git a/libtransmission/utils.c b/libtransmission/utils.c index 4567dc799..7c5ee1933 100644 --- a/libtransmission/utils.c +++ b/libtransmission/utils.c @@ -1108,32 +1108,27 @@ tr_lowerBound( const void * key, { size_t first = 0; const char * cbase = base; + tr_bool exact = FALSE; + int c; while( nmemb ) { const size_t half = nmemb / 2; const size_t middle = first + half; - const int c = compar( key, cbase + size*middle ); + c = compar( key, cbase + size*middle ); - if( c < 0 ) - { + if( c <= 0 ) { + if( c == 0 ) + exact = TRUE; + nmemb = half; + } else { first = middle + 1; nmemb = nmemb - half - 1; } - else if( !c ) - { - if( exact_match ) - *exact_match = TRUE; - return middle; - } - else - { - nmemb = half; - } } if( exact_match ) - *exact_match = FALSE; + *exact_match = exact; return first; }