template <class T, class BASE> byte * IteratedHashBase<T, BASE>::CreateUpdateSpace(size_t &size) { unsigned int blockSize = this->BlockSize(); unsigned int num = ModPowerOf2(m_countLo, blockSize); size = blockSize - num; return (byte *)DataBuf() + num; }
inline T1 RoundDownToMultipleOf(const T1 &n, const T2 &m) { if (IsPowerOf2(m)) return n - ModPowerOf2(n, m); else return n - n%m; }
template <class T, class BASE> void IteratedHashBase<T, BASE>::Update(const byte *input, size_t len) { HashWordType oldCountLo = m_countLo, oldCountHi = m_countHi; if ((m_countLo = oldCountLo + HashWordType(len)) < oldCountLo) m_countHi++; // carry from low to high m_countHi += (HashWordType)SafeRightShift<8*sizeof(HashWordType)>(len); if (m_countHi < oldCountHi || SafeRightShift<2*8*sizeof(HashWordType)>(len) != 0) throw HashInputTooLong(this->AlgorithmName()); unsigned int blockSize = this->BlockSize(); unsigned int num = ModPowerOf2(oldCountLo, blockSize); T* dataBuf = this->DataBuf(); byte* data = (byte *)dataBuf; if (num != 0) // process left over data { if (num+len >= blockSize) { memcpy(data+num, input, blockSize-num); HashBlock(dataBuf); input += (blockSize-num); len -= (blockSize-num); num = 0; // drop through and do the rest } else { memcpy(data+num, input, len); return; } } // now process the input data in blocks of blockSize bytes and save the leftovers to m_data if (len >= blockSize) { if (input == data) { assert(len == blockSize); HashBlock(dataBuf); return; } else if (IsAligned<T>(input)) { size_t leftOver = HashMultipleBlocks((T *)input, len); input += (len - leftOver); len = leftOver; } else do { // copy input first if it's not aligned correctly memcpy(data, input, blockSize); HashBlock(dataBuf); input+=blockSize; len-=blockSize; } while (len >= blockSize); } if (len && data != input) memcpy(data, input, len); }
template <class T, class BASE> byte * IteratedHashBase<T, BASE>::CreateUpdateSpace(unsigned int &size) { unsigned int blockSize = BlockSize(); unsigned int num = ModPowerOf2(m_countLo, blockSize); size = blockSize - num; return (byte *)m_data.begin() + num; }
template <class T, class BASE> void IteratedHashBase<T, BASE>::Update(const byte *input, unsigned int len) { HashWordType tmp = m_countLo; if ((m_countLo = tmp + len) < tmp) m_countHi++; // carry from low to high m_countHi += SafeRightShift<8*sizeof(HashWordType)>(len); unsigned int blockSize = BlockSize(); unsigned int num = ModPowerOf2(tmp, blockSize); if (num != 0) // process left over data { if ((num+len) >= blockSize) { memcpy((byte *)m_data.begin()+num, input, blockSize-num); HashBlock(m_data); input += (blockSize-num); len-=(blockSize - num); num=0; // drop through and do the rest } else { memcpy((byte *)m_data.begin()+num, input, len); return; } } // now process the input data in blocks of blockSize bytes and save the leftovers to m_data if (len >= blockSize) { if (input == (byte *)m_data.begin()) { assert(len == blockSize); HashBlock(m_data); return; } else if (IsAligned<T>(input)) { unsigned int leftOver = HashMultipleBlocks((T *)input, len); input += (len - leftOver); len = leftOver; } else do { // copy input first if it's not aligned correctly memcpy(m_data, input, blockSize); HashBlock(m_data); input+=blockSize; len-=blockSize; } while (len >= blockSize); } memcpy(m_data, input, len); }
template <class T, class BASE> void IteratedHashBase<T, BASE>::PadLastBlock(unsigned int lastBlockSize, byte padFirst) { unsigned int blockSize = BlockSize(); unsigned int num = ModPowerOf2(m_countLo, blockSize); ((byte *)m_data.begin())[num++]=padFirst; if (num <= lastBlockSize) memset((byte *)m_data.begin()+num, 0, lastBlockSize-num); else { memset((byte *)m_data.begin()+num, 0, blockSize-num); HashBlock(m_data); memset(m_data, 0, lastBlockSize); } }
template <class T, class BASE> void IteratedHashBase<T, BASE>::PadLastBlock(unsigned int lastBlockSize, byte padFirst) { unsigned int blockSize = this->BlockSize(); unsigned int num = ModPowerOf2(m_countLo, blockSize); T* dataBuf = this->DataBuf(); byte* data = (byte *)dataBuf; data[num++] = padFirst; if (num <= lastBlockSize) memset(data+num, 0, lastBlockSize-num); else { memset(data+num, 0, blockSize-num); HashBlock(dataBuf); memset(data, 0, lastBlockSize); } }
inline bool IsAlignedOn(const void *p, unsigned int alignment) { return alignment==1 || (IsPowerOf2(alignment) ? ModPowerOf2((size_t)p, alignment) == 0 : (size_t)p % alignment == 0); }