]> git.tdb.fi Git - libs/core.git/commitdiff
Add some more hash utility functions
authorMikko Rasa <tdb@tdb.fi>
Wed, 17 Nov 2021 12:15:18 +0000 (14:15 +0200)
committerMikko Rasa <tdb@tdb.fi>
Thu, 18 Nov 2021 00:23:36 +0000 (02:23 +0200)
source/core/hash.h

index a7e8cb165722cf7aa38aac417d97c21d2abd5004..e2201cf22110280172828fff9021d4e1daa36036 100644 (file)
@@ -62,6 +62,38 @@ struct HashTraits<N, 3>
        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.
@@ -86,10 +118,7 @@ template<unsigned N>
 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;
@@ -102,6 +131,14 @@ template<unsigned N>
 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