Fix the hash computation in chunks so large files can be hashed without problems.

This commit is contained in:
King_DuckZ 2014-09-24 17:59:08 +02:00
parent 905fbcc905
commit 34f3fbf852
2 changed files with 66 additions and 24 deletions

31
main.d
View file

@ -5,6 +5,9 @@ import std.file;
import std.algorithm;
extern(C) void tiger (char* parMessage, ulong parLength, out ulong[3] parOut, char parPadding);
extern(C) void tiger_init (out ulong[3] parOut);
extern(C) void tiger_chunk (char* parMessage, ulong parLength, out ulong[3] parOut);
extern(C) void tiger_last_chunk (char* parMessage, ulong parBuffLength, ulong parTotalLength, out ulong[3] parOut, char parPadding);
ulong swapLong (ulong parNum) {
parNum = (parNum & 0x00000000FFFFFFFF) << 32 | (parNum & 0xFFFFFFFF00000000) >> 32;
@ -29,21 +32,35 @@ ulong[3] getTiger (in string parData, bool parV2) {
}
ulong[3] getTiger (ref File parData, bool parV2) {
const auto buff_length = 8192;
ubyte[] unaligned = new ubyte[buff_length + ulong.alignof - 1];
const auto buff_length = 64 * 128;
char[] unaligned = new char[buff_length + ulong.alignof - 1];
size_t offset = ((cast(size_t)unaligned.ptr + (ulong.alignof - 1)) & ~cast(size_t)(ulong.alignof - 1)) - cast(size_t)unaligned.ptr;
assert(offset >= 0 && offset < ulong.alignof);
const char padding = (parV2 ? 0x80 : 0x01);
assert(offset + buff_length <= unaligned.length);
ubyte[] aligned = unaligned[offset .. buff_length];
char[] aligned = unaligned[offset .. buff_length];
assert(aligned.length == buff_length);
ulong[3] retval;
foreach (ubyte[] buff; parData.byChunk(aligned)) {
assert((cast(size_t)buff.ptr & cast(size_t)(ulong.alignof - 1)) == 0);
tiger((cast(char[])buff).ptr, buff.length, retval, padding);
auto data_left = parData.size;
tiger_init(retval);
while (data_left >= buff_length) {
parData.rawRead(aligned);
tiger_chunk(aligned.ptr, buff_length, retval);
data_left -= buff_length;
}
const char padding = (parV2 ? 0x80 : 0x01);
if (data_left) {
parData.rawRead(aligned[0 .. data_left]);
const ulong proc_length = data_left & ~0x3fUL;
tiger_chunk(aligned.ptr, proc_length, retval);
tiger_last_chunk(aligned.ptr + proc_length, data_left - proc_length, parData.size, retval, padding);
}
else {
tiger_last_chunk(null, 0, parData.size, retval, padding);
}
return retval;
}

59
tiger.c
View file

@ -27,6 +27,11 @@ typedef unsigned char byte;
extern word64 table[4*256];
union RawAccessULL4 {
word64 ull[8];
unsigned char raw[64];
};
#define t1 (table)
#define t2 (table+256)
#define t3 (table+256*2)
@ -125,7 +130,6 @@ extern word64 table[4*256];
register word64 a, b, c, tmpa; \
word64 aa, bb, cc; \
register word64 x0, x1, x2, x3, x4, x5, x6, x7; \
register word32 i; \
int pass_no; \
\
a = state[0]; \
@ -143,7 +147,7 @@ extern word64 table[4*256];
}
/* The compress function is a function. Requires smaller cache? */
tiger_compress(word64 *str, word64 state[3])
void tiger_compress(word64 *str, word64 state[3])
{
tiger_compress_macro(((word64*)str), ((word64*)state));
}
@ -156,14 +160,20 @@ tiger_compress(word64 *str, word64 state[3])
tiger_compress_macro(((word64*)str), ((word64*)state))
#endif
tiger(word64 *str, word64 length, word64 res[3], byte pad)
void tiger_init(word64 res[3])
{
register word64 i, j;
unsigned char temp[64];
res[0]=0x0123456789ABCDEFLL;
res[1]=0xFEDCBA9876543210LL;
res[2]=0xF096A5B4C3B2E187LL;
}
void tiger_chunk(word64 *str, word64 length, word64 res[3])
{
register word64 i;
#ifdef BIG_ENDIAN
register word64 j;
unsigned char temp[64];
#endif
for(i=length; i>=64; i-=64)
{
@ -176,33 +186,48 @@ tiger(word64 *str, word64 length, word64 res[3], byte pad)
#endif
str += 8;
}
}
void tiger_last_chunk(word64 *str, word64 length, word64 reallength, word64 res[3], byte pad)
{
const word64 i = length & 0x3f;
register word64 j;
union RawAccessULL4 temp;
#ifdef BIG_ENDIAN
for(j=0; j<i; j++)
temp[j^7] = ((byte*)str)[j];
temp.raw[j^7] = ((byte*)str)[j];
temp[j^7] = pad;
temp.raw[j^7] = pad;
j++;
for(; j&7; j++)
temp[j^7] = 0;
temp.raw[j^7] = 0;
#else
for(j=0; j<i; j++)
temp[j] = ((byte*)str)[j];
temp.raw[j] = ((byte*)str)[j];
temp[j++] = pad;
temp.raw[j++] = pad;
for(; j&7; j++)
temp[j] = 0;
temp.raw[j] = 0;
#endif
if(j>56)
{
for(; j<64; j++)
temp[j] = 0;
tiger_compress(((word64*)temp), res);
temp.raw[j] = 0;
tiger_compress((temp.ull), res);
j=0;
}
for(; j<56; j++)
temp[j] = 0;
((word64*)(&(temp[56])))[0] = ((word64)length)<<3;
tiger_compress(((word64*)temp), res);
temp.raw[j] = 0;
temp.ull[7] = reallength<<3;
tiger_compress((temp.ull), res);
}
void tiger(word64 *str, word64 length, word64 res[3], byte pad)
{
const word64 proc_length = length & ~0x3fULL;
tiger_init(res);
tiger_chunk(str, proc_length, res);
tiger_last_chunk(str + (proc_length / 8), length - proc_length, length, res, pad);
}