universe@563: /* universe@563: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. universe@563: * universe@563: * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. universe@563: * universe@563: * Redistribution and use in source and binary forms, with or without universe@563: * modification, are permitted provided that the following conditions are met: universe@563: * universe@563: * 1. Redistributions of source code must retain the above copyright universe@563: * notice, this list of conditions and the following disclaimer. universe@563: * universe@563: * 2. Redistributions in binary form must reproduce the above copyright universe@563: * notice, this list of conditions and the following disclaimer in the universe@563: * documentation and/or other materials provided with the distribution. universe@563: * universe@563: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" universe@563: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE universe@563: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE universe@563: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE universe@563: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR universe@563: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF universe@563: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS universe@563: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN universe@563: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) universe@563: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE universe@563: * POSSIBILITY OF SUCH DAMAGE. universe@563: */ universe@563: universe@563: #include "cx/hash_key.h" universe@563: #include universe@563: universe@563: void cx_hash_murmur(CxHashKey *key) { universe@690: unsigned char const *data = key->data; universe@604: if (data == NULL) { universe@628: // extension: special value for NULL universe@604: key->hash = 1574210520u; universe@604: return; universe@604: } universe@563: size_t len = key->len; universe@563: universe@563: unsigned m = 0x5bd1e995; universe@563: unsigned r = 24; universe@563: unsigned h = 25 ^ len; universe@563: unsigned i = 0; universe@563: while (len >= 4) { universe@563: unsigned k = data[i + 0] & 0xFF; universe@563: k |= (data[i + 1] & 0xFF) << 8; universe@563: k |= (data[i + 2] & 0xFF) << 16; universe@563: k |= (data[i + 3] & 0xFF) << 24; universe@563: universe@563: k *= m; universe@563: k ^= k >> r; universe@563: k *= m; universe@563: universe@563: h *= m; universe@563: h ^= k; universe@563: universe@563: i += 4; universe@563: len -= 4; universe@563: } universe@563: universe@563: switch (len) { universe@563: case 3: universe@563: h ^= (data[i + 2] & 0xFF) << 16; universe@563: __attribute__((__fallthrough__)); universe@563: case 2: universe@563: h ^= (data[i + 1] & 0xFF) << 8; universe@563: __attribute__((__fallthrough__)); universe@563: case 1: universe@563: h ^= (data[i + 0] & 0xFF); universe@563: h *= m; universe@563: __attribute__((__fallthrough__)); universe@628: default: // do nothing universe@678: ; universe@563: } universe@563: universe@563: h ^= h >> 13; universe@563: h *= m; universe@563: h ^= h >> 15; universe@563: universe@563: key->hash = h; universe@563: } universe@563: universe@563: CxHashKey cx_hash_key_str(char const *str) { universe@563: CxHashKey key; universe@690: key.data = str; universe@604: key.len = str == NULL ? 0 : strlen(str); universe@563: cx_hash_murmur(&key); universe@563: return key; universe@563: } universe@563: universe@563: CxHashKey cx_hash_key_bytes( universe@563: unsigned char const *bytes, universe@563: size_t len universe@563: ) { universe@563: CxHashKey key; universe@690: key.data = bytes; universe@563: key.len = len; universe@563: cx_hash_murmur(&key); universe@563: return key; universe@563: } universe@563: universe@563: CxHashKey cx_hash_key( universe@603: void const *obj, universe@563: size_t len universe@563: ) { universe@563: CxHashKey key; universe@690: key.data = obj; universe@563: key.len = len; universe@563: cx_hash_murmur(&key); universe@563: return key; universe@563: }