Fix the hash computation in chunks so large files can be hashed without problems.
This commit is contained in:
parent
905fbcc905
commit
34f3fbf852
2 changed files with 66 additions and 24 deletions
31
main.d
31
main.d
|
@ -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
59
tiger.c
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue