--- /dev/null
+#ifndef MSP_CRYPTO_BLOCKHASH_H_
+#define MSP_CRYPTO_BLOCKHASH_H_
+
+#include <algorithm>
+#include "hash.h"
+
+namespace Msp {
+namespace Crypto {
+
+template<unsigned B>
+class BlockHash: public Hash
+{
+protected:
+ enum
+ {
+ BLOCK_SIZE = B
+ };
+
+ char unprocessed[BLOCK_SIZE];
+ unsigned unprocessed_bytes;
+
+ BlockHash();
+
+public:
+ using Hash::update;
+ virtual void update(const char *, unsigned);
+
+protected:
+ virtual void process_block(const char *) = 0;
+};
+
+
+template<unsigned B>
+inline BlockHash<B>::BlockHash():
+ unprocessed_bytes(0)
+{ }
+
+template<unsigned B>
+void BlockHash<B>::update(const char *data, unsigned len)
+{
+ if(unprocessed_bytes && unprocessed_bytes+len>=BLOCK_SIZE)
+ {
+ unsigned needed = BLOCK_SIZE-unprocessed_bytes;
+ std::copy(data, data+needed, unprocessed+unprocessed_bytes);
+ process_block(unprocessed);
+ data += needed;
+ len -= needed;
+ unprocessed_bytes = 0;
+ }
+
+ while(len>=BLOCK_SIZE)
+ {
+ process_block(data);
+ data += BLOCK_SIZE;
+ len -= BLOCK_SIZE;
+ }
+
+ if(len>0)
+ {
+ std::copy(data, data+len, unprocessed+unprocessed_bytes);
+ unprocessed_bytes += len;
+ }
+}
+
+} // namespace Crypto
+} // namespace Msp
+
+#endif