Contributor: KKTOS
{
	THashTable unit - Delphi 1 version
 by kktos, May 1997.
 This code is FREEWARE.
 *** Please, if you enhance it, mail me at kktos@sirius.fr ***
}
unit HashTabl;
interface
uses Classes;
type
	TDeleteType= (dtDelete, dtDetach);
{ Class THashList, from Delphi 2 TList source
	used internally, but you can use it for any purpose
}
	THashItem= record
		key:	longint;
	 obj:	TObject;
	end;
	PHashItemList = ^THashItemList;
 THashItemList = array[0..0] of THashItem;
 THashList = class(TObject)
 private
 	Flist:		PHashItemList;
 	Fcount: 		integer;
		Fcapacity:	integer;
 memSize:		longint;
 FdeleteType:	TDeleteType;
 protected
 	procedure Error;
 	function Get(Index: Integer): THashItem;
 	procedure Grow;
 	procedure Put(Index: Integer; const Item: THashItem);
 	procedure SetCapacity(NewCapacity: Integer);
 	procedure SetCount(NewCount: Integer);
 public
 		constructor Create;
 	destructor Destroy; override;
 	function Add(const Item: THashItem): Integer;
 	procedure Clear(dt: TDeleteType);
 	procedure Detach(Index: Integer);
 	procedure Delete(Index: Integer);
 	function Expand: THashList;
 	function IndexOf(key: longint): Integer;
 	procedure Pack;
 	property DeleteType: TDeleteType			read FdeleteType	write FdeleteType;
 	property Capacity: Integer				read FCapacity		write SetCapacity;
 	property Count: Integer					read FCount		write SetCount;
		property Items[Index: Integer]: THashItem	read Get			write Put; 	default;
 end;
{ Class THashTable
	the real hashtable.
}
 THashTable= class(TObject)
 private
		Ftable:	THashList;
		procedure Error;
		function getCount: integer;
 procedure setCount(count: integer);
		function getCapacity: integer;
 procedure setCapacity(capacity: integer);
		function getItem(index: integer): TObject;
 procedure setItem(index: integer; obj: TObject);
		function getDeleteType: TDeleteType;
 procedure setDeleteType(dt: TDeleteType);
 public
 		constructor Create;
 		destructor Destroy; override;
		procedure Add(const key: string; value: TObject);
 	function Get(const key: string): TObject;
 	procedure Detach(const key: string);
 	procedure Delete(const key: string);
 	procedure Clear(dt: TDeleteType);
 		procedure Pack;
 	property DeleteType: TDeleteType			read getDeleteType	write setDeleteType;
	 	property Count: integer 					read getCount		write setCount;
 	property Capacity: Integer				read getCapacity	write setCapacity;
 	property Items[index: Integer]: TObject		read getItem		write setItem;
 property Table: THashList				read Ftable;
 end;
function hash(key: Pointer; length: longint; level: longint): longint; 
implementation
uses SysUtils, Consts;
type
	longArray=	packed array[0..3] of byte;
	longArrayPtr=	^longArray;
	array12=		packed array[0..11] of byte;
	array12Ptr=	^array12;
 longPtr=		^longint;
{ --- Class THashList ---
	brute copy of TList D2 source, with some minors changes
 no comment, see TList
}
{-----------------------------------------------------------------------------}
constructor THashList.Create;
begin
	FdeleteType:= dtDelete;
	FCapacity:= 0;
 FCount:= 0;
 memSize:= 4;
 Flist:= AllocMem(memSize);
 SetCapacity(100);
end;
{-----------------------------------------------------------------------------}
destructor THashList.Destroy;
begin
	Clear(FdeleteType);
 FreeMem(FList, memSize);
end;
{-----------------------------------------------------------------------------}
function THashList.Add(const Item: THashItem): Integer;
begin
	Result := FCount;
	if(Result = FCapacity) then Grow;
	FList^[Result].key:= Item.key;
	FList^[Result].obj:= Item.obj;
	Inc(FCount);
end;
{-----------------------------------------------------------------------------}
procedure THashList.Clear(dt: TDeleteType);
var
	i:	integer;
begin
	if(dt=dtDelete) then
		for i := FCount - 1 downto 0 do
		 	if(Items[i].obj  nil) then
 			Items[i].obj.Free;
 {FreeMem(FList, memSize);
 memSize:= 4;
 Flist:= AllocMem(memSize);}
	FCapacity:= 0;
 FCount:= 0;
end;
{-----------------------------------------------------------------------------}
{ know BC++ ? remember TArray::Detach?
	if not, Detach remove the item from the list without disposing the object
}
procedure THashList.Detach(Index: Integer);
begin
	if((Index < 0) or (Index>= FCount)) then Error;
	Dec(FCount);
	if(Index < FCount) then System.Move(FList^[Index + 1], FList^[Index], (FCount - Index) * SizeOf(THashItem)); end; {-----------------------------------------------------------------------------} { know BC++ ? remember TArray::Destroy ? renames delete 'cause destroy... if not, Delete remove the item from the list AND dispose the object } procedure THashList.Delete(Index: Integer); begin if((Index < 0) or (Index>= FCount)) then Error;
	Dec(FCount);
	if(Index < FCount) then begin FList^[Index].obj.Free; System.Move(FList^[Index + 1], FList^[Index], (FCount - Index) * SizeOf(THashItem)); end; end; {-----------------------------------------------------------------------------} procedure THashList.Error; begin raise EListError.CreateRes(SListIndexError); end; {-----------------------------------------------------------------------------} function THashList.Expand: THashList; begin if(FCount = FCapacity) then Grow; Result:= Self; end; {-----------------------------------------------------------------------------} function THashList.Get(Index: Integer): THashItem; begin if((Index < 0) or (Index>= FCount)) then Error;
	Result.key:= FList^[Index].key;
	Result.obj:= FList^[Index].obj;
end;
{-----------------------------------------------------------------------------}
procedure THashList.Grow;
var
 Delta: Integer;
begin
	if FCapacity> 8 then Delta := 16
 else	if FCapacity> 4 then Delta := 8
 else	Delta := 4;
	SetCapacity(FCapacity + Delta);
end;
{-----------------------------------------------------------------------------}
function THashList.IndexOf(key: longint): Integer;
begin
	Result := 0;
	while (Result < FCount) and (FList^[Result].key  key) do Inc(Result);
	if Result = FCount then Result:= -1;
end;
{-----------------------------------------------------------------------------}
procedure THashList.Put(Index: Integer; const Item: THashItem);
begin
	if (Index < 0) or (Index>= FCount) then Error;
	FList^[Index].key:= Item.key;
	FList^[Index].obj:= Item.obj;
end;
{-----------------------------------------------------------------------------}
procedure THashList.Pack;
var
 i: Integer;
begin
	for i := FCount - 1 downto 0 do
	 	if Items[i].obj = nil then Delete(i);
end;
{-----------------------------------------------------------------------------}
procedure THashList.SetCapacity(NewCapacity: Integer);
begin
	if((NewCapacity < FCount) or (NewCapacity> MaxListSize)) then Error;
	if(NewCapacity  FCapacity) then begin
		FList:= ReallocMem(FList, memSize, NewCapacity * SizeOf(THashItem));
 	memSize:= NewCapacity * SizeOf(THashItem);
		FCapacity:= NewCapacity;
	end;
end;
{-----------------------------------------------------------------------------}
procedure THashList.SetCount(NewCount: Integer);
begin
	if((NewCount < 0) or (NewCount> MaxListSize)) then Error;
	if(NewCount> FCapacity) then SetCapacity(NewCount);
	if(NewCount> FCount) then
		FillChar(FList^[FCount], (NewCount - FCount) * SizeOf(THashItem), 0);
	FCount:= NewCount;
end;
{ --- Class THashTable ---
	it's just a list of THashItems.
 you provide a key (string) and an object;
 a unique numeric key (longint) is compute (see hash);
 when you get an object, you provide string key, and as fast as possible
 the object is here.
 Really fast;
 Really smart, because of string keys.
}
{-----------------------------------------------------------------------------}
constructor THashTable.Create;
begin
	inherited Create;
 Ftable:= THashList.Create;
end;
{-----------------------------------------------------------------------------}
destructor THashTable.Destroy;
begin
	Ftable.Free;
	inherited Destroy;
end;
{-----------------------------------------------------------------------------}
procedure THashTable.Error;
begin
	raise EListError.CreateRes(SListIndexError);
end;
{-----------------------------------------------------------------------------}
{
	Add 'value' object with key 'key'
}
procedure THashTable.Add(const key: string; value: TObject);
var
	item:	THashItem;
begin
	item.key:= hash(pointer(longint(@key)+1),length(key),0);
 item.obj:= value;
	Ftable.Add(item);
end;
{-----------------------------------------------------------------------------}
{
	Get object with key 'key'
}
function THashTable.Get(const key: string): TObject;
var
	index:	integer;
begin
	index:= Ftable.IndexOf(hash(pointer(longint(@key)+1),length(key),0));
	if(index<0) then Error; result:= Ftable[index].obj; end; {-----------------------------------------------------------------------------} { Detach (remove item, do not dispose object) object with key 'key' } procedure THashTable.Detach(const key: string); var index: integer; begin index:= Ftable.IndexOf(hash(pointer(longint(@key)+1),length(key),0)); if(index>=0) then
 	Ftable.Detach(index);
end;
{-----------------------------------------------------------------------------}
{
	Delete (remove item, dispose object) object with key 'key'
}
procedure THashTable.Delete(const key: string);
var
	index:	integer;
begin
	index:= Ftable.IndexOf(hash(pointer(longint(@key)+1),length(key),0));
 if(index>=0) then
 	Ftable.Delete(index);
end;
{-----------------------------------------------------------------------------}
{
	Clear the list; i.e: remove all the items (detach or delete depending of 'dt')
}
procedure THashTable.Clear(dt: TDeleteType);
begin
	Ftable.Clear(dt);
end;
{-----------------------------------------------------------------------------}
procedure THashTable.Pack;
begin
	Ftable.Pack;
end;
{-----------------------------------------------------------------------------}
function THashTable.getCount: integer;				begin result:= Ftable.Count; end;
procedure THashTable.setCount(count: integer);		begin Ftable.Count:= count; end;
function THashTable.getCapacity: integer;			begin result:= Ftable.Capacity; end;
procedure THashTable.setCapacity(capacity: integer);	begin Ftable.Capacity:= capacity; end;
function THashTable.getDeleteType: TDeleteType;		begin result:= Ftable.DeleteType; end;
procedure THashTable.setDeleteType(dt: TDeleteType);	begin Ftable.DeleteType:= dt; end;
function THashTable.getItem(index: integer): TObject;	begin result:= Ftable[index].obj; end;
{-----------------------------------------------------------------------------}
procedure THashTable.setItem(index: integer; obj: TObject);
var
	item:	THashItem;
begin
	item.key:= Ftable[index].key;
 item.obj:= obj;
	Ftable[index]:= item;
end;
{-----------------------------------------------------------------------------}
{ original code from lookup2.c, by Bob Jenkins, December 1996
	http://ourworld.compuserve.com/homepages/bob_jenkins/
 PLEASE, let me know if there is problem with it, or if you have a better one. THANKS.
}
function hash(key: Pointer; length: longint; level: longint): longint;
var
	a,b,c:		longint;
 len:			longint;
 k: 			array12Ptr;
 lp:			longPtr;
begin
	k:= array12Ptr(key);
	len:= length;
 a:= 9ドルE3779B9;
 b:= a;
 c:= level;
 if((longint(key) and 3)  0) then begin
	 while(len>=12) do begin	{unaligned}
			inc(a, (longint(k^[00]) +(longint(k^[01]) shl 8) + (longint(k^[02]) shl 16) + (longint(k^[03]) shl 24)));
 inc(b, (longint(k^[04]) +(longint(k^[05]) shl 8) + (longint(k^[06]) shl 16) + (longint(k^[07]) shl 24)));
 inc(c, (longint(k^[08]) +(longint(k^[09]) shl 8) + (longint(k^[10]) shl 16) + (longint(k^[11]) shl 24)));
 {mix(a,b,c);}
			inc(a , b xor $FFFFFFFF + 1); inc(a , c xor $FFFFFFFF + 1); a:= a xor (c shr 13);
			inc(b , c xor $FFFFFFFF + 1); inc(b , a xor $FFFFFFFF + 1); b:= b xor (a shl 8);
			inc(c , a xor $FFFFFFFF + 1); inc(c , b xor $FFFFFFFF + 1); c:= c xor (b shr 13);
			inc(a , b xor $FFFFFFFF + 1); inc(a , c xor $FFFFFFFF + 1); a:= a xor (c shr 12);
			inc(b , c xor $FFFFFFFF + 1); inc(b , a xor $FFFFFFFF + 1); b:= b xor (a shl 16);
			inc(c , a xor $FFFFFFFF + 1); inc(c , b xor $FFFFFFFF + 1); c:= c xor (b shr 5);
			inc(a , b xor $FFFFFFFF + 1); inc(a , c xor $FFFFFFFF + 1); a:= a xor (c shr 3);
		 inc(b , c xor $FFFFFFFF + 1); inc(b , a xor $FFFFFFFF + 1); b:= b xor (a shl 10);
			inc(c , a xor $FFFFFFFF + 1); inc(c , b xor $FFFFFFFF + 1); c:= c xor (b shr 15);
 inc(longint(k),12);
 dec(len,12);
 end;
 end
 else begin
	 while(len>=12) do begin	{aligned}
 	lp:= longPtr(k);
			inc(a, lp^); inc(lp,4);
			inc(b, lp^); inc(lp,4);
 inc(c, lp^);
 {mix(a,b,c);}
			inc(a , b xor $FFFFFFFF + 1); inc(a , c xor $FFFFFFFF + 1); a:= a xor (c shr 13);
			inc(b , c xor $FFFFFFFF + 1); inc(b , a xor $FFFFFFFF + 1); b:= b xor (a shl 8);
			inc(c , a xor $FFFFFFFF + 1); inc(c , b xor $FFFFFFFF + 1); c:= c xor (b shr 13);
			inc(a , b xor $FFFFFFFF + 1); inc(a , c xor $FFFFFFFF + 1); a:= a xor (c shr 12);
			inc(b , c xor $FFFFFFFF + 1); inc(b , a xor $FFFFFFFF + 1); b:= b xor (a shl 16);
			inc(c , a xor $FFFFFFFF + 1); inc(c , b xor $FFFFFFFF + 1); c:= c xor (b shr 5);
			inc(a , b xor $FFFFFFFF + 1); inc(a , c xor $FFFFFFFF + 1); a:= a xor (c shr 3);
		 inc(b , c xor $FFFFFFFF + 1); inc(b , a xor $FFFFFFFF + 1); b:= b xor (a shl 10);
			inc(c , a xor $FFFFFFFF + 1); inc(c , b xor $FFFFFFFF + 1); c:= c xor (b shr 15);
 inc(longint(k),12);
 dec(len,12);
 end;
 end;
 inc(c,length);
	if(len>=11) then inc(c, (longint(k^[10]) shl 24));
	if(len>=10) then inc(c, (longint(k^[9]) shl 16));
	if(len>=9) then inc(c, (longint(k^[8]) shl 8));
	if(len>=8) then inc(b, (longint(k^[7]) shl 24));
	if(len>=7) then inc(b, (longint(k^[6]) shl 16));
	if(len>=6) then inc(b, (longint(k^[5]) shl 8));
	if(len>=5) then inc(b, longint(k^[4]));
	if(len>=4) then inc(a, (longint(k^[3]) shl 24));
	if(len>=3) then inc(a, (longint(k^[2]) shl 16));
	if(len>=2) then inc(a, (longint(k^[1]) shl 8));
	if(len>=1) then inc(a, longint(k^[0]));
 {mix(a,b,c);}
	inc(a , b xor $FFFFFFFF + 1); inc(a , c xor $FFFFFFFF + 1); a:= a xor (c shr 13);
	inc(b , c xor $FFFFFFFF + 1); inc(b , a xor $FFFFFFFF + 1); b:= b xor (a shl 8);
	inc(c , a xor $FFFFFFFF + 1); inc(c , b xor $FFFFFFFF + 1); c:= c xor (b shr 13);
	inc(a , b xor $FFFFFFFF + 1); inc(a , c xor $FFFFFFFF + 1); a:= a xor (c shr 12);
	inc(b , c xor $FFFFFFFF + 1); inc(b , a xor $FFFFFFFF + 1); b:= b xor (a shl 16);
	inc(c , a xor $FFFFFFFF + 1); inc(c , b xor $FFFFFFFF + 1); c:= c xor (b shr 5);
	inc(a , b xor $FFFFFFFF + 1); inc(a , c xor $FFFFFFFF + 1); a:= a xor (c shr 3);
 inc(b , c xor $FFFFFFFF + 1); inc(b , a xor $FFFFFFFF + 1); b:= b xor (a shl 10);
	inc(c , a xor $FFFFFFFF + 1); inc(c , b xor $FFFFFFFF + 1); c:= c xor (b shr 15);
 result:= longint(c);
end;
end.


AltStyle によって変換されたページ (->オリジナル) /