fix the 1.04 bencode errors reported in the forums this morning. add regression tests.
This commit is contained in:
parent
7394a49a09
commit
3334ea8401
|
@ -136,6 +136,29 @@ testStr( void )
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
testString( const char * str, int isGood )
|
||||
{
|
||||
benc_val_t val;
|
||||
const uint8_t * end = NULL;
|
||||
char * saved;
|
||||
const size_t len = strlen( str );
|
||||
int savedLen;
|
||||
int err = tr_bencParse( str, str+len, &val , &end );
|
||||
if( !isGood ) {
|
||||
check( err );
|
||||
} else {
|
||||
check( !err );
|
||||
check( end == (const uint8_t*)str + len );
|
||||
saved = tr_bencSave( &val, &savedLen );
|
||||
check( !strcmp( saved, str ) );
|
||||
check( len == (size_t)savedLen );
|
||||
tr_free( saved );
|
||||
tr_bencFree( &val );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
testParse( void )
|
||||
{
|
||||
|
@ -184,15 +207,22 @@ testParse( void )
|
|||
tr_free( saved );
|
||||
tr_bencFree( &val );
|
||||
|
||||
end = NULL;
|
||||
snprintf( (char*)buf, sizeof( buf ), "llleee" );
|
||||
err = tr_bencParse( buf, buf + sizeof( buf ), &val , &end );
|
||||
check( !err );
|
||||
check( end == buf + 6 );
|
||||
saved = tr_bencSave( &val, &len );
|
||||
check( !strcmp( saved, "llleee" ) );
|
||||
tr_free( saved );
|
||||
tr_bencFree( &val );
|
||||
if(( err = testString( "llleee", TRUE )))
|
||||
return err;
|
||||
if(( err = testString( "d3:cow3:moo4:spam4:eggse", TRUE )))
|
||||
return err;
|
||||
if(( err = testString( "d4:spaml1:a1:bee", TRUE )))
|
||||
return err;
|
||||
#if 0
|
||||
if(( err = testString( "d9:publisher3:bob18:publisher.location4:home17:publisher-webpage15:www.example.come", TRUE )))
|
||||
return err;
|
||||
#endif
|
||||
if(( err = testString( "d8:completei1e8:intervali1800e12:min intervali1800e5:peers0:e", TRUE )))
|
||||
return err;
|
||||
if(( err = testString( "d1:ai0e1:be", FALSE ))) /* odd number of children */
|
||||
return err;
|
||||
if(( err = testString( "", FALSE )))
|
||||
return err;
|
||||
|
||||
/* nested containers
|
||||
* parse an unsorted dict
|
||||
|
@ -209,13 +239,6 @@ testParse( void )
|
|||
tr_free( saved );
|
||||
tr_bencFree( &val );
|
||||
|
||||
end = NULL;
|
||||
snprintf( (char*)buf, sizeof( buf ), "d8:completei1e8:intervali1800e12:min intervali1800e5:peers0:e" );
|
||||
err = tr_bencParse( buf, buf+sizeof( buf ), &val, &end );
|
||||
check( !err );
|
||||
check( end == buf + strlen( (const char*)buf ) );
|
||||
tr_bencFree( &val );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,27 +41,25 @@
|
|||
**/
|
||||
|
||||
static int
|
||||
isInt( const benc_val_t * val )
|
||||
isType( const benc_val_t * val, int type )
|
||||
{
|
||||
return val!=NULL && val->type==TYPE_INT;
|
||||
return ( ( val != NULL ) && ( val->type == type ) );
|
||||
}
|
||||
|
||||
static int
|
||||
isList( const benc_val_t * val )
|
||||
{
|
||||
return val!=NULL && val->type==TYPE_LIST;
|
||||
}
|
||||
|
||||
static int
|
||||
isDict( const benc_val_t * val )
|
||||
{
|
||||
return val!=NULL && val->type==TYPE_DICT;
|
||||
}
|
||||
#define isInt(v) ( isType( ( v ), TYPE_INT ) )
|
||||
#define isString(v) ( isType( ( v ), TYPE_STR ) )
|
||||
#define isList(v) ( isType( ( v ), TYPE_LIST ) )
|
||||
#define isDict(v) ( isType( ( v ), TYPE_DICT ) )
|
||||
|
||||
static int
|
||||
isContainer( const benc_val_t * val )
|
||||
{
|
||||
return val!=NULL && ( val->type & ( TYPE_DICT | TYPE_LIST ) );
|
||||
return isList(val) || isDict(val);
|
||||
}
|
||||
static int
|
||||
isSomething( const benc_val_t * val )
|
||||
{
|
||||
return isContainer(val) || isInt(val) || isString(val);
|
||||
}
|
||||
|
||||
benc_val_t*
|
||||
|
@ -229,6 +227,8 @@ tr_bencParse( const void * buf_in,
|
|||
const uint8_t * bufend = bufend_in;
|
||||
tr_ptrArray * parentStack = tr_ptrArrayNew( );
|
||||
|
||||
tr_bencInit( top, 0 );
|
||||
|
||||
while( buf != bufend )
|
||||
{
|
||||
if( buf > bufend ) /* no more text to parse... */
|
||||
|
@ -274,9 +274,15 @@ tr_bencParse( const void * buf_in,
|
|||
}
|
||||
else if( *buf=='e' ) /* end of list or dict */
|
||||
{
|
||||
benc_val_t * node;
|
||||
++buf;
|
||||
if( tr_ptrArrayEmpty( parentStack ) )
|
||||
return TR_ERROR;
|
||||
|
||||
node = tr_ptrArrayBack( parentStack );
|
||||
if( isDict( node ) && ( node->val.l.count % 2 ) )
|
||||
return TR_ERROR; /* odd # of children in dict */
|
||||
|
||||
tr_ptrArrayPop( parentStack );
|
||||
if( tr_ptrArrayEmpty( parentStack ) )
|
||||
break;
|
||||
|
@ -308,7 +314,7 @@ tr_bencParse( const void * buf_in,
|
|||
}
|
||||
}
|
||||
|
||||
err = tr_ptrArrayEmpty( parentStack ) ? 0 : 1;
|
||||
err = !isSomething( top ) || !tr_ptrArrayEmpty( parentStack );
|
||||
|
||||
if( !err && ( setme_end != NULL ) )
|
||||
*setme_end = buf;
|
||||
|
@ -511,20 +517,21 @@ struct SaveNode
|
|||
static struct SaveNode*
|
||||
nodeNewDict( const benc_val_t * val )
|
||||
{
|
||||
int i, j, n;
|
||||
int i, j;
|
||||
int nKeys;
|
||||
struct SaveNode * node;
|
||||
struct KeyIndex * indices;
|
||||
|
||||
assert( isDict( val ) );
|
||||
|
||||
n = val->val.l.count;
|
||||
nKeys = val->val.l.count / 2;
|
||||
node = tr_new0( struct SaveNode, 1 );
|
||||
node->val = val;
|
||||
node->children = tr_new0( int, n );
|
||||
node->children = tr_new0( int, nKeys * 2 );
|
||||
|
||||
/* ugh, a dictionary's children have to be sorted by key... */
|
||||
indices = tr_new( struct KeyIndex, n );
|
||||
for( i=j=0; i<n; i+=2, ++j ) {
|
||||
indices = tr_new( struct KeyIndex, nKeys );
|
||||
for( i=j=0; i<(nKeys*2); i+=2, ++j ) {
|
||||
indices[j].key = val->val.l.vals[i].val.s.s;
|
||||
indices[j].index = i;
|
||||
}
|
||||
|
@ -535,7 +542,7 @@ nodeNewDict( const benc_val_t * val )
|
|||
node->children[ node->childCount++ ] = index + 1;
|
||||
}
|
||||
|
||||
assert( node->childCount == n );
|
||||
assert( node->childCount == nKeys * 2 );
|
||||
tr_free( indices );
|
||||
return node;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue