mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-12 19:29:27 +02:00
+ String and TObject extensions to TFPHashTable
git-svn-id: trunk@4774 -
This commit is contained in:
parent
847377bf79
commit
54cf00e8f5
@ -312,25 +312,23 @@ type
|
|||||||
usually via a mod operator; }
|
usually via a mod operator; }
|
||||||
THashFunction = function(const S: string; const TableSize: Longword): Longword;
|
THashFunction = function(const S: string; const TableSize: Longword): Longword;
|
||||||
|
|
||||||
TIteratorMethod = procedure(Item: Pointer; const Key: string;
|
|
||||||
var Continue: Boolean) of object;
|
|
||||||
|
|
||||||
{ THTNode }
|
{ THTNode }
|
||||||
|
|
||||||
THTNode = class(TObject)
|
THTCustomNode = class(TObject)
|
||||||
private
|
private
|
||||||
FData: pointer;
|
|
||||||
FKey: string;
|
FKey: string;
|
||||||
public
|
public
|
||||||
constructor CreateWith(const AString: String);
|
constructor CreateWith(const AString: String);
|
||||||
function HasKey(const AKey: string): boolean;
|
function HasKey(const AKey: string): boolean;
|
||||||
property Key: string read FKey;
|
property Key: string read FKey;
|
||||||
property Data: pointer read FData write FData;
|
|
||||||
end;
|
end;
|
||||||
|
THTCustomNodeClass = Class of THTCustomNode;
|
||||||
|
|
||||||
|
|
||||||
{ TFPHashTable }
|
{ TFPCustomHashTable }
|
||||||
|
|
||||||
TFPHashTable = class(TObject)
|
TFPCustomHashTable = class(TObject)
|
||||||
private
|
private
|
||||||
FHashTable: TFPObjectList;
|
FHashTable: TFPObjectList;
|
||||||
FHashTableSize: Longword;
|
FHashTableSize: Longword;
|
||||||
@ -346,26 +344,24 @@ type
|
|||||||
function GetMaxChainLength: Longword;
|
function GetMaxChainLength: Longword;
|
||||||
function Chain(const index: Longword):TFPObjectList;
|
function Chain(const index: Longword):TFPObjectList;
|
||||||
protected
|
protected
|
||||||
|
Function CreateNewNode(const aKey : string) : THTCustomNode; virtual; abstract;
|
||||||
|
Procedure AddNode(ANode : THTCustomNode); virtual; abstract;
|
||||||
function ChainLength(const ChainIndex: Longword): Longword; virtual;
|
function ChainLength(const ChainIndex: Longword): Longword; virtual;
|
||||||
procedure SetData(const index: string; const AValue: Pointer); virtual;
|
function FindOrCreateNew(const aKey: string): THTCustomNode; virtual;
|
||||||
function GetData(const index: string):Pointer; virtual;
|
|
||||||
function FindOrCreateNew(const aKey: string): THTNode; virtual;
|
|
||||||
function ForEachCall(aMethod: TIteratorMethod): THTNode; virtual;
|
|
||||||
procedure SetHashFunction(AHashFunction: THashFunction); virtual;
|
procedure SetHashFunction(AHashFunction: THashFunction); virtual;
|
||||||
|
Function FindChainForAdd(Const aKey : String) : TFPObjectList;
|
||||||
public
|
public
|
||||||
constructor Create;
|
constructor Create;
|
||||||
constructor CreateWith(AHashTableSize: Longword; aHashFunc: THashFunction);
|
constructor CreateWith(AHashTableSize: Longword; aHashFunc: THashFunction);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
procedure ChangeTableSize(const ANewSize: Longword); virtual;
|
procedure ChangeTableSize(const ANewSize: Longword); virtual;
|
||||||
procedure Clear; virtual;
|
procedure Clear; virtual;
|
||||||
procedure Add(const aKey: string; AItem: pointer); virtual;
|
|
||||||
procedure Delete(const aKey: string); virtual;
|
procedure Delete(const aKey: string); virtual;
|
||||||
function Find(const aKey: string): THTNode;
|
function Find(const aKey: string): THTCustomNode;
|
||||||
function IsEmpty: boolean;
|
function IsEmpty: boolean;
|
||||||
property HashFunction: THashFunction read FHashFunction write SetHashFunction;
|
property HashFunction: THashFunction read FHashFunction write SetHashFunction;
|
||||||
property Count: Longword read FCount;
|
property Count: Longword read FCount;
|
||||||
property HashTableSize: Longword read FHashTableSize write SetHashTableSize;
|
property HashTableSize: Longword read FHashTableSize write SetHashTableSize;
|
||||||
property Items[const index: string]: Pointer read GetData write SetData; default;
|
|
||||||
property HashTable: TFPObjectList read FHashTable;
|
property HashTable: TFPObjectList read FHashTable;
|
||||||
property VoidSlots: Longword read GetVoidSlots;
|
property VoidSlots: Longword read GetVoidSlots;
|
||||||
property LoadFactor: double read GetLoadFactor;
|
property LoadFactor: double read GetLoadFactor;
|
||||||
@ -375,6 +371,88 @@ type
|
|||||||
property Density: Longword read GetDensity;
|
property Density: Longword read GetDensity;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TFPDataHashTable : Hash table with simple data pointers }
|
||||||
|
|
||||||
|
THTDataNode = Class(THTCustomNode)
|
||||||
|
Private
|
||||||
|
FData: pointer;
|
||||||
|
public
|
||||||
|
property Data: pointer read FData write FData;
|
||||||
|
end;
|
||||||
|
// For compatibility
|
||||||
|
THTNode = THTDataNode;
|
||||||
|
|
||||||
|
TDataIteratorMethod = procedure(Item: Pointer; const Key: string; var Continue: Boolean) of object;
|
||||||
|
// For compatibility
|
||||||
|
TIteratorMethod = TDataIteratorMethod;
|
||||||
|
|
||||||
|
TFPDataHashTable = Class(TFPCustomHashTable)
|
||||||
|
Protected
|
||||||
|
Function CreateNewNode(const aKey : String) : THTCustomNode; override;
|
||||||
|
Procedure AddNode(ANode : THTCustomNode); override;
|
||||||
|
procedure SetData(const index: string; const AValue: Pointer); virtual;
|
||||||
|
function GetData(const index: string):Pointer; virtual;
|
||||||
|
function ForEachCall(aMethod: TDataIteratorMethod): THTDataNode; virtual;
|
||||||
|
Public
|
||||||
|
procedure Add(const aKey: string; AItem: pointer); virtual;
|
||||||
|
property Items[const index: string]: Pointer read GetData write SetData; default;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TFPStringHashTable : Hash table with simple strings as data }
|
||||||
|
THTStringNode = Class(THTCustomNode)
|
||||||
|
Private
|
||||||
|
FData : String;
|
||||||
|
public
|
||||||
|
property Data: String read FData write FData;
|
||||||
|
end;
|
||||||
|
TStringIteratorMethod = procedure(Item: String; const Key: string; var Continue: Boolean) of object;
|
||||||
|
|
||||||
|
TFPStringHashTable = Class(TFPCustomHashTable)
|
||||||
|
Protected
|
||||||
|
Function CreateNewNode(const aKey : String) : THTCustomNode; override;
|
||||||
|
Procedure AddNode(ANode : THTCustomNode); override;
|
||||||
|
procedure SetData(const Index, AValue: string); virtual;
|
||||||
|
function GetData(const index: string): String; virtual;
|
||||||
|
function ForEachCall(aMethod: TStringIteratorMethod): THTStringNode; virtual;
|
||||||
|
Public
|
||||||
|
procedure Add(const aKey,aItem: string); virtual;
|
||||||
|
property Items[const index: string]: String read GetData write SetData; default;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TFPStringHashTable : Hash table with simple strings as data }
|
||||||
|
|
||||||
|
|
||||||
|
THTObjectNode = Class(THTCustomNode)
|
||||||
|
Private
|
||||||
|
FData : TObject;
|
||||||
|
public
|
||||||
|
property Data: TObject read FData write FData;
|
||||||
|
end;
|
||||||
|
|
||||||
|
THTOwnedObjectNode = Class(THTObjectNode)
|
||||||
|
public
|
||||||
|
Destructor Destroy; override;
|
||||||
|
end;
|
||||||
|
TObjectIteratorMethod = procedure(Item: TObject; const Key: string; var Continue: Boolean) of object;
|
||||||
|
|
||||||
|
TFPObjectHashTable = Class(TFPCustomHashTable)
|
||||||
|
Private
|
||||||
|
FOwnsObjects : Boolean;
|
||||||
|
Protected
|
||||||
|
Function CreateNewNode(const aKey : String) : THTCustomNode; override;
|
||||||
|
Procedure AddNode(ANode : THTCustomNode); override;
|
||||||
|
procedure SetData(const Index: string; AObject : TObject); virtual;
|
||||||
|
function GetData(const index: string): TObject; virtual;
|
||||||
|
function ForEachCall(aMethod: TObjectIteratorMethod): THTObjectNode; virtual;
|
||||||
|
Public
|
||||||
|
constructor Create(AOwnsObjects : Boolean = True);
|
||||||
|
constructor CreateWith(AHashTableSize: Longword; aHashFunc: THashFunction; AOwnsObjects : Boolean = True);
|
||||||
|
procedure Add(const aKey: string; AItem : TObject); virtual;
|
||||||
|
property Items[const index: string]: TObject read GetData write SetData; default;
|
||||||
|
Property OwnsObjects : Boolean Read FOwnsObjects Write FOwnsObjects;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
EDuplicate = class(Exception);
|
EDuplicate = class(Exception);
|
||||||
EKeyNotFound = class(Exception);
|
EKeyNotFound = class(Exception);
|
||||||
|
|
||||||
@ -1566,13 +1644,13 @@ end;
|
|||||||
|
|
||||||
{ THTNode }
|
{ THTNode }
|
||||||
|
|
||||||
constructor THTNode.CreateWith(const AString: string);
|
constructor THTCustomNode.CreateWith(const AString: string);
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
FKey := AString;
|
FKey := AString;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function THTNode.HasKey(const AKey: string): boolean;
|
function THTCustomNode.HasKey(const AKey: string): boolean;
|
||||||
begin
|
begin
|
||||||
if Length(AKey) <> Length(FKey) then
|
if Length(AKey) <> Length(FKey) then
|
||||||
begin
|
begin
|
||||||
@ -1583,17 +1661,14 @@ begin
|
|||||||
Result := CompareMem(PChar(FKey), PChar(AKey), length(AKey));
|
Result := CompareMem(PChar(FKey), PChar(AKey), length(AKey));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TFPHashTable }
|
{ TFPCustomHashTable }
|
||||||
|
|
||||||
constructor TFPHashTable.Create;
|
constructor TFPCustomHashTable.Create;
|
||||||
begin
|
begin
|
||||||
Inherited Create;
|
CreateWith(196613,@RSHash);
|
||||||
FHashTable := TFPObjectList.Create(True);
|
|
||||||
HashTableSize := 196613;
|
|
||||||
FHashFunction := @RSHash;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
constructor TFPHashTable.CreateWith(AHashTableSize: Longword;
|
constructor TFPCustomHashTable.CreateWith(AHashTableSize: Longword;
|
||||||
aHashFunc: THashFunction);
|
aHashFunc: THashFunction);
|
||||||
begin
|
begin
|
||||||
Inherited Create;
|
Inherited Create;
|
||||||
@ -1602,28 +1677,23 @@ begin
|
|||||||
FHashFunction := aHashFunc;
|
FHashFunction := aHashFunc;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TFPHashTable.Destroy;
|
destructor TFPCustomHashTable.Destroy;
|
||||||
begin
|
begin
|
||||||
FHashTable.Free;
|
FHashTable.Free;
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFPHashTable.GetDensity: Longword;
|
function TFPCustomHashTable.GetDensity: Longword;
|
||||||
begin
|
begin
|
||||||
Result := FHashTableSize - VoidSlots
|
Result := FHashTableSize - VoidSlots
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFPHashTable.GetNumberOfCollisions: Longword;
|
function TFPCustomHashTable.GetNumberOfCollisions: Longword;
|
||||||
begin
|
begin
|
||||||
Result := FCount -(FHashTableSize - VoidSlots)
|
Result := FCount -(FHashTableSize - VoidSlots)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFPHashTable.SetData(const index: string; const AValue: Pointer);
|
procedure TFPCustomHashTable.SetHashTableSize(const Value: Longword);
|
||||||
begin
|
|
||||||
FindOrCreateNew(index).Data := AValue;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TFPHashTable.SetHashTableSize(const Value: Longword);
|
|
||||||
var
|
var
|
||||||
i: Longword;
|
i: Longword;
|
||||||
newSize: Longword;
|
newSize: Longword;
|
||||||
@ -1644,7 +1714,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFPHashTable.InitializeHashTable;
|
procedure TFPCustomHashTable.InitializeHashTable;
|
||||||
var
|
var
|
||||||
i: LongWord;
|
i: LongWord;
|
||||||
begin
|
begin
|
||||||
@ -1654,12 +1724,12 @@ begin
|
|||||||
FCount := 0;
|
FCount := 0;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFPHashTable.ChangeTableSize(const ANewSize: Longword);
|
procedure TFPCustomHashTable.ChangeTableSize(const ANewSize: Longword);
|
||||||
var
|
var
|
||||||
SavedTable: TFPObjectList;
|
SavedTable: TFPObjectList;
|
||||||
SavedTableSize: Longword;
|
SavedTableSize: Longword;
|
||||||
i, j: Longword;
|
i, j: Longword;
|
||||||
temp: THTNode;
|
temp: THTCustomNode;
|
||||||
begin
|
begin
|
||||||
SavedTable := FHashTable;
|
SavedTable := FHashTable;
|
||||||
SavedTableSize := FHashTableSize;
|
SavedTableSize := FHashTableSize;
|
||||||
@ -1672,14 +1742,14 @@ begin
|
|||||||
if Assigned(SavedTable[i]) then
|
if Assigned(SavedTable[i]) then
|
||||||
for j := 0 to TFPObjectList(SavedTable[i]).Count -1 do
|
for j := 0 to TFPObjectList(SavedTable[i]).Count -1 do
|
||||||
begin
|
begin
|
||||||
temp := THTNode(TFPObjectList(SavedTable[i])[j]);
|
temp := THTCustomNode(TFPObjectList(SavedTable[i])[j]);
|
||||||
Add(temp.Key, temp.Data);
|
AddNode(temp);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
SavedTable.Free;
|
SavedTable.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFPHashTable.SetHashFunction(AHashFunction: THashFunction);
|
procedure TFPCustomHashTable.SetHashFunction(AHashFunction: THashFunction);
|
||||||
begin
|
begin
|
||||||
if IsEmpty then
|
if IsEmpty then
|
||||||
FHashFunction := AHashFunction
|
FHashFunction := AHashFunction
|
||||||
@ -1687,7 +1757,7 @@ begin
|
|||||||
raise Exception.Create(NotEmptyMsg);
|
raise Exception.Create(NotEmptyMsg);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFPHashTable.Find(const aKey: string): THTNode;
|
function TFPCustomHashTable.Find(const aKey: string): THTCustomNode;
|
||||||
var
|
var
|
||||||
hashCode: Longword;
|
hashCode: Longword;
|
||||||
chn: TFPObjectList;
|
chn: TFPObjectList;
|
||||||
@ -1699,27 +1769,107 @@ begin
|
|||||||
begin
|
begin
|
||||||
if chn.count>0 then
|
if chn.count>0 then
|
||||||
for i := 0 to chn.Count - 1 do
|
for i := 0 to chn.Count - 1 do
|
||||||
if THTNode(chn[i]).HasKey(aKey) then
|
if THTCustomNode(chn[i]).HasKey(aKey) then
|
||||||
begin
|
begin
|
||||||
result := THTNode(chn[i]);
|
result := THTCustomNode(chn[i]);
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
Result := nil;
|
Result := nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFPHashTable.GetData(const Index: string): Pointer;
|
Function TFPCustomHashTable.FindChainForAdd(Const aKey : String) : TFPObjectList;
|
||||||
|
|
||||||
var
|
var
|
||||||
node: THTNode;
|
hashCode: Longword;
|
||||||
|
i: Longword;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
node := Find(Index);
|
hashCode := FHashFunction(aKey, FHashTableSize);
|
||||||
if Assigned(node) then
|
Result := Chain(hashCode);
|
||||||
Result := node.Data
|
if Assigned(Result) then
|
||||||
|
begin
|
||||||
|
if Result.count>0 then
|
||||||
|
for i := 0 to Result.Count - 1 do
|
||||||
|
if THTCustomNode(Result[i]).HasKey(aKey) then
|
||||||
|
Raise EDuplicate.CreateFmt(DuplicateMsg, [aKey]);
|
||||||
|
end
|
||||||
else
|
else
|
||||||
Result := nil;
|
begin
|
||||||
|
FHashTable[hashcode] := TFPObjectList.Create(true);
|
||||||
|
Result := Chain(hashcode);
|
||||||
|
end;
|
||||||
|
inc(FCount);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFPHashTable.FindOrCreateNew(const aKey: string): THTNode;
|
|
||||||
|
procedure TFPCustomHashTable.Delete(const aKey: string);
|
||||||
|
var
|
||||||
|
hashCode: Longword;
|
||||||
|
chn: TFPObjectList;
|
||||||
|
i: Longword;
|
||||||
|
begin
|
||||||
|
hashCode := FHashFunction(aKey, FHashTableSize);
|
||||||
|
chn := Chain(hashCode);
|
||||||
|
if Assigned(chn) then
|
||||||
|
begin
|
||||||
|
if chn.count>0 then
|
||||||
|
for i := 0 to chn.Count - 1 do
|
||||||
|
if THTCustomNode(chn[i]).HasKey(aKey) then
|
||||||
|
begin
|
||||||
|
chn.Delete(i);
|
||||||
|
dec(FCount);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
raise EKeyNotFound.CreateFmt(KeyNotFoundMsg, ['Delete', aKey]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFPCustomHashTable.IsEmpty: boolean;
|
||||||
|
begin
|
||||||
|
Result := (FCount = 0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFPCustomHashTable.Chain(const index: Longword): TFPObjectList;
|
||||||
|
begin
|
||||||
|
Result := TFPObjectList(FHashTable[index]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFPCustomHashTable.GetVoidSlots: Longword;
|
||||||
|
var
|
||||||
|
i: Longword;
|
||||||
|
num: Longword;
|
||||||
|
begin
|
||||||
|
num := 0;
|
||||||
|
if FHashTableSize>0 Then
|
||||||
|
for i:= 0 to FHashTableSize-1 do
|
||||||
|
if Not Assigned(Chain(i)) then
|
||||||
|
inc(num);
|
||||||
|
result := num;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFPCustomHashTable.GetLoadFactor: double;
|
||||||
|
begin
|
||||||
|
Result := Count / FHashTableSize;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFPCustomHashTable.GetAVGChainLen: double;
|
||||||
|
begin
|
||||||
|
result := Count / (FHashTableSize - VoidSlots);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFPCustomHashTable.GetMaxChainLength: Longword;
|
||||||
|
var
|
||||||
|
i: Longword;
|
||||||
|
begin
|
||||||
|
Result := 0;
|
||||||
|
if FHashTableSize>0 Then
|
||||||
|
for i := 0 to FHashTableSize-1 do
|
||||||
|
if ChainLength(i) > Result then
|
||||||
|
Result := ChainLength(i);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFPCustomHashTable.FindOrCreateNew(const aKey: string): THTCustomNode;
|
||||||
var
|
var
|
||||||
hashCode: Longword;
|
hashCode: Longword;
|
||||||
chn: TFPObjectList;
|
chn: TFPObjectList;
|
||||||
@ -1731,7 +1881,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
if chn.count>0 then
|
if chn.count>0 then
|
||||||
for i := 0 to chn.Count - 1 do
|
for i := 0 to chn.Count - 1 do
|
||||||
if THTNode(chn[i]).HasKey(aKey) then
|
if THTCustomNode(chn[i]).HasKey(aKey) then
|
||||||
begin
|
begin
|
||||||
Result := THTNode(chn[i]);
|
Result := THTNode(chn[i]);
|
||||||
exit;
|
exit;
|
||||||
@ -1743,11 +1893,11 @@ begin
|
|||||||
chn := Chain(hashcode);
|
chn := Chain(hashcode);
|
||||||
end;
|
end;
|
||||||
inc(FCount);
|
inc(FCount);
|
||||||
Result := THTNode.CreateWith(aKey);
|
Result := CreateNewNode(aKey);
|
||||||
chn.Add(Result);
|
chn.Add(Result);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFPHashTable.ChainLength(const ChainIndex: Longword): Longword;
|
function TFPCustomHashTable.ChainLength(const ChainIndex: Longword): Longword;
|
||||||
begin
|
begin
|
||||||
if Assigned(Chain(ChainIndex)) then
|
if Assigned(Chain(ChainIndex)) then
|
||||||
Result := Chain(ChainIndex).Count
|
Result := Chain(ChainIndex).Count
|
||||||
@ -1755,7 +1905,7 @@ begin
|
|||||||
Result := 0;
|
Result := 0;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFPHashTable.Clear;
|
procedure TFPCustomHashTable.Clear;
|
||||||
var
|
var
|
||||||
i: Longword;
|
i: Longword;
|
||||||
begin
|
begin
|
||||||
@ -1768,7 +1918,44 @@ begin
|
|||||||
FCount := 0;
|
FCount := 0;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFPHashTable.ForEachCall(aMethod: TIteratorMethod): THTNode;
|
|
||||||
|
|
||||||
|
{ TFPDataHashTable }
|
||||||
|
|
||||||
|
procedure TFPDataHashTable.Add(const aKey: string; aItem: pointer);
|
||||||
|
var
|
||||||
|
chn: TFPObjectList;
|
||||||
|
NewNode: THtDataNode;
|
||||||
|
begin
|
||||||
|
chn:=FindChainForAdd(akey);
|
||||||
|
NewNode := THtDataNode(CreateNewNode(aKey));
|
||||||
|
NewNode.Data := aItem;
|
||||||
|
chn.Add(NewNode);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFPDataHashTable.GetData(const Index: string): Pointer;
|
||||||
|
var
|
||||||
|
node: THTDataNode;
|
||||||
|
begin
|
||||||
|
node := THTDataNode(Find(Index));
|
||||||
|
if Assigned(node) then
|
||||||
|
Result := node.Data
|
||||||
|
else
|
||||||
|
Result := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFPDataHashTable.SetData(const index: string; const AValue: Pointer);
|
||||||
|
begin
|
||||||
|
THTDataNode(FindOrCreateNew(index)).Data := AValue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Function TFPDataHashTable.CreateNewNode(const aKey : string) : THTCustomNode;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Result:=THTDataNode.CreateWith(aKey);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFPDataHashTable.ForEachCall(aMethod: TDataIteratorMethod): THTDataNode;
|
||||||
var
|
var
|
||||||
i, j: Longword;
|
i, j: Longword;
|
||||||
continue: boolean;
|
continue: boolean;
|
||||||
@ -1783,10 +1970,10 @@ begin
|
|||||||
if chain(i).count>0 then
|
if chain(i).count>0 then
|
||||||
for j := 0 to Chain(i).Count-1 do
|
for j := 0 to Chain(i).Count-1 do
|
||||||
begin
|
begin
|
||||||
aMethod(THTNode(Chain(i)[j]).Data, THTNode(Chain(i)[j]).Key, continue);
|
aMethod(THTDataNode(Chain(i)[j]).Data, THTDataNode(Chain(i)[j]).Key, continue);
|
||||||
if not continue then
|
if not continue then
|
||||||
begin
|
begin
|
||||||
Result := THTNode(Chain(i)[j]);
|
Result := THTDataNode(Chain(i)[j]);
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -1794,97 +1981,175 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFPHashTable.Add(const aKey: string; aItem: pointer);
|
Procedure TFPDataHashTable.AddNode(ANode : THTCustomNode);
|
||||||
var
|
|
||||||
hashCode: Longword;
|
|
||||||
chn: TFPObjectList;
|
|
||||||
i: Longword;
|
|
||||||
NewNode: THtNode;
|
|
||||||
begin
|
begin
|
||||||
hashCode := FHashFunction(aKey, FHashTableSize);
|
With THTDataNode(ANode) do
|
||||||
chn := Chain(hashCode);
|
Add(Key,Data);
|
||||||
if Assigned(chn) then
|
end;
|
||||||
begin
|
|
||||||
if chn.count>0 then
|
{ TFPStringHashTable }
|
||||||
for i := 0 to chn.Count - 1 do
|
|
||||||
if THTNode(chn[i]).HasKey(aKey) then
|
Procedure TFPStringHashTable.AddNode(ANode : THTCustomNode);
|
||||||
Raise EDuplicate.CreateFmt(DuplicateMsg, [aKey]);
|
|
||||||
end
|
begin
|
||||||
|
With THTStringNode(ANode) do
|
||||||
|
Add(Key,Data);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFPStringHashTable.GetData(const Index: string): String;
|
||||||
|
var
|
||||||
|
node: THTStringNode;
|
||||||
|
begin
|
||||||
|
node := THTStringNode(Find(Index));
|
||||||
|
if Assigned(node) then
|
||||||
|
Result := node.Data
|
||||||
else
|
else
|
||||||
begin
|
Result := '';
|
||||||
FHashTable[hashcode] := TFPObjectList.Create(true);
|
end;
|
||||||
chn := Chain(hashcode);
|
|
||||||
end;
|
procedure TFPStringHashTable.SetData(const index, AValue: string);
|
||||||
inc(FCount);
|
begin
|
||||||
NewNode := THTNode.CreateWith(aKey);
|
THTStringNode(FindOrCreateNew(index)).Data := AValue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFPStringHashTable.Add(const aKey, aItem: string);
|
||||||
|
var
|
||||||
|
chn: TFPObjectList;
|
||||||
|
NewNode: THtStringNode;
|
||||||
|
|
||||||
|
begin
|
||||||
|
chn:=FindChainForAdd(akey);
|
||||||
|
NewNode := THtStringNode(CreateNewNode(aKey));
|
||||||
NewNode.Data := aItem;
|
NewNode.Data := aItem;
|
||||||
chn.Add(NewNode);
|
chn.Add(NewNode);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFPHashTable.Delete(const aKey: string);
|
Function TFPStringHashTable.CreateNewNode(const aKey : string) : THTCustomNode;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Result:=THTStringNode.CreateWith(aKey);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function TFPStringHashTable.ForEachCall(aMethod: TStringIteratorMethod): THTStringNode;
|
||||||
var
|
var
|
||||||
hashCode: Longword;
|
i, j: Longword;
|
||||||
chn: TFPObjectList;
|
continue: boolean;
|
||||||
i: Longword;
|
|
||||||
begin
|
begin
|
||||||
hashCode := FHashFunction(aKey, FHashTableSize);
|
Result := nil;
|
||||||
chn := Chain(hashCode);
|
continue := true;
|
||||||
if Assigned(chn) then
|
if FHashTableSize>0 then
|
||||||
begin
|
|
||||||
if chn.count>0 then
|
|
||||||
for i := 0 to chn.Count - 1 do
|
|
||||||
if THTNode(chn[i]).HasKey(aKey) then
|
|
||||||
begin
|
|
||||||
chn.Delete(i);
|
|
||||||
dec(FCount);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
raise EKeyNotFound.CreateFmt(KeyNotFoundMsg, ['Delete', aKey]);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TFPHashTable.IsEmpty: boolean;
|
|
||||||
begin
|
|
||||||
Result := (FCount = 0);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TFPHashTable.Chain(const index: Longword): TFPObjectList;
|
|
||||||
begin
|
|
||||||
Result := TFPObjectList(FHashTable[index]);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TFPHashTable.GetVoidSlots: Longword;
|
|
||||||
var
|
|
||||||
i: Longword;
|
|
||||||
num: Longword;
|
|
||||||
begin
|
|
||||||
num := 0;
|
|
||||||
if FHashTableSize>0 Then
|
|
||||||
for i:= 0 to FHashTableSize-1 do
|
|
||||||
if Not Assigned(Chain(i)) then
|
|
||||||
inc(num);
|
|
||||||
result := num;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TFPHashTable.GetLoadFactor: double;
|
|
||||||
begin
|
|
||||||
Result := Count / FHashTableSize;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TFPHashTable.GetAVGChainLen: double;
|
|
||||||
begin
|
|
||||||
result := Count / (FHashTableSize - VoidSlots);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TFPHashTable.GetMaxChainLength: Longword;
|
|
||||||
var
|
|
||||||
i: Longword;
|
|
||||||
begin
|
|
||||||
Result := 0;
|
|
||||||
if FHashTableSize>0 Then
|
|
||||||
for i := 0 to FHashTableSize-1 do
|
for i := 0 to FHashTableSize-1 do
|
||||||
if ChainLength(i) > Result then
|
begin
|
||||||
Result := ChainLength(i);
|
if assigned(Chain(i)) then
|
||||||
|
begin
|
||||||
|
if chain(i).count>0 then
|
||||||
|
for j := 0 to Chain(i).Count-1 do
|
||||||
|
begin
|
||||||
|
aMethod(THTStringNode(Chain(i)[j]).Data, THTStringNode(Chain(i)[j]).Key, continue);
|
||||||
|
if not continue then
|
||||||
|
begin
|
||||||
|
Result := THTStringNode(Chain(i)[j]);
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TFPObjectHashTable }
|
||||||
|
|
||||||
|
Procedure TFPObjectHashTable.AddNode(ANode : THTCustomNode);
|
||||||
|
|
||||||
|
begin
|
||||||
|
With THTObjectNode(ANode) do
|
||||||
|
Add(Key,Data);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFPObjectHashTable.GetData(const Index: string): TObject;
|
||||||
|
var
|
||||||
|
node: THTObjectNode;
|
||||||
|
begin
|
||||||
|
node := THTObjectNode(Find(Index));
|
||||||
|
if Assigned(node) then
|
||||||
|
Result := node.Data
|
||||||
|
else
|
||||||
|
Result := Nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFPObjectHashTable.SetData(const index : string; AObject : TObject);
|
||||||
|
begin
|
||||||
|
THTObjectNode(FindOrCreateNew(index)).Data := AObject;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFPObjectHashTable.Add(const aKey: string; AItem : TObject);
|
||||||
|
var
|
||||||
|
chn: TFPObjectList;
|
||||||
|
NewNode: THTObjectNode;
|
||||||
|
|
||||||
|
begin
|
||||||
|
chn:=FindChainForAdd(akey);
|
||||||
|
NewNode := THTObjectNode(CreateNewNode(aKey));
|
||||||
|
NewNode.Data := aItem;
|
||||||
|
chn.Add(NewNode);
|
||||||
|
end;
|
||||||
|
|
||||||
|
Function TFPObjectHashTable.CreateNewNode(const aKey : string) : THTCustomNode;
|
||||||
|
|
||||||
|
begin
|
||||||
|
If OwnsObjects then
|
||||||
|
Result:=THTOwnedObjectNode.CreateWith(aKey)
|
||||||
|
else
|
||||||
|
Result:=THTObjectNode.CreateWith(aKey);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function TFPObjectHashTable.ForEachCall(aMethod: TObjectIteratorMethod): THTObjectNode;
|
||||||
|
var
|
||||||
|
i, j: Longword;
|
||||||
|
continue: boolean;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
continue := true;
|
||||||
|
if FHashTableSize>0 then
|
||||||
|
for i := 0 to FHashTableSize-1 do
|
||||||
|
begin
|
||||||
|
if assigned(Chain(i)) then
|
||||||
|
begin
|
||||||
|
if chain(i).count>0 then
|
||||||
|
for j := 0 to Chain(i).Count-1 do
|
||||||
|
begin
|
||||||
|
aMethod(THTObjectNode(Chain(i)[j]).Data, THTObjectNode(Chain(i)[j]).Key, continue);
|
||||||
|
if not continue then
|
||||||
|
begin
|
||||||
|
Result := THTObjectNode(Chain(i)[j]);
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TFPObjectHashTable.Create(AOwnsObjects : Boolean = True);
|
||||||
|
|
||||||
|
begin
|
||||||
|
Inherited Create;
|
||||||
|
FOwnsObjects:=AOwnsObjects;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TFPObjectHashTable.CreateWith(AHashTableSize: Longword; aHashFunc: THashFunction; AOwnsObjects : Boolean = True);
|
||||||
|
|
||||||
|
begin
|
||||||
|
Inherited CreateWith(AHashTableSize,AHashFunc);
|
||||||
|
FOwnsObjects:=AOwnsObjects;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Destructor THTOwnedObjectNode.Destroy;
|
||||||
|
|
||||||
|
begin
|
||||||
|
FreeAndNil(FData);
|
||||||
|
Inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
Loading…
Reference in New Issue
Block a user