+/**
+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)); }