Changeset 7854
 Timestamp:
 Feb 9, 2009, 5:25:48 PM (13 years ago)
 Location:
 trunk/libtransmission
 Files:

 4 edited
Legend:
 Unmodified
 Added
 Removed

trunk/libtransmission/rpcimpl.c
r7853 r7854 1041 1041 } 1042 1042 1043 static void1044 addToken( tr_benc * list,1045 const char * token,1046 size_t len )1047 {1048 char * p;1049 const char * end = token + len;1050 const long a = strtol( token, &p, 10 );1051 1052 if( p == end )1053 tr_bencListAddInt( list, a );1054 else if( *p == '' && isdigit( p[1] ) )1055 {1056 const long b = strtol( p + 1, &p, 10 );1057 if( ( p == end ) && ( b > a ) )1058 {1059 long i;1060 for( i = a; i <= b; ++i )1061 tr_bencListAddInt( list, i );1062 }1063 }1064 }1065 1066 1043 /** 1067 1044 * Munge the URI into a usable form. … … 1075 1052 void 1076 1053 tr_rpc_parse_list_str( tr_benc * setme, 1077 const char * str _in,1054 const char * str, 1078 1055 int len ) 1079 1056 1080 1057 { 1081 char * str = tr_strndup( str_in, len ); 1082 int isNum; 1083 int isNumList; 1084 int commaCount; 1085 const char * walk; 1086 1087 isNum = 1; 1088 isNumList = 1; 1089 commaCount = 0; 1090 walk = str; 1091 for( ; *walk && ( isNumList  isNum ); ++walk ) 1092 { 1093 if( isNumList ) isNumList = *walk == ''  isdigit( *walk ) 1094  *walk == ','; 1095 if( isNum ) isNum = *walk == ''  isdigit( *walk ); 1096 if( *walk == ',' ) ++commaCount; 1097 } 1098 1099 if( isNum ) 1100 tr_bencInitInt( setme, strtol( str, NULL, 10 ) ); 1101 else if( !isNumList ) 1058 int valueCount; 1059 int * values = tr_parseNumberRange( str, len, &valueCount ); 1060 1061 if( valueCount == 0 ) 1102 1062 tr_bencInitStr( setme, str, len ); 1103 else 1104 { 1105 tr_bencInitList( setme, commaCount + 1 ); 1106 walk = str; 1107 while( *walk ) 1108 { 1109 const char * p = strchr( walk, ',' ); 1110 if( !p ) 1111 p = walk + strlen( walk ); 1112 addToken( setme, walk, p  walk ); 1113 if( *p != ',' ) 1114 break; 1115 walk = p + 1; 1116 } 1117 } 1118 1119 tr_free( str ); 1063 else if( valueCount == 1 ) 1064 tr_bencInitInt( setme, values[0] ); 1065 else { 1066 int i; 1067 tr_bencInitList( setme, valueCount ); 1068 for( i=0; i<valueCount; ++i ) 1069 tr_bencListAddInt( setme, values[i] ); 1070 } 1071 1072 tr_free( values ); 1120 1073 } 1121 1074 
trunk/libtransmission/utilstest.c
r7783 r7854 186 186 } 187 187 188 static int 189 test_numbers( void ) 190 { 191 int i; 192 int count; 193 int * numbers; 194 195 numbers = tr_parseNumberRange( "110,13,1619", 1, &count ); 196 check( count == 15 ); 197 check( numbers != NULL ); 198 check( numbers[0] == 1 ); 199 check( numbers[5] == 6 ); 200 check( numbers[9] == 10 ); 201 check( numbers[10] == 13 ); 202 check( numbers[11] == 16 ); 203 check( numbers[14] == 19 ); 204 tr_free( numbers ); 205 206 numbers = tr_parseNumberRange( "15,37,26", 1, &count ); 207 check( count == 7 ); 208 check( numbers != NULL ); 209 for( i=0; i<count; ++i ) 210 check( numbers[i] == i+1 ); 211 tr_free( numbers ); 212 213 numbers = tr_parseNumberRange( "1Hello", 1, &count ); 214 check( count == 0 ); 215 check( numbers == NULL ); 216 217 numbers = tr_parseNumberRange( "1", 1, &count ); 218 check( count == 0 ); 219 check( numbers == NULL ); 220 221 numbers = tr_parseNumberRange( "Hello", 1, &count ); 222 check( count == 0 ); 223 check( numbers == NULL ); 224 225 return 0; 226 } 227 188 228 int 189 229 main( void ) … … 212 252 if( ( i = test_utf8( ) ) ) 213 253 return i; 254 if( ( i = test_numbers( ) ) ) 255 return i; 214 256 215 257 /* test that tr_cryptoRandInt() stays inbounds */ 
trunk/libtransmission/utils.c
r7797 r7854 1379 1379 return ret; 1380 1380 } 1381 1382 /*** 1383 **** 1384 ***/ 1385 1386 struct number_range 1387 { 1388 int low; 1389 int high; 1390 }; 1391 1392 /** 1393 * This should be a single number (ex. "6") or a range (ex. "69"). 1394 * Anything else is an error and will return failure. 1395 */ 1396 static tr_bool 1397 parseNumberSection( const char * str, int len, struct number_range * setme ) 1398 { 1399 long a, b; 1400 tr_bool success; 1401 char * end; 1402 const int error = errno; 1403 char * tmp = tr_strndup( str, len ); 1404 1405 errno = 0; 1406 a = strtol( tmp, &end, 10 ); 1407 if( errno  ( end == tmp ) ) { 1408 success = FALSE; 1409 } else if( *end != '' ) { 1410 b = a; 1411 success = TRUE; 1412 } else { 1413 const char * pch = end + 1; 1414 b = strtol( pch, &end, 10 ); 1415 if( errno  ( pch == end ) ) 1416 success = FALSE; 1417 else if( *end ) /* trailing data */ 1418 success = FALSE; 1419 else 1420 success = TRUE; 1421 } 1422 tr_free( tmp ); 1423 1424 setme>low = MIN( a, b ); 1425 setme>high = MAX( a, b ); 1426 1427 errno = error; 1428 return success; 1429 } 1430 1431 static int 1432 compareInt( const void * va, const void * vb ) 1433 { 1434 const int a = *(const int *)va; 1435 const int b = *(const int *)vb; 1436 return a  b; 1437 } 1438 1439 /** 1440 * Given a string like "14" or "14,6,9,1451", this allocates and returns an 1441 * array of setmeCount ints of all the values in the array. 1442 * For example, "58" will return [ 5, 6, 7, 8 ] and setmeCount will be 4. 1443 * It's the caller's responsibility to call tr_free() on the returned array. 1444 * If a fragment of the string can't be parsed, NULL is returned. 1445 */ 1446 int* 1447 tr_parseNumberRange( const char * str_in, int len, int * setmeCount ) 1448 { 1449 int n = 0; 1450 int * uniq = NULL; 1451 char * str = tr_strndup( str_in, len ); 1452 const char * walk; 1453 tr_list * ranges = NULL; 1454 tr_bool success = TRUE; 1455 1456 walk = str; 1457 while( walk && *walk && success ) { 1458 struct number_range range; 1459 const char * pch = strchr( walk, ',' ); 1460 if( pch ) { 1461 success = parseNumberSection( walk, pchwalk, &range ); 1462 walk = pch + 1; 1463 } else { 1464 success = parseNumberSection( walk, strlen( walk ), &range ); 1465 walk += strlen( walk ); 1466 } 1467 if( success ) 1468 tr_list_append( &ranges, tr_memdup( &range, sizeof( struct number_range ) ) ); 1469 } 1470 1471 if( !success ) 1472 { 1473 *setmeCount = 0; 1474 uniq = NULL; 1475 } 1476 else 1477 { 1478 int i; 1479 int n2; 1480 tr_list * l; 1481 int * sorted = NULL; 1482 1483 /* build a sorted number array */ 1484 n = n2 = 0; 1485 for( l=ranges; l!=NULL; l=l>next ) { 1486 const struct number_range * r = l>data; 1487 n += r>high + 1  r>low; 1488 } 1489 sorted = tr_new( int, n ); 1490 for( l=ranges; l!=NULL; l=l>next ) { 1491 const struct number_range * r = l>data; 1492 int i; 1493 for( i=r>low; i<=r>high; ++i ) 1494 sorted[n2++] = i; 1495 } 1496 qsort( sorted, n, sizeof( int ), compareInt ); 1497 assert( n == n2 ); 1498 1499 /* remove duplicates */ 1500 uniq = tr_new( int, n ); 1501 for( i=n=0; i<n2; ++i ) 1502 if( !n  uniq[n1] != sorted[i] ) 1503 uniq[n++] = sorted[i]; 1504 1505 tr_free( sorted ); 1506 } 1507 1508 /* cleanup */ 1509 tr_list_free( &ranges, tr_free ); 1510 tr_free( str ); 1511 1512 /* return the result */ 1513 *setmeCount = n; 1514 return uniq; 1515 } 
trunk/libtransmission/utils.h
r7845 r7854 452 452 double tr_getRatio( double numerator, double denominator ); 453 453 454 int* tr_parseNumberRange( const char * str, int str_len, int * setmeCount ); 455 454 456 455 457 int tr_ptr2int( void* );
Note: See TracChangeset
for help on using the changeset viewer.