Ignore:
Timestamp:
Feb 9, 2009, 5:34:43 PM (13 years ago)
Author:
charles
Message:

(1.5x libT) backport #1671, #1798

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/1.5x/libtransmission/utils.c

    r7813 r7855  
    13791379    return ret;
    13801380}
     1381
     1382/***
     1383****
     1384***/
     1385
     1386struct 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. "6-9").
     1394 * Anything else is an error and will return failure.
     1395 */
     1396static tr_bool
     1397parseNumberSection( 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
     1431static int
     1432compareInt( 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 "1-4" or "1-4,6,9,14-51", this allocates and returns an
     1441 * array of setmeCount ints of all the values in the array.
     1442 * For example, "5-8" 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 */
     1446int*
     1447tr_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, pch-walk, &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[n-1] != 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}
Note: See TracChangeset for help on using the changeset viewer.