2004-07-29 06:33:18 +00:00
|
|
|
{
|
|
|
|
:: X2UtHashes contains a base class for hashes (also known as associative
|
|
|
|
:: arrays), as well as various default implementations.
|
|
|
|
::
|
|
|
|
:: This unit contains code based on Bob Jenkins' optimized hashing algorithm:
|
|
|
|
:: http://burtleburtle.net/bob/hash/doobs.html
|
|
|
|
::
|
|
|
|
:: Last changed: $Date$
|
|
|
|
:: Revision: $Rev$
|
|
|
|
:: Author: $Author$
|
|
|
|
}
|
|
|
|
unit X2UtHashes;
|
|
|
|
|
|
|
|
interface
|
|
|
|
uses
|
|
|
|
SysUtils,
|
|
|
|
X2UtBinaryTree;
|
|
|
|
|
|
|
|
type
|
|
|
|
{
|
2004-07-29 13:48:35 +00:00
|
|
|
:$ Internal representation of a hash item
|
2004-07-29 06:33:18 +00:00
|
|
|
}
|
2004-07-29 13:48:35 +00:00
|
|
|
PX2UtHashItem = ^TX2UtHashItem;
|
|
|
|
TX2UtHashItem = record
|
|
|
|
Prev: PX2UtHashItem;
|
|
|
|
Next: PX2UtHashItem;
|
2004-07-29 06:33:18 +00:00
|
|
|
Key: String;
|
|
|
|
Value: record end;
|
|
|
|
end;
|
|
|
|
|
2004-07-29 13:48:35 +00:00
|
|
|
{
|
|
|
|
:$ Internal hash list
|
|
|
|
}
|
|
|
|
PX2UtHashList = ^TX2UtHashList;
|
|
|
|
TX2UtHashList = record
|
|
|
|
Root: PX2UtHashItem;
|
|
|
|
end;
|
|
|
|
|
2004-07-29 06:33:18 +00:00
|
|
|
{
|
|
|
|
:$ Hash implementation
|
|
|
|
|
|
|
|
:: This class implements a hash without knowing anything about
|
|
|
|
:: the data it contains.
|
|
|
|
}
|
|
|
|
TX2UtCustomHash = class(TX2UtCustomBTree)
|
|
|
|
private
|
2004-07-29 13:48:35 +00:00
|
|
|
FHashCursor: PX2UtHashItem;
|
2004-07-29 06:33:18 +00:00
|
|
|
FHashDataSize: Cardinal;
|
2004-07-29 13:48:35 +00:00
|
|
|
FHashItemSize: Cardinal;
|
2004-07-29 06:33:18 +00:00
|
|
|
|
|
|
|
function GetCurrentKey(): String;
|
2004-07-29 13:48:35 +00:00
|
|
|
function GetHashTotalSize(): Cardinal;
|
2004-07-29 06:33:18 +00:00
|
|
|
protected
|
|
|
|
function Hash(const AValue: String): Cardinal; virtual;
|
|
|
|
|
2004-07-29 13:48:35 +00:00
|
|
|
function GetItemData(const AItem: PX2UtHashItem): Pointer; virtual;
|
|
|
|
function LookupItem(const AKey: String;
|
|
|
|
out ANode: PX2UtBTreeNode;
|
2004-07-29 06:33:18 +00:00
|
|
|
const ACanCreate: Boolean = False;
|
2004-07-29 13:48:35 +00:00
|
|
|
const ASetCursor: Boolean = False): PX2UtHashItem;
|
2004-07-29 06:33:18 +00:00
|
|
|
|
|
|
|
procedure FreeNode(var ANode: PX2UtBTreeNode); override;
|
|
|
|
|
|
|
|
procedure ClearCursor(); override;
|
|
|
|
function ValidCursor(const ARaiseError: Boolean = True): Boolean; override;
|
|
|
|
|
2004-07-29 13:48:35 +00:00
|
|
|
procedure InitHashItem(var AItem: PX2UtHashItem); virtual;
|
|
|
|
procedure FreeHashItem(var AItem: PX2UtHashItem); virtual;
|
2004-07-29 06:33:18 +00:00
|
|
|
|
2004-07-29 13:48:35 +00:00
|
|
|
property HashCursor: PX2UtHashItem read FHashCursor write FHashCursor;
|
|
|
|
property HashItemSize: Cardinal read FHashItemSize;
|
|
|
|
property HashTotalSize: Cardinal read GetHashTotalSize;
|
2004-07-29 06:33:18 +00:00
|
|
|
property HashDataSize: Cardinal read FHashDataSize write FHashDataSize;
|
|
|
|
|
|
|
|
//:$ Returns the key at the current cursor location.
|
|
|
|
property CurrentKey: String read GetCurrentKey;
|
|
|
|
public
|
2004-07-29 13:48:35 +00:00
|
|
|
constructor Create(); override;
|
|
|
|
|
2004-07-29 06:33:18 +00:00
|
|
|
//:$ Deletes an item from the hash.
|
|
|
|
procedure Delete(const AKey: String);
|
|
|
|
|
|
|
|
function Next(): Boolean; override;
|
|
|
|
|
|
|
|
//:$ Checks if a key exists in the hash.
|
|
|
|
//:: If the ASetCursor parameter is set to True, the cursor will be
|
|
|
|
//:: positioned at the item if it is found.
|
|
|
|
function Exists(const AKey: String; const ASetCursor: Boolean = False): Boolean;
|
|
|
|
end;
|
|
|
|
|
|
|
|
{
|
|
|
|
:$ Hash implementation for pointer values
|
|
|
|
}
|
|
|
|
(*
|
|
|
|
TX2UtHash = class(TX2UtCustomHash)
|
|
|
|
private
|
|
|
|
function GetItem(Key: String): Pointer;
|
|
|
|
procedure SetItem(Key: String; const Value: Pointer);
|
|
|
|
|
|
|
|
function GetCurrentValue(): Pointer;
|
|
|
|
public
|
|
|
|
constructor Create(); override;
|
|
|
|
property CurrentKey;
|
|
|
|
|
|
|
|
//:$ Gets or sets an item.
|
|
|
|
property Items[Key: String]: Pointer read GetItem
|
|
|
|
write SetItem; default;
|
|
|
|
|
|
|
|
//:$ Returns the value at the current cursor location.
|
|
|
|
property CurrentValue: Pointer read GetCurrentValue;
|
|
|
|
end;
|
2004-07-29 13:48:35 +00:00
|
|
|
*)
|
2004-07-29 06:33:18 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
:$ Hash implementation for string values
|
|
|
|
}
|
|
|
|
TX2UtStringHash = class(TX2UtCustomHash)
|
|
|
|
private
|
|
|
|
function GetItem(Key: String): String;
|
|
|
|
procedure SetItem(Key: String; const Value: String);
|
|
|
|
|
|
|
|
function GetCurrentValue(): String;
|
|
|
|
protected
|
2004-07-29 13:48:35 +00:00
|
|
|
procedure InitHashItem(var AItem: PX2UtHashItem); override;
|
|
|
|
procedure FreeHashItem(var AItem: PX2UtHashItem); override;
|
2004-07-29 06:33:18 +00:00
|
|
|
public
|
|
|
|
constructor Create(); override;
|
|
|
|
property CurrentKey;
|
|
|
|
|
|
|
|
//:$ Gets or sets an item.
|
|
|
|
property Items[Key: String]: String read GetItem
|
|
|
|
write SetItem; default;
|
|
|
|
|
|
|
|
//:$ Returns the value at the current cursor location.
|
|
|
|
property CurrentValue: String read GetCurrentValue;
|
|
|
|
end;
|
|
|
|
|
|
|
|
implementation
|
2004-07-29 13:48:35 +00:00
|
|
|
resourcestring
|
|
|
|
RSEmptyKey = 'Cannot hash an empty key!';
|
|
|
|
|
|
|
|
|
|
|
|
{======================== TX2UtCustomHash
|
|
|
|
Initialization
|
|
|
|
========================================}
|
|
|
|
constructor TX2UtCustomHash.Create;
|
|
|
|
begin
|
|
|
|
inherited;
|
|
|
|
|
|
|
|
FHashItemSize := SizeOf(TX2UtHashItem);
|
|
|
|
DataSize := FHashItemSize;
|
|
|
|
end;
|
|
|
|
|
2004-07-29 06:33:18 +00:00
|
|
|
|
|
|
|
{======================== TX2UtCustomHash
|
|
|
|
Hashing
|
|
|
|
========================================}
|
2004-07-29 13:48:35 +00:00
|
|
|
procedure Mix(var A, B, C: Cardinal);
|
2004-07-29 15:49:42 +00:00
|
|
|
begin
|
|
|
|
Dec(A, B); Dec(A, C); C := C shr 13; A := A xor C;
|
|
|
|
Dec(B, C); Dec(B, A); A := A shl 8; B := B xor A;
|
|
|
|
Dec(C, A); Dec(C, B); B := B shr 13; C := C xor B;
|
|
|
|
Dec(A, B); Dec(A, C); C := C shr 12; A := A xor C;
|
|
|
|
Dec(B, C); Dec(B, A); A := A shl 16; B := B xor A;
|
|
|
|
Dec(C, A); Dec(C, B); B := B shr 5; C := C xor B;
|
|
|
|
Dec(A, B); Dec(A, C); C := C shr 3; A := A xor C;
|
|
|
|
Dec(B, C); Dec(B, A); A := A shl 10; B := B xor A;
|
|
|
|
Dec(C, A); Dec(C, B); B := B shr 15; C := C xor B;
|
2004-07-29 13:48:35 +00:00
|
|
|
end;
|
|
|
|
|
2004-07-29 06:33:18 +00:00
|
|
|
function TX2UtCustomHash.Hash;
|
2004-07-29 15:49:42 +00:00
|
|
|
var
|
|
|
|
iA: Cardinal;
|
|
|
|
iB: Cardinal;
|
|
|
|
iC: Cardinal;
|
|
|
|
iLength: Cardinal;
|
|
|
|
pValue: PChar;
|
|
|
|
|
2004-07-29 06:33:18 +00:00
|
|
|
begin
|
|
|
|
Result := 0;
|
2004-07-29 13:48:35 +00:00
|
|
|
|
2004-07-29 15:49:42 +00:00
|
|
|
iA := $9e3779b9;
|
|
|
|
iB := iA;
|
|
|
|
iC := iA;
|
|
|
|
iLength := Length(AValue);
|
|
|
|
pValue := PChar(AValue);
|
2004-07-29 13:48:35 +00:00
|
|
|
|
2004-07-29 15:49:42 +00:00
|
|
|
// Handle most of the key
|
|
|
|
while (iLength >= 12) do
|
|
|
|
begin
|
|
|
|
Inc(iA, Ord(pValue[0]) + (Ord(pValue[1]) shl 8) + (Ord(pValue[2]) shl 16) +
|
|
|
|
(Ord(pValue[3]) shl 24));
|
|
|
|
Inc(iB, Ord(pValue[4]) + (Ord(pValue[5]) shl 8) + (Ord(pValue[6]) shl 16) +
|
|
|
|
(Ord(pValue[7]) shl 24));
|
|
|
|
Inc(iA, Ord(pValue[8]) + (Ord(pValue[9]) shl 8) + (Ord(pValue[10]) shl 16) +
|
|
|
|
(Ord(pValue[11]) shl 24));
|
|
|
|
|
|
|
|
Mix(iA, iB, iC);
|
|
|
|
Inc(pValue, 12);
|
|
|
|
Dec(iLength, 12);
|
|
|
|
end;
|
|
|
|
|
|
|
|
// Handle the last 11 bytes
|
|
|
|
Inc(iC, iLength);
|
|
|
|
|
|
|
|
while iLength > 0 do
|
|
|
|
begin
|
|
|
|
case iLength of
|
|
|
|
11: Inc(iC, Ord(pValue[10]) shr 24);
|
|
|
|
10: Inc(iC, Ord(pValue[9]) shr 16);
|
|
|
|
9: Inc(iC, Ord(pValue[8]) shr 8);
|
|
|
|
8: Inc(iB, Ord(pValue[7]) shr 24);
|
|
|
|
7: Inc(iB, Ord(pValue[6]) shr 16);
|
|
|
|
6: Inc(iB, Ord(pValue[5]) shr 8);
|
|
|
|
5: Inc(iB, Ord(pValue[4]));
|
|
|
|
4: Inc(iA, Ord(pValue[3]) shr 24);
|
|
|
|
3: Inc(iA, Ord(pValue[2]) shr 16);
|
|
|
|
2: Inc(iA, Ord(pValue[1]) shr 8);
|
|
|
|
1: Inc(iA, Ord(pValue[0]));
|
|
|
|
end;
|
|
|
|
|
|
|
|
Dec(iLength);
|
|
|
|
end;
|
|
|
|
|
|
|
|
Mix(iA, iB, iC);
|
|
|
|
Result := iC;
|
2004-07-29 06:33:18 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{======================== TX2UtCustomHash
|
|
|
|
Tree Traversing
|
|
|
|
========================================}
|
|
|
|
function TX2UtCustomHash.ValidCursor;
|
|
|
|
begin
|
|
|
|
Result := inherited ValidCursor(ARaiseError);
|
|
|
|
if Result then
|
|
|
|
begin
|
2004-07-29 13:48:35 +00:00
|
|
|
Result := Assigned(FHashCursor);
|
|
|
|
|
|
|
|
if (not Result) and (ARaiseError) then
|
|
|
|
raise EX2UtBTreeInvalidCursor.Create(RSInvalidCursor);
|
2004-07-29 06:33:18 +00:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TX2UtCustomHash.ClearCursor;
|
|
|
|
begin
|
|
|
|
inherited;
|
|
|
|
|
|
|
|
FHashCursor := nil;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TX2UtCustomHash.Next;
|
|
|
|
begin
|
|
|
|
if Assigned(FHashCursor) then
|
|
|
|
FHashCursor := FHashCursor^.Next;
|
|
|
|
|
|
|
|
if not Assigned(FHashCursor) then
|
|
|
|
begin
|
|
|
|
Result := inherited Next();
|
|
|
|
if Result then
|
2004-07-29 13:48:35 +00:00
|
|
|
FHashCursor := PX2UtHashList(GetNodeData(Cursor))^.Root;
|
2004-07-29 06:33:18 +00:00
|
|
|
end else
|
|
|
|
Result := True;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
{======================== TX2UtCustomHash
|
|
|
|
Item Management
|
|
|
|
========================================}
|
2004-07-29 13:48:35 +00:00
|
|
|
function TX2UtCustomHash.GetItemData;
|
|
|
|
begin
|
|
|
|
Assert(HashDataSize > 0, RSInvalidDataSize);
|
|
|
|
Result := Pointer(Cardinal(AItem) + HashItemSize);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TX2UtCustomHash.LookupItem;
|
2004-07-29 06:33:18 +00:00
|
|
|
var
|
2004-07-29 15:49:42 +00:00
|
|
|
iIndex: Cardinal;
|
2004-07-29 13:48:35 +00:00
|
|
|
pData: PX2UtHashList;
|
|
|
|
pFound: PX2UtHashItem;
|
|
|
|
pItem: PX2UtHashItem;
|
|
|
|
pLast: PX2UtHashItem;
|
2004-07-29 06:33:18 +00:00
|
|
|
|
|
|
|
begin
|
2004-07-29 13:48:35 +00:00
|
|
|
Result := nil;
|
2004-07-29 06:33:18 +00:00
|
|
|
iIndex := Hash(AKey);
|
2004-07-29 13:48:35 +00:00
|
|
|
ANode := inherited LookupNode(iIndex, ACanCreate, ASetCursor);
|
|
|
|
|
|
|
|
if Assigned(ANode) then
|
|
|
|
begin
|
|
|
|
pData := PX2UtHashList(GetNodeData(ANode));
|
|
|
|
pItem := pData^.Root;
|
|
|
|
pLast := nil;
|
|
|
|
|
|
|
|
if Assigned(pItem) then
|
|
|
|
begin
|
|
|
|
pFound := nil;
|
|
|
|
|
|
|
|
// Find key
|
|
|
|
repeat
|
|
|
|
if pItem.Key = AKey then
|
|
|
|
begin
|
|
|
|
pFound := pItem;
|
|
|
|
break;
|
|
|
|
end;
|
|
|
|
|
|
|
|
pLast := pItem;
|
|
|
|
pItem := pItem^.Next;
|
|
|
|
until not Assigned(pItem);
|
|
|
|
|
|
|
|
pItem := pFound;
|
|
|
|
end;
|
|
|
|
|
|
|
|
if Assigned(pItem) then
|
|
|
|
Result := pItem
|
|
|
|
else if ACanCreate then
|
|
|
|
begin
|
|
|
|
InitHashItem(pItem);
|
|
|
|
|
|
|
|
if not Assigned(pData^.Root) then
|
|
|
|
pData^.Root := pItem;
|
|
|
|
|
|
|
|
if Assigned(pLast) then
|
|
|
|
pLast^.Next := pItem;
|
|
|
|
|
|
|
|
pItem^.Prev := pLast;
|
|
|
|
pItem^.Next := nil;
|
|
|
|
pItem^.Key := AKey;
|
|
|
|
Result := pItem;
|
|
|
|
end else
|
|
|
|
Result := nil;
|
|
|
|
end;
|
|
|
|
|
|
|
|
if Assigned(Result) and ASetCursor then
|
|
|
|
FHashCursor := Result;
|
2004-07-29 06:33:18 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TX2UtCustomHash.Delete;
|
2004-07-29 13:48:35 +00:00
|
|
|
var
|
|
|
|
bFree: Boolean;
|
|
|
|
pData: PX2UtHashList;
|
|
|
|
pNode: PX2UtBTreeNode;
|
|
|
|
pItem: PX2UtHashItem;
|
|
|
|
|
2004-07-29 06:33:18 +00:00
|
|
|
begin
|
2004-07-29 13:48:35 +00:00
|
|
|
pItem := LookupItem(AKey, pNode);
|
|
|
|
if Assigned(pItem) then
|
|
|
|
begin
|
|
|
|
pData := GetItemData(pItem);
|
|
|
|
|
|
|
|
if pData^.Root = pItem then
|
|
|
|
begin
|
|
|
|
if Assigned(pItem^.Next) then
|
|
|
|
pData^.Root := pItem^.Next
|
|
|
|
else if Assigned(pItem^.Prev) then
|
|
|
|
pData^.Root := pItem^.Prev
|
|
|
|
else
|
|
|
|
pData^.Root := nil;
|
|
|
|
end;
|
|
|
|
|
|
|
|
bFree := (not Assigned(pData^.Root));
|
|
|
|
FreeHashItem(pItem);
|
|
|
|
|
|
|
|
if bFree then
|
|
|
|
FreeNode(pNode);
|
|
|
|
end;
|
|
|
|
|
2004-07-29 06:33:18 +00:00
|
|
|
inherited Delete(Hash(AKey));
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TX2UtCustomHash.Exists;
|
|
|
|
begin
|
|
|
|
Result := inherited Exists(Hash(AKey), ASetCursor);
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
function TX2UtCustomHash.GetCurrentKey;
|
|
|
|
var
|
|
|
|
pKey: PString;
|
|
|
|
|
|
|
|
begin
|
|
|
|
Result := '';
|
|
|
|
if ValidCursor(True) then
|
|
|
|
begin
|
2004-07-29 13:48:35 +00:00
|
|
|
Result := HashCursor^.Key;
|
2004-07-29 06:33:18 +00:00
|
|
|
{
|
|
|
|
pKey := GetNodeInternal(Cursor);
|
|
|
|
Result := pKey^;
|
|
|
|
}
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
2004-07-29 13:48:35 +00:00
|
|
|
procedure TX2UtCustomHash.FreeNode;
|
2004-07-29 06:33:18 +00:00
|
|
|
var
|
2004-07-29 13:48:35 +00:00
|
|
|
pData: PX2UtHashItem;
|
|
|
|
pNext: PX2UtHashItem;
|
2004-07-29 06:33:18 +00:00
|
|
|
|
|
|
|
begin
|
2004-07-29 13:48:35 +00:00
|
|
|
pData := PX2UtHashList(GetNodeData(ANode))^.Root;
|
|
|
|
while Assigned(pData) do
|
|
|
|
begin
|
|
|
|
pNext := pData^.Next;
|
|
|
|
FreeHashItem(pData);
|
|
|
|
pData := pNext;
|
|
|
|
end;
|
2004-07-29 06:33:18 +00:00
|
|
|
|
2004-07-29 13:48:35 +00:00
|
|
|
inherited;
|
2004-07-29 06:33:18 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
2004-07-29 13:48:35 +00:00
|
|
|
procedure TX2UtCustomHash.InitHashItem;
|
2004-07-29 06:33:18 +00:00
|
|
|
begin
|
2004-07-29 13:48:35 +00:00
|
|
|
Assert(HashDataSize > 0, RSInvalidDataSize);
|
|
|
|
GetMem(AItem, HashTotalSize);
|
|
|
|
FillChar(AItem^, HashTotalSize, #0);
|
|
|
|
end;
|
2004-07-29 06:33:18 +00:00
|
|
|
|
2004-07-29 13:48:35 +00:00
|
|
|
procedure TX2UtCustomHash.FreeHashItem;
|
|
|
|
begin
|
|
|
|
if Assigned(AItem^.Prev) then
|
|
|
|
AItem^.Prev^.Next := AItem^.Next;
|
|
|
|
|
|
|
|
if Assigned(AItem^.Next) then
|
|
|
|
AItem^.Next^.Prev := AItem^.Prev;
|
|
|
|
|
|
|
|
FreeMem(AItem, HashTotalSize);
|
|
|
|
ClearCursor();
|
|
|
|
|
|
|
|
AItem := nil;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
function TX2UtCustomHash.GetHashTotalSize;
|
|
|
|
begin
|
|
|
|
Result := FHashItemSize + FHashDataSize;
|
2004-07-29 06:33:18 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
{============================== TX2UtHash
|
|
|
|
Item Management
|
|
|
|
========================================}
|
2004-07-29 13:48:35 +00:00
|
|
|
(*
|
2004-07-29 06:33:18 +00:00
|
|
|
constructor TX2UtHash.Create;
|
|
|
|
begin
|
|
|
|
inherited;
|
|
|
|
|
|
|
|
DataSize := SizeOf(Pointer);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TX2UtHash.GetItem;
|
|
|
|
var
|
|
|
|
pNode: PX2UtBTreeNode;
|
|
|
|
|
|
|
|
begin
|
|
|
|
pNode := LookupNode(Key);
|
|
|
|
if Assigned(pNode) then
|
|
|
|
Result := PPointer(GetNodeData(pNode))^;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TX2UtHash.SetItem;
|
|
|
|
var
|
|
|
|
pNode: PX2UtBTreeNode;
|
|
|
|
|
|
|
|
begin
|
|
|
|
pNode := LookupNode(Key, True);
|
|
|
|
if Assigned(pNode) then
|
|
|
|
PPointer(GetNodeData(pNode))^ := Value;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TX2UtHash.GetCurrentValue;
|
|
|
|
begin
|
|
|
|
Result := nil;
|
|
|
|
if ValidCursor(True) then
|
|
|
|
Result := PPointer(GetNodeData(Cursor))^;
|
|
|
|
end;
|
2004-07-29 13:48:35 +00:00
|
|
|
*)
|
2004-07-29 06:33:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
{======================== TX2UtStringHash
|
|
|
|
Item Management
|
|
|
|
========================================}
|
|
|
|
constructor TX2UtStringHash.Create;
|
|
|
|
begin
|
|
|
|
inherited;
|
|
|
|
|
2004-07-29 13:48:35 +00:00
|
|
|
HashDataSize := SizeOf(PString);
|
2004-07-29 06:33:18 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
function TX2UtStringHash.GetItem;
|
|
|
|
var
|
|
|
|
pNode: PX2UtBTreeNode;
|
2004-07-29 13:48:35 +00:00
|
|
|
pItem: PX2UtHashItem;
|
2004-07-29 06:33:18 +00:00
|
|
|
|
|
|
|
begin
|
2004-07-29 13:48:35 +00:00
|
|
|
pItem := LookupItem(Key, pNode);
|
|
|
|
if Assigned(pItem) then
|
|
|
|
Result := PString(GetItemData(pItem))^;
|
2004-07-29 06:33:18 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TX2UtStringHash.SetItem;
|
|
|
|
var
|
|
|
|
pNode: PX2UtBTreeNode;
|
2004-07-29 13:48:35 +00:00
|
|
|
pItem: PX2UtHashItem;
|
2004-07-29 06:33:18 +00:00
|
|
|
|
|
|
|
begin
|
2004-07-29 13:48:35 +00:00
|
|
|
Assert(Length(Key) > 0, RSEmptyKey);
|
|
|
|
pItem := LookupItem(Key, pNode, True);
|
|
|
|
if Assigned(pItem) then
|
|
|
|
PString(GetItemData(pItem))^ := Value;
|
2004-07-29 06:33:18 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
2004-07-29 13:48:35 +00:00
|
|
|
procedure TX2UtStringHash.InitHashItem;
|
2004-07-29 06:33:18 +00:00
|
|
|
var
|
|
|
|
pData: PString;
|
|
|
|
|
|
|
|
begin
|
|
|
|
inherited;
|
|
|
|
|
2004-07-29 13:48:35 +00:00
|
|
|
pData := GetItemData(AItem);
|
2004-07-29 06:33:18 +00:00
|
|
|
Initialize(pData^);
|
|
|
|
end;
|
|
|
|
|
2004-07-29 13:48:35 +00:00
|
|
|
procedure TX2UtStringHash.FreeHashItem;
|
2004-07-29 06:33:18 +00:00
|
|
|
var
|
|
|
|
pData: PString;
|
|
|
|
|
|
|
|
begin
|
2004-07-29 13:48:35 +00:00
|
|
|
pData := GetItemData(AItem);
|
2004-07-29 06:33:18 +00:00
|
|
|
Finalize(pData^);
|
|
|
|
|
|
|
|
inherited;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
function TX2UtStringHash.GetCurrentValue;
|
|
|
|
var
|
|
|
|
pData: PString;
|
|
|
|
|
|
|
|
begin
|
|
|
|
if ValidCursor() then
|
2004-07-29 13:48:35 +00:00
|
|
|
Result := PString(GetItemData(HashCursor))^;
|
2004-07-29 06:33:18 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
end.
|