(trunk libT) #1559 (partial): add tr_bencDictMerge() + unit tests. patch by KyleK and charles_
This commit is contained in:
parent
659afd89be
commit
72b9845a5e
|
@ -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
|
||||
|
|
|
@ -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<sourceCount; ++i )
|
||||
{
|
||||
const char * key;
|
||||
const tr_benc * val;
|
||||
|
||||
if( tr_bencDictChild( source, i, &key, &val ) )
|
||||
{
|
||||
int64_t i64;
|
||||
const char * str;
|
||||
|
||||
if( tr_bencGetInt( val, &i64 ) )
|
||||
{
|
||||
tr_bencDictRemove( target, key );
|
||||
tr_bencDictAddInt( target, key, i64 );
|
||||
}
|
||||
else if( tr_bencGetStr( val, &str ) )
|
||||
{
|
||||
tr_bencDictRemove( target, key );
|
||||
tr_bencDictAddStr( target, key, str );
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_err( "tr_bencMergeDicts skipping \"%s\"", key );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
static int
|
||||
saveFile( const char * filename,
|
||||
const char * content,
|
||||
|
|
|
@ -70,139 +70,92 @@ void tr_bencPrint( const tr_benc * );
|
|||
|
||||
void tr_bencFree( tr_benc * );
|
||||
|
||||
char* tr_bencSave( const tr_benc * val,
|
||||
int * len );
|
||||
char* tr_bencSave( const tr_benc * val, int * len );
|
||||
|
||||
char* tr_bencSaveAsJSON( const tr_benc * top,
|
||||
int * len );
|
||||
char* tr_bencSaveAsJSON( const tr_benc * top, int * len );
|
||||
|
||||
int tr_bencSaveFile( const char * filename,
|
||||
const tr_benc * );
|
||||
int tr_bencSaveFile( const char * filename, const tr_benc * );
|
||||
|
||||
int tr_bencSaveJSONFile( const char * filename,
|
||||
const tr_benc * );
|
||||
int tr_bencSaveJSONFile( const char * filename, const tr_benc * );
|
||||
|
||||
void tr_bencInitStr( tr_benc *,
|
||||
const void * str,
|
||||
int str_len );
|
||||
void tr_bencInitStr( tr_benc *, const void * str, int str_len );
|
||||
|
||||
void tr_bencInitRaw( tr_benc *,
|
||||
const void * raw,
|
||||
size_t raw_len );
|
||||
void tr_bencInitRaw( tr_benc *, const void * raw, size_t raw_len );
|
||||
|
||||
void tr_bencInitInt( tr_benc *,
|
||||
int64_t num );
|
||||
void tr_bencInitInt( tr_benc *, int64_t num );
|
||||
|
||||
int tr_bencInitDict( tr_benc *,
|
||||
size_t reserveCount );
|
||||
int tr_bencInitDict( tr_benc *, size_t reserveCount );
|
||||
|
||||
int tr_bencInitList( tr_benc *,
|
||||
size_t reserveCount );
|
||||
int tr_bencInitList( tr_benc *, size_t reserveCount );
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
int tr_bencListReserve( tr_benc *,
|
||||
size_t reserveCount );
|
||||
int tr_bencListReserve( tr_benc *, size_t reserveCount );
|
||||
|
||||
tr_benc * tr_bencListAdd( tr_benc * );
|
||||
|
||||
tr_benc * tr_bencListAddInt( tr_benc *,
|
||||
int64_t val );
|
||||
tr_benc * tr_bencListAddInt( tr_benc *, int64_t val );
|
||||
|
||||
tr_benc * tr_bencListAddStr( tr_benc *,
|
||||
const char * val );
|
||||
tr_benc * tr_bencListAddStr( tr_benc *, const char * val );
|
||||
|
||||
tr_benc * tr_bencListAddList( tr_benc *,
|
||||
size_t reserveCount );
|
||||
tr_benc * tr_bencListAddList( tr_benc *, size_t reserveCount );
|
||||
|
||||
tr_benc * tr_bencListAddDict( tr_benc *,
|
||||
size_t reserveCount );
|
||||
tr_benc * tr_bencListAddDict( tr_benc *, size_t reserveCount );
|
||||
|
||||
size_t tr_bencListSize( const tr_benc * list );
|
||||
|
||||
tr_benc * tr_bencListChild( tr_benc * list,
|
||||
size_t n );
|
||||
tr_benc * tr_bencListChild( tr_benc * list, size_t n );
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
int tr_bencDictReserve( tr_benc *,
|
||||
size_t reserveCount );
|
||||
int tr_bencDictReserve( tr_benc *, size_t reserveCount );
|
||||
|
||||
int tr_bencDictRemove( tr_benc *,
|
||||
const char * key );
|
||||
int tr_bencDictRemove( tr_benc *, const char * key );
|
||||
|
||||
tr_benc * tr_bencDictAdd( tr_benc *,
|
||||
const char * key );
|
||||
tr_benc * tr_bencDictAdd( tr_benc *, const char * key );
|
||||
|
||||
tr_benc * tr_bencDictAddDouble( tr_benc *,
|
||||
const char * key,
|
||||
double d );
|
||||
tr_benc * tr_bencDictAddDouble( tr_benc *, const char * key, double );
|
||||
|
||||
tr_benc * tr_bencDictAddInt( tr_benc *,
|
||||
const char * key,
|
||||
int64_t val );
|
||||
tr_benc * tr_bencDictAddInt( tr_benc *, const char * key, int64_t );
|
||||
|
||||
tr_benc * tr_bencDictAddStr( tr_benc *,
|
||||
const char * key,
|
||||
const char * val );
|
||||
tr_benc * tr_bencDictAddStr( tr_benc *, const char * key, const char * );
|
||||
|
||||
tr_benc * tr_bencDictAddList( tr_benc *,
|
||||
const char * key,
|
||||
size_t reserve );
|
||||
tr_benc * tr_bencDictAddList( tr_benc *, const char * key, size_t reserve );
|
||||
|
||||
tr_benc * tr_bencDictAddDict( tr_benc *,
|
||||
const char * key,
|
||||
size_t reserve );
|
||||
tr_benc * tr_bencDictAddDict( tr_benc *, const char * key, size_t reserve );
|
||||
|
||||
tr_benc * tr_bencDictAddRaw( tr_benc *,
|
||||
const char * key,
|
||||
const void *,
|
||||
size_t len );
|
||||
tr_benc * tr_bencDictAddRaw( tr_benc *, const char * key,
|
||||
const void * raw, size_t rawlen );
|
||||
|
||||
tr_benc* tr_bencDictFind( tr_benc *,
|
||||
const char * key );
|
||||
tr_benc* tr_bencDictFind( tr_benc *, const char * key );
|
||||
|
||||
int tr_bencDictFindList( tr_benc *,
|
||||
const char * key,
|
||||
tr_benc ** setme );
|
||||
tr_bool tr_bencDictFindList( tr_benc *, const char * key, tr_benc ** setme );
|
||||
|
||||
int tr_bencDictFindDict( tr_benc *,
|
||||
const char * key,
|
||||
tr_benc ** setme );
|
||||
tr_bool tr_bencDictFindDict( tr_benc *, const char * key, tr_benc ** setme );
|
||||
|
||||
int tr_bencDictFindInt( tr_benc *,
|
||||
const char * key,
|
||||
int64_t * setme );
|
||||
tr_bool tr_bencDictFindInt( tr_benc *, const char * key, int64_t * setme );
|
||||
|
||||
int tr_bencDictFindDouble( tr_benc *,
|
||||
const char * key,
|
||||
double * setme );
|
||||
tr_bool tr_bencDictFindDouble( tr_benc *, const char * key, double * setme );
|
||||
|
||||
int tr_bencDictFindStr( tr_benc *,
|
||||
const char * key,
|
||||
const char ** setme );
|
||||
tr_bool tr_bencDictFindStr( tr_benc *, const char * key, const char ** setme );
|
||||
|
||||
int tr_bencDictFindRaw( tr_benc *,
|
||||
const char * key,
|
||||
const uint8_t ** setme_raw,
|
||||
size_t * setme_len );
|
||||
tr_bool tr_bencDictFindRaw( tr_benc *, const char * key,
|
||||
const uint8_t ** setme_raw, size_t * setme_len );
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
int tr_bencGetInt( const tr_benc * val,
|
||||
int64_t * setme );
|
||||
tr_bool tr_bencGetInt( const tr_benc * val, int64_t * setme );
|
||||
|
||||
int tr_bencGetStr( const tr_benc * val,
|
||||
const char ** setme );
|
||||
tr_bool tr_bencGetStr( const tr_benc * val, const char ** setme );
|
||||
|
||||
tr_bool tr_bencIsType( const tr_benc *, int type );
|
||||
|
||||
int tr_bencIsType( const tr_benc *,
|
||||
int type );
|
||||
|
||||
#define tr_bencIsInt( b ) tr_bencIsType( ( b ), TYPE_INT )
|
||||
#define tr_bencIsDict( b ) tr_bencIsType( ( b ), TYPE_DICT )
|
||||
|
@ -225,4 +178,10 @@ int tr_bencParseStr( const uint8_t * buf,
|
|||
const uint8_t ** setme_str,
|
||||
size_t * setme_strlen );
|
||||
|
||||
/**
|
||||
***
|
||||
**/
|
||||
|
||||
void tr_bencMergeDicts( tr_benc * b1, const tr_benc * b2 );
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue