diff --git a/libtransmission/bencode-test.c b/libtransmission/bencode-test.c index 6bce1008b..41f7b3cfb 100644 --- a/libtransmission/bencode-test.c +++ b/libtransmission/bencode-test.c @@ -361,6 +361,55 @@ testJSON( void ) return 0; } +static int +testMerge( void ) +{ + tr_benc dest, src; + int64_t i; + const char * s; + + /* initial dictionary (default values) */ + tr_bencInitDict( &dest, 10 ); + tr_bencDictAddInt( &dest, "i1", 1 ); + tr_bencDictAddInt( &dest, "i2", 2 ); + tr_bencDictAddInt( &dest, "i4", -35 ); /* remains untouched */ + tr_bencDictAddStr( &dest, "s5", "abc" ); + tr_bencDictAddStr( &dest, "s6", "def" ); + tr_bencDictAddStr( &dest, "s7", "127.0.0.1" ); /* remains untouched */ + + /* new dictionary, will overwrite items in dest */ + tr_bencInitDict( &src, 10 ); + tr_bencDictAddInt( &src, "i1", 1 ); /* same value */ + tr_bencDictAddInt( &src, "i2", 4 ); /* new value */ + tr_bencDictAddInt( &src, "i3", 3 ); /* new key:value */ + tr_bencDictAddStr( &src, "s5", "abc" ); /* same value */ + tr_bencDictAddStr( &src, "s6", "xyz" ); /* new value */ + tr_bencDictAddStr( &src, "s8", "ghi" ); /* new key:value */ + + tr_bencMergeDicts( &dest, /*const*/ &src ); + + check( tr_bencDictFindInt( &dest, "i1", &i )); + check( i == 1); + check( tr_bencDictFindInt( &dest, "i2", &i )); + check( i == 4); + check( tr_bencDictFindInt( &dest, "i3", &i )); + check( i == 3); + check( tr_bencDictFindInt( &dest, "i4", &i )); + check( i == -35); + check( tr_bencDictFindStr( &dest, "s5", &s )); + check( strcmp( "abc", s ) == 0 ); + check( tr_bencDictFindStr( &dest, "s6", &s )); + check( strcmp( "xyz", s ) == 0 ); + check( tr_bencDictFindStr( &dest, "s7", &s )); + check( strcmp( "127.0.0.1", s ) == 0 ); + check( tr_bencDictFindStr( &dest, "s8", &s )); + check( strcmp( "ghi", s ) == 0 ); + + tr_bencFree( &dest ); + tr_bencFree( &src ); + return 0; +} + static int testStackSmash( int depth ) { @@ -396,16 +445,19 @@ main( void ) { int i; - if( ( i = testInt( ) ) ) + if(( i = testInt( ))) return i; - if( ( i = testStr( ) ) ) + if(( i = testStr( ))) return i; - if( ( i = testParse( ) ) ) + if(( i = testParse( ))) return i; - if( ( i = testJSON( ) ) ) + if(( i = testJSON( ))) + return i; + + if(( i = testMerge( ))) return i; #ifndef WIN32 diff --git a/libtransmission/bencode.c b/libtransmission/bencode.c index da0835b8f..1e546d30c 100644 --- a/libtransmission/bencode.c +++ b/libtransmission/bencode.c @@ -34,24 +34,22 @@ *** **/ -int -tr_bencIsType( const tr_benc * val, - int type ) +tr_bool +tr_bencIsType( const tr_benc * val, int type ) { return ( val ) && ( val->type == type ); } -static int +static tr_bool isContainer( const tr_benc * val ) { return tr_bencIsList( val ) || tr_bencIsDict( val ); } -static int +static tr_bool isSomething( const tr_benc * val ) { - return isContainer( val ) || tr_bencIsInt( val ) || tr_bencIsString( - val ); + return isContainer( val ) || tr_bencIsInt( val ) || tr_bencIsString( val ); } static void @@ -382,8 +380,7 @@ dictIndexOf( const tr_benc * val, } tr_benc * -tr_bencDictFind( tr_benc * val, - const char * key ) +tr_bencDictFind( tr_benc * val, const char * key ) { const int i = dictIndexOf( val, key ); @@ -417,7 +414,7 @@ tr_bencListChild( tr_benc * val, return ret; } -int +tr_bool tr_bencGetInt( const tr_benc * val, int64_t * setme ) { @@ -428,7 +425,7 @@ tr_bencGetInt( const tr_benc * val, return success; } -int +tr_bool tr_bencGetStr( const tr_benc * val, const char ** setme ) { @@ -439,12 +436,10 @@ tr_bencGetStr( const tr_benc * val, return success; } -int -tr_bencDictFindInt( tr_benc * dict, - const char * key, - int64_t * setme ) +tr_bool +tr_bencDictFindInt( tr_benc * dict, const char * key, int64_t * setme ) { - int found = FALSE; + tr_bool found = FALSE; tr_benc * child = tr_bencDictFindType( dict, key, TYPE_INT ); if( child ) @@ -452,25 +447,22 @@ tr_bencDictFindInt( tr_benc * dict, return found; } -int -tr_bencDictFindDouble( tr_benc * dict, - const char * key, - double * setme ) +tr_bool +tr_bencDictFindDouble( tr_benc * dict, const char * key, double * setme ) { const char * str; - const int success = tr_bencDictFindStr( dict, key, &str ); + const tr_bool success = tr_bencDictFindStr( dict, key, &str ); if( success ) *setme = strtod( str, NULL ); + return success; } -int -tr_bencDictFindList( tr_benc * dict, - const char * key, - tr_benc ** setme ) +tr_bool +tr_bencDictFindList( tr_benc * dict, const char * key, tr_benc ** setme ) { - int found = FALSE; + tr_bool found = FALSE; tr_benc * child = tr_bencDictFindType( dict, key, TYPE_LIST ); if( child ) @@ -478,15 +470,14 @@ tr_bencDictFindList( tr_benc * dict, *setme = child; found = TRUE; } + return found; } -int -tr_bencDictFindDict( tr_benc * dict, - const char * key, - tr_benc ** setme ) +tr_bool +tr_bencDictFindDict( tr_benc * dict, const char * key, tr_benc ** setme ) { - int found = FALSE; + tr_bool found = FALSE; tr_benc * child = tr_bencDictFindType( dict, key, TYPE_DICT ); if( child ) @@ -494,15 +485,14 @@ tr_bencDictFindDict( tr_benc * dict, *setme = child; found = TRUE; } + return found; } -int -tr_bencDictFindStr( tr_benc * dict, - const char * key, - const char ** setme ) +tr_bool +tr_bencDictFindStr( tr_benc * dict, const char * key, const char ** setme ) { - int found = FALSE; + tr_bool found = FALSE; tr_benc * child = tr_bencDictFindType( dict, key, TYPE_STR ); if( child ) @@ -510,16 +500,17 @@ tr_bencDictFindStr( tr_benc * dict, *setme = child->val.s.s; found = TRUE; } + return found; } -int -tr_bencDictFindRaw( tr_benc * dict, - const char * key, - const uint8_t ** setme_raw, - size_t * setme_len ) +tr_bool +tr_bencDictFindRaw( tr_benc * dict, + const char * key, + const uint8_t ** setme_raw, + size_t * setme_len ) { - int found = FALSE; + tr_bool found = FALSE; tr_benc * child = tr_bencDictFindType( dict, key, TYPE_STR ); if( child ) @@ -528,6 +519,7 @@ tr_bencDictFindRaw( tr_benc * dict, *setme_len = child->val.s.i; found = TRUE; } + return found; } @@ -1316,6 +1308,76 @@ tr_bencSaveAsJSON( const tr_benc * top, **** ***/ +static size_t +tr_bencDictSize( const tr_benc * dict ) +{ + size_t count = 0; + + if( tr_bencIsDict( dict ) ) + count = dict->val.l.count / 2; + + return count; +} + +static tr_bool +tr_bencDictChild( const tr_benc * dict, size_t n, const char ** key, const tr_benc ** val ) +{ + tr_bool success = 0; + + assert( tr_bencIsDict( dict ) ); + + if( tr_bencIsDict( dict ) && (n*2)+1 <= dict->val.l.count ) + { + tr_benc * k = dict->val.l.vals + (n*2); + tr_benc * v = dict->val.l.vals + (n*2) + 1; + if(( success = tr_bencGetStr( k, key ) && isSomething( v ))) + *val = v; + } + + return success; +} + +void +tr_bencMergeDicts( tr_benc * target, const tr_benc * source ) +{ + size_t i; + const size_t sourceCount = tr_bencDictSize( source ); + + assert( tr_bencIsDict( target ) ); + assert( tr_bencIsDict( source ) ); + + for( i=0; i