netwerk/cache2/CacheHashUtils.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial