Please help me convert C code from this:
Please help me convert C code from this:
const ULONG length = MOV_make_string2(tdbb, value, value->getTextType(), &address, buffer, false);
for (const UCHAR* end = address + length; address < end; ++address)
{
impure->vlu_misc.vlu_int64 = (impure->vlu_misc.vlu_int64 << 4) + *address;
const SINT64 n = impure->vlu_misc.vlu_int64 & CONST64(0xF000000000000000);
if (n)
impure->vlu_misc.vlu_int64 ^= n >> 56;
impure->vlu_misc.vlu_int64 &= ~n;
}
where vlu_int64 is SINT64, address is UCHAR*.
This is C implementation of HASH function from Firebird.
My implementation "almost" works:
var
s : AnsiString;
b : Byte;
h : Int64; //result hash
n : Int64;
i : Integer;
begin
h := 0;
s := trim(mmo1.text);
for i := 1 to Length(s) do
begin
b := Byte(s[i]);
h := Int64(h shl 4)) + b;
n := Int64(h and Int64($F000000000000000));
if n > 0 then
begin
h := Int64(h xor Int64(n shr 56)));
end;
h := Int64(h and Int64(not n));
end;
end;
For short string result is compatible with FB hash, but when h value is big then result is bad.
What I'm doing wrong?
const ULONG length = MOV_make_string2(tdbb, value, value->getTextType(), &address, buffer, false);
for (const UCHAR* end = address + length; address < end; ++address)
{
impure->vlu_misc.vlu_int64 = (impure->vlu_misc.vlu_int64 << 4) + *address;
const SINT64 n = impure->vlu_misc.vlu_int64 & CONST64(0xF000000000000000);
if (n)
impure->vlu_misc.vlu_int64 ^= n >> 56;
impure->vlu_misc.vlu_int64 &= ~n;
}
where vlu_int64 is SINT64, address is UCHAR*.
This is C implementation of HASH function from Firebird.
My implementation "almost" works:
var
s : AnsiString;
b : Byte;
h : Int64; //result hash
n : Int64;
i : Integer;
begin
h := 0;
s := trim(mmo1.text);
for i := 1 to Length(s) do
begin
b := Byte(s[i]);
h := Int64(h shl 4)) + b;
n := Int64(h and Int64($F000000000000000));
if n > 0 then
begin
h := Int64(h xor Int64(n shr 56)));
end;
h := Int64(h and Int64(not n));
end;
end;
For short string result is compatible with FB hash, but when h value is big then result is bad.
What I'm doing wrong?
if (n) means if n <> 0
ReplyDeleteeither inline asm and use sar or div 2^56
I change code to:
ReplyDeletefor i := 1 to Length(s) do
begin
b := Byte(s[i]);
h := Int64((Int64(h) shl 4) + b);
n := Int64(Int64(h) and Int64($F000000000000000));
if n <> 0 then
begin
h := Int64(Int64(h) xor (h div Int64(Int64(2) shl 56)));
end;
h := Int64(h and Int64(not Int64(n)));
end;
...but I still get incorrect result on long strings.
this code works properly:
ReplyDeletefor i := 1 to Length(s) do
begin
b := Byte(s[i]);
h := Int64((Int64(h) shl 4) + b);
n := Int64(Int64(h) and Int64($F000000000000000));
if n <> 0 then
begin
h := Int64(Int64(h) xor ((n shr 56) or ((0 - ((n shr 63) and 1)) shl 8)));
end;
h := Int64(h and Int64(not Int64(n)));
end;