lazarus/components/sparta/generics/source/generics.hashes.pas
hnb d53cfa9c28 Merged revision(s) 51414, 51448-51450, 51468, 51473, 51477, 51480, 51483, 51486, 51511, 51543-51544, 51638, 52714, 52725-52727 from branches/free-sparta:
sparta: initial commit of "compilable" new sparta package - smart form editor. !NOTE: not for daily usage.
........
sparta: Initial conception for package for MDI: sparta_MDI. Base for sparta_DockedFormEditor package.
........
sparta: Generics.Collections library ( sync with https://github.com/dathox/generics.collections SHA fda586932bd80ef58c08f8ebf5a24316ca4ccca5)
........
sparta: smart form editor adjustment for new sparta_MDI
........
sparta: new class "TFormImpl" for MDI solution (created from TDesignedFormImpl). 
........
sparta: 
-MDI form container "TFormContainer"
-New IResizeFrame interface to handle MDI form moving
-New frame TfrFormBackgroundForMDI
........
sparta: sparta_MDI package modifications:
-new class TMultiplyResizer to menage MDI desktop
-more generic resizer: TAbstractResizer. Base for IDE resizer and TMultiplyResizer
-more advanced IResizeFrame interface


........
sparta: 
-DockedFormEditor adjustment for latest changes in mdi package
-small changes in mdi (visibility of methods).
-OnModified method for IResizeFrame

........
sparta: MDI
-simulate MDI forms order for TMultiplyResizer
-property DesignedForm: IDesignedForm for IResizeFrame
........
sparta:
-IMPORTANT! pixel perfect form resizing (fix for problems for controls with align alLeft, alRight etc on design form).
-Fix problem for windows: wrong design design window width (a little bigger than designed size) TFormImpl.SetRealBounds -> AdjustSize
........
sparta: mdi bug fix for AV in TMultiplyResizer
........
Fix compilation for FPC 3.0 (TRect changes in FPC 3.1 trunk)
........
sparta: Cannot resize the docked form designer, issue #29380 patch from Anthony Walter. Thanks!
........
sparta ToolsAPI: Delphi compatible ToolsAPI/DesignIDE interface at XE2 level (proxy for IDEIntf). Initial commit (no functionality yet), just interfaces and classes without implementation:

designeditors.pas:
-TComponentEditor

designintf.pas:
-Interfaces: IEventInfo, IClass, IActivatable, IDesignObject, IDesignPersistent, IDesignerSelections, IDesigner60, IDesigner70, IDesigner80, IDesigner100, IDesigner, IComponentEditor
-TBaseComponentEditor
-RegisterComponentEditor

designmenus.pas:
-Interfaces: IMenuItems, IMenu, IMainMenu, IPopupMenu, IMenuItem

 
 


........
when form is removed we need to remove all handlers located in collections FFormsStack and FForms. Necessary to avoid AV.
........
sparta: more correct and simpler calculation of form border for Windows
........
sparta: 
  * Fix for loop error for resize. Highly visible problem for docked forms/frames with Align=alClient. 
  * New THookFrame class as new meta class for Frames.
........
updated lpl
........

git-svn-id: trunk@52728 -
2016-07-20 10:40:03 +00:00

916 lines
24 KiB
ObjectPascal

{
This file is part of the Free Pascal run time library.
Copyright (c) 2014 by Maciej Izak (hnb)
member of the Free Sparta development team (http://freesparta.com)
Copyright(c) 2004-2014 DaThoX
It contains the Free Pascal generics library
See the file COPYING.FPC, included in this distribution,
for details about the copyright.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
**********************************************************************}
unit Generics.Hashes;
{$MODE DELPHI}{$H+}
{$POINTERMATH ON}
{$MACRO ON}
{$COPERATORS ON}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
interface
uses
Classes, SysUtils;
// Original version of Bob Jenkins Hash
// http://burtleburtle.net/bob/c/lookup3.c
function HashWord(
AKey: PLongWord; //* the key, an array of uint32_t values */
ALength: SizeInt; //* the length of the key, in uint32_ts */
AInitVal: UInt32): UInt32; //* the previous hash, or an arbitrary value */
procedure HashWord2 (
AKey: PLongWord; //* the key, an array of uint32_t values */
ALength: SizeInt; //* the length of the key, in uint32_ts */
var APrimaryHashAndInitVal: UInt32; //* IN: seed OUT: primary hash value */
var ASecondaryHashAndInitVal: UInt32); //* IN: more seed OUT: secondary hash value */
function HashLittle(AKey: Pointer; ALength: SizeInt; AInitVal: UInt32): UInt32;
procedure HashLittle2(
AKey: Pointer; //* the key to hash */
ALength: SizeInt; //* length of the key */
var APrimaryHashAndInitVal: UInt32; //* IN: primary initval, OUT: primary hash */
var ASecondaryHashAndInitVal: UInt32); //* IN: secondary initval, OUT: secondary hash */
function DelphiHashLittle(AKey: Pointer; ALength: SizeInt; AInitVal: UInt32): Int32;
procedure DelphiHashLittle2(AKey: Pointer; ALength: SizeInt; var APrimaryHashAndInitVal, ASecondaryHashAndInitVal: UInt32);
// hash function from fstl
function SimpleChecksumHash(AKey: Pointer; ALength: SizeInt): UInt32;
// some other hashes
// http://stackoverflow.com/questions/14409466/simple-hash-functions
// http://www.partow.net/programming/hashfunctions/
// http://en.wikipedia.org/wiki/List_of_hash_functions
// http://www.cse.yorku.ca/~oz/hash.html
// https://code.google.com/p/hedgewars/source/browse/hedgewars/adler32.pas
function Adler32(AKey: Pointer; ALength: SizeInt): UInt32;
function sdbm(AKey: Pointer; ALength: SizeInt): UInt32;
implementation
function SimpleChecksumHash(AKey: Pointer; ALength: SizeInt): UInt32;
var
i: Integer;
ABuffer: PUInt8 absolute AKey;
begin
Result := 0;
for i := 0 to ALength - 1 do
Inc(Result,ABuffer[i]);
end;
function Adler32(AKey: Pointer; ALength: SizeInt): UInt32;
const
MOD_ADLER = 65521;
var
ABuffer: PUInt8 absolute AKey;
a: UInt32 = 1;
b: UInt32 = 0;
n: Integer;
begin
for n := 0 to ALength -1 do
begin
a := (a + ABuffer[n]) mod MOD_ADLER;
b := (b + a) mod MOD_ADLER;
end;
Result := (b shl 16) or a;
end;
function sdbm(AKey: Pointer; ALength: SizeInt): UInt32;
var
c: PUInt8 absolute AKey;
i: Integer;
begin
Result := 0;
c := AKey;
for i := 0 to ALength - 1 do
begin
Result := c^ + (Result shl 6) + (Result shl 16) {%H-}- Result;
Inc(c);
end;
end;
{ BobJenkinsHash }
{$define mix_abc :=
a -= c; a := a xor (((c)shl(4)) or ((c)shr(32-(4)))); c += b;
b -= a; b := b xor (((a)shl(6)) or ((a)shr(32-(6)))); a += c;
c -= b; c := c xor (((b)shl(8)) or ((b)shr(32-(8)))); b += a;
a -= c; a := a xor (((c)shl(16)) or ((c)shr(32-(16)))); c += b;
b -= a; b := b xor (((a)shl(19)) or ((a)shr(32-(19)))); a += c;
c -= b; c := c xor (((b)shl(4)) or ((b)shr(32-(4)))); b += a
}
{$define final_abc :=
c := c xor b; c -= (((b)shl(14)) or ((b)shr(32-(14))));
a := a xor c; a -= (((c)shl(11)) or ((c)shr(32-(11))));
b := b xor a; b -= (((a)shl(25)) or ((a)shr(32-(25))));
c := c xor b; c -= (((b)shl(16)) or ((b)shr(32-(16))));
a := a xor c; a -= (((c)shl(4)) or ((c)shr(32-(4))));
b := b xor a; b -= (((a)shl(14)) or ((a)shr(32-(14))));
c := c xor b; c -= (((b)shl(24)) or ((b)shr(32-(24))))
}
function HashWord(
AKey: PLongWord; //* the key, an array of uint32_t values */
ALength: SizeInt; //* the length of the key, in uint32_ts */
AInitVal: UInt32): UInt32; //* the previous hash, or an arbitrary value */
var
a,b,c: UInt32;
label
Case0, Case1, Case2, Case3;
begin
//* Set up the internal state */
a := $DEADBEEF + (UInt32(ALength) shl 2) + AInitVal;
b := a;
c := b;
//*------------------------------------------------- handle most of the key */
while ALength > 3 do
begin
a += AKey[0];
b += AKey[1];
c += AKey[2];
mix_abc;
ALength -= 3;
AKey += 3;
end;
//*------------------------------------------- handle the last 3 uint32_t's */
case ALength of //* all the case statements fall through */
3: goto Case3;
2: goto Case2;
1: goto Case1;
0: goto Case0;
end;
Case3: c+=AKey[2];
Case2: b+=AKey[1];
Case1: a+=AKey[0];
final_abc;
Case0: //* case 0: nothing left to add */
//*------------------------------------------------------ report the result */
Result := c;
end;
procedure HashWord2 (
AKey: PLongWord; //* the key, an array of uint32_t values */
ALength: SizeInt; //* the length of the key, in uint32_ts */
var APrimaryHashAndInitVal: UInt32; //* IN: seed OUT: primary hash value */
var ASecondaryHashAndInitVal: UInt32); //* IN: more seed OUT: secondary hash value */
var
a,b,c: UInt32;
label
Case0, Case1, Case2, Case3;
begin
//* Set up the internal state */
a := $deadbeef + (UInt32(ALength shl 2)) + APrimaryHashAndInitVal;
b := a;
c := b;
c += ASecondaryHashAndInitVal;
//*------------------------------------------------- handle most of the key */
while ALength > 3 do
begin
a += AKey[0];
b += AKey[1];
c += AKey[2];
mix_abc;
ALength -= 3;
AKey += 3;
end;
//*------------------------------------------- handle the last 3 uint32_t's */
case ALength of //* all the case statements fall through */
3: goto Case3;
2: goto Case2;
1: goto Case1;
0: goto Case0;
end;
Case3: c+=AKey[2];
Case2: b+=AKey[1];
Case1: a+=AKey[0];
final_abc;
Case0: //* case 0: nothing left to add */
//*------------------------------------------------------ report the result */
APrimaryHashAndInitVal := c;
ASecondaryHashAndInitVal := b;
end;
function HashLittle(AKey: Pointer; ALength: SizeInt; AInitVal: UInt32): UInt32;
var
a, b, c: UInt32;
u: record case byte of
0: (ptr: Pointer);
1: (i: PtrUint);
end absolute AKey;
k32: ^UInt32 absolute AKey;
k16: ^UInt16 absolute AKey;
k8: ^UInt8 absolute AKey;
label _10, _8, _6, _4, _2;
label Case12, Case11, Case10, Case9, Case8, Case7, Case6, Case5, Case4, Case3, Case2, Case1;
begin
a := $DEADBEEF + UInt32(ALength) + AInitVal;
b := a;
c := b;
{$IFDEF ENDIAN_LITTLE}
if (u.i and $3) = 0 then
begin
while (ALength > 12) do
begin
a += k32[0];
b += k32[1];
c += k32[2];
mix_abc;
ALength -= 12;
k32 += 3;
end;
case ALength of
12: begin c += k32[2]; b += k32[1]; a += k32[0]; end;
11: begin c += k32[2] and $ffffff; b += k32[1]; a += k32[0]; end;
10: begin c += k32[2] and $ffff; b += k32[1]; a += k32[0]; end;
9 : begin c += k32[2] and $ff; b += k32[1]; a += k32[0]; end;
8 : begin b += k32[1]; a += k32[0]; end;
7 : begin b += k32[1] and $ffffff; a += k32[0]; end;
6 : begin b += k32[1] and $ffff; a += k32[0]; end;
5 : begin b += k32[1] and $ff; a += k32[0]; end;
4 : begin a += k32[0]; end;
3 : begin a += k32[0] and $ffffff; end;
2 : begin a += k32[0] and $ffff; end;
1 : begin a += k32[0] and $ff; end;
0 : Exit(c); // zero length strings require no mixing
end
end
else
if (u.i and $1) = 0 then
begin
while (ALength > 12) do
begin
a += k16[0] + (UInt32(k16[1]) shl 16);
b += k16[2] + (UInt32(k16[3]) shl 16);
c += k16[4] + (UInt32(k16[5]) shl 16);
mix_abc;
ALength -= 12;
k16 += 6;
end;
case ALength of
12:
begin
c+=k16[4]+((UInt32(k16[5])) shl 16);
b+=k16[2]+((UInt32(k16[3])) shl 16);
a+=k16[0]+((UInt32(k16[1])) shl 16);
end;
11:
begin
c+=(UInt32(k8[10])) shl 16; //* fall through */
goto _10;
end;
10:
begin _10:
c+=k16[4];
b+=k16[2]+((UInt32(k16[3])) shl 16);
a+=k16[0]+((UInt32(k16[1])) shl 16);
end;
9 :
begin
c+=k8[8]; //* fall through */
goto _8;
end;
8 :
begin _8:
b+=k16[2]+((UInt32(k16[3])) shl 16);
a+=k16[0]+((UInt32(k16[1])) shl 16);
end;
7 :
begin
b+=(UInt32(k8[6])) shl 16; //* fall through */
goto _6;
end;
6 :
begin _6:
b+=k16[2];
a+=k16[0]+((UInt32(k16[1])) shl 16);
end;
5 :
begin
b+=k8[4]; //* fall through */
goto _4;
end;
4 :
begin _4:
a+=k16[0]+((UInt32(k16[1])) shl 16);
end;
3 :
begin
a+=(UInt32(k8[2])) shl 16; //* fall through */
goto _2;
end;
2 :
begin _2:
a+=k16[0];
end;
1 :
begin
a+=k8[0];
end;
0 : Exit(c); //* zero length requires no mixing */
end;
end
else
{$ENDIF}
begin
while ALength > 12 do
begin
a += k8[0];
a += (UInt32(k8[1])) shl 8;
a += (UInt32(k8[2])) shl 16;
a += (UInt32(k8[3])) shl 24;
b += k8[4];
b += (UInt32(k8[5])) shl 8;
b += (UInt32(k8[6])) shl 16;
b += (UInt32(k8[7])) shl 24;
c += k8[8];
c += (UInt32(k8[9])) shl 8;
c += (UInt32(k8[10])) shl 16;
c += (UInt32(k8[11])) shl 24;
mix_abc;
ALength -= 12;
k8 += 12;
end;
case ALength of
12: goto Case12;
11: goto Case11;
10: goto Case10;
9 : goto Case9;
8 : goto Case8;
7 : goto Case7;
6 : goto Case6;
5 : goto Case5;
4 : goto Case4;
3 : goto Case3;
2 : goto Case2;
1 : goto Case1;
0 : Exit(c);
end;
Case12: c+=(UInt32(k8[11])) shl 24;
Case11: c+=(UInt32(k8[10])) shl 16;
Case10: c+=(UInt32(k8[9])) shl 8;
Case9: c+=k8[8];
Case8: b+=(UInt32(k8[7])) shl 24;
Case7: b+=(UInt32(k8[6])) shl 16;
Case6: b+=(UInt32(k8[5])) shl 8;
Case5: b+=k8[4];
Case4: a+=(UInt32(k8[3])) shl 24;
Case3: a+=(UInt32(k8[2])) shl 16;
Case2: a+=(UInt32(k8[1])) shl 8;
Case1: a+=k8[0];
end;
final_abc;
Result := c;
end;
(*
* hashlittle2: return 2 32-bit hash values
*
* This is identical to hashlittle(), except it returns two 32-bit hash
* values instead of just one. This is good enough for hash table
* lookup with 2^^64 buckets, or if you want a second hash if you're not
* happy with the first, or if you want a probably-unique 64-bit ID for
* the key. *pc is better mixed than *pb, so use *pc first. If you want
* a 64-bit value do something like "*pc + (((uint64_t)*pb)<<32)".
*)
procedure HashLittle2(
AKey: Pointer; //* the key to hash */
ALength: SizeInt; //* length of the key */
var APrimaryHashAndInitVal: UInt32; //* IN: primary initval, OUT: primary hash */
var ASecondaryHashAndInitVal: UInt32); //* IN: secondary initval, OUT: secondary hash */
var
a,b,c: UInt32;
u: record case byte of
0: (ptr: Pointer);
1: (i: PtrUint);
end absolute AKey;
k32: ^UInt32 absolute AKey;
k16: ^UInt16 absolute AKey;
k8: ^UInt8 absolute AKey;
label _10, _8, _6, _4, _2;
label Case12, Case11, Case10, Case9, Case8, Case7, Case6, Case5, Case4, Case3, Case2, Case1;
begin
//* Set up the internal state */
a := $DEADBEEF + UInt32(ALength) + APrimaryHashAndInitVal;
b := a;
c := b;
c += ASecondaryHashAndInitVal;
{$IFDEF ENDIAN_LITTLE}
if (u.i and $3) = 0 then
begin
while (ALength > 12) do
begin
a += k32[0];
b += k32[1];
c += k32[2];
mix_abc;
ALength -= 12;
k32 += 3;
end;
case ALength of
12: begin c += k32[2]; b += k32[1]; a += k32[0]; end;
11: begin c += k32[2] and $ffffff; b += k32[1]; a += k32[0]; end;
10: begin c += k32[2] and $ffff; b += k32[1]; a += k32[0]; end;
9 : begin c += k32[2] and $ff; b += k32[1]; a += k32[0]; end;
8 : begin b += k32[1]; a += k32[0]; end;
7 : begin b += k32[1] and $ffffff; a += k32[0]; end;
6 : begin b += k32[1] and $ffff; a += k32[0]; end;
5 : begin b += k32[1] and $ff; a += k32[0]; end;
4 : begin a += k32[0]; end;
3 : begin a += k32[0] and $ffffff; end;
2 : begin a += k32[0] and $ffff; end;
1 : begin a += k32[0] and $ff; end;
0 :
begin
APrimaryHashAndInitVal := c;
ASecondaryHashAndInitVal := b;
Exit; // zero length strings require no mixing
end;
end
end
else
if (u.i and $1) = 0 then
begin
while (ALength > 12) do
begin
a += k16[0] + (UInt32(k16[1]) shl 16);
b += k16[2] + (UInt32(k16[3]) shl 16);
c += k16[4] + (UInt32(k16[5]) shl 16);
mix_abc;
ALength -= 12;
k16 += 6;
end;
case ALength of
12:
begin
c+=k16[4]+((UInt32(k16[5])) shl 16);
b+=k16[2]+((UInt32(k16[3])) shl 16);
a+=k16[0]+((UInt32(k16[1])) shl 16);
end;
11:
begin
c+=(UInt32(k8[10])) shl 16; //* fall through */
goto _10;
end;
10:
begin _10:
c+=k16[4];
b+=k16[2]+((UInt32(k16[3])) shl 16);
a+=k16[0]+((UInt32(k16[1])) shl 16);
end;
9 :
begin
c+=k8[8]; //* fall through */
goto _8;
end;
8 :
begin _8:
b+=k16[2]+((UInt32(k16[3])) shl 16);
a+=k16[0]+((UInt32(k16[1])) shl 16);
end;
7 :
begin
b+=(UInt32(k8[6])) shl 16; //* fall through */
goto _6;
end;
6 :
begin _6:
b+=k16[2];
a+=k16[0]+((UInt32(k16[1])) shl 16);
end;
5 :
begin
b+=k8[4]; //* fall through */
goto _4;
end;
4 :
begin _4:
a+=k16[0]+((UInt32(k16[1])) shl 16);
end;
3 :
begin
a+=(UInt32(k8[2])) shl 16; //* fall through */
goto _2;
end;
2 :
begin _2:
a+=k16[0];
end;
1 :
begin
a+=k8[0];
end;
0 :
begin
APrimaryHashAndInitVal := c;
ASecondaryHashAndInitVal := b;
Exit; // zero length strings require no mixing
end;
end;
end
else
{$ENDIF}
begin
while ALength > 12 do
begin
a += k8[0];
a += (UInt32(k8[1])) shl 8;
a += (UInt32(k8[2])) shl 16;
a += (UInt32(k8[3])) shl 24;
b += k8[4];
b += (UInt32(k8[5])) shl 8;
b += (UInt32(k8[6])) shl 16;
b += (UInt32(k8[7])) shl 24;
c += k8[8];
c += (UInt32(k8[9])) shl 8;
c += (UInt32(k8[10])) shl 16;
c += (UInt32(k8[11])) shl 24;
mix_abc;
ALength -= 12;
k8 += 12;
end;
case ALength of
12: goto Case12;
11: goto Case11;
10: goto Case10;
9 : goto Case9;
8 : goto Case8;
7 : goto Case7;
6 : goto Case6;
5 : goto Case5;
4 : goto Case4;
3 : goto Case3;
2 : goto Case2;
1 : goto Case1;
0 :
begin
APrimaryHashAndInitVal := c;
ASecondaryHashAndInitVal := b;
Exit; // zero length strings require no mixing
end;
end;
Case12: c+=(UInt32(k8[11])) shl 24;
Case11: c+=(UInt32(k8[10])) shl 16;
Case10: c+=(UInt32(k8[9])) shl 8;
Case9: c+=k8[8];
Case8: b+=(UInt32(k8[7])) shl 24;
Case7: b+=(UInt32(k8[6])) shl 16;
Case6: b+=(UInt32(k8[5])) shl 8;
Case5: b+=k8[4];
Case4: a+=(UInt32(k8[3])) shl 24;
Case3: a+=(UInt32(k8[2])) shl 16;
Case2: a+=(UInt32(k8[1])) shl 8;
Case1: a+=k8[0];
end;
final_abc;
APrimaryHashAndInitVal := c;
ASecondaryHashAndInitVal := b;
end;
procedure DelphiHashLittle2(AKey: Pointer; ALength: SizeInt; var APrimaryHashAndInitVal, ASecondaryHashAndInitVal: UInt32);
var
a,b,c: UInt32;
u: record case byte of
0: (ptr: Pointer);
1: (i: PtrUint);
end absolute AKey;
k32: ^UInt32 absolute AKey;
k16: ^UInt16 absolute AKey;
k8: ^UInt8 absolute AKey;
label _10, _8, _6, _4, _2;
label Case12, Case11, Case10, Case9, Case8, Case7, Case6, Case5, Case4, Case3, Case2, Case1;
begin
//* Set up the internal state */
a := $DEADBEEF + UInt32(ALength shl 2) + APrimaryHashAndInitVal; // delphi version bug? original version don't have "shl 2"
b := a;
c := b;
c += ASecondaryHashAndInitVal;
{$IFDEF ENDIAN_LITTLE}
if (u.i and $3) = 0 then
begin
while (ALength > 12) do
begin
a += k32[0];
b += k32[1];
c += k32[2];
mix_abc;
ALength -= 12;
k32 += 3;
end;
case ALength of
12: begin c += k32[2]; b += k32[1]; a += k32[0]; end;
11: begin c += k32[2] and $ffffff; b += k32[1]; a += k32[0]; end;
10: begin c += k32[2] and $ffff; b += k32[1]; a += k32[0]; end;
9 : begin c += k32[2] and $ff; b += k32[1]; a += k32[0]; end;
8 : begin b += k32[1]; a += k32[0]; end;
7 : begin b += k32[1] and $ffffff; a += k32[0]; end;
6 : begin b += k32[1] and $ffff; a += k32[0]; end;
5 : begin b += k32[1] and $ff; a += k32[0]; end;
4 : begin a += k32[0]; end;
3 : begin a += k32[0] and $ffffff; end;
2 : begin a += k32[0] and $ffff; end;
1 : begin a += k32[0] and $ff; end;
0 :
begin
APrimaryHashAndInitVal := c;
ASecondaryHashAndInitVal := b;
Exit; // zero length strings require no mixing
end;
end
end
else
if (u.i and $1) = 0 then
begin
while (ALength > 12) do
begin
a += k16[0] + (UInt32(k16[1]) shl 16);
b += k16[2] + (UInt32(k16[3]) shl 16);
c += k16[4] + (UInt32(k16[5]) shl 16);
mix_abc;
ALength -= 12;
k16 += 6;
end;
case ALength of
12:
begin
c+=k16[4]+((UInt32(k16[5])) shl 16);
b+=k16[2]+((UInt32(k16[3])) shl 16);
a+=k16[0]+((UInt32(k16[1])) shl 16);
end;
11:
begin
c+=(UInt32(k8[10])) shl 16; //* fall through */
goto _10;
end;
10:
begin _10:
c+=k16[4];
b+=k16[2]+((UInt32(k16[3])) shl 16);
a+=k16[0]+((UInt32(k16[1])) shl 16);
end;
9 :
begin
c+=k8[8]; //* fall through */
goto _8;
end;
8 :
begin _8:
b+=k16[2]+((UInt32(k16[3])) shl 16);
a+=k16[0]+((UInt32(k16[1])) shl 16);
end;
7 :
begin
b+=(UInt32(k8[6])) shl 16; //* fall through */
goto _6;
end;
6 :
begin _6:
b+=k16[2];
a+=k16[0]+((UInt32(k16[1])) shl 16);
end;
5 :
begin
b+=k8[4]; //* fall through */
goto _4;
end;
4 :
begin _4:
a+=k16[0]+((UInt32(k16[1])) shl 16);
end;
3 :
begin
a+=(UInt32(k8[2])) shl 16; //* fall through */
goto _2;
end;
2 :
begin _2:
a+=k16[0];
end;
1 :
begin
a+=k8[0];
end;
0 :
begin
APrimaryHashAndInitVal := c;
ASecondaryHashAndInitVal := b;
Exit; // zero length strings require no mixing
end;
end;
end
else
{$ENDIF}
begin
while ALength > 12 do
begin
a += k8[0];
a += (UInt32(k8[1])) shl 8;
a += (UInt32(k8[2])) shl 16;
a += (UInt32(k8[3])) shl 24;
b += k8[4];
b += (UInt32(k8[5])) shl 8;
b += (UInt32(k8[6])) shl 16;
b += (UInt32(k8[7])) shl 24;
c += k8[8];
c += (UInt32(k8[9])) shl 8;
c += (UInt32(k8[10])) shl 16;
c += (UInt32(k8[11])) shl 24;
mix_abc;
ALength -= 12;
k8 += 12;
end;
case ALength of
12: goto Case12;
11: goto Case11;
10: goto Case10;
9 : goto Case9;
8 : goto Case8;
7 : goto Case7;
6 : goto Case6;
5 : goto Case5;
4 : goto Case4;
3 : goto Case3;
2 : goto Case2;
1 : goto Case1;
0 :
begin
APrimaryHashAndInitVal := c;
ASecondaryHashAndInitVal := b;
Exit; // zero length strings require no mixing
end;
end;
Case12: c+=(UInt32(k8[11])) shl 24;
Case11: c+=(UInt32(k8[10])) shl 16;
Case10: c+=(UInt32(k8[9])) shl 8;
Case9: c+=k8[8];
Case8: b+=(UInt32(k8[7])) shl 24;
Case7: b+=(UInt32(k8[6])) shl 16;
Case6: b+=(UInt32(k8[5])) shl 8;
Case5: b+=k8[4];
Case4: a+=(UInt32(k8[3])) shl 24;
Case3: a+=(UInt32(k8[2])) shl 16;
Case2: a+=(UInt32(k8[1])) shl 8;
Case1: a+=k8[0];
end;
final_abc;
APrimaryHashAndInitVal := c;
ASecondaryHashAndInitVal := b;
end;
function DelphiHashLittle(AKey: Pointer; ALength: SizeInt; AInitVal: UInt32): Int32;
var
a, b, c: UInt32;
u: record case byte of
0: (ptr: Pointer);
1: (i: PtrUint);
end absolute AKey;
k32: ^UInt32 absolute AKey;
//k16: ^UInt16 absolute AKey;
k8: ^UInt8 absolute AKey;
label Case12, Case11, Case10, Case9, Case8, Case7, Case6, Case5, Case4, Case3, Case2, Case1;
begin
a := $DEADBEEF + UInt32(ALength shl 2) + AInitVal; // delphi version bug? original version don't have "shl 2"
b := a;
c := b;
{.$IFDEF ENDIAN_LITTLE} // Delphi version don't care
if (u.i and $3) = 0 then
begin
while (ALength > 12) do
begin
a += k32[0];
b += k32[1];
c += k32[2];
mix_abc;
ALength -= 12;
k32 += 3;
end;
case ALength of
12: begin c += k32[2]; b += k32[1]; a += k32[0]; end;
11: begin c += k32[2] and $ffffff; b += k32[1]; a += k32[0]; end;
10: begin c += k32[2] and $ffff; b += k32[1]; a += k32[0]; end;
9 : begin c += k32[2] and $ff; b += k32[1]; a += k32[0]; end;
8 : begin b += k32[1]; a += k32[0]; end;
7 : begin b += k32[1] and $ffffff; a += k32[0]; end;
6 : begin b += k32[1] and $ffff; a += k32[0]; end;
5 : begin b += k32[1] and $ff; a += k32[0]; end;
4 : begin a += k32[0]; end;
3 : begin a += k32[0] and $ffffff; end;
2 : begin a += k32[0] and $ffff; end;
1 : begin a += k32[0] and $ff; end;
0 : Exit(c); // zero length strings require no mixing
end
end
else
{.$ENDIF}
begin
while ALength > 12 do
begin
a += k8[0];
a += (UInt32(k8[1])) shl 8;
a += (UInt32(k8[2])) shl 16;
a += (UInt32(k8[3])) shl 24;
b += k8[4];
b += (UInt32(k8[5])) shl 8;
b += (UInt32(k8[6])) shl 16;
b += (UInt32(k8[7])) shl 24;
c += k8[8];
c += (UInt32(k8[9])) shl 8;
c += (UInt32(k8[10])) shl 16;
c += (UInt32(k8[11])) shl 24;
mix_abc;
ALength -= 12;
k8 += 12;
end;
case ALength of
12: goto Case12;
11: goto Case11;
10: goto Case10;
9 : goto Case9;
8 : goto Case8;
7 : goto Case7;
6 : goto Case6;
5 : goto Case5;
4 : goto Case4;
3 : goto Case3;
2 : goto Case2;
1 : goto Case1;
0 : Exit(c);
end;
Case12: c+=(UInt32(k8[11])) shl 24;
Case11: c+=(UInt32(k8[10])) shl 16;
Case10: c+=(UInt32(k8[9])) shl 8;
Case9: c+=k8[8];
Case8: b+=(UInt32(k8[7])) shl 24;
Case7: b+=(UInt32(k8[6])) shl 16;
Case6: b+=(UInt32(k8[5])) shl 8;
Case5: b+=k8[4];
Case4: a+=(UInt32(k8[3])) shl 24;
Case3: a+=(UInt32(k8[2])) shl 16;
Case2: a+=(UInt32(k8[1])) shl 8;
Case1: a+=k8[0];
end;
final_abc;
Result := Int32(c);
end;
end.