static constexpr bool folded = true;
};
+/**
+Computes a single round of a hash, adding one byte of data. N must be a native
+hash size.
+*/
+template<unsigned N>
+typename HashTraits<N>::ResultType hash_round(typename HashTraits<N>::HashType result, uint8_t byte)
+{
+ constexpr typename HashTraits<N>::HashType prime = HashTraits<N>::prime;
+ return (result^byte)*prime;
+}
+
+/**
+Updates a previously computed hash by adding bytes to it. N must be a native
+hash size.
+*/
+template<unsigned N>
+typename HashTraits<N>::ResultType hash_update(typename HashTraits<N>::HashType result, const void *data, std::size_t size)
+{
+ const uint8_t *ptr = static_cast<const uint8_t *>(data);
+ for(unsigned i=0; i<size; ++i)
+ result = hash_round<N>(result, *ptr++);
+ return result;
+}
+
+template<unsigned N>
+typename HashTraits<N>::ResultType hash_update(typename HashTraits<N>::HashType result, const std::string &str)
+{ return hash_update<N>(result, str.data(), str.size()); }
+
+// For some reason this causes an ambiguity error without the enable_if.
+template<unsigned N, typename T>
+typename std::enable_if<!std::is_same<T, std::string>::value, typename HashTraits<N>::ResultType>::type hash_update(typename HashTraits<N>::HashType result, const T &obj)
+{ return hash_update<N>(result, &obj, sizeof(obj)); }
/**
Manually folds a hash to a smaller size.
typename HashTraits<N>::ResultType hash(const void *data, std::size_t size)
{
constexpr unsigned hash_bits = std::numeric_limits<typename HashTraits<N>::HashType>::digits;
- constexpr typename HashTraits<N>::HashType prime = HashTraits<hash_bits>::prime;
- typename HashTraits<N>::HashType result = HashTraits<hash_bits>::offset;
- for(unsigned i=0; i<size; ++i)
- result = (result^*(reinterpret_cast<const unsigned char *>(data)+i))*prime;
+ typename HashTraits<N>::HashType result = hash_update<hash_bits>(HashTraits<hash_bits>::offset, data, size);
if(HashTraits<N>::folded)
result = hash_fold<N>(result);
return result;
typename HashTraits<N>::ResultType hash(const std::string &str)
{ return hash<N>(str.data(), str.size()); }
+/**
+Convenience function to compute an N-bit hash of any object. The entire object
+representation is hashed, including any padding bytes.
+*/
+template<unsigned N, typename T>
+typename HashTraits<N>::ResultType hash(const T &obj)
+{ return hash<N>(&obj, sizeof(obj)); }
+
} // namespace Msp
#endif