1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2024-12-25 01:03:01 +00:00

(trunk libT) avoid about 75% of the strdup/malloc/frees in benc by using a union of char* and a small string buffer, and using the buffer if the string is small enough

This commit is contained in:
Charles Kerr 2009-06-01 22:15:50 +00:00
parent 7f85090587
commit 9bfec90e43
2 changed files with 70 additions and 43 deletions

View file

@ -358,9 +358,30 @@ tr_bencLoad( const void * buf_in,
****
***/
/* returns true if the given string length would fit in our string buffer */
static TR_INLINE int
stringFitsInBuffer( const tr_benc * val, int len )
{
return len < (int)sizeof( val->val.s.str.buf );
}
/* returns true if the benc's string was malloced.
* this occurs when the string is too long for our string buffer */
static TR_INLINE int
stringIsAlloced( const tr_benc * val )
{
return !stringFitsInBuffer( val, val->val.s.len );
}
/* returns a const pointer to the benc's string */
static TR_INLINE const char*
getStr( const tr_benc* val )
{
return stringIsAlloced(val) ? val->val.s.str.ptr : val->val.s.str.buf;
}
static int
dictIndexOf( const tr_benc * val,
const char * key )
dictIndexOf( const tr_benc * val, const char * key )
{
if( tr_bencIsDict( val ) )
{
@ -370,10 +391,9 @@ dictIndexOf( const tr_benc * val,
for( i = 0; ( i + 1 ) < val->val.l.count; i += 2 )
{
const tr_benc * child = val->val.l.vals + i;
if( ( child->type == TR_TYPE_STR )
&& ( child->val.s.i == len )
&& !memcmp( child->val.s.s, key, len ) )
&& ( child->val.s.len == len )
&& !memcmp( getStr(child), key, len ) )
return i;
}
}
@ -444,7 +464,7 @@ tr_bencGetStr( const tr_benc * val,
const int success = tr_bencIsString( val );
if( success )
*setme = val->val.s.s;
*setme = getStr( val );
return success;
}
@ -452,6 +472,7 @@ tr_bencGetStr( const tr_benc * val,
tr_bool
tr_bencGetBool( const tr_benc * val, tr_bool * setme )
{
const char * str;
tr_bool success = FALSE;
if(( success = tr_bencIsBool( val )))
@ -461,9 +482,9 @@ tr_bencGetBool( const tr_benc * val, tr_bool * setme )
if(( success = ( val->val.i==0 || val->val.i==1 ) ))
*setme = val->val.i!=0;
if( !success && tr_bencIsString( val ) )
if(( success = ( !strcmp(val->val.s.s,"true") || !strcmp(val->val.s.s,"false"))))
*setme = !strcmp(val->val.s.s,"true");
if( !success && tr_bencGetStr( val, &str ) )
if(( success = ( !strcmp(str,"true") || !strcmp(str,"false"))))
*setme = !strcmp(str,"true");
return success;
}
@ -488,10 +509,10 @@ tr_bencGetReal( const tr_benc * val, double * setme )
/* the json spec requires a '.' decimal point regardless of locale */
tr_strlcpy( locale, setlocale( LC_NUMERIC, NULL ), sizeof( locale ) );
setlocale( LC_NUMERIC, "POSIX" );
d = strtod( val->val.s.s, &endptr );
d = strtod( getStr(val), &endptr );
setlocale( LC_NUMERIC, locale );
if(( success = ( val->val.s.s != endptr ) && !*endptr ))
if(( success = ( getStr(val) != endptr ) && !*endptr ))
*setme = d;
}
@ -545,8 +566,8 @@ tr_bencDictFindRaw( tr_benc * dict,
const tr_bool found = tr_bencDictFindType( dict, key, TR_TYPE_STR, &child );
if( found ) {
*setme_raw = (uint8_t*) child->val.s.s;
*setme_len = child->val.s.i;
*setme_raw = (uint8_t*) getStr(child);
*setme_len = child->val.s.len;
}
return found;
@ -557,30 +578,31 @@ tr_bencDictFindRaw( tr_benc * dict,
***/
void
tr_bencInitRaw( tr_benc * val,
const void * src,
size_t byteCount )
tr_bencInitRaw( tr_benc * val, const void * src, size_t byteCount )
{
tr_bencInit( val, TR_TYPE_STR );
val->val.s.i = byteCount;
val->val.s.s = tr_memdup( src, byteCount );
if( stringFitsInBuffer( val, val->val.s.len = byteCount ))
memcpy( val->val.s.str.buf, src, byteCount );
else
val->val.s.str.ptr = tr_memdup( src, byteCount );
}
void
tr_bencInitStr( tr_benc * val,
const void * str,
int len )
tr_bencInitStr( tr_benc * val, const void * str, int len )
{
tr_bencInit( val, TR_TYPE_STR );
val->val.s.s = tr_strndup( str, len );
if( val->val.s.s == NULL )
val->val.s.i = 0;
if( str == NULL )
len = 0;
else if( len < 0 )
val->val.s.i = strlen( val->val.s.s );
else
val->val.s.i = len;
len = strlen( str );
if( stringFitsInBuffer( val, val->val.s.len = len )) {
memcpy( val->val.s.str.buf, str, len );
val->val.s.str.buf[len] = '\0';
} else
val->val.s.str.ptr = tr_strndup( str, len );
}
void
@ -764,9 +786,10 @@ tr_bencDictAddStr( tr_benc * dict, const char * key, const char * val )
/* see if it already exists, and if so, try to reuse it */
if(( child = tr_bencDictFind( dict, key ))) {
if( tr_bencIsString( child ) )
tr_free( child->val.s.s );
else {
if( tr_bencIsString( child ) ) {
if( stringIsAlloced( child ) )
tr_free( child->val.s.str.ptr );
} else {
tr_bencDictRemove( dict, key );
child = NULL;
}
@ -885,7 +908,7 @@ nodeNewDict( const tr_benc * val )
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].key = getStr(&val->val.l.vals[i]);
indices[j].index = i;
}
qsort( indices, j, sizeof( struct KeyIndex ), compareKeyIndex );
@ -1081,8 +1104,8 @@ saveRealFunc( const tr_benc * val, void * evbuf )
static void
saveStringFunc( const tr_benc * val, void * evbuf )
{
evbuffer_add_printf( evbuf, "%lu:", (unsigned long)val->val.s.i );
evbuffer_add( evbuf, val->val.s.s, val->val.s.i );
evbuffer_add_printf( evbuf, "%lu:", (unsigned long)val->val.s.len );
evbuffer_add( evbuf, getStr(val), val->val.s.len );
}
static void
@ -1141,7 +1164,8 @@ static void
freeStringFunc( const tr_benc * val,
void * freeme )
{
tr_ptrArrayAppend( freeme, val->val.s.s );
if( stringIsAlloced( val ) )
tr_ptrArrayAppend( freeme, val->val.s.str.ptr );
}
static void
@ -1302,10 +1326,10 @@ static void
jsonStringFunc( const tr_benc * val, void * vdata )
{
struct jsonWalk * data = vdata;
const unsigned char * it = (const unsigned char *) val->val.s.s;
const unsigned char * end = it + val->val.s.i;
const unsigned char * it = (const unsigned char *) getStr(val);
const unsigned char * end = it + val->val.s.len;
evbuffer_expand( data->out, val->val.s.i + 2 );
evbuffer_expand( data->out, val->val.s.len + 2 );
evbuffer_add( data->out, "\"", 1 );
for( ; it!=end; ++it )

View file

@ -49,8 +49,6 @@ enum
* it's included in the header for inlining and composition */
typedef struct tr_benc
{
char type;
union
{
uint8_t b; /* bool type */
@ -61,17 +59,22 @@ typedef struct tr_benc
struct /* string type */
{
size_t i; /* the string length */
char * s; /* the string */
size_t len; /* the string length */
union {
char buf[16]; /* a local buffer */
char * ptr; /* alloc'ed string */
} str;
} s;
struct /* list & dict types */
{
struct tr_benc * vals; /* nodes */
size_t alloc; /* nodes allocated */
size_t count; /* nodes used */
struct tr_benc * vals; /* nodes */
} l;
} val;
char type;
} tr_benc;
/***