/src/mozilla-central/netwerk/cache2/CacheHashUtils.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | | |
5 | | #include "CacheHashUtils.h" |
6 | | |
7 | | #include "mozilla/BasePrincipal.h" |
8 | | #include "plstr.h" |
9 | | |
10 | | namespace mozilla { |
11 | | namespace net { |
12 | | |
13 | | /** |
14 | | * CacheHash::Hash(const char * key, uint32_t initval) |
15 | | * |
16 | | * See http://burtleburtle.net/bob/hash/evahash.html for more information |
17 | | * about this hash function. |
18 | | * |
19 | | * This algorithm is used to check the data integrity. |
20 | | */ |
21 | | |
22 | | static inline void hashmix(uint32_t& a, uint32_t& b, uint32_t& c) |
23 | 0 | { |
24 | 0 | a -= b; a -= c; a ^= (c>>13); |
25 | 0 | b -= c; b -= a; b ^= (a<<8); |
26 | 0 | c -= a; c -= b; c ^= (b>>13); |
27 | 0 | a -= b; a -= c; a ^= (c>>12); |
28 | 0 | b -= c; b -= a; b ^= (a<<16); |
29 | 0 | c -= a; c -= b; c ^= (b>>5); |
30 | 0 | a -= b; a -= c; a ^= (c>>3); |
31 | 0 | b -= c; b -= a; b ^= (a<<10); |
32 | 0 | c -= a; c -= b; c ^= (b>>15); |
33 | 0 | } |
34 | | |
35 | | CacheHash::Hash32_t |
36 | | CacheHash::Hash(const char *aData, uint32_t aSize, uint32_t aInitval) |
37 | 0 | { |
38 | 0 | const uint8_t *k = reinterpret_cast<const uint8_t*>(aData); |
39 | 0 | uint32_t a, b, c, len; |
40 | 0 |
|
41 | 0 | /* Set up the internal state */ |
42 | 0 | len = aSize; |
43 | 0 | a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */ |
44 | 0 | c = aInitval; /* variable initialization of internal state */ |
45 | 0 |
|
46 | 0 | /*---------------------------------------- handle most of the key */ |
47 | 0 | while (len >= 12) |
48 | 0 | { |
49 | 0 | a += k[0] + (uint32_t(k[1])<<8) + (uint32_t(k[2])<<16) + (uint32_t(k[3])<<24); |
50 | 0 | b += k[4] + (uint32_t(k[5])<<8) + (uint32_t(k[6])<<16) + (uint32_t(k[7])<<24); |
51 | 0 | c += k[8] + (uint32_t(k[9])<<8) + (uint32_t(k[10])<<16) + (uint32_t(k[11])<<24); |
52 | 0 | hashmix(a, b, c); |
53 | 0 | k += 12; len -= 12; |
54 | 0 | } |
55 | 0 |
|
56 | 0 | /*------------------------------------- handle the last 11 bytes */ |
57 | 0 | c += aSize; |
58 | 0 | switch(len) { /* all the case statements fall through */ |
59 | 0 | case 11: c += (uint32_t(k[10])<<24); MOZ_FALLTHROUGH; |
60 | 0 | case 10: c += (uint32_t(k[9])<<16); MOZ_FALLTHROUGH; |
61 | 0 | case 9 : c += (uint32_t(k[8])<<8); MOZ_FALLTHROUGH; |
62 | 0 | /* the low-order byte of c is reserved for the length */ |
63 | 0 | case 8 : b += (uint32_t(k[7])<<24); MOZ_FALLTHROUGH; |
64 | 0 | case 7 : b += (uint32_t(k[6])<<16); MOZ_FALLTHROUGH; |
65 | 0 | case 6 : b += (uint32_t(k[5])<<8); MOZ_FALLTHROUGH; |
66 | 0 | case 5 : b += k[4]; MOZ_FALLTHROUGH; |
67 | 0 | case 4 : a += (uint32_t(k[3])<<24); MOZ_FALLTHROUGH; |
68 | 0 | case 3 : a += (uint32_t(k[2])<<16); MOZ_FALLTHROUGH; |
69 | 0 | case 2 : a += (uint32_t(k[1])<<8); MOZ_FALLTHROUGH; |
70 | 0 | case 1 : a += k[0]; |
71 | 0 | /* case 0: nothing left to add */ |
72 | 0 | } |
73 | 0 | hashmix(a, b, c); |
74 | 0 |
|
75 | 0 | return c; |
76 | 0 | } |
77 | | |
78 | | CacheHash::Hash16_t |
79 | | CacheHash::Hash16(const char *aData, uint32_t aSize, uint32_t aInitval) |
80 | 0 | { |
81 | 0 | Hash32_t hash = Hash(aData, aSize, aInitval); |
82 | 0 | return (hash & 0xFFFF); |
83 | 0 | } |
84 | | |
85 | | NS_IMPL_ISUPPORTS0(CacheHash) |
86 | | |
87 | | CacheHash::CacheHash(uint32_t aInitval) |
88 | | : mA(0x9e3779b9) |
89 | | , mB(0x9e3779b9) |
90 | | , mC(aInitval) |
91 | | , mPos(0) |
92 | | , mBuf(0) |
93 | | , mBufPos(0) |
94 | | , mLength(0) |
95 | | , mFinalized(false) |
96 | 0 | {} |
97 | | |
98 | | void |
99 | | CacheHash::Feed(uint32_t aVal, uint8_t aLen) |
100 | 0 | { |
101 | 0 | switch (mPos) { |
102 | 0 | case 0: |
103 | 0 | mA += aVal; |
104 | 0 | mPos ++; |
105 | 0 | break; |
106 | 0 |
|
107 | 0 | case 1: |
108 | 0 | mB += aVal; |
109 | 0 | mPos ++; |
110 | 0 | break; |
111 | 0 |
|
112 | 0 | case 2: |
113 | 0 | mPos = 0; |
114 | 0 | if (aLen == 4) { |
115 | 0 | mC += aVal; |
116 | 0 | hashmix(mA, mB, mC); |
117 | 0 | } |
118 | 0 | else { |
119 | 0 | mC += aVal << 8; |
120 | 0 | } |
121 | 0 | } |
122 | 0 |
|
123 | 0 | mLength += aLen; |
124 | 0 | } |
125 | | |
126 | | void |
127 | | CacheHash::Update(const char *aData, uint32_t aLen) |
128 | 0 | { |
129 | 0 | const uint8_t *data = reinterpret_cast<const uint8_t*>(aData); |
130 | 0 |
|
131 | 0 | MOZ_ASSERT(!mFinalized); |
132 | 0 |
|
133 | 0 | if (mBufPos) { |
134 | 0 | while (mBufPos != 4 && aLen) { |
135 | 0 | mBuf += uint32_t(*data) << 8*mBufPos; |
136 | 0 | data++; |
137 | 0 | mBufPos++; |
138 | 0 | aLen--; |
139 | 0 | } |
140 | 0 |
|
141 | 0 | if (mBufPos == 4) { |
142 | 0 | mBufPos = 0; |
143 | 0 | Feed(mBuf); |
144 | 0 | mBuf = 0; |
145 | 0 | } |
146 | 0 | } |
147 | 0 |
|
148 | 0 | if (!aLen) |
149 | 0 | return; |
150 | 0 | |
151 | 0 | while (aLen >= 4) { |
152 | 0 | Feed(data[0] + (uint32_t(data[1]) << 8) + (uint32_t(data[2]) << 16) + |
153 | 0 | (uint32_t(data[3]) << 24)); |
154 | 0 | data += 4; |
155 | 0 | aLen -= 4; |
156 | 0 | } |
157 | 0 |
|
158 | 0 | switch (aLen) { |
159 | 0 | case 3: mBuf += data[2] << 16; MOZ_FALLTHROUGH; |
160 | 0 | case 2: mBuf += data[1] << 8; MOZ_FALLTHROUGH; |
161 | 0 | case 1: mBuf += data[0]; |
162 | 0 | } |
163 | 0 |
|
164 | 0 | mBufPos = aLen; |
165 | 0 | } |
166 | | |
167 | | CacheHash::Hash32_t |
168 | | CacheHash::GetHash() |
169 | 0 | { |
170 | 0 | if (!mFinalized) |
171 | 0 | { |
172 | 0 | if (mBufPos) { |
173 | 0 | Feed(mBuf, mBufPos); |
174 | 0 | } |
175 | 0 | mC += mLength; |
176 | 0 | hashmix(mA, mB, mC); |
177 | 0 | mFinalized = true; |
178 | 0 | } |
179 | 0 |
|
180 | 0 | return mC; |
181 | 0 | } |
182 | | |
183 | | CacheHash::Hash16_t |
184 | | CacheHash::GetHash16() |
185 | 0 | { |
186 | 0 | Hash32_t hash = GetHash(); |
187 | 0 | return (hash & 0xFFFF); |
188 | 0 | } |
189 | | |
190 | | OriginAttrsHash |
191 | | GetOriginAttrsHash(const mozilla::OriginAttributes &aOA) |
192 | 0 | { |
193 | 0 | nsAutoCString suffix; |
194 | 0 | aOA.CreateSuffix(suffix); |
195 | 0 |
|
196 | 0 | SHA1Sum sum; |
197 | 0 | SHA1Sum::Hash hash; |
198 | 0 | sum.update(suffix.BeginReading(), suffix.Length()); |
199 | 0 | sum.finish(hash); |
200 | 0 |
|
201 | 0 | return BigEndian::readUint64(&hash); |
202 | 0 | } |
203 | | |
204 | | } // namespace net |
205 | | } // namespace mozilla |