summaryrefslogtreecommitdiffstats
path: root/include/fnv_hash.h
blob: c85b3c27c96ee48ca2837e410371e9a3e1e82404 (plain) (blame)
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#ifndef _FNV_HASH_H_
#define _FNV_HASH_H_
/*
 * Fowler / Noll / Vo Hash (FNV Hash)
 * http://www.isthe.com/chongo/tech/comp/fnv/
 *
 * This is an implementation of the algorithms posted above.
 * This file is placed in the public domain by Peter Wemm.
 *
 * $FreeBSD: src/sys/sys/fnv_hash.h,v 1.2 2001/03/20 02:10:18 peter Exp $
 */

typedef unsigned int Fnv32_t;
typedef unsigned long long Fnv64_t;

#define FNV1_32_INIT ((Fnv32_t) 33554467UL)
#define FNV1_64_INIT ((Fnv64_t) 0xcbf29ce484222325ULL)

#define FNV_32_PRIME ((Fnv32_t) 0x01000193UL)
#define FNV_64_PRIME ((Fnv64_t) 0x100000001b3ULL)

static __inline Fnv32_t
fnv_32_buf(const void *buf, size_t len, Fnv32_t hval)
{
    const unsigned char *s = (const unsigned char *)buf;

    while (len-- != 0) {
        hval *= FNV_32_PRIME;
        hval ^= *s++;
    }
    return hval;
}

static __inline Fnv32_t
fnv_32_str(const char *str, Fnv32_t hval)
{
    const unsigned char *s = (const unsigned char *)str;
    Fnv32_t c;

    while ((c = *s++) != 0) {
        hval *= FNV_32_PRIME;
        hval ^= c;
    }
    return hval;
}

static __inline Fnv32_t
fnv1a_32_str(const char *str, Fnv32_t hval)
{
    const unsigned char *s = (const unsigned char *)str;
    Fnv32_t c;

    while ((c = *s++) != 0) {
        hval ^= c;
        hval *= FNV_32_PRIME;
    }
    return hval;
}

static __inline Fnv32_t
fnv1a_32_strcase(const char *str, Fnv32_t hval)
{
    const unsigned char *s = (const unsigned char *)str;
    Fnv32_t c;

    while ((c = *s++) != 0) {
        hval ^= toupper(c);
        hval *= FNV_32_PRIME;
    }
    return hval;
}

static __inline Fnv32_t
fnv1a_32_dbcs_strcase(const char *str, Fnv32_t hval)
{
    const unsigned char *s = (const unsigned char *)str;
    Fnv32_t c;
    char isDBCS = 0;

    while ((c = *s++) != 0) {
        if (isDBCS)
        {
            // 2nd DBCS 
            isDBCS = 0;
        } else {
            // ASCII?
            if ( c < 0x80)
            c = toupper(c);
            else
            isDBCS = 1;
        }
        hval ^= c;
        hval *= FNV_32_PRIME;
    }
    return hval;
}

static __inline Fnv64_t
fnv_64_buf(const void *buf, size_t len, Fnv64_t hval)
{
    const unsigned char *s = (const unsigned char *)buf;

    while (len-- != 0) {
        hval *= FNV_64_PRIME;
        hval ^= *s++;
    }
    return hval;
}

static __inline Fnv64_t
fnv_64_str(const char *str, Fnv64_t hval)
{
    const unsigned char *s = (const unsigned char *)str;
    Fnv64_t c;

    while ((c = *s++) != 0) {
        hval *= FNV_64_PRIME;
        hval ^= c;
    }
    return hval;
}

static __inline Fnv64_t
fnv1a_64_strcase(const char *str, Fnv64_t hval)
{
    const unsigned char *s = (const unsigned char *)str;
    Fnv64_t c;

    while ((c = *s++) != 0) {
        hval ^= toupper(c);
        hval *= FNV_64_PRIME;
    }
    return hval;
}

#define FNV1A_CHAR(c,hval) do { hval^=(unsigned char)c; hval*=FNV_32_PRIME; } while(0)
#endif