netsukuku/src/hash.c

167 lines
4.3 KiB
C
Raw Normal View History

2013-09-16 09:53:25 +00:00
/* This file is part of Netsukuku
* (c) Copyright 2005 Andrea Lo Pumo aka AlpT <alpt@freaknet.org>
*
* This source code is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* This source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* Please refer to the GNU Public License for more details.
*
* You should have received a copy of the GNU Public License along with
* this source code; if not, write to:
* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* --
* hash.c: hash functions
*/
#include "includes.h"
#include "hash.h"
/* Robert Jenkins's 32 bit Mix Function */
unsigned int inthash(unsigned int key)
{
key += (key << 12);
key ^= (key >> 22);
key += (key << 4);
key ^= (key >> 9);
key += (key << 10);
key ^= (key >> 2);
key += (key << 7);
key ^= (key >> 12);
return key;
}
/* Ripped 32bit Hash function
*
* Fowler/Noll/Vo hash
*
* See http://www.isthe.com/chongo/tech/comp/fnv/index.html
* for more details as well as other forms of the FNV hash.
*
***
*
* Use the recommended 32 bit FNV-1 hash, pass FNV1_32_INIT as the
* u_long hashval argument to fnv_32_buf().
*
***
*
* Please do not copyright this code. This code is in the public domain.
*
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* By:
* chongo <Landon Curt Noll> /\oo/\
* http://www.isthe.com/chongo/
* Share and Enjoy! :-)
*
* fnv_32_buf - perform a 32 bit Fowler/Noll/Vo hash on a buffer
* `hval' - previous hash value or 0 if first call
* returns:
* 32 bit hash as a static hash type
*/
u_long fnv_32_buf(void *buf, size_t len, u_long hval)
{
u_char *bp = (u_char *)buf; /* start of buffer */
u_char *be = bp + len; /* beyond end of buffer */
/*
* FNV-1 hash each octet in the buffer
*/
while (bp < be) {
/* multiply by the 32 bit FNV magic prime mod 2^32 */
hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
/* xor the bottom with the current octet */
hval ^= (u_long)*bp++;
}
/* return our new hash value */
return hval;
}
/*
* Ripped from glibc.
* This is the hashing function specified by the ELF ABI. In the
* first five operations no overflow is possible so we optimized it a
* bit.
*/
inline unsigned int dl_elf_hash (const unsigned char *name)
{
unsigned long int hash = 0;
if (*name != '\0') {
hash = *name++;
if (*name != '\0') {
hash = (hash << 4) + *name++;
if (*name != '\0') {
hash = (hash << 4) + *name++;
if (*name != '\0') {
hash = (hash << 4) + *name++;
if (*name != '\0') {
hash = (hash << 4) + *name++;
while (*name != '\0') {
unsigned long int hi;
hash = (hash << 4) + *name++;
hi = hash & 0xf0000000;
/* The algorithm specified in the ELF ABI is as
follows:
if (hi != 0)
hash ^= hi >> 24;
hash &= ~hi;
But the following is equivalent and a lot
faster, especially on modern processors. */
hash ^= hi;
hash ^= hi >> 24;
}
}
}
}
}
}
return hash;
}
/*
* hash_time: As the name says: hash time!
* This function generates the hash of the timeval struct which refer
* to the current time.
* If h_sec or h_usec are not null, it stores in them respectively the hash of
* the second and the microsecond.
*/
int hash_time(int *h_sec, int *h_usec)
{
struct timeval t;
char str[sizeof(struct timeval)+1];
u_int elf_hash;
gettimeofday(&t, 0);
memcpy(str, &t, sizeof(struct timeval));
str[sizeof(struct timeval)]=0;
elf_hash=dl_elf_hash((u_char *)str);
if(h_sec)
*h_sec=inthash(t.tv_sec);
if(h_usec)
*h_usec=inthash(t.tv_usec);
return inthash(elf_hash);
}