Changeset 706:4ffbc9f1e922 in freeDiameter for libfdproto/lists.c
- Timestamp:
- Feb 9, 2011, 3:26:58 PM (13 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libfdproto/lists.c
r662 r706 163 163 164 164 165 /********************************************************************************************************/166 /* Hash function -- credits to Austin Appleby, thank you ^^ */167 /* See http://murmurhash.googlepages.com for more information on this function */168 169 /* the strings are NOT always aligned properly (ex: received in RADIUS message), so we use the aligned MurmurHash2 function as needed */170 #define _HASH_MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }171 uint32_t fd_hash ( char * string, size_t len )172 {173 uint32_t hash = len;174 char * data = string;175 176 const unsigned int m = 0x5bd1e995;177 const int r = 24;178 int align = (long)string & 3;179 180 if (!align || (len < 4)) {181 182 /* In case data is aligned, MurmurHash2 function */183 while(len >= 4)184 {185 /* Mix 4 bytes at a time into the hash */186 uint32_t k = *(uint32_t *)data; /* We don't care about the byte order */187 188 _HASH_MIX(hash, k, m);189 190 data += 4;191 len -= 4;192 }193 194 /* Handle the last few bytes of the input */195 switch(len) {196 case 3: hash ^= data[2] << 16;197 case 2: hash ^= data[1] << 8;198 case 1: hash ^= data[0];199 hash *= m;200 }201 202 } else {203 /* Unaligned data, use alignment-safe slower version */204 205 /* Pre-load the temp registers */206 uint32_t t = 0, d = 0;207 switch(align)208 {209 case 1: t |= data[2] << 16;210 case 2: t |= data[1] << 8;211 case 3: t |= data[0];212 }213 t <<= (8 * align);214 215 data += 4-align;216 len -= 4-align;217 218 /* From this point, "data" can be read by chunks of 4 bytes */219 220 int sl = 8 * (4-align);221 int sr = 8 * align;222 223 /* Mix */224 while(len >= 4)225 {226 uint32_t k;227 228 d = *(unsigned int *)data;229 k = (t >> sr) | (d << sl);230 231 _HASH_MIX(hash, k, m);232 233 t = d;234 235 data += 4;236 len -= 4;237 }238 239 /* Handle leftover data in temp registers */240 d = 0;241 if(len >= align)242 {243 uint32_t k;244 245 switch(align)246 {247 case 3: d |= data[2] << 16;248 case 2: d |= data[1] << 8;249 case 1: d |= data[0];250 }251 252 k = (t >> sr) | (d << sl);253 _HASH_MIX(hash, k, m);254 255 data += align;256 len -= align;257 258 /* Handle tail bytes */259 260 switch(len)261 {262 case 3: hash ^= data[2] << 16;263 case 2: hash ^= data[1] << 8;264 case 1: hash ^= data[0];265 hash *= m;266 };267 }268 else269 {270 switch(len)271 {272 case 3: d |= data[2] << 16;273 case 2: d |= data[1] << 8;274 case 1: d |= data[0];275 case 0: hash ^= (t >> sr) | (d << sl);276 hash *= m;277 }278 }279 280 281 }282 283 /* Do a few final mixes of the hash to ensure the last few284 bytes are well-incorporated. */285 hash ^= hash >> 13;286 hash *= m;287 hash ^= hash >> 15;288 289 return hash;290 }
Note: See TracChangeset
for help on using the changeset viewer.