diff --git a/v2/engine/object.c b/v2/engine/object.c index 07298ad01..bbff79ee7 100644 --- a/v2/engine/object.c +++ b/v2/engine/object.c @@ -9,11 +9,12 @@ * object.c - object manipulation routines * * External functions: - * object_new() - create an object from a string - * object_copy() - return a copy of an object - * object_free() - free an object - * object_str() - get the string value of an object - * object_done() - free string tables + * object_new() - create an object from a string + * object_new_range() - create an object from a string of given length + * object_copy() - return a copy of an object + * object_free() - free an object + * object_str() - get the string value of an object + * object_done() - free string tables * * This implementation builds a hash table of all strings, so that multiple * calls of object_new() on the same string allocate memory for the string once. @@ -128,28 +129,27 @@ static char * allocate( size_t n ) } -static unsigned int hash_keyval( char const * key ) +static unsigned int hash_keyval( char const * key, int const size ) { + unsigned int const magic = 2147059363; unsigned int hash = 0; - unsigned i; - unsigned int len = strlen( key ); - for ( i = 0; i < len / sizeof( unsigned int ); ++i ) + unsigned int i; + for ( i = 0; i < size / sizeof( unsigned int ); ++i ) { unsigned int val; memcpy( &val, key, sizeof( unsigned int ) ); - hash = hash * 2147059363 + val; + hash = hash * magic + val; key += sizeof( unsigned int ); } { unsigned int val = 0; - memcpy( &val, key, len % sizeof( unsigned int ) ); - hash = hash * 2147059363 + val; + memcpy( &val, key, size % sizeof( unsigned int ) ); + hash = hash * magic + val; } - hash += (hash >> 17); - return hash; + return hash + ( hash >> 17 ); } @@ -193,16 +193,16 @@ static void string_set_resize( string_set * set ) } -static char const * string_set_insert( string_set * set, char const * string ) +static char const * string_set_insert( string_set * set, char const * string, + int const size ) { - unsigned hash = hash_keyval( string ); + unsigned hash = hash_keyval( string, size ); unsigned pos = hash % set->num; - unsigned len; struct hash_item * result; for ( result = set->data[ pos ]; result; result = result->header.next ) - if ( !strcmp( result->data, string ) ) + if ( !result->data[ size ] && !memcmp( result->data, string, size ) ) return result->data; if ( set->size >= set->num ) @@ -211,17 +211,18 @@ static char const * string_set_insert( string_set * set, char const * string ) pos = hash % set->num; } - len = strlen( string ) + 1; - result = (struct hash_item *)allocate( sizeof( struct hash_header ) + len ); + result = (struct hash_item *)allocate( sizeof( struct hash_header ) + size + + 1 ); result->header.hash = hash; result->header.next = set->data[ pos ]; #ifndef NDEBUG result->header.magic = OBJECT_MAGIC; #endif - memcpy( result->data, string, len ); - assert( hash_keyval( result->data ) == result->header.hash ); + memcpy( result->data, string, size ); + result->data[ size ] = '\0'; + assert( hash_keyval( result->data, size ) == result->header.hash ); set->data[ pos ] = result; - strtotal += len; + strtotal += size + 1; ++set->size; return result->data; @@ -243,32 +244,41 @@ static void object_validate( OBJECT * obj ) /* - * object_new() - create an object from a string. + * object_new_range() - create an object from a string of given length */ -OBJECT * object_new( char const * string ) +OBJECT * object_new_range( char const * const string, int const size ) { ++strcount_in; #ifdef BJAM_NO_MEM_CACHE { - int const len = strlen( string ) + 1; struct hash_item * const m = (struct hash_item *)BJAM_MALLOC( sizeof( - struct hash_header ) + len ); - - strtotal += len; - memcpy( m->data, string, len ); + struct hash_header ) + size + 1 ); + strtotal += size + 1; + memcpy( m->data, string, size ); + m->data[ size ] = '\0'; m->header.magic = OBJECT_MAGIC; return (OBJECT *)m->data; } #else if ( !strhash.data ) string_set_init( &strhash ); - return (OBJECT *)string_set_insert( &strhash, string ); + return (OBJECT *)string_set_insert( &strhash, string, size ); #endif } +/* + * object_new() - create an object from a string + */ + +OBJECT * object_new( char const * const string ) +{ + return object_new_range( string, strlen( string ) ); +} + + #ifndef object_copy /* @@ -337,7 +347,7 @@ unsigned int object_hash( OBJECT * obj ) { object_validate( obj ); #ifdef BJAM_NO_MEM_CACHE - return hash_keyval( object_str( obj ) ); + return hash_keyval( object_str( obj ), strlen( object_str( obj ) ) ); #else return object_get_item( obj )->header.hash; #endif diff --git a/v2/engine/object.h b/v2/engine/object.h index 19f7b16c5..cabb9f6f2 100644 --- a/v2/engine/object.h +++ b/v2/engine/object.h @@ -13,8 +13,9 @@ typedef struct _object OBJECT; -OBJECT * object_new ( char const * ); -void object_done( void ); +OBJECT * object_new( char const * const ); +OBJECT * object_new_range( char const * const, int const size ); +void object_done( void ); #if defined(NDEBUG) && !defined(BJAM_NO_MEM_CACHE)