157 lines
3.2 KiB
C
157 lines
3.2 KiB
C
|
/*-------------------------------------------------------------------------
|
||
|
*
|
||
|
* hashfn.c--
|
||
|
*
|
||
|
*
|
||
|
* Copyright (c) 1994, Regents of the University of California
|
||
|
*
|
||
|
*
|
||
|
* IDENTIFICATION
|
||
|
* $Header: /cvsroot/pgsql/src/backend/utils/hash/hashfn.c,v 1.1.1.1 1996/07/09 06:22:08 scrappy Exp $
|
||
|
*
|
||
|
*-------------------------------------------------------------------------
|
||
|
*/
|
||
|
#include <string.h>
|
||
|
#include "utils/hsearch.h"
|
||
|
|
||
|
/*
|
||
|
* Assume that we've already split the bucket to which this
|
||
|
* key hashes, calculate that bucket, and check that in fact
|
||
|
* we did already split it.
|
||
|
*/
|
||
|
long
|
||
|
string_hash(char *key, int keysize)
|
||
|
{
|
||
|
int h;
|
||
|
register unsigned char *k = (unsigned char *) key;
|
||
|
|
||
|
h = 0;
|
||
|
/*
|
||
|
* Convert string to integer
|
||
|
*/
|
||
|
while (*k)
|
||
|
h = h * PRIME1 ^ (*k++ - ' ');
|
||
|
h %= PRIME2;
|
||
|
|
||
|
return (h);
|
||
|
}
|
||
|
|
||
|
|
||
|
long
|
||
|
tag_hash(int *key, int keysize)
|
||
|
{
|
||
|
register long h = 0;
|
||
|
|
||
|
/*
|
||
|
* Convert tag to integer; Use four byte chunks in a "jump table"
|
||
|
* to go a little faster. Currently the maximum keysize is 16
|
||
|
* (mar 17 1992) I have put in cases for up to 24. Bigger than
|
||
|
* this will resort to the old behavior of the for loop. (see the
|
||
|
* default case).
|
||
|
*/
|
||
|
switch (keysize)
|
||
|
{
|
||
|
case 6*sizeof(int):
|
||
|
h = h * PRIME1 ^ (*key);
|
||
|
key++;
|
||
|
/* fall through */
|
||
|
|
||
|
case 5*sizeof(int):
|
||
|
h = h * PRIME1 ^ (*key);
|
||
|
key++;
|
||
|
/* fall through */
|
||
|
|
||
|
case 4*sizeof(int):
|
||
|
h = h * PRIME1 ^ (*key);
|
||
|
key++;
|
||
|
/* fall through */
|
||
|
|
||
|
case 3*sizeof(int):
|
||
|
h = h * PRIME1 ^ (*key);
|
||
|
key++;
|
||
|
/* fall through */
|
||
|
|
||
|
case 2*sizeof(int):
|
||
|
h = h * PRIME1 ^ (*key);
|
||
|
key++;
|
||
|
/* fall through */
|
||
|
|
||
|
case sizeof(int):
|
||
|
h = h * PRIME1 ^ (*key);
|
||
|
key++;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
for(; keysize > (sizeof(int)-1); keysize -= sizeof(int), key++)
|
||
|
h = h * PRIME1 ^ (*key);
|
||
|
/*
|
||
|
* now let's grab the last few bytes of the tag if the tag
|
||
|
* has (size % 4) != 0 (which it sometimes will on a sun3).
|
||
|
*/
|
||
|
if (keysize)
|
||
|
{
|
||
|
char *keytmp = (char *)key;
|
||
|
|
||
|
switch (keysize)
|
||
|
{
|
||
|
case 3:
|
||
|
h = h * PRIME1 ^ (*keytmp);
|
||
|
keytmp++;
|
||
|
/* fall through */
|
||
|
case 2:
|
||
|
h = h * PRIME1 ^ (*keytmp);
|
||
|
keytmp++;
|
||
|
/* fall through */
|
||
|
case 1:
|
||
|
h = h * PRIME1 ^ (*keytmp);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
h %= PRIME2;
|
||
|
return (h);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This is INCREDIBLY ugly, but fast.
|
||
|
* We break the string up into 8 byte units. On the first time
|
||
|
* through the loop we get the "leftover bytes" (strlen % 8).
|
||
|
* On every other iteration, we perform 8 HASHC's so we handle
|
||
|
* all 8 bytes. Essentially, this saves us 7 cmp & branch
|
||
|
* instructions. If this routine is heavily used enough, it's
|
||
|
* worth the ugly coding
|
||
|
*/
|
||
|
long
|
||
|
disk_hash(char *key)
|
||
|
{
|
||
|
register int n = 0;
|
||
|
register char *str = key;
|
||
|
register int len = strlen(key);
|
||
|
register int loop;
|
||
|
|
||
|
#define HASHC n = *str++ + 65599 * n
|
||
|
|
||
|
if (len > 0) {
|
||
|
loop = (len + 8 - 1) >> 3;
|
||
|
|
||
|
switch(len & (8 - 1)) {
|
||
|
case 0: do { /* All fall throughs */
|
||
|
HASHC;
|
||
|
case 7: HASHC;
|
||
|
case 6: HASHC;
|
||
|
case 5: HASHC;
|
||
|
case 4: HASHC;
|
||
|
case 3: HASHC;
|
||
|
case 2: HASHC;
|
||
|
case 1: HASHC;
|
||
|
} while (--loop);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
return(n);
|
||
|
}
|
||
|
|
||
|
|