diff --git a/ChangeLog b/ChangeLog index 54ebb862a..154a2ec23 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2015-12-20 Werner Lemberg + + [base] Introduce hash lookup, compare, and free function pointers. + + * include/freetype/internal/fthash.c (FT_Hash_LookupFunc, + FT_Hash_CompareFunc, FT_Hash_FreeFunc): New typedefs. + (FT_HashRec): Add `lookup', `compare', and `free' fields. + + * src/base/fthash.c (hash_str_lookup, hash_str_compare, + hash_str_free): New functions. + (ft_hash_init): Set function pointers. + (hash_bucket, ft_hash_free): Use them. + 2015-12-20 Werner Lemberg [base, bdf] Use a union as a hash key. diff --git a/include/freetype/internal/fthash.h b/include/freetype/internal/fthash.h index 3449b754e..80c4b9be8 100644 --- a/include/freetype/internal/fthash.h +++ b/include/freetype/internal/fthash.h @@ -68,12 +68,28 @@ FT_BEGIN_HEADER typedef struct FT_HashnodeRec_ *FT_Hashnode; + typedef FT_ULong + (*FT_Hash_LookupFunc)( FT_Hashkey* key ); + + typedef FT_Bool + (*FT_Hash_CompareFunc)( FT_Hashkey* a, + FT_Hashkey* b ); + + typedef void + (*FT_Hash_FreeFunc)( FT_Hashnode hn, + FT_Memory memory ); + + typedef struct FT_HashRec_ { FT_UInt limit; FT_UInt size; FT_UInt used; + FT_Hash_LookupFunc lookup; + FT_Hash_CompareFunc compare; + FT_Hash_FreeFunc free; + FT_Hashnode* table; } FT_HashRec; diff --git a/src/base/fthash.c b/src/base/fthash.c index 091646aee..d73c5df5b 100644 --- a/src/base/fthash.c +++ b/src/base/fthash.c @@ -46,27 +46,56 @@ #define INITIAL_HT_SIZE 241 - static FT_Hashnode* - hash_bucket( FT_Hashkey key, - FT_Hash hash ) + static FT_ULong + hash_str_lookup( FT_Hashkey* key ) { - const char* kp = key.str; - FT_ULong res = 0; - FT_Hashnode* bp = hash->table; - FT_Hashnode* ndp; + const char* kp = key->str; + FT_ULong res = 0; /* Mocklisp hash function. */ while ( *kp ) res = ( res << 5 ) - res + (FT_ULong)*kp++; + return res; + } + + + static FT_Bool + hash_str_compare( FT_Hashkey* a, + FT_Hashkey* b ) + { + if ( a->str[0] == b->str[0] && + ft_strcmp( a->str, b->str ) == 0 ) + return 1; + + return 0; + } + + + static void + hash_str_free( FT_Hashnode hn, + FT_Memory memory ) + { + FT_FREE( hn ); + } + + + static FT_Hashnode* + hash_bucket( FT_Hashkey key, + FT_Hash hash ) + { + FT_ULong res = 0; + FT_Hashnode* bp = hash->table; + FT_Hashnode* ndp; + + + res = (hash->lookup)( &key ); + ndp = bp + ( res % hash->size ); while ( *ndp ) { - kp = (*ndp)->key.str; - - if ( kp[0] == key.str[0] && - ft_strcmp( kp, key.str ) == 0 ) + if ( (hash->compare)( &(*ndp)->key, &key ) ) break; ndp--; @@ -124,6 +153,10 @@ hash->limit = sz / 3; hash->used = 0; + hash->lookup = hash_str_lookup; + hash->compare = hash_str_compare; + hash->free = hash_str_free; + FT_MEM_NEW_ARRAY( hash->table, sz ); return error; @@ -141,8 +174,11 @@ FT_UInt i; - for ( i = 0; i < sz; i++, bp++ ) - FT_FREE( *bp ); + if ( hash->free ) + { + for ( i = 0; i < sz; i++, bp++ ) + (hash->free)( *bp, memory ); + } FT_FREE( hash->table ); }