(trunk libT) #3678 "benc walking could be more efficient" -- fixed.

This commit is contained in:
Charles Kerr 2010-10-26 19:30:35 +00:00
parent bd30dd291f
commit a9e740cb2c
1 changed files with 46 additions and 57 deletions

View File

@ -941,18 +941,16 @@ struct SaveNode
int * children; int * children;
}; };
static struct SaveNode* static void
nodeNewDict( const tr_benc * val ) nodeInitDict( struct SaveNode * node, const tr_benc * val )
{ {
int i, j; int i, j;
int nKeys; int nKeys;
struct SaveNode * node;
struct KeyIndex * indices; struct KeyIndex * indices;
assert( tr_bencIsDict( val ) ); assert( tr_bencIsDict( val ) );
nKeys = val->val.l.count / 2; nKeys = val->val.l.count / 2;
node = tr_new0( struct SaveNode, 1 );
node->val = val; node->val = val;
node->children = tr_new0( int, nKeys * 2 ); node->children = tr_new0( int, nKeys * 2 );
@ -973,53 +971,40 @@ nodeNewDict( const tr_benc * val )
assert( node->childCount == nKeys * 2 ); assert( node->childCount == nKeys * 2 );
tr_free( indices ); tr_free( indices );
return node;
} }
static struct SaveNode* static void
nodeNewList( const tr_benc * val ) nodeInitList( struct SaveNode * node, const tr_benc * val )
{ {
int i, n; int i, n;
struct SaveNode * node;
assert( tr_bencIsList( val ) ); assert( tr_bencIsList( val ) );
n = val->val.l.count; n = val->val.l.count;
node = tr_new0( struct SaveNode, 1 );
node->val = val; node->val = val;
node->childCount = n; node->childCount = n;
node->children = tr_new0( int, n ); node->children = tr_new0( int, n );
for( i = 0; i < n; ++i ) /* a list's children don't need to be reordered */ for( i = 0; i < n; ++i ) /* a list's children don't need to be reordered */
node->children[i] = i; node->children[i] = i;
return node;
} }
static struct SaveNode* static void
nodeNewLeaf( const tr_benc * val ) nodeInitLeaf( struct SaveNode * node, const tr_benc * val )
{ {
struct SaveNode * node;
assert( !isContainer( val ) ); assert( !isContainer( val ) );
node = tr_new0( struct SaveNode, 1 );
node->val = val; node->val = val;
return node;
} }
static struct SaveNode* static void
nodeNew( const tr_benc * val ) nodeInit( struct SaveNode * node, const tr_benc * val )
{ {
struct SaveNode * node; static const struct SaveNode INIT_NODE = { NULL, 0, 0, 0, NULL };
*node = INIT_NODE;
if( tr_bencIsList( val ) ) if( tr_bencIsList( val ) ) nodeInitList( node, val );
node = nodeNewList( val ); else if( tr_bencIsDict( val ) ) nodeInitDict( node, val );
else if( tr_bencIsDict( val ) ) else nodeInitLeaf( node, val );
node = nodeNewDict( val );
else
node = nodeNewLeaf( val );
return node;
} }
typedef void ( *BencWalkFunc )( const tr_benc * val, void * user_data ); typedef void ( *BencWalkFunc )( const tr_benc * val, void * user_data );
@ -1045,13 +1030,15 @@ bencWalk( const tr_benc * top,
const struct WalkFuncs * walkFuncs, const struct WalkFuncs * walkFuncs,
void * user_data ) void * user_data )
{ {
tr_ptrArray stack = TR_PTR_ARRAY_INIT; int stackSize = 0;
int stackAlloc = 64;
struct SaveNode * stack = tr_new( struct SaveNode, stackAlloc );
tr_ptrArrayAppend( &stack, nodeNew( top ) ); nodeInit( &stack[stackSize++], top );
while( !tr_ptrArrayEmpty( &stack ) ) while( stackSize > 0 )
{ {
struct SaveNode * node = tr_ptrArrayBack( &stack ); struct SaveNode * node = &stack[stackSize-1];
const tr_benc * val; const tr_benc * val;
if( !node->valIsVisited ) if( !node->valIsVisited )
@ -1068,9 +1055,8 @@ bencWalk( const tr_benc * top,
{ {
if( isContainer( node->val ) ) if( isContainer( node->val ) )
walkFuncs->containerEndFunc( node->val, user_data ); walkFuncs->containerEndFunc( node->val, user_data );
tr_ptrArrayPop( &stack ); --stackSize;
tr_free( node->children ); tr_free( node->children );
tr_free( node );
continue; continue;
} }
@ -1093,17 +1079,27 @@ bencWalk( const tr_benc * top,
break; break;
case TR_TYPE_LIST: case TR_TYPE_LIST:
if( val != node->val ) if( val == node->val )
tr_ptrArrayAppend( &stack, nodeNew( val ) );
else
walkFuncs->listBeginFunc( val, user_data ); walkFuncs->listBeginFunc( val, user_data );
else {
if( stackAlloc == stackSize ) {
stackAlloc *= 2;
stack = tr_renew( struct SaveNode, stack, stackAlloc );
}
nodeInit( &stack[stackSize++], val );
}
break; break;
case TR_TYPE_DICT: case TR_TYPE_DICT:
if( val != node->val ) if( val == node->val )
tr_ptrArrayAppend( &stack, nodeNew( val ) );
else
walkFuncs->dictBeginFunc( val, user_data ); walkFuncs->dictBeginFunc( val, user_data );
else {
if( stackAlloc == stackSize ) {
stackAlloc *= 2;
stack = tr_renew( struct SaveNode, stack, stackAlloc );
}
nodeInit( &stack[stackSize++], val );
}
break; break;
default: default:
@ -1113,7 +1109,7 @@ bencWalk( const tr_benc * top,
} }
} }
tr_ptrArrayDestruct( &stack, NULL ); tr_free( stack );
} }
/**** /****
@ -1191,42 +1187,35 @@ static const struct WalkFuncs saveFuncs = { saveIntFunc,
***/ ***/
static void static void
freeDummyFunc( const tr_benc * val UNUSED, freeDummyFunc( const tr_benc * val UNUSED, void * buf UNUSED )
void * buf UNUSED )
{} {}
static void static void
freeStringFunc( const tr_benc * val, freeStringFunc( const tr_benc * val, void * unused UNUSED )
void * freeme )
{ {
if( stringIsAlloced( val ) ) if( stringIsAlloced( val ) )
tr_ptrArrayAppend( freeme, val->val.s.str.ptr ); tr_free( val->val.s.str.ptr );
} }
static void static void
freeContainerBeginFunc( const tr_benc * val, freeContainerEndFunc( const tr_benc * val, void * unused UNUSED )
void * freeme )
{ {
tr_ptrArrayAppend( freeme, val->val.l.vals ); tr_free( val->val.l.vals );
} }
static const struct WalkFuncs freeWalkFuncs = { freeDummyFunc, static const struct WalkFuncs freeWalkFuncs = { freeDummyFunc,
freeDummyFunc, freeDummyFunc,
freeDummyFunc, freeDummyFunc,
freeStringFunc, freeStringFunc,
freeContainerBeginFunc, freeDummyFunc,
freeContainerBeginFunc, freeDummyFunc,
freeDummyFunc }; freeContainerEndFunc };
void void
tr_bencFree( tr_benc * val ) tr_bencFree( tr_benc * val )
{ {
if( isSomething( val ) ) if( isSomething( val ) )
{ bencWalk( val, &freeWalkFuncs, NULL );
tr_ptrArray a = TR_PTR_ARRAY_INIT;
bencWalk( val, &freeWalkFuncs, &a );
tr_ptrArrayDestruct( &a, tr_free );
}
} }
/*** /***