andre@3: /*- andre@3: * Copyright (c) 1990, 1993 andre@3: * The Regents of the University of California. All rights reserved. andre@3: * andre@3: * This code is derived from software contributed to Berkeley by andre@3: * Margo Seltzer. andre@3: * andre@3: * Redistribution and use in source and binary forms, with or without andre@3: * modification, are permitted provided that the following conditions andre@3: * are met: andre@3: * 1. Redistributions of source code must retain the above copyright andre@3: * notice, this list of conditions and the following disclaimer. andre@3: * 2. Redistributions in binary form must reproduce the above copyright andre@3: * notice, this list of conditions and the following disclaimer in the andre@3: * documentation and/or other materials provided with the distribution. andre@3: * 3. ***REMOVED*** - see andre@3: * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change andre@3: * 4. Neither the name of the University nor the names of its contributors andre@3: * may be used to endorse or promote products derived from this software andre@3: * without specific prior written permission. andre@3: * andre@3: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND andre@3: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE andre@3: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE andre@3: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE andre@3: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL andre@3: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS andre@3: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) andre@3: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT andre@3: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY andre@3: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF andre@3: * SUCH DAMAGE. andre@3: */ andre@3: andre@3: #if defined(LIBC_SCCS) && !defined(lint) andre@3: static char sccsid[] = "@(#)hash_func.c 8.2 (Berkeley) 2/21/94"; andre@3: #endif /* LIBC_SCCS and not lint */ andre@3: andre@3: #ifndef macintosh andre@3: #include andre@3: #endif andre@3: #include "mcom_db.h" andre@3: #include "hash.h" andre@3: #include "page.h" andre@3: /* #include "extern.h" */ andre@3: andre@3: #if 0 andre@3: static uint32 hash1 __P((const void *, size_t)); andre@3: static uint32 hash2 __P((const void *, size_t)); andre@3: static uint32 hash3 __P((const void *, size_t)); andre@3: #endif andre@3: static uint32 hash4 __P((const void *, size_t)); andre@3: andre@3: /* Global default hash function */ andre@3: uint32 (*__default_hash) __P((const void *, size_t)) = hash4; andre@3: andre@3: /* andre@3: * HASH FUNCTIONS andre@3: * andre@3: * Assume that we've already split the bucket to which this key hashes, andre@3: * calculate that bucket, and check that in fact we did already split it. andre@3: * andre@3: * This came from ejb's hsearch. andre@3: */ andre@3: andre@3: #define PRIME1 37 andre@3: #define PRIME2 1048583 andre@3: andre@3: #if 0 andre@3: static uint32 andre@3: hash1(const void *keyarg, register size_t len) andre@3: { andre@3: register const uint8 *key; andre@3: register uint32 h; andre@3: andre@3: /* Convert string to integer */ andre@3: for (key = (const uint8 *)keyarg, h = 0; len--;) andre@3: h = h * PRIME1 ^ (*key++ - ' '); andre@3: h %= PRIME2; andre@3: return (h); andre@3: } andre@3: andre@3: /* andre@3: * Phong's linear congruential hash andre@3: */ andre@3: #define dcharhash(h, c) ((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c)) andre@3: andre@3: static uint32 andre@3: hash2(const void *keyarg, size_t len) andre@3: { andre@3: register const uint8 *e, *key; andre@3: register uint32 h; andre@3: register uint8 c; andre@3: andre@3: key = (const uint8 *)keyarg; andre@3: e = key + len; andre@3: for (h = 0; key != e;) { andre@3: c = *key++; andre@3: if (!c && key > e) andre@3: break; andre@3: dcharhash(h, c); andre@3: } andre@3: return (h); andre@3: } andre@3: andre@3: /* andre@3: * This is INCREDIBLY ugly, but fast. We break the string up into 8 byte andre@3: * units. On the first time through the loop we get the "leftover bytes" andre@3: * (strlen % 8). On every other iteration, we perform 8 HASHC's so we handle andre@3: * all 8 bytes. Essentially, this saves us 7 cmp & branch instructions. If andre@3: * this routine is heavily used enough, it's worth the ugly coding. andre@3: * andre@3: * OZ's original sdbm hash andre@3: */ andre@3: static uint32 andre@3: hash3(const void *keyarg, register size_t len) andre@3: { andre@3: register const uint8 *key; andre@3: register size_t loop; andre@3: register uint32 h; andre@3: andre@3: #define HASHC h = *key++ + 65599 * h andre@3: andre@3: h = 0; andre@3: key = (const uint8 *)keyarg; andre@3: if (len > 0) { andre@3: loop = (len + 8 - 1) >> 3; andre@3: andre@3: switch (len & (8 - 1)) { andre@3: case 0: andre@3: do { andre@3: HASHC; andre@3: /* FALLTHROUGH */ andre@3: case 7: andre@3: HASHC; andre@3: /* FALLTHROUGH */ andre@3: case 6: andre@3: HASHC; andre@3: /* FALLTHROUGH */ andre@3: case 5: andre@3: HASHC; andre@3: /* FALLTHROUGH */ andre@3: case 4: andre@3: HASHC; andre@3: /* FALLTHROUGH */ andre@3: case 3: andre@3: HASHC; andre@3: /* FALLTHROUGH */ andre@3: case 2: andre@3: HASHC; andre@3: /* FALLTHROUGH */ andre@3: case 1: andre@3: HASHC; andre@3: } while (--loop); andre@3: } andre@3: } andre@3: return (h); andre@3: } andre@3: #endif /* 0 */ andre@3: andre@3: /* Hash function from Chris Torek. */ andre@3: static uint32 andre@3: hash4(const void *keyarg, register size_t len) andre@3: { andre@3: register const uint8 *key; andre@3: register size_t loop; andre@3: register uint32 h; andre@3: andre@3: #define HASH4a h = (h << 5) - h + *key++; andre@3: #define HASH4b h = (h << 5) + h + *key++; andre@3: #define HASH4 HASH4b andre@3: andre@3: h = 0; andre@3: key = (const uint8 *)keyarg; andre@3: if (len > 0) { andre@3: loop = (len + 8 - 1) >> 3; andre@3: andre@3: switch (len & (8 - 1)) { andre@3: case 0: andre@3: do { andre@3: HASH4; andre@3: /* FALLTHROUGH */ andre@3: case 7: andre@3: HASH4; andre@3: /* FALLTHROUGH */ andre@3: case 6: andre@3: HASH4; andre@3: /* FALLTHROUGH */ andre@3: case 5: andre@3: HASH4; andre@3: /* FALLTHROUGH */ andre@3: case 4: andre@3: HASH4; andre@3: /* FALLTHROUGH */ andre@3: case 3: andre@3: HASH4; andre@3: /* FALLTHROUGH */ andre@3: case 2: andre@3: HASH4; andre@3: /* FALLTHROUGH */ andre@3: case 1: andre@3: HASH4; andre@3: } while (--loop); andre@3: } andre@3: } andre@3: return (h); andre@3: }