mirror of
https://github.com/transmission/transmission
synced 2024-12-24 08:43:27 +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:
parent
7f85090587
commit
9bfec90e43
2 changed files with 70 additions and 43 deletions
|
@ -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 )
|
||||
|
|
|
@ -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;
|
||||
|
||||
/***
|
||||
|
|
Loading…
Reference in a new issue