1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2024-12-24 16:52:39 +00:00

(trunk libT) #1671: transmission-remote --get option not including all files

This commit is contained in:
Charles Kerr 2009-02-09 17:25:48 +00:00
parent c08f370e8a
commit 65bba3fdfb
4 changed files with 191 additions and 59 deletions

View file

@ -1040,29 +1040,6 @@ tr_rpc_request_exec_json( tr_session * session,
tr_bencFree( &top );
}
static void
addToken( tr_benc * list,
const char * token,
size_t len )
{
char * p;
const char * end = token + len;
const long a = strtol( token, &p, 10 );
if( p == end )
tr_bencListAddInt( list, a );
else if( *p == '-' && isdigit( p[1] ) )
{
const long b = strtol( p + 1, &p, 10 );
if( ( p == end ) && ( b > a ) )
{
long i;
for( i = a; i <= b; ++i )
tr_bencListAddInt( list, i );
}
}
}
/**
* Munge the URI into a usable form.
*
@ -1074,49 +1051,25 @@ addToken( tr_benc * list,
*/
void
tr_rpc_parse_list_str( tr_benc * setme,
const char * str_in,
const char * str,
int len )
{
char * str = tr_strndup( str_in, len );
int isNum;
int isNumList;
int commaCount;
const char * walk;
int valueCount;
int * values = tr_parseNumberRange( str, len, &valueCount );
isNum = 1;
isNumList = 1;
commaCount = 0;
walk = str;
for( ; *walk && ( isNumList || isNum ); ++walk )
{
if( isNumList ) isNumList = *walk == '-' || isdigit( *walk )
|| *walk == ',';
if( isNum ) isNum = *walk == '-' || isdigit( *walk );
if( *walk == ',' ) ++commaCount;
}
if( isNum )
tr_bencInitInt( setme, strtol( str, NULL, 10 ) );
else if( !isNumList )
if( valueCount == 0 )
tr_bencInitStr( setme, str, len );
else
{
tr_bencInitList( setme, commaCount + 1 );
walk = str;
while( *walk )
{
const char * p = strchr( walk, ',' );
if( !p )
p = walk + strlen( walk );
addToken( setme, walk, p - walk );
if( *p != ',' )
break;
walk = p + 1;
}
else if( valueCount == 1 )
tr_bencInitInt( setme, values[0] );
else {
int i;
tr_bencInitList( setme, valueCount );
for( i=0; i<valueCount; ++i )
tr_bencListAddInt( setme, values[i] );
}
tr_free( str );
tr_free( values );
}
void

View file

@ -185,6 +185,46 @@ test_utf8( void )
return 0;
}
static int
test_numbers( void )
{
int i;
int count;
int * numbers;
numbers = tr_parseNumberRange( "1-10,13,16-19", -1, &count );
check( count == 15 );
check( numbers != NULL );
check( numbers[0] == 1 );
check( numbers[5] == 6 );
check( numbers[9] == 10 );
check( numbers[10] == 13 );
check( numbers[11] == 16 );
check( numbers[14] == 19 );
tr_free( numbers );
numbers = tr_parseNumberRange( "1-5,3-7,2-6", -1, &count );
check( count == 7 );
check( numbers != NULL );
for( i=0; i<count; ++i )
check( numbers[i] == i+1 );
tr_free( numbers );
numbers = tr_parseNumberRange( "1-Hello", -1, &count );
check( count == 0 );
check( numbers == NULL );
numbers = tr_parseNumberRange( "1-", -1, &count );
check( count == 0 );
check( numbers == NULL );
numbers = tr_parseNumberRange( "Hello", -1, &count );
check( count == 0 );
check( numbers == NULL );
return 0;
}
int
main( void )
{
@ -211,6 +251,8 @@ main( void )
return i;
if( ( i = test_utf8( ) ) )
return i;
if( ( i = test_numbers( ) ) )
return i;
/* test that tr_cryptoRandInt() stays in-bounds */
for( i = 0; i < 100000; ++i )

View file

@ -1378,3 +1378,138 @@ tr_utf8clean( const char * str, int max_len, tr_bool * err )
evbuffer_free( buf );
return ret;
}
/***
****
***/
struct number_range
{
int low;
int high;
};
/**
* This should be a single number (ex. "6") or a range (ex. "6-9").
* Anything else is an error and will return failure.
*/
static tr_bool
parseNumberSection( const char * str, int len, struct number_range * setme )
{
long a, b;
tr_bool success;
char * end;
const int error = errno;
char * tmp = tr_strndup( str, len );
errno = 0;
a = strtol( tmp, &end, 10 );
if( errno || ( end == tmp ) ) {
success = FALSE;
} else if( *end != '-' ) {
b = a;
success = TRUE;
} else {
const char * pch = end + 1;
b = strtol( pch, &end, 10 );
if( errno || ( pch == end ) )
success = FALSE;
else if( *end ) /* trailing data */
success = FALSE;
else
success = TRUE;
}
tr_free( tmp );
setme->low = MIN( a, b );
setme->high = MAX( a, b );
errno = error;
return success;
}
static int
compareInt( const void * va, const void * vb )
{
const int a = *(const int *)va;
const int b = *(const int *)vb;
return a - b;
}
/**
* Given a string like "1-4" or "1-4,6,9,14-51", this allocates and returns an
* array of setmeCount ints of all the values in the array.
* For example, "5-8" will return [ 5, 6, 7, 8 ] and setmeCount will be 4.
* It's the caller's responsibility to call tr_free() on the returned array.
* If a fragment of the string can't be parsed, NULL is returned.
*/
int*
tr_parseNumberRange( const char * str_in, int len, int * setmeCount )
{
int n = 0;
int * uniq = NULL;
char * str = tr_strndup( str_in, len );
const char * walk;
tr_list * ranges = NULL;
tr_bool success = TRUE;
walk = str;
while( walk && *walk && success ) {
struct number_range range;
const char * pch = strchr( walk, ',' );
if( pch ) {
success = parseNumberSection( walk, pch-walk, &range );
walk = pch + 1;
} else {
success = parseNumberSection( walk, strlen( walk ), &range );
walk += strlen( walk );
}
if( success )
tr_list_append( &ranges, tr_memdup( &range, sizeof( struct number_range ) ) );
}
if( !success )
{
*setmeCount = 0;
uniq = NULL;
}
else
{
int i;
int n2;
tr_list * l;
int * sorted = NULL;
/* build a sorted number array */
n = n2 = 0;
for( l=ranges; l!=NULL; l=l->next ) {
const struct number_range * r = l->data;
n += r->high + 1 - r->low;
}
sorted = tr_new( int, n );
for( l=ranges; l!=NULL; l=l->next ) {
const struct number_range * r = l->data;
int i;
for( i=r->low; i<=r->high; ++i )
sorted[n2++] = i;
}
qsort( sorted, n, sizeof( int ), compareInt );
assert( n == n2 );
/* remove duplicates */
uniq = tr_new( int, n );
for( i=n=0; i<n2; ++i )
if( !n || uniq[n-1] != sorted[i] )
uniq[n++] = sorted[i];
tr_free( sorted );
}
/* cleanup */
tr_list_free( &ranges, tr_free );
tr_free( str );
/* return the result */
*setmeCount = n;
return uniq;
}

View file

@ -451,6 +451,8 @@ static TR_INLINE tr_bool tr_bitfieldHas( const tr_bitfield * b, size_t nth )
double tr_getRatio( double numerator, double denominator );
int* tr_parseNumberRange( const char * str, int str_len, int * setmeCount );
int tr_ptr2int( void* );