Coverage Report

Created: 2024-11-21 14:31

/root/doris/be/src/gutil/hash/hash.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2011 Google Inc. All Rights Reserved.
2
//
3
// This is the legacy unified hash library implementation. Its components are
4
// being split up into smaller, dedicated libraries. What remains here are
5
// things still being migrated.
6
//
7
// To find the implementation of the core Bob Jenkins lookup2 hash, look in
8
// jenkins.cc.
9
10
#include "gutil/hash/hash.h"
11
12
#include "common/logging.h"
13
14
#include "gutil/hash/jenkins.h"
15
#include "gutil/hash/jenkins_lookup2.h"
16
#include "gutil/integral_types.h"
17
18
// For components that ship code externally (notably the Google Search
19
// Appliance) we want to change the fingerprint function so that
20
// attackers cannot mount offline attacks to find collisions with
21
// google.com internal fingerprints (most importantly, for URL
22
// fingerprints).
23
#ifdef GOOGLECLIENT
24
#error Do not compile this into binaries that we deliver to users!
25
#error Instead, use
26
#endif
27
#ifdef EXTERNAL_FP
28
static const uint32 kFingerprintSeed0 = 0xabc;
29
static const uint32 kFingerprintSeed1 = 0xdef;
30
#else
31
static const uint32 kFingerprintSeed0 = 0;
32
static const uint32 kFingerprintSeed1 = 102072;
33
#endif
34
35
20
static inline uint32 char2unsigned(char c) {
36
20
    return static_cast<uint32>(static_cast<unsigned char>(c));
37
20
}
38
39
0
uint64 FingerprintReferenceImplementation(const char* s, uint32 len) {
40
0
    uint32 hi = Hash32StringWithSeed(s, len, kFingerprintSeed0);
41
0
    uint32 lo = Hash32StringWithSeed(s, len, kFingerprintSeed1);
42
0
    return CombineFingerprintHalves(hi, lo);
43
0
}
44
45
// This is a faster version of FingerprintReferenceImplementation(),
46
// making use of the fact that we're hashing the same string twice.
47
// The code is tedious to read, but it's just two interleaved copies of
48
// Hash32StringWithSeed().
49
7
uint64 FingerprintInterleavedImplementation(const char* s, uint32 len) {
50
7
    uint32 a, b, c = kFingerprintSeed0, d, e, f = kFingerprintSeed1;
51
7
    uint32 keylen;
52
53
7
    a = b = d = e = 0x9e3779b9UL; // the golden ratio; an arbitrary value
54
55
7
    keylen = len;
56
7
    if (keylen >= 4 * sizeof(a)) {
57
0
        uint32 word32AtOffset0 = Google1At(s);
58
0
        do {
59
0
            a += word32AtOffset0;
60
0
            d += word32AtOffset0;
61
0
            b += Google1At(s + sizeof(a));
62
0
            e += Google1At(s + sizeof(a));
63
0
            c += Google1At(s + sizeof(a) * 2);
64
0
            f += Google1At(s + sizeof(a) * 2);
65
0
            s += 3 * sizeof(a);
66
0
            word32AtOffset0 = Google1At(s);
67
0
            mix(a, b, c);
68
0
            mix(d, e, f);
69
0
            keylen -= 3 * static_cast<uint32>(sizeof(a));
70
0
        } while (keylen >= 4 * sizeof(a));
71
0
        if (keylen >= 3 * sizeof(a)) {
72
0
            a += word32AtOffset0;
73
0
            d += word32AtOffset0;
74
0
            b += Google1At(s + sizeof(a));
75
0
            e += Google1At(s + sizeof(a));
76
0
            c += Google1At(s + sizeof(a) * 2);
77
0
            f += Google1At(s + sizeof(a) * 2);
78
0
            s += 3 * sizeof(a);
79
0
            mix(a, b, c);
80
0
            mix(d, e, f);
81
0
            keylen -= 3 * static_cast<uint32>(sizeof(a));
82
0
            DCHECK_LT(keylen, sizeof(a));
83
0
            c += len;
84
0
            f += len;
85
0
            switch (keylen) { // deal with rest.  Cases fall through
86
0
            case 3:
87
0
                a += char2unsigned(s[2]) << 16;
88
0
                d += char2unsigned(s[2]) << 16;
89
0
            case 2:
90
0
                a += char2unsigned(s[1]) << 8;
91
0
                d += char2unsigned(s[1]) << 8;
92
0
            case 1:
93
0
                a += char2unsigned(s[0]);
94
0
                d += char2unsigned(s[0]);
95
0
            }
96
0
        } else {
97
0
            DCHECK(sizeof(a) <= keylen && keylen < 3 * sizeof(a));
98
0
            c += len;
99
0
            f += len;
100
0
            switch (keylen) { // deal with rest.  Cases fall through
101
0
            case 11:
102
0
                c += char2unsigned(s[10]) << 24;
103
0
                f += char2unsigned(s[10]) << 24;
104
0
            case 10:
105
0
                c += char2unsigned(s[9]) << 16;
106
0
                f += char2unsigned(s[9]) << 16;
107
0
            case 9:
108
0
                c += char2unsigned(s[8]) << 8;
109
0
                f += char2unsigned(s[8]) << 8;
110
0
            case 8:
111
0
                b += Google1At(s + 4);
112
0
                a += word32AtOffset0;
113
0
                e += Google1At(s + 4);
114
0
                d += word32AtOffset0;
115
0
                break;
116
0
            case 7:
117
0
                b += char2unsigned(s[6]) << 16;
118
0
                e += char2unsigned(s[6]) << 16;
119
0
            case 6:
120
0
                b += char2unsigned(s[5]) << 8;
121
0
                e += char2unsigned(s[5]) << 8;
122
0
            case 5:
123
0
                b += char2unsigned(s[4]);
124
0
                e += char2unsigned(s[4]);
125
0
            case 4:
126
0
                a += word32AtOffset0;
127
0
                d += word32AtOffset0;
128
0
            }
129
0
        }
130
7
    } else {
131
7
        if (keylen >= 3 * sizeof(a)) {
132
0
            a += Google1At(s);
133
0
            d += Google1At(s);
134
0
            b += Google1At(s + sizeof(a));
135
0
            e += Google1At(s + sizeof(a));
136
0
            c += Google1At(s + sizeof(a) * 2);
137
0
            f += Google1At(s + sizeof(a) * 2);
138
0
            s += 3 * sizeof(a);
139
0
            mix(a, b, c);
140
0
            mix(d, e, f);
141
0
            keylen -= 3 * static_cast<uint32>(sizeof(a));
142
0
        }
143
7
        c += len;
144
7
        f += len;
145
7
        switch (keylen) { // deal with rest.  Cases fall through
146
0
        case 11:
147
0
            c += char2unsigned(s[10]) << 24;
148
0
            f += char2unsigned(s[10]) << 24;
149
0
        case 10:
150
0
            c += char2unsigned(s[9]) << 16;
151
0
            f += char2unsigned(s[9]) << 16;
152
0
        case 9:
153
0
            c += char2unsigned(s[8]) << 8;
154
0
            f += char2unsigned(s[8]) << 8;
155
1
        case 8:
156
1
            b += Google1At(s + 4);
157
1
            a += Google1At(s);
158
1
            e += Google1At(s + 4);
159
1
            d += Google1At(s);
160
1
            break;
161
0
        case 7:
162
0
            b += char2unsigned(s[6]) << 16;
163
0
            e += char2unsigned(s[6]) << 16;
164
3
        case 6:
165
3
            b += char2unsigned(s[5]) << 8;
166
3
            e += char2unsigned(s[5]) << 8;
167
3
        case 5:
168
3
            b += char2unsigned(s[4]);
169
3
            e += char2unsigned(s[4]);
170
3
        case 4:
171
3
            a += Google1At(s);
172
3
            d += Google1At(s);
173
3
            break;
174
0
        case 3:
175
0
            a += char2unsigned(s[2]) << 16;
176
0
            d += char2unsigned(s[2]) << 16;
177
2
        case 2:
178
2
            a += char2unsigned(s[1]) << 8;
179
2
            d += char2unsigned(s[1]) << 8;
180
2
        case 1:
181
2
            a += char2unsigned(s[0]);
182
2
            d += char2unsigned(s[0]);
183
7
        }
184
7
    }
185
7
    mix(a, b, c);
186
7
    mix(d, e, f);
187
7
    return CombineFingerprintHalves(c, f);
188
7
}