private void Absorb(byte[] data, int off, long databitlen)
{
long i, j, wholeBlocks;
if ((bitsInQueue % 8) != 0)
{
throw new InvalidOperationException("attempt to absorb with odd length queue.");
}
if (squeezing)
{
throw new InvalidOperationException("attempt to absorb while squeezing.");
}
i = 0;
while (i < databitlen)
{
if ((bitsInQueue == 0) && (databitlen >= rate) && (i <= (databitlen - rate)))
{
wholeBlocks = (databitlen - i) / rate;
for (j = 0; j < wholeBlocks; j++)
{
Array.Copy(data, (int)(off + (i / 8) + (j * chunk.Length)), chunk, 0, chunk.Length);
//displayIntermediateValues.displayBytes(1, "Block to be absorbed", curData, rate / 8);
KeccakAbsorb(state, chunk, chunk.Length);
}
i += wholeBlocks * rate;
}
else
{
int partialBlock = (int)(databitlen - i);
if (partialBlock + bitsInQueue > rate)
{
partialBlock = rate - bitsInQueue;
}
int partialByte = partialBlock % 8;
partialBlock -= partialByte;
Array.Copy(data, off + (int)(i / 8), dataQueue, bitsInQueue / 8, partialBlock / 8);
bitsInQueue += partialBlock;
i += partialBlock;
if (bitsInQueue == rate)
{
AbsorbQueue();
}
if (partialByte > 0)
{
int mask = (1 << partialByte) - 1;
dataQueue[bitsInQueue / 8] = (byte)(data[off + ((int)(i / 8))] & mask);
bitsInQueue += partialByte;
i += partialByte;
}
}
}
}