aboutsummaryrefslogtreecommitdiffstats
path: root/lib/lookup.c
blob: 0dad247ffe18664eab520baff5e8ab239490ad96 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/* 
 * Hash lookup function.
 * Copyright (C) 2003, 2004 Mondru AB.
 * 
 * The contents of this file may be used under the terms of the GNU
 * General Public License Version 2, provided that the above copyright
 * notice and this permission notice is included in all copies or
 * substantial portions of the software.
 * 
 */

/**
 * lookup()
 * Generates a 32 bit hash.
 * Based on public domain code by Bob Jenkins
 * It should be one of the best hash functions around in terms of both
 * statistical properties and speed. It is NOT recommended for cryptographic
 * purposes.
 **/
unsigned long int lookup(k, length, level)
register unsigned char *k;	/* the key */
register unsigned long int length;	/* the length of the key */
register unsigned long int level;	/* the previous hash, or an arbitrary value */
{

#define mix(a,b,c) \
{ \
  a -= b; a -= c; a ^= (c>>13); \
  b -= c; b -= a; b ^= (a<<8); \
  c -= a; c -= b; c ^= (b>>13); \
  a -= b; a -= c; a ^= (c>>12);  \
  b -= c; b -= a; b ^= (a<<16); \
  c -= a; c -= b; c ^= (b>>5); \
  a -= b; a -= c; a ^= (c>>3);  \
  b -= c; b -= a; b ^= (a<<10); \
  c -= a; c -= b; c ^= (b>>15); \
}

	typedef unsigned long int ub4;	/* unsigned 4-byte quantities */
	register unsigned long int a, b, c, len;

	/* Set up the internal state */
	len = length;
	a = b = 0x9e3779b9;	/* the golden ratio; an arbitrary value */
	c = level;		/* the previous hash value */

  /*---------------------------------------- handle most of the key */
	while (len >= 12) {
		a += (k[0] + ((ub4) k[1] << 8) + ((ub4) k[2] << 16) +
		      ((ub4) k[3] << 24));
		b += (k[4] + ((ub4) k[5] << 8) + ((ub4) k[6] << 16) +
		      ((ub4) k[7] << 24));
		c += (k[8] + ((ub4) k[9] << 8) + ((ub4) k[10] << 16) +
		      ((ub4) k[11] << 24));
		mix(a, b, c);
		k += 12;
		len -= 12;
	}

  /*------------------------------------- handle the last 11 bytes */
	c += length;
	switch (len) {		/* all the case statements fall through */
	case 11:
		c += ((ub4) k[10] << 24);
	case 10:
		c += ((ub4) k[9] << 16);
	case 9:
		c += ((ub4) k[8] << 8);
		/* the first byte of c is reserved for the length */
	case 8:
		b += ((ub4) k[7] << 24);
	case 7:
		b += ((ub4) k[6] << 16);
	case 6:
		b += ((ub4) k[5] << 8);
	case 5:
		b += k[4];
	case 4:
		a += ((ub4) k[3] << 24);
	case 3:
		a += ((ub4) k[2] << 16);
	case 2:
		a += ((ub4) k[1] << 8);
	case 1:
		a += k[0];
		/* case 0: nothing left to add */
	}
	mix(a, b, c);
  /*-------------------------------------------- report the result */
	return c;
}