diff options
Diffstat (limited to 'mysys/hash.c')
-rw-r--r-- | mysys/hash.c | 114 |
1 files changed, 26 insertions, 88 deletions
diff --git a/mysys/hash.c b/mysys/hash.c index 973f6f7cefa..11cbbd6b898 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -29,16 +29,27 @@ #define HIGHFIND 4 #define HIGHUSED 8 +typedef struct st_hash_info { + uint next; /* index to next key */ + byte *data; /* data for current entry */ +} HASH_LINK; + static uint hash_mask(uint hashnr,uint buffmax,uint maxlength); static void movelink(HASH_LINK *array,uint pos,uint next_link,uint newlink); -static uint calc_hashnr(const byte *key,uint length); -static uint calc_hashnr_caseup(const byte *key,uint length); static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length); +static uint calc_hash(HASH *hash,const byte *key,uint length) +{ + ulong nr1=1, nr2=4; + hash->charset->coll->hash_sort(hash->charset,(uchar*) key,length,&nr1,&nr2); + return nr1; +} -my_bool _hash_init(HASH *hash,uint size,uint key_offset,uint key_length, - hash_get_key get_key, - void (*free_element)(void*),uint flags CALLER_INFO_PROTO) +my_bool +_hash_init(HASH *hash,CHARSET_INFO *charset, + uint size,uint key_offset,uint key_length, + hash_get_key get_key, + void (*free_element)(void*),uint flags CALLER_INFO_PROTO) { DBUG_ENTER("hash_init"); DBUG_PRINT("enter",("hash: %lx size: %d",hash,size)); @@ -47,7 +58,7 @@ my_bool _hash_init(HASH *hash,uint size,uint key_offset,uint key_length, if (my_init_dynamic_array_ci(&hash->array,sizeof(HASH_LINK),size,0)) { hash->free=0; /* Allow call to hash_free */ - DBUG_RETURN(TRUE); + DBUG_RETURN(1); } hash->key_offset=key_offset; hash->key_length=key_length; @@ -56,10 +67,7 @@ my_bool _hash_init(HASH *hash,uint size,uint key_offset,uint key_length, hash->get_key=get_key; hash->free=free_element; hash->flags=flags; - if (flags & HASH_CASE_INSENSITIVE) - hash->calc_hashnr=calc_hashnr_caseup; - else - hash->calc_hashnr=calc_hashnr; + hash->charset=charset; DBUG_RETURN(0); } @@ -109,77 +117,9 @@ static uint hash_rec_mask(HASH *hash,HASH_LINK *pos,uint buffmax, { uint length; byte *key= (byte*) hash_key(hash,pos->data,&length,0); - return hash_mask((*hash->calc_hashnr)(key,length),buffmax,maxlength); -} - -#ifndef NEW_HASH_FUNCTION - - /* Calc hashvalue for a key */ - -static uint calc_hashnr(const byte *key,uint length) -{ - register uint nr=1, nr2=4; - while (length--) - { - nr^= (((nr & 63)+nr2)*((uint) (uchar) *key++))+ (nr << 8); - nr2+=3; - } - return((uint) nr); + return hash_mask(calc_hash(hash,key,length),buffmax,maxlength); } - /* Calc hashvalue for a key, case indepenently */ - -static uint calc_hashnr_caseup(const byte *key,uint length) -{ - register uint nr=1, nr2=4; - while (length--) - { - nr^= (((nr & 63)+nr2)*((uint) (uchar) toupper(*key++)))+ (nr << 8); - nr2+=3; - } - return((uint) nr); -} - -#else - -/* - * Fowler/Noll/Vo hash - * - * The basis of the hash algorithm was taken from an idea sent by email to the - * IEEE Posix P1003.2 mailing list from Phong Vo (kpv@research.att.com) and - * Glenn Fowler (gsf@research.att.com). Landon Curt Noll (chongo@toad.com) - * later improved on their algorithm. - * - * The magic is in the interesting relationship between the special prime - * 16777619 (2^24 + 403) and 2^32 and 2^8. - * This works well on both numbers and strings. - */ - -uint calc_hashnr(const byte *key, uint len) -{ - const byte *end=key+len; - uint hash; - for (hash = 0; key < end; key++) - { - hash *= 16777619; - hash ^= (uint) *(uchar*) key; - } - return (hash); -} - -uint calc_hashnr_caseup(const byte *key, uint len) -{ - const byte *end=key+len; - uint hash; - for (hash = 0; key < end; key++) - { - hash *= 16777619; - hash ^= (uint) (uchar) toupper(*key); - } - return (hash); -} - -#endif /* for compilers which can not handle inline */ @@ -190,7 +130,7 @@ unsigned int rec_hashnr(HASH *hash,const byte *record) { uint length; byte *key= (byte*) hash_key(hash,record,&length,0); - return (*hash->calc_hashnr)(key,length); + return calc_hash(hash,key,length); } @@ -206,8 +146,7 @@ gptr hash_search(HASH *hash,const byte *key,uint length) flag=1; if (hash->records) { - idx=hash_mask((*hash->calc_hashnr)(key,length ? length : - hash->key_length), + idx=hash_mask(calc_hash(hash,key,length ? length : hash->key_length), hash->blength,hash->records); do { @@ -277,16 +216,15 @@ static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length) { uint rec_keylength; byte *rec_key= (byte*) hash_key(hash,pos->data,&rec_keylength,1); - return (length && length != rec_keylength) || - (hash->flags & HASH_CASE_INSENSITIVE ? - my_casecmp(rec_key,key,rec_keylength) : - memcmp(rec_key,key,rec_keylength)); + return ((length && length != rec_keylength) || + my_strnncoll(hash->charset, (uchar*) rec_key, rec_keylength, + (uchar*) key, length)); } /* Write a hash-key to the hash-index */ -my_bool hash_insert(HASH *info,const byte *record) +my_bool my_hash_insert(HASH *info,const byte *record) { int flag; uint halfbuff,hash_nr,first_index,idx; @@ -519,7 +457,7 @@ my_bool hash_update(HASH *hash,byte *record,byte *old_key,uint old_key_length) /* Search after record with key */ - idx=hash_mask((*hash->calc_hashnr)(old_key,(old_key_length ? + idx=hash_mask(calc_hash(hash, old_key,(old_key_length ? old_key_length : hash->key_length)), blength,records); |