diff --git a/UnitTests/Units/HashesTest.pas b/UnitTests/Units/HashesTest.pas
index a371d3c..eb5bbbd 100644
--- a/UnitTests/Units/HashesTest.pas
+++ b/UnitTests/Units/HashesTest.pas
@@ -13,65 +13,65 @@ type
private
FHash: TX2CustomHash;
protected
- procedure TearDown(); override;
- procedure FillTestItems(); virtual; abstract;
+ procedure TearDown; override;
+ procedure FillTestItems; virtual; abstract;
published
- procedure testSet(); virtual; abstract;
- procedure testGet(); virtual; abstract;
- procedure testClear();
- procedure testDelete(); virtual; abstract;
- procedure testIterate(); virtual; abstract;
- procedure testEnumerator(); virtual; abstract;
+ procedure testSet; virtual; abstract;
+ procedure testGet; virtual; abstract;
+ procedure testClear;
+ procedure testDelete; virtual; abstract;
+ procedure testIterate; virtual; abstract;
+ procedure testEnumerator; virtual; abstract;
end;
// Two test cases involving all value managers.
// This should be sufficient for a realistic scenario.
THashesSITest = class(THashesTest)
private
- function GetHash(): TX2SIHash;
+ function GetHash: TX2SIHash;
property Hash: TX2SIHash read GetHash;
protected
- procedure SetUp(); override;
- procedure FillTestItems(); override;
+ procedure SetUp; override;
+ procedure FillTestItems; override;
published
- procedure testSet(); override;
- procedure testGet(); override;
- procedure testDelete(); override;
- procedure testIterate(); override;
- procedure testEnumerator(); override;
+ procedure testSet; override;
+ procedure testGet; override;
+ procedure testDelete; override;
+ procedure testIterate; override;
+ procedure testEnumerator; override;
end;
THashesPOTest = class(THashesTest)
private
- function GetHash(): TX2POHash;
+ function GetHash: TX2POHash;
property Hash: TX2POHash read GetHash;
protected
- procedure SetUp(); override;
- procedure FillTestItems(); override;
+ procedure SetUp; override;
+ procedure FillTestItems; override;
published
- procedure testSet(); override;
- procedure testGet(); override;
- procedure testDelete(); override;
- procedure testIterate(); override;
- procedure testEnumerator(); override;
+ procedure testSet; override;
+ procedure testGet; override;
+ procedure testDelete; override;
+ procedure testIterate; override;
+ procedure testEnumerator; override;
end;
THashesVariantTest = class(THashesTest)
private
- function GetHash(): TX2SVHash;
+ function GetHash: TX2SVHash;
property Hash: TX2SVHash read GetHash;
protected
- procedure SetUp(); override;
- procedure FillTestItems(); override;
+ procedure SetUp; override;
+ procedure FillTestItems; override;
published
- procedure testSet(); override;
- procedure testGet(); override;
- procedure testDelete(); override;
- procedure testIterate(); override;
- procedure testEnumerator(); override;
+ procedure testSet; override;
+ procedure testGet; override;
+ procedure testDelete; override;
+ procedure testIterate; override;
+ procedure testEnumerator; override;
end;
THashesBugTest = class(TTestCase)
@@ -101,8 +101,8 @@ end;
procedure THashesTest.testClear;
begin
- FillTestItems();
- FHash.Clear();
+ FillTestItems;
+ FHash.Clear;
CheckEquals(0, FHash.Count);
end;
@@ -112,7 +112,7 @@ procedure THashesSITest.SetUp;
begin
inherited;
- FHash := TX2SIHash.Create();
+ FHash := TX2SIHash.Create;
end;
procedure THashesSITest.FillTestItems;
@@ -124,13 +124,13 @@ end;
procedure THashesSITest.testSet;
begin
- FillTestItems();
+ FillTestItems;
CheckEquals(3, Hash.Count);
end;
procedure THashesSITest.testGet;
begin
- FillTestItems();
+ FillTestItems;
CheckEquals(1, Hash['Key1']);
CheckEquals(2, Hash['Key2']);
CheckEquals(3, Hash['Key3']);
@@ -138,7 +138,7 @@ end;
procedure THashesSITest.testDelete;
begin
- FillTestItems();
+ FillTestItems;
Hash.Delete('Key2');
CheckEquals(2, Hash.Count);
@@ -154,7 +154,7 @@ var
begin
{$IFDEF D2006PLUS}
- FillTestItems();
+ FillTestItems;
FillChar(aPresent, SizeOf(aPresent), #0);
for sKey in Hash do
@@ -188,10 +188,10 @@ var
aPresent: array[1..3] of Boolean;
begin
- FillTestItems();
+ FillTestItems;
FillChar(aPresent, SizeOf(aPresent), #0);
- Hash.First();
- while Hash.Next() do
+ Hash.First;
+ while Hash.Next do
if ((Hash.CurrentKey = 'Key1') and (Hash.CurrentValue = 1)) or
((Hash.CurrentKey = 'Key2') and (Hash.CurrentValue = 2)) or
((Hash.CurrentKey = 'Key3') and (Hash.CurrentValue = 3)) then
@@ -203,7 +203,7 @@ begin
end;
-function THashesSITest.GetHash(): TX2SIHash;
+function THashesSITest.GetHash: TX2SIHash;
begin
Result := TX2SIHash(FHash);
end;
@@ -219,20 +219,20 @@ end;
procedure THashesPOTest.FillTestItems;
begin
- Hash[Pointer(0)] := TObject0.Create();
- Hash[Pointer(1)] := TObject1.Create();
- Hash[Pointer(2)] := TObject2.Create();
+ Hash[Pointer(0)] := TObject0.Create;
+ Hash[Pointer(1)] := TObject1.Create;
+ Hash[Pointer(2)] := TObject2.Create;
end;
procedure THashesPOTest.testSet;
begin
- FillTestItems();
+ FillTestItems;
CheckEquals(3, Hash.Count);
end;
procedure THashesPOTest.testGet;
begin
- FillTestItems();
+ FillTestItems;
CheckTrue(Hash[Pointer(0)] is TObject0);
CheckTrue(Hash[Pointer(1)] is TObject1);
CheckTrue(Hash[Pointer(2)] is TObject2);
@@ -240,7 +240,7 @@ end;
procedure THashesPOTest.testDelete;
begin
- FillTestItems();
+ FillTestItems;
Hash.Delete(Pointer(1));
CheckEquals(2, Hash.Count);
@@ -256,7 +256,7 @@ var
begin
{$IFDEF D2006PLUS}
- FillTestItems();
+ FillTestItems;
FillChar(aPresent, SizeOf(aPresent), #0);
for pKey in Hash do
@@ -273,10 +273,10 @@ var
aPresent: array[0..2] of Boolean;
begin
- FillTestItems();
+ FillTestItems;
FillChar(aPresent, SizeOf(aPresent), #0);
- Hash.First();
- while Hash.Next() do
+ Hash.First;
+ while Hash.Next do
if ((Hash.CurrentKey = Pointer(0)) and (Hash.CurrentValue is TObject0)) or
((Hash.CurrentKey = Pointer(1)) and (Hash.CurrentValue is TObject1)) or
((Hash.CurrentKey = Pointer(2)) and (Hash.CurrentValue is TObject2)) then
@@ -288,7 +288,7 @@ begin
end;
-function THashesPOTest.GetHash(): TX2POHash;
+function THashesPOTest.GetHash: TX2POHash;
begin
Result := TX2POHash(FHash);
end;
@@ -298,10 +298,10 @@ procedure THashesVariantTest.SetUp;
begin
inherited;
- FHash := TX2SVHash.Create();
+ FHash := TX2SVHash.Create;
end;
-function THashesVariantTest.GetHash(): TX2SVHash;
+function THashesVariantTest.GetHash: TX2SVHash;
begin
Result := TX2SVHash(FHash);
end;
@@ -315,13 +315,13 @@ end;
procedure THashesVariantTest.testSet;
begin
- FillTestItems();
+ FillTestItems;
CheckEquals(3, Hash.Count);
end;
procedure THashesVariantTest.testGet;
begin
- FillTestItems();
+ FillTestItems;
CheckTrue(Hash['Key1'] = 'String');
CheckTrue(Hash['Key2'] = 5);
CheckTrue(Hash['Key3'] = 40.4);
@@ -329,7 +329,7 @@ end;
procedure THashesVariantTest.testDelete;
begin
- FillTestItems();
+ FillTestItems;
Hash.Delete('Key2');
CheckEquals(2, Hash.Count);
@@ -348,10 +348,10 @@ var
aPresent: array[0..2] of Boolean;
begin
- FillTestItems();
+ FillTestItems;
FillChar(aPresent, SizeOf(aPresent), #0);
- Hash.First();
- while Hash.Next() do
+ Hash.First;
+ while Hash.Next do
if ((Hash.CurrentKey = 'Key1') and (Hash.CurrentValue = 'String')) then
aPresent[0] := True
else if ((Hash.CurrentKey = 'Key2') and (Hash.CurrentValue = 5)) then
diff --git a/UnitTests/X2UtUnitTests.dpr b/UnitTests/X2UtUnitTests.dpr
index 9bffaa8..ee10f01 100644
--- a/UnitTests/X2UtUnitTests.dpr
+++ b/UnitTests/X2UtUnitTests.dpr
@@ -7,7 +7,9 @@ uses
BitsTest in 'Units\BitsTest.pas',
HashesTest in 'Units\HashesTest.pas',
PersistTest in 'Units\PersistTest.pas',
- X2UtSingleInstance in '..\X2UtSingleInstance.pas';
+ X2UtSingleInstance in '..\X2UtSingleInstance.pas',
+ X2UtHashes in '..\X2UtHashes.pas',
+ X2UtHashesVariants in '..\X2UtHashesVariants.pas';
//SettingsTest in 'Units\SettingsTest.pas',
//IniParserTest in 'Units\IniParserTest.pas';
diff --git a/UnitTests/X2UtUnitTests.dproj b/UnitTests/X2UtUnitTests.dproj
index dde386d..89568c0 100644
--- a/UnitTests/X2UtUnitTests.dproj
+++ b/UnitTests/X2UtUnitTests.dproj
@@ -42,53 +42,18 @@
Delphi.Personality
VCLApplication
-
- ip-to-country.csv countries.csv geo.db
- False
- True
- False
-
-
- False
- False
- 1
- 0
- 0
- 0
- False
- False
- False
- False
- False
- 1043
- 1252
-
-
-
-
- 1.0.0.0
-
-
-
-
-
- 1.0.0.0
-
-
-
-
+ip-to-country.csv countries.csv geo.dbFalseTrueFalseFalseFalse1000FalseFalseFalseFalseFalse104312521.0.0.01.0.0.0X2UtUnitTests.dpr
-
+
MainSource
+
+
-
\ No newline at end of file
diff --git a/X2UtHashes.pas b/X2UtHashes.pas
index da2560c..f583b7c 100644
--- a/X2UtHashes.pas
+++ b/X2UtHashes.pas
@@ -52,11 +52,14 @@ type
{
:$ Internal representation of a hash item.
}
+ PX2HashCookie = Pointer;
+
PX2HashItem = ^TX2HashItem;
TX2HashItem = record
ID: Cardinal;
end;
+
PX2HashBucket = ^TX2HashBucket;
TX2HashBucket = record
ID: Cardinal;
@@ -65,135 +68,154 @@ type
Items: array[0..Pred(LeafSize)] of PX2HashItem;
end;
+
PX2HashValue = ^TX2HashValue;
TX2HashValue = record
ID: Cardinal;
Next: PX2HashValue;
- Key: Pointer;
- Value: Pointer;
+ Key: PX2HashCookie;
+ Value: PX2HashCookie;
end;
+
TX2BucketPath = record
Bucket: PX2HashBucket;
Index: Integer;
end;
+
+ PX2HashStringCookie = ^TX2HashStringCookie;
+ TX2HashStringCookie = record
+ Length: Cardinal;
+ Value: PChar;
+ end;
+
+
{
:$ Default cursor implementation.
- :: Traverses the hash trie from top-to-bottom, left-to-right.
+ :: Traverses the hash tree from top-to-bottom, left-to-right.
}
TX2HashCursor = class(TObject)
private
- FBucketPath: array of TX2BucketPath;
- FCurrent: PX2HashValue;
+ FBucketPath: array of TX2BucketPath;
+ FCurrent: PX2HashValue;
protected
- function GetCurrent(): PX2HashValue; virtual;
+ function GetCurrent: PX2HashValue; virtual;
public
constructor Create(const ABucket: PX2HashBucket); virtual;
- procedure First(); virtual;
- function Next(): Boolean; virtual;
+ procedure First; virtual;
+ function Next: Boolean; virtual;
- property Current: PX2HashValue read GetCurrent;
+ property Current: PX2HashValue read GetCurrent;
end;
{$IFDEF D2005PLUS}
{$ENDREGION}
+
{$REGION 'Internal value managers'}
{$ENDIF}
{
:$ Base value manager.
}
- TX2CustomHashManager = class(TObject)
+ TX2CustomHashManager = class(TObject)
protected
- procedure Initialize(var AData: Pointer); virtual;
- procedure Finalize(var AData: Pointer); virtual;
+ procedure FreeCookie(var ACookie: PX2HashCookie); virtual;
- function DataSize(const AData: Pointer): Cardinal; virtual;
- function DataPointer(const AData: Pointer): Pointer; virtual;
-
- function ToPointer(const AValue: Pointer; const ASize: Cardinal): Pointer; overload; virtual;
- function ToValue(const AData: Pointer; var AValue): Cardinal; overload; virtual;
-
- function Compare(const AData: Pointer; const AValue: Pointer;
- const ASize: Cardinal): Boolean; virtual;
+ function Hash(ACookie: PX2HashCookie): Cardinal; virtual; abstract;
+ function Compare(const ACookie1, ACookie2: PX2HashCookie): Boolean; virtual; abstract;
+ function Clone(const ACookie: PX2HashCookie): PX2HashCookie; virtual; abstract;
end;
+
TX2HashPointerManager = class(TX2CustomHashManager)
protected
- function ToPointer(const AValue: Pointer): Pointer; overload;
- function ToValue(const AData: Pointer): Pointer; overload;
+ function CreateCookie(const AValue: Pointer): PX2HashCookie; overload;
+ function GetValue(const ACookie: PX2HashCookie): Pointer; overload;
+
+ function Hash(ACookie: PX2HashCookie): Cardinal; override;
+ function Compare(const ACookie1, ACookie2: PX2HashCookie): Boolean; override;
+ function Clone(const ACookie: PX2HashCookie): PX2HashCookie; override;
end;
+
{
:$ Integer value class.
}
TX2HashIntegerManager = class(TX2CustomHashManager)
protected
- function ToPointer(const AValue: Integer): Pointer; overload;
- function ToValue(const AData: Pointer): Integer; overload;
+ function CreateCookie(const AValue: Integer): PX2HashCookie; overload;
+ function GetValue(const ACookie: PX2HashCookie): Integer; overload;
+
+ function Hash(ACookie: PX2HashCookie): Cardinal; override;
+ function Compare(const ACookie1, ACookie2: PX2HashCookie): Boolean; override;
+ function Clone(const ACookie: PX2HashCookie): PX2HashCookie; override;
end;
+
{
:$ Object value class.
}
- TX2HashObjectManager = class(TX2CustomHashManager)
+ TX2HashObjectManager = class(TX2CustomHashManager)
private
- FOwnsObjects: Boolean;
+ FOwnsObjects: Boolean;
protected
- procedure Finalize(var AData: Pointer); override;
+ procedure FreeCookie(var ACookie: PX2HashCookie); override;
- function ToPointer(const AValue: TObject): Pointer; overload;
- function ToValue(const AData: Pointer): TObject; overload;
+ function CreateCookie(const AValue: TObject): PX2HashCookie; overload;
+ function GetValue(const ACookie: PX2HashCookie): TObject; overload;
- property OwnsObjects: Boolean read FOwnsObjects write FOwnsObjects;
+ function Hash(ACookie: PX2HashCookie): Cardinal; override;
+ function Compare(const ACookie1, ACookie2: PX2HashCookie): Boolean; override;
+ function Clone(const ACookie: PX2HashCookie): PX2HashCookie; override;
+
+ property OwnsObjects: Boolean read FOwnsObjects write FOwnsObjects;
end;
+
{
:$ String value class.
}
- TX2HashStringManager = class(TX2CustomHashManager)
+ TX2HashStringManager = class(TX2CustomHashManager)
protected
- procedure Finalize(var AData: Pointer); override;
+ procedure FreeCookie(var ACookie: PX2HashCookie); override;
- function DataSize(const AData: Pointer): Cardinal; override;
- function DataPointer(const AData: Pointer): Pointer; override;
+ function CreateCookie(const AValue: string): PX2HashCookie; overload;
+ function GetValue(const ACookie: PX2HashCookie): string; overload;
- function ToPointer(const AValue: Pointer; const ASize: Cardinal): Pointer; override;
- function ToValue(const AData: Pointer; var AValue): Cardinal; override;
- function ToPointer(const AValue: String): Pointer; overload;
- function ToValue(const AData: Pointer): String; overload;
-
- function Compare(const AData: Pointer; const AValue: Pointer;
- const ASize: Cardinal): Boolean; override;
+ function Hash(ACookie: PX2HashCookie): Cardinal; override;
+ function Compare(const ACookie1, ACookie2: PX2HashCookie): Boolean; override;
+ function Clone(const ACookie: PX2HashCookie): PX2HashCookie; override;
end;
{$IFDEF D2005PLUS}
{$ENDREGION}
+
{$REGION 'Delphi 2006 enumerator support'}
{$ENDIF}
{
:$ Base enumerator class.
}
- TX2HashEnumerator = class(TObject)
+ TX2HashEnumerator = class(TObject)
private
FCursor: TX2HashCursor;
FManager: TX2CustomHashManager;
FEnumKeys: Boolean;
- function GetCursor(): Pointer;
+ function GetCursor: PX2HashCookie;
protected
property Manager: TX2CustomHashManager read FManager;
- property Cursor: Pointer read GetCursor;
+ property Cursor: PX2HashCookie read GetCursor;
public
constructor Create(const AHash: TX2CustomHash;
const AEnumKeys: Boolean);
- destructor Destroy(); override;
+ destructor Destroy; override;
- function MoveNext(): Boolean;
+ function MoveNext: Boolean;
end;
+
{
:$ Enumerator for pointer values.
}
@@ -201,9 +223,10 @@ type
private
function GetCurrent: Pointer;
public
- property Current: Pointer read GetCurrent;
+ property Current: Pointer read GetCurrent;
end;
+
{
:$ Enumerator for integer values.
}
@@ -211,9 +234,10 @@ type
private
function GetCurrent: Integer;
public
- property Current: Integer read GetCurrent;
+ property Current: Integer read GetCurrent;
end;
+
{
:$ Enumerator for object values.
}
@@ -221,21 +245,23 @@ type
private
function GetCurrent: TObject;
public
- property Current: TObject read GetCurrent;
+ property Current: TObject read GetCurrent;
end;
+
{
:$ Enumerator for string values
}
TX2HashStringEnumerator = class(TX2HashEnumerator)
private
- function GetCurrent(): String;
+ function GetCurrent: String;
public
- property Current: String read GetCurrent;
+ property Current: String read GetCurrent;
end;
{$IFDEF D2005PLUS}
{$ENDREGION}
+
{$REGION 'Abstract hash implementation'}
{$ENDIF}
{
@@ -250,47 +276,46 @@ type
FKeyManager: TX2CustomHashManager;
FValueManager: TX2CustomHashManager;
protected
- function CreateCursor(): TX2HashCursor; virtual;
- function CreateKeyManager(): TX2CustomHashManager; virtual; abstract;
- function CreateValueManager(): TX2CustomHashManager; virtual; abstract;
- procedure InvalidateCursor();
+ function CreateCursor: TX2HashCursor; virtual;
+ function CreateKeyManager: TX2CustomHashManager; virtual; abstract;
+ function CreateValueManager: TX2CustomHashManager; virtual; abstract;
+ procedure InvalidateCursor;
- function Hash(const AKey: Pointer; const ASize: Cardinal): Cardinal; virtual;
function CursorRequired(const ARaiseException: Boolean = True): Boolean;
function InternalFind(const ABucket: PX2HashBucket;
- const AHash: Cardinal; const AKey: Pointer;
- const ASize: Cardinal;
+ const AHash: Cardinal; const AKey: PX2HashCookie;
const AAllowCreate: Boolean;
const AExisting: PX2HashValue = nil): PX2HashValue;
function InternalDelete(const ABucket: PX2HashBucket;
- const AHash: Cardinal; const AKey: Pointer;
- const ASize: Cardinal): Boolean;
+ const AHash: Cardinal; const AKey: PX2HashCookie): Boolean;
- function Find(const AKey: Pointer; const ASize: Cardinal;
- const AAllowCreate: Boolean): PX2HashValue; overload;
- function Exists(const AKey: Pointer; const ASize: Cardinal): Boolean; overload;
- function Delete(const AKey: Pointer; const ASize: Cardinal): Boolean; overload;
+ { :$ AKey will be freed by these methods, so make sure to pass a Clone
+ :$ if you need it afterwards! }
+ function Find(const AKey: PX2HashCookie; const AAllowCreate: Boolean): PX2HashValue; overload;
+ function Exists(const AKey: PX2HashCookie): Boolean; overload;
+ function Delete(const AKey: PX2HashCookie): Boolean; overload;
procedure SetValue(const AValue: PX2HashValue; const AData: Pointer);
- property Cursor: TX2HashCursor read FCursor;
- property KeyManager: TX2CustomHashManager read FKeyManager;
- property ValueManager: TX2CustomHashManager read FValueManager;
+ property Cursor: TX2HashCursor read FCursor;
+ property KeyManager: TX2CustomHashManager read FKeyManager;
+ property ValueManager: TX2CustomHashManager read FValueManager;
public
- constructor Create(); virtual;
- destructor Destroy(); override;
+ constructor Create; virtual;
+ destructor Destroy; override;
- procedure Clear();
+ procedure Clear;
- procedure First();
- function Next(): Boolean;
+ procedure First;
+ function Next: Boolean;
- property Count: Integer read FCount;
+ property Count: Integer read FCount;
end;
{$IFDEF D2005PLUS}
{$ENDREGION}
+
{$REGION 'Base hash classes'}
{$ENDIF}
{
@@ -298,79 +323,92 @@ type
}
TX2CustomPointerHash = class(TX2CustomHash)
private
- function GetCurrentKey(): Pointer;
+ function GetCurrentKey: Pointer;
+ function GetKeyManager: TX2HashPointerManager;
protected
- function CreateKeyManager(): TX2CustomHashManager; override;
- function Find(const AKey: Pointer;
- const AAllowCreate: Boolean): PX2HashValue; overload;
+ function CreateKeyManager: TX2CustomHashManager; override;
+ function Find(const AKey: Pointer; const AAllowCreate: Boolean): PX2HashValue; overload;
+
+ property KeyManager: TX2HashPointerManager read GetKeyManager;
public
- function GetEnumerator(): TX2HashPointerEnumerator;
+ function GetEnumerator: TX2HashPointerEnumerator;
function Exists(const AKey: Pointer): Boolean; overload;
function Delete(const AKey: Pointer): Boolean; overload;
- property CurrentKey: Pointer read GetCurrentKey;
+ property CurrentKey: Pointer read GetCurrentKey;
end;
+
{
:$ Base hash implementation for integer keys.
}
TX2CustomIntegerHash = class(TX2CustomHash)
private
- function GetCurrentKey(): Integer;
+ function GetCurrentKey: Integer;
+ function GetKeyManager: TX2HashIntegerManager;
protected
- function CreateKeyManager(): TX2CustomHashManager; override;
- function Find(const AKey: Integer;
- const AAllowCreate: Boolean): PX2HashValue; overload;
+ function CreateKeyManager: TX2CustomHashManager; override;
+ function Find(const AKey: Integer; const AAllowCreate: Boolean): PX2HashValue; overload;
+
+ property KeyManager: TX2HashIntegerManager read GetKeyManager;
public
- function GetEnumerator(): TX2HashIntegerEnumerator;
+ function GetEnumerator: TX2HashIntegerEnumerator;
function Exists(const AKey: Integer): Boolean; overload;
function Delete(const AKey: Integer): Boolean; overload;
- property CurrentKey: Integer read GetCurrentKey;
+ property CurrentKey: Integer read GetCurrentKey;
end;
+
{
:$ Base hash implementation for object keys.
}
TX2CustomObjectHash = class(TX2CustomHash)
private
- function GetCurrentKey(): TObject;
+ function GetCurrentKey: TObject;
+ function GetKeyManager: TX2HashObjectManager;
protected
- function CreateKeyManager(): TX2CustomHashManager; override;
- function Find(const AKey: TObject;
- const AAllowCreate: Boolean): PX2HashValue; overload;
+ function CreateKeyManager: TX2CustomHashManager; override;
+ function Find(const AKey: TObject; const AAllowCreate: Boolean): PX2HashValue; overload;
+
+ property KeyManager: TX2HashObjectManager read GetKeyManager;
public
- function GetEnumerator(): TX2HashObjectEnumerator;
+ function GetEnumerator: TX2HashObjectEnumerator;
function Exists(const AKey: TObject): Boolean; overload;
function Delete(const AKey: TObject): Boolean; overload;
- property CurrentKey: TObject read GetCurrentKey;
+ property CurrentKey: TObject read GetCurrentKey;
end;
+
{
:$ Base hash implementation for string keys.
}
TX2CustomStringHash = class(TX2CustomHash)
protected
- function GetCurrentKey(): String;
+ function GetCurrentKey: String;
+ private
+ function GetKeyManager: TX2HashStringManager;
protected
- function CreateKeyManager(): TX2CustomHashManager; override;
- function Find(const AKey: String;
- const AAllowCreate: Boolean): PX2HashValue; overload;
+ function CreateKeyManager: TX2CustomHashManager; override;
+ function Find(const AKey: String; const AAllowCreate: Boolean): PX2HashValue; overload;
+
+ property KeyManager: TX2HashStringManager read GetKeyManager;
public
- function GetEnumerator(): TX2HashStringEnumerator;
+ function GetEnumerator: TX2HashStringEnumerator;
function Exists(const AKey: String): Boolean; overload;
function Delete(const AKey: String): Boolean; overload;
- property CurrentKey: String read GetCurrentKey;
+ property CurrentKey: String read GetCurrentKey;
end;
{$IFDEF D2005PLUS}
{$ENDREGION}
+
{$REGION 'Concrete hash classes'}
{$ENDIF}
{
@@ -378,264 +416,344 @@ type
}
TX2PPHash = class(TX2CustomPointerHash)
protected
- function GetCurrentValue(): Pointer;
+ function GetCurrentValue: Pointer;
function GetValue(Key: Pointer): Pointer;
procedure SetValue(Key: Pointer; const Value: Pointer);
+ private
+ function GetValueManager: TX2HashPointerManager;
protected
- function CreateValueManager(): TX2CustomHashManager; override;
+ function CreateValueManager: TX2CustomHashManager; override;
+
+ property ValueManager: TX2HashPointerManager read GetValueManager;
public
- property CurrentValue: Pointer read GetCurrentValue;
- property Values[Key: Pointer]: Pointer read GetValue write SetValue; default;
+ property CurrentValue: Pointer read GetCurrentValue;
+ property Values[Key: Pointer]: Pointer read GetValue write SetValue; default;
end;
+
{
:$ Pointer-to-Integer hash.
}
TX2PIHash = class(TX2CustomPointerHash)
protected
- function GetCurrentValue(): Integer;
+ function GetCurrentValue: Integer;
function GetValue(Key: Pointer): Integer;
procedure SetValue(Key: Pointer; const Value: Integer);
+ private
+ function GetValueManager: TX2HashIntegerManager;
protected
- function CreateValueManager(): TX2CustomHashManager; override;
+ function CreateValueManager: TX2CustomHashManager; override;
+
+ property ValueManager: TX2HashIntegerManager read GetValueManager;
public
- property CurrentValue: Integer read GetCurrentValue;
- property Values[Key: Pointer]: Integer read GetValue write SetValue; default;
+ property CurrentValue: Integer read GetCurrentValue;
+ property Values[Key: Pointer]: Integer read GetValue write SetValue; default;
end;
+
{
:$ Pointer-to-Object hash.
}
TX2POHash = class(TX2CustomPointerHash)
protected
- function GetCurrentValue(): TObject;
- function GetOwnsObjects(): Boolean;
+ function GetCurrentValue: TObject;
+ function GetOwnsObjects: Boolean;
procedure SetOwnsObjects(const Value: Boolean);
function GetValue(Key: Pointer): TObject;
procedure SetValue(Key: Pointer; const Value: TObject);
+ private
+ function GetValueManager: TX2HashObjectManager;
protected
- function CreateValueManager(): TX2CustomHashManager; override;
+ function CreateValueManager: TX2CustomHashManager; override;
+
+ property ValueManager: TX2HashObjectManager read GetValueManager;
public
constructor Create(const AOwnsObjects: Boolean = False); reintroduce;
- property CurrentValue: TObject read GetCurrentValue;
- property OwnsObjects: Boolean read GetOwnsObjects write SetOwnsObjects;
- property Values[Key: Pointer]: TObject read GetValue write SetValue; default;
+ property CurrentValue: TObject read GetCurrentValue;
+ property OwnsObjects: Boolean read GetOwnsObjects write SetOwnsObjects;
+ property Values[Key: Pointer]: TObject read GetValue write SetValue; default;
end;
+
{
:$ Pointer-to-String hash.
}
TX2PSHash = class(TX2CustomPointerHash)
protected
- function GetCurrentValue(): String;
+ function GetCurrentValue: String;
function GetValue(Key: Pointer): String;
procedure SetValue(Key: Pointer; const Value: String);
+ private
+ function GetValueManager: TX2HashStringManager;
protected
- function CreateValueManager(): TX2CustomHashManager; override;
+ function CreateValueManager: TX2CustomHashManager; override;
+
+ property ValueManager: TX2HashStringManager read GetValueManager;
public
- property CurrentValue: String read GetCurrentValue;
- property Values[Key: Pointer]: String read GetValue write SetValue; default;
+ property CurrentValue: String read GetCurrentValue;
+ property Values[Key: Pointer]: String read GetValue write SetValue; default;
end;
+
{
:$ Integer-to-Pointer hash.
}
TX2IPHash = class(TX2CustomIntegerHash)
protected
- function GetCurrentValue(): Pointer;
+ function GetCurrentValue: Pointer;
function GetValue(Key: Integer): Pointer;
procedure SetValue(Key: Integer; const Value: Pointer);
+ private
+ function GetValueManager: TX2HashPointerManager;
protected
- function CreateValueManager(): TX2CustomHashManager; override;
+ function CreateValueManager: TX2CustomHashManager; override;
+
+ property ValueManager: TX2HashPointerManager read GetValueManager;
public
- property CurrentValue: Pointer read GetCurrentValue;
- property Values[Key: Integer]: Pointer read GetValue write SetValue; default;
+ property CurrentValue: Pointer read GetCurrentValue;
+ property Values[Key: Integer]: Pointer read GetValue write SetValue; default;
end;
+
{
:$ Integer-to-Integer hash.
}
TX2IIHash = class(TX2CustomIntegerHash)
protected
- function GetCurrentValue(): Integer;
+ function GetCurrentValue: Integer;
function GetValue(Key: Integer): Integer;
procedure SetValue(Key: Integer; const Value: Integer);
+ private
+ function GetValueManager: TX2HashIntegerManager;
protected
- function CreateValueManager(): TX2CustomHashManager; override;
+ function CreateValueManager: TX2CustomHashManager; override;
+
+ property ValueManager: TX2HashIntegerManager read GetValueManager;
public
- property CurrentValue: Integer read GetCurrentValue;
- property Values[Key: Integer]: Integer read GetValue write SetValue; default;
+ property CurrentValue: Integer read GetCurrentValue;
+ property Values[Key: Integer]: Integer read GetValue write SetValue; default;
end;
+
{
:$ Integer-to-Object hash.
}
TX2IOHash = class(TX2CustomIntegerHash)
+ private
+ function GetValueManager: TX2HashObjectManager;
protected
- function GetCurrentValue(): TObject;
- function GetOwnsObjects(): Boolean;
+ function GetCurrentValue: TObject;
+ function GetOwnsObjects: Boolean;
procedure SetOwnsObjects(const Value: Boolean);
function GetValue(Key: Integer): TObject;
procedure SetValue(Key: Integer; const Value: TObject);
protected
- function CreateValueManager(): TX2CustomHashManager; override;
+ function CreateValueManager: TX2CustomHashManager; override;
+
+ property ValueManager: TX2HashObjectManager read GetValueManager;
public
constructor Create(const AOwnsObjects: Boolean = False); reintroduce;
- property CurrentValue: TObject read GetCurrentValue;
- property OwnsObjects: Boolean read GetOwnsObjects write SetOwnsObjects;
- property Values[Key: Integer]: TObject read GetValue write SetValue; default;
+ property CurrentValue: TObject read GetCurrentValue;
+ property OwnsObjects: Boolean read GetOwnsObjects write SetOwnsObjects;
+ property Values[Key: Integer]: TObject read GetValue write SetValue; default;
end;
+
{
:$ Integer-to-String hash.
}
TX2ISHash = class(TX2CustomIntegerHash)
+ private
+ function GetValueManager: TX2HashStringManager;
protected
- function GetCurrentValue(): String;
+ function GetCurrentValue: String;
function GetValue(Key: Integer): String;
procedure SetValue(Key: Integer; const Value: String);
protected
- function CreateValueManager(): TX2CustomHashManager; override;
+ function CreateValueManager: TX2CustomHashManager; override;
+
+ property ValueManager: TX2HashStringManager read GetValueManager;
public
- property CurrentValue: String read GetCurrentValue;
- property Values[Key: Integer]: String read GetValue write SetValue; default;
+ property CurrentValue: String read GetCurrentValue;
+ property Values[Key: Integer]: String read GetValue write SetValue; default;
end;
+
{
:$ Object-to-Pointer hash.
}
TX2OPHash = class(TX2CustomObjectHash)
+ private
+ function GetValueManager: TX2HashPointerManager;
protected
- function GetCurrentValue(): Pointer;
+ function GetCurrentValue: Pointer;
function GetValue(Key: TObject): Pointer;
procedure SetValue(Key: TObject; const Value: Pointer);
protected
- function CreateValueManager(): TX2CustomHashManager; override;
+ function CreateValueManager: TX2CustomHashManager; override;
+
+ property ValueManager: TX2HashPointerManager read GetValueManager;
public
- property CurrentValue: Pointer read GetCurrentValue;
- property Values[Key: TObject]: Pointer read GetValue write SetValue; default;
+ property CurrentValue: Pointer read GetCurrentValue;
+ property Values[Key: TObject]: Pointer read GetValue write SetValue; default;
end;
+
{
:$ Object-to-Integer hash.
}
TX2OIHash = class(TX2CustomObjectHash)
+ private
+ function GetValueManager: TX2HashIntegerManager;
protected
- function GetCurrentValue(): Integer;
+ function GetCurrentValue: Integer;
function GetValue(Key: TObject): Integer;
procedure SetValue(Key: TObject; const Value: Integer);
protected
- function CreateValueManager(): TX2CustomHashManager; override;
+ function CreateValueManager: TX2CustomHashManager; override;
+
+ property ValueManager: TX2HashIntegerManager read GetValueManager;
public
- property CurrentValue: Integer read GetCurrentValue;
- property Values[Key: TObject]: Integer read GetValue write SetValue; default;
+ property CurrentValue: Integer read GetCurrentValue;
+ property Values[Key: TObject]: Integer read GetValue write SetValue; default;
end;
+
{
:$ Object-to-Object hash.
}
TX2OOHash = class(TX2CustomObjectHash)
+ private
+ function GetValueManager: TX2HashObjectManager;
protected
- function GetCurrentValue(): TObject;
- function GetOwnsObjects(): Boolean;
+ function GetCurrentValue: TObject;
+ function GetOwnsObjects: Boolean;
procedure SetOwnsObjects(const Value: Boolean);
function GetValue(Key: TObject): TObject;
procedure SetValue(Key: TObject; const Value: TObject);
protected
- function CreateValueManager(): TX2CustomHashManager; override;
+ function CreateValueManager: TX2CustomHashManager; override;
+
+ property ValueManager: TX2HashObjectManager read GetValueManager;
public
constructor Create(const AOwnsObjects: Boolean = False); reintroduce;
- property CurrentValue: TObject read GetCurrentValue;
- property OwnsObjects: Boolean read GetOwnsObjects write SetOwnsObjects;
- property Values[Key: TObject]: TObject read GetValue write SetValue; default;
+ property CurrentValue: TObject read GetCurrentValue;
+ property OwnsObjects: Boolean read GetOwnsObjects write SetOwnsObjects;
+ property Values[Key: TObject]: TObject read GetValue write SetValue; default;
end;
+
{
:$ Object-to-String hash.
}
TX2OSHash = class(TX2CustomObjectHash)
+ private
+ function GetValueManager: TX2HashStringManager;
protected
- function GetCurrentValue(): String;
+ function GetCurrentValue: String;
function GetValue(Key: TObject): String;
procedure SetValue(Key: TObject; const Value: String);
protected
- function CreateValueManager(): TX2CustomHashManager; override;
+ function CreateValueManager: TX2CustomHashManager; override;
+
+ property ValueManager: TX2HashStringManager read GetValueManager;
public
- property CurrentValue: String read GetCurrentValue;
- property Values[Key: TObject]: String read GetValue write SetValue; default;
+ property CurrentValue: String read GetCurrentValue;
+ property Values[Key: TObject]: String read GetValue write SetValue; default;
end;
+
{
:$ String-to-Pointer hash.
}
TX2SPHash = class(TX2CustomStringHash)
+ private
+ function GetValueManager: TX2HashPointerManager;
protected
- function GetCurrentValue(): Pointer;
+ function GetCurrentValue: Pointer;
function GetValue(Key: String): Pointer;
procedure SetValue(Key: String; const Value: Pointer);
protected
- function CreateValueManager(): TX2CustomHashManager; override;
+ function CreateValueManager: TX2CustomHashManager; override;
+
+ property ValueManager: TX2HashPointerManager read GetValueManager;
public
- property CurrentValue: Pointer read GetCurrentValue;
- property Values[Key: String]: Pointer read GetValue write SetValue; default;
+ property CurrentValue: Pointer read GetCurrentValue;
+ property Values[Key: String]: Pointer read GetValue write SetValue; default;
end;
+
{
:$ String-to-Integer hash.
}
TX2SIHash = class(TX2CustomStringHash)
+ private
+ function GetValueManager: TX2HashIntegerManager;
protected
- function GetCurrentValue(): Integer;
+ function GetCurrentValue: Integer;
function GetValue(Key: String): Integer;
procedure SetValue(Key: String; const Value: Integer);
protected
- function CreateValueManager(): TX2CustomHashManager; override;
+ function CreateValueManager: TX2CustomHashManager; override;
+
+ property ValueManager: TX2HashIntegerManager read GetValueManager;
public
- property CurrentValue: Integer read GetCurrentValue;
- property Values[Key: String]: Integer read GetValue write SetValue; default;
+ property CurrentValue: Integer read GetCurrentValue;
+ property Values[Key: String]: Integer read GetValue write SetValue; default;
end;
+
{
:$ String-to-Object hash.
}
TX2SOHash = class(TX2CustomStringHash)
+ private
+ function GetValueManager: TX2HashObjectManager;
protected
- function GetCurrentValue(): TObject;
- function GetOwnsObjects(): Boolean;
+ function GetCurrentValue: TObject;
+ function GetOwnsObjects: Boolean;
procedure SetOwnsObjects(const Value: Boolean);
function GetValue(Key: String): TObject;
procedure SetValue(Key: String; const Value: TObject);
protected
- function CreateValueManager(): TX2CustomHashManager; override;
+ function CreateValueManager: TX2CustomHashManager; override;
+
+ property ValueManager: TX2HashObjectManager read GetValueManager;
public
constructor Create(const AOwnsObjects: Boolean = False); reintroduce;
- property CurrentValue: TObject read GetCurrentValue;
- property OwnsObjects: Boolean read GetOwnsObjects write SetOwnsObjects;
- property Values[Key: String]: TObject read GetValue write SetValue; default;
+ property CurrentValue: TObject read GetCurrentValue;
+ property OwnsObjects: Boolean read GetOwnsObjects write SetOwnsObjects;
+ property Values[Key: String]: TObject read GetValue write SetValue; default;
end;
+
{
:$ String-to-String hash.
}
TX2SSHash = class(TX2CustomStringHash)
+ private
+ function GetValueManager: TX2HashStringManager;
protected
- function GetCurrentValue(): String;
+ function GetCurrentValue: String;
function GetValue(Key: String): String;
procedure SetValue(Key: String; const Value: String);
protected
- function CreateValueManager(): TX2CustomHashManager; override;
+ function CreateValueManager: TX2CustomHashManager; override;
+
+ property ValueManager: TX2HashStringManager read GetValueManager;
public
- property CurrentValue: String read GetCurrentValue;
- property Values[Key: String]: String read GetValue write SetValue; default;
+ property CurrentValue: String read GetCurrentValue;
+ property Values[Key: String]: String read GetValue write SetValue; default;
end;
{$IFDEF D2005PLUS}
{$ENDREGION}
{$ENDIF}
+
implementation
const
HIDBucket = 1;
@@ -650,7 +768,7 @@ var
{========================================
CRC32
========================================}
-procedure CRC32Init();
+procedure CRC32Init;
var
iItem: Integer;
iPoly: Integer;
@@ -659,30 +777,31 @@ var
begin
for iItem := 255 downto 0 do
begin
- iValue := iItem;
+ iValue := iItem;
for iPoly := 8 downto 1 do
if (iValue and $1) <> 0 then
- iValue := (iValue shr $1) xor CRC32Poly
+ iValue := (iValue shr $1) xor CRC32Poly
else
- iValue := iValue shr $1;
+ iValue := iValue shr $1;
CRC32Table[iItem] := iValue;
end;
end;
+
function CRC32(const AKey: Pointer; const ASize: Cardinal): Cardinal;
var
iByte: Integer;
pByte: ^Byte;
begin
- Result := $FFFFFFFF;
- pByte := AKey;
+ Result := $FFFFFFFF;
+ pByte := AKey;
for iByte := Pred(ASize) downto 0 do
begin
- Result := (((Result shr 8) and $00FFFFFF) xor
+ Result := (((Result shr 8) and $00FFFFFF) xor
(CRC32Table[(Result xor pByte^) and $FF]));
Inc(pByte);
end;
@@ -697,34 +816,36 @@ end;
========================================}
constructor TX2HashCursor.Create(const ABucket: PX2HashBucket);
begin
- inherited Create();
+ inherited Create;
SetLength(FBucketPath, 1);
with FBucketPath[0] do
begin
- Bucket := ABucket;
- Index := 0;
+ Bucket := ABucket;
+ Index := 0;
end;
- FCurrent := nil;
+ FCurrent := nil;
end;
-function TX2HashCursor.GetCurrent(): PX2HashValue;
+
+function TX2HashCursor.GetCurrent: PX2HashValue;
begin
- Result := FCurrent;
+ Result := FCurrent;
end;
-procedure TX2HashCursor.First();
+procedure TX2HashCursor.First;
begin
if Length(FBucketPath) > 1 then
SetLength(FBucketPath, 1);
- FBucketPath[0].Index := 0;
- FCurrent := nil;
+ FBucketPath[0].Index := 0;
+ FCurrent := nil;
end;
-function TX2HashCursor.Next(): Boolean;
+
+function TX2HashCursor.Next: Boolean;
var
bFound: Boolean;
iIndex: Integer;
@@ -732,21 +853,21 @@ var
pItem: PX2HashItem;
begin
- Result := False;
- iIndex := High(FBucketPath);
+ Result := False;
+ iIndex := High(FBucketPath);
if iIndex = -1 then
exit;
- if (FCurrent <> nil) and (FCurrent^.Next <> nil) then
+ if Assigned(FCurrent) and Assigned(FCurrent^.Next) then
begin
- FCurrent := FCurrent^.Next;
- Result := True;
+ FCurrent := FCurrent^.Next;
+ Result := True;
exit;
end;
repeat
pBucket := FBucketPath[iIndex].Bucket;
- bFound := False;
+ bFound := False;
while FBucketPath[iIndex].Index < LeafSize do
begin
@@ -763,17 +884,17 @@ begin
SetLength(FBucketPath, iIndex + 1);
with FBucketPath[iIndex] do
begin
- Bucket := PX2HashBucket(pItem);
- Index := 0;
+ Bucket := PX2HashBucket(pItem);
+ Index := 0;
end;
- bFound := True;
+ bFound := True;
break;
end;
HIDValue:
begin
// Got a value
- FCurrent := PX2HashValue(pItem);
- Result := True;
+ FCurrent := PX2HashValue(pItem);
+ Result := True;
Inc(FBucketPath[iIndex].Index);
exit;
end;
@@ -802,172 +923,210 @@ end;
{========================================
TX2CustomHashManager
========================================}
-procedure TX2CustomHashManager.Initialize(var AData: Pointer);
+procedure TX2CustomHashManager.FreeCookie(var ACookie: Pointer);
begin
- AData := nil;
-end;
-
-procedure TX2CustomHashManager.Finalize(var AData: Pointer);
-begin
- AData := nil;
-end;
-
-function TX2CustomHashManager.DataSize(const AData: Pointer): Cardinal;
-begin
- Result := SizeOf(Pointer);
-end;
-
-function TX2CustomHashManager.DataPointer(const AData: Pointer): Pointer;
-begin
- Result := AData;
-end;
-
-function TX2CustomHashManager.ToPointer(const AValue: Pointer;
- const ASize: Cardinal): Pointer;
-begin
- Result := Pointer(AValue^);
-end;
-
-function TX2CustomHashManager.ToValue(const AData: Pointer;
- var AValue): Cardinal;
-begin
- Result := DataSize(AData);
- Pointer(AValue) := AData;
-end;
-
-function TX2CustomHashManager.Compare(const AData: Pointer; const AValue: Pointer;
- const ASize: Cardinal): Boolean;
-begin
- Result := (Pointer(AValue^) = AData);
+ ACookie := nil;
end;
{========================================
TX2HashPointerManager
========================================}
-function TX2HashPointerManager.ToPointer(const AValue: Pointer): Pointer;
+function TX2HashPointerManager.CreateCookie(const AValue: Pointer): PX2HashCookie;
begin
- Result := ToPointer(@AValue, SizeOf(Pointer));
+ Result := AValue;
end;
-function TX2HashPointerManager.ToValue(const AData: Pointer): Pointer;
+
+function TX2HashPointerManager.GetValue(const ACookie: PX2HashCookie): Pointer;
begin
- ToValue(AData, Result);
+ Result := ACookie;
+end;
+
+
+function TX2HashPointerManager.Hash(ACookie: PX2HashCookie): Cardinal;
+var
+ value: Pointer;
+
+begin
+ value := GetValue(ACookie);
+ Result := CRC32(@value, SizeOf(Pointer));
+end;
+
+
+function TX2HashPointerManager.Compare(const ACookie1, ACookie2: PX2HashCookie): Boolean;
+begin
+ Result := (GetValue(ACookie1) = GetValue(ACookie2));
+end;
+
+
+function TX2HashPointerManager.Clone(const ACookie: PX2HashCookie): PX2HashCookie;
+begin
+ Result := ACookie;
end;
{========================================
TX2HashIntegerManager
========================================}
-function TX2HashIntegerManager.ToPointer(const AValue: Integer): Pointer;
+function TX2HashIntegerManager.CreateCookie(const AValue: Integer): PX2HashCookie;
begin
- Result := ToPointer(@AValue, SizeOf(Integer));
+ Result := PX2HashCookie(AValue);
end;
-function TX2HashIntegerManager.ToValue(const AData: Pointer): Integer;
+
+function TX2HashIntegerManager.GetValue(const ACookie: PX2HashCookie): Integer;
begin
- ToValue(AData, Result);
+ Result := Integer(ACookie);
+end;
+
+
+function TX2HashIntegerManager.Hash(ACookie: PX2HashCookie): Cardinal;
+var
+ value: Integer;
+
+begin
+ value := GetValue(ACookie);
+ Result := CRC32(@value, SizeOf(Integer));
+end;
+
+
+function TX2HashIntegerManager.Compare(const ACookie1, ACookie2: PX2HashCookie): Boolean;
+begin
+ Result := (GetValue(ACookie1) = GetValue(ACookie2));
+end;
+
+
+function TX2HashIntegerManager.Clone(const ACookie: PX2HashCookie): PX2HashCookie;
+begin
+ Result := ACookie;
end;
{========================================
TX2HashObjectManager
========================================}
-procedure TX2HashObjectManager.Finalize(var AData: Pointer);
+procedure TX2HashObjectManager.FreeCookie(var ACookie: PX2HashCookie);
begin
- if (AData <> nil) and (FOwnsObjects) then
- TObject(AData).Free();
+ if Assigned(ACookie) and (FOwnsObjects) then
+ GetValue(ACookie).Free;
inherited;
end;
-function TX2HashObjectManager.ToPointer(const AValue: TObject): Pointer;
+
+function TX2HashObjectManager.CreateCookie(const AValue: TObject): PX2HashCookie;
begin
- Result := ToPointer(@AValue, SizeOf(Integer));
+ Result := PX2HashCookie(AValue);
end;
-function TX2HashObjectManager.ToValue(const AData: Pointer): TObject;
+
+function TX2HashObjectManager.GetValue(const ACookie: PX2HashCookie): TObject;
begin
- ToValue(AData, Result);
+ Result := TObject(ACookie);
+end;
+
+
+function TX2HashObjectManager.Hash(ACookie: PX2HashCookie): Cardinal;
+var
+ value: TObject;
+
+begin
+ value := GetValue(ACookie);
+ Result := CRC32(@value, SizeOf(TObject));
+end;
+
+
+function TX2HashObjectManager.Compare(const ACookie1, ACookie2: PX2HashCookie): Boolean;
+begin
+ Result := (GetValue(ACookie1) = GetValue(ACookie2));
+end;
+
+
+function TX2HashObjectManager.Clone(const ACookie: PX2HashCookie): PX2HashCookie;
+begin
+ Result := ACookie;
end;
{========================================
TX2HashStringManager
========================================}
-procedure TX2HashStringManager.Finalize(var AData: Pointer);
+procedure TX2HashStringManager.FreeCookie(var ACookie: PX2HashCookie);
+var
+ stringCookie: PX2HashStringCookie;
+
begin
- if AData <> nil then
- FreeMem(AData, PCardinal(AData)^ + SizeOf(Cardinal));
-
+ if Assigned(ACookie) then
+ begin
+ stringCookie := ACookie;
+
+ if stringCookie^.Length > 0 then
+ FreeMem(stringCookie^.Value, Succ(stringCookie^.Length));
+
+ Dispose(stringCookie);
+ end;
+
inherited;
end;
-function TX2HashStringManager.DataSize(const AData: Pointer): Cardinal;
-begin
- Result := PCardinal(AData)^;
-end;
-function TX2HashStringManager.DataPointer(const AData: Pointer): Pointer;
-begin
- Result := AData;
- Inc(PCardinal(Result));
-end;
-
-function TX2HashStringManager.ToPointer(const AValue: Pointer;
- const ASize: Cardinal): Pointer;
+function TX2HashStringManager.CreateCookie(const AValue: string): PX2HashCookie;
var
- pData: Pointer;
+ stringCookie: PX2HashStringCookie;
begin
- // Add a 4-byte Length to the start, emulating AnsiStrings
- // (except for the reference counting)
- GetMem(Result, ASize + SizeOf(Cardinal));
- PCardinal(Result)^ := ASize;
- pData := Result;
- Inc(PCardinal(pData));
- Move(AValue^, pData^, ASize);
+ New(stringCookie);
+ stringCookie^.Length := Length(AValue);
+
+ GetMem(stringCookie^.Value, Succ(Length(AValue)));
+ StrPCopy(stringCookie^.Value, AValue);
+
+ Result := stringCookie;
end;
-function TX2HashStringManager.ToValue(const AData: Pointer;
- var AValue): Cardinal;
+
+function TX2HashStringManager.GetValue(const ACookie: PX2HashCookie): string;
var
- pData: Pointer;
-
-begin
- Result := DataSize(AData);
- pData := DataPointer(AData);
+ stringCookie: PX2HashStringCookie;
- SetLength(String(AValue), Result);
- if Result > 0 then
- Move(pData^, PChar(String(AValue))^, Result);
-end;
-
-function TX2HashStringManager.ToPointer(const AValue: String): Pointer;
begin
- Result := ToPointer(PChar(AValue), Length(AValue));
+ Result := '';
+ if Assigned(ACookie) then
+ begin
+ stringCookie := ACookie;
+ if stringCookie^.Length > 0 then
+ begin
+ SetLength(Result, stringCookie^.Length);
+ Move(stringCookie^.Value^, Result[1], stringCookie^.Length);
+ end;
+ end;
end;
-function TX2HashStringManager.ToValue(const AData: Pointer): String;
-begin
- ToValue(AData, Result);
-end;
-
-function TX2HashStringManager.Compare(const AData: Pointer; const AValue: Pointer;
- const ASize: Cardinal): Boolean;
+function TX2HashStringManager.Hash(ACookie: PX2HashCookie): Cardinal;
var
- pSource: PChar;
+ stringCookie: PX2HashStringCookie;
begin
- Result := False;
- if ASize <> PCardinal(AData)^ then
- exit;
+ Result := 0;
+ if Assigned(ACookie) then
+ begin
+ stringCookie := ACookie;
+ Result := CRC32(stringCookie^.Value, stringCookie^.Length);
+ end;
+end;
- pSource := AData;
- Inc(PCardinal(pSource));
- Result := CompareMem(pSource, AValue, ASize);
+function TX2HashStringManager.Compare(const ACookie1, ACookie2: PX2HashCookie): Boolean;
+begin
+ Result := (GetValue(ACookie1) = GetValue(ACookie2));
+end;
+
+
+function TX2HashStringManager.Clone(const ACookie: PX2HashCookie): PX2HashCookie;
+begin
+ Result := CreateCookie(GetValue(ACookie));
end;
{$IFDEF D2005PLUS}
{$ENDREGION}
@@ -978,17 +1137,18 @@ end;
{========================== TX2CustomHash
Initialization
========================================}
-constructor TX2CustomHash.Create();
+constructor TX2CustomHash.Create;
begin
inherited;
- FKeyManager := CreateKeyManager();
- FValueManager := CreateValueManager();
+ FKeyManager := CreateKeyManager;
+ FValueManager := CreateValueManager;
end;
-destructor TX2CustomHash.Destroy();
+
+destructor TX2CustomHash.Destroy;
begin
- Clear();
+ Clear;
FreeAndNil(FValueManager);
FreeAndNil(FKeyManager);
FreeAndNil(FCursor);
@@ -997,14 +1157,15 @@ begin
end;
-function TX2CustomHash.CreateCursor(): TX2HashCursor;
+function TX2CustomHash.CreateCursor: TX2HashCursor;
begin
- Result := nil;
+ Result := nil;
if Assigned(FRoot) then
- Result := TX2HashCursor.Create(FRoot);
+ Result := TX2HashCursor.Create(FRoot);
end;
-procedure TX2CustomHash.InvalidateCursor();
+
+procedure TX2CustomHash.InvalidateCursor;
begin
FreeAndNil(FCursor);
end;
@@ -1019,20 +1180,16 @@ asm
ROR eax, cl
end;
-function TX2CustomHash.Hash(const AKey: Pointer; const ASize: Cardinal): Cardinal;
-begin
- Result := CRC32(AKey, ASize);
-end;
function TX2CustomHash.CursorRequired(const ARaiseException: Boolean): Boolean;
begin
- Result := True;
+ Result := True;
if not Assigned(FCursor) then
if Assigned(FRoot) then
- FCursor := CreateCursor()
+ FCursor := CreateCursor
else
begin
- Result := False;
+ Result := False;
if ARaiseException then
raise EX2HashNoCursor.Create('Cursor not available!');
end;
@@ -1040,113 +1197,109 @@ end;
function TX2CustomHash.InternalFind(const ABucket: PX2HashBucket;
- const AHash: Cardinal; const AKey: Pointer;
- const ASize: Cardinal;
+ const AHash: Cardinal; const AKey: PX2HashCookie;
const AAllowCreate: Boolean;
const AExisting: PX2HashValue): PX2HashValue;
- function CreateValue(): PX2HashValue;
+ function CreateValue: PX2HashValue;
begin
if AExisting = nil then
begin
GetMem(Result, SizeOf(TX2HashValue));
FillChar(Result^, SizeOf(TX2HashValue), #0);
- Result^.ID := HIDValue;
- Result^.Key := FKeyManager.ToPointer(AKey, ASize);
+ Result^.ID := HIDValue;
+ Result^.Key := KeyManager.Clone(AKey);
Inc(FCount);
end else
- Result := AExisting;
+ Result := AExisting;
- InvalidateCursor();
+ InvalidateCursor;
end;
var
- iCount: Integer;
- iIndex: Integer;
- iKey: Integer;
- pBucket: PX2HashBucket;
- pKey: Pointer;
- pNext: PX2HashValue;
- pValue: PX2HashValue;
+ bucketCount: Integer;
+ bucketIndex: Integer;
+ bucket: PX2HashBucket;
+ key: Pointer;
+ nextValue: PX2HashValue;
+ value: PX2HashValue;
begin
- Result := nil;
- iIndex := (AHash and $FF);
+ Result := nil;
+ bucketIndex := (AHash and $FF);
- if ABucket^.Items[iIndex] = nil then
+ if ABucket^.Items[bucketIndex] = nil then
begin
if AAllowCreate then
begin
// New value
- Result := CreateValue();
- ABucket^.Items[iIndex] := PX2HashItem(Result);
+ Result := CreateValue;
+ ABucket^.Items[bucketIndex] := PX2HashItem(Result);
Inc(ABucket^.Count);
end;
end else
- case ABucket^.Items[iIndex]^.ID of
+ case ABucket^.Items[bucketIndex]^.ID of
HIDBucket:
// Bucket, continue down
- Result := InternalFind(PX2HashBucket(ABucket^.Items[iIndex]),
- ROR(AHash), AKey, ASize, AAllowCreate);
+ Result := InternalFind(PX2HashBucket(ABucket^.Items[bucketIndex]),
+ ROR(AHash), AKey, AAllowCreate);
HIDValue:
begin
- iCount := 0;
- pValue := PX2HashValue(ABucket^.Items[iIndex]);
- while pValue <> nil do
+ bucketCount := 0;
+ value := PX2HashValue(ABucket^.Items[bucketIndex]);
+ while Assigned(value) do
begin
- if FKeyManager.Compare(pValue^.Key, AKey, ASize) then
+ if KeyManager.Compare(value^.Key, AKey) then
begin
// Found existing key
- Result := pValue;
+ Result := value;
exit;
end;
- pValue := pValue^.Next;
- Inc(iCount);
+ value := value^.Next;
+ Inc(bucketCount);
end;
if AAllowCreate then
- if (iCount >= BucketSize) then
+ if (bucketCount >= BucketSize) then
begin
// Bucket full
- GetMem(pBucket, SizeOf(TX2HashBucket));
- FillChar(pBucket^, SizeOf(TX2HashBucket), #0);
- pBucket^.ID := HIDBucket;
- pBucket^.Level := ABucket^.Level + 1;
+ GetMem(bucket, SizeOf(TX2HashBucket));
+ FillChar(bucket^, SizeOf(TX2HashBucket), #0);
+ bucket^.ID := HIDBucket;
+ bucket^.Level := ABucket^.Level + 1;
- pValue := PX2HashValue(ABucket^.Items[iIndex]);
- while pValue <> nil do
+ value := PX2HashValue(ABucket^.Items[bucketIndex]);
+ while Assigned(value) do
begin
// Transfer item
- iKey := FKeyManager.DataSize(pValue^.Key);
- pKey := FKeyManager.DataPointer(pValue^.Key);
- pNext := pValue^.Next;
- pValue^.Next := nil;
+ key := KeyManager.Clone(value^.Key);
+ nextValue := value^.Next;
+ value^.Next := nil;
- InternalFind(pBucket, ROR(Hash(@pKey, iKey), pBucket^.Level * 8),
- pKey, iKey, True, pValue);
+ InternalFind(bucket, ROR(KeyManager.Hash(key), bucket^.Level * 8),
+ key, True, value);
-
- pValue := pNext;
+ value := nextValue;
end;
- Result := InternalFind(pBucket, ROR(AHash), AKey, ASize, True);
- ABucket^.Items[iIndex] := PX2HashItem(pBucket);
+ Result := InternalFind(bucket, ROR(AHash), AKey, True);
+ ABucket^.Items[bucketIndex] := PX2HashItem(bucket);
end else
begin
// New value
- Result := CreateValue();
- Result^.Next := PX2HashValue(ABucket^.Items[iIndex]);
- ABucket^.Items[iIndex] := PX2HashItem(Result);
+ Result := CreateValue;
+ Result^.Next := PX2HashValue(ABucket^.Items[bucketIndex]);
+ ABucket^.Items[bucketIndex] := PX2HashItem(Result);
end;
end;
end;
end;
+
function TX2CustomHash.InternalDelete(const ABucket: PX2HashBucket;
const AHash: Cardinal;
- const AKey: Pointer;
- const ASize: Cardinal): Boolean;
+ const AKey: PX2HashCookie): Boolean;
var
iIndex: Integer;
pBucket: PX2HashBucket;
@@ -1154,77 +1307,83 @@ var
pValue: PX2HashValue;
begin
- Result := False;
- iIndex := (AHash and $FF);
+ Result := False;
+ iIndex := (AHash and $FF);
- if ABucket^.Items[iIndex] <> nil then
+ if Assigned(ABucket^.Items[iIndex]) then
case ABucket^.Items[iIndex]^.ID of
HIDBucket:
begin
// Bucket, continue down
pBucket := PX2HashBucket(ABucket^.Items[iIndex]);
- Result := InternalDelete(pBucket, ROR(AHash), AKey, ASize);
+ Result := InternalDelete(pBucket, ROR(AHash), AKey);
if pBucket^.Count = 0 then
begin
FreeMem(pBucket, SizeOf(TX2HashBucket));
- ABucket^.Items[iIndex] := nil;
+ ABucket^.Items[iIndex] := nil;
end;
end;
HIDValue:
begin
- pPrev := nil;
- pValue := PX2HashValue(ABucket^.Items[iIndex]);
- while pValue <> nil do
+ pPrev := nil;
+ pValue := PX2HashValue(ABucket^.Items[iIndex]);
+ while Assigned(pValue) do
begin
- if FKeyManager.Compare(pValue^.Key, AKey, ASize) then
+ if KeyManager.Compare(pValue^.Key, AKey) then
begin
// Found key
if pPrev = nil then
begin
- ABucket^.Items[iIndex] := PX2HashItem(pValue^.Next);
+ ABucket^.Items[iIndex] := PX2HashItem(pValue^.Next);
if ABucket^.Items[iIndex] = nil then
Dec(ABucket^.Count);
end else
pPrev^.Next := pValue^.Next;
- FKeyManager.Finalize(pValue^.Key);
- FValueManager.Finalize(pValue^.Value);
+ KeyManager.FreeCookie(pValue^.Key);
+ ValueManager.FreeCookie(pValue^.Value);
FreeMem(pValue, SizeOf(TX2HashValue));
Dec(FCount);
- Result := True;
+ Result := True;
exit;
end;
- pPrev := pValue;
- pValue := pValue^.Next;
+ pPrev := pValue;
+ pValue := pValue^.Next;
end;
end;
end;
end;
-function TX2CustomHash.Find(const AKey: Pointer; const ASize: Cardinal;
- const AAllowCreate: Boolean): PX2HashValue;
+function TX2CustomHash.Find(const AKey: PX2HashCookie; const AAllowCreate: Boolean): PX2HashValue;
+var
+ cookie: PX2HashCookie;
+
begin
- Result := nil;
- if not Assigned(FRoot) then
- if AAllowCreate then
- begin
- // Create root bucket
- GetMem(FRoot, SizeOf(TX2HashBucket));
- FillChar(FRoot^, SizeOf(TX2HashBucket), #0);
- FRoot^.ID := HIDBucket;
- end else
- exit;
+ Result := nil;
+ try
+ if not Assigned(FRoot) then
+ if AAllowCreate then
+ begin
+ // Create root bucket
+ GetMem(FRoot, SizeOf(TX2HashBucket));
+ FillChar(FRoot^, SizeOf(TX2HashBucket), #0);
+ FRoot^.ID := HIDBucket;
+ end else
+ exit;
- Result := InternalFind(FRoot, Hash(AKey, ASize), AKey, ASize,
- AAllowCreate);
+ Result := InternalFind(FRoot, KeyManager.Hash(AKey), AKey, AAllowCreate);
+ finally
+ cookie := AKey;
+ KeyManager.FreeCookie(cookie);
+ end;
end;
-procedure TX2CustomHash.Clear();
+procedure TX2CustomHash.Clear;
procedure DestroyBucket(const ABucket: PX2HashBucket);
var
iItem: Integer;
@@ -1233,20 +1392,20 @@ procedure TX2CustomHash.Clear();
begin
for iItem := Pred(LeafSize) downto 0 do
- if ABucket^.Items[iItem] <> nil then
+ if Assigned(ABucket^.Items[iItem]) then
case ABucket^.Items[iItem].ID of
HIDBucket:
DestroyBucket(PX2HashBucket(ABucket^.Items[iItem]));
HIDValue:
begin
- pValue := PX2HashValue(ABucket^.Items[iItem]);
+ pValue := PX2HashValue(ABucket^.Items[iItem]);
repeat
- FKeyManager.Finalize(pValue^.Key);
- FValueManager.Finalize(pValue^.Value);
+ KeyManager.FreeCookie(pValue^.Key);
+ ValueManager.FreeCookie(pValue^.Value);
- pNext := pValue^.Next;
+ pNext := pValue^.Next;
FreeMem(pValue, SizeOf(TX2HashValue));
- pValue := pNext;
+ pValue := pNext;
until pValue = nil;
end;
end;
@@ -1255,58 +1414,65 @@ procedure TX2CustomHash.Clear();
end;
begin
- if FRoot <> nil then
+ if Assigned(FRoot) then
begin
DestroyBucket(FRoot);
- FCount := 0;
- FRoot := nil;
+ FCount := 0;
+ FRoot := nil;
end;
end;
-function TX2CustomHash.Exists(const AKey: Pointer;
- const ASize: Cardinal): Boolean;
+function TX2CustomHash.Exists(const AKey: PX2HashCookie): Boolean;
begin
- Result := (Assigned(FRoot) and (Find(AKey, ASize, False) <> nil));
+ Result := Assigned(Find(AKey, False));
end;
-function TX2CustomHash.Delete(const AKey: Pointer;
- const ASize: Cardinal): Boolean;
-begin
- Result := False;
- if not Assigned(FRoot) then
- exit;
- Result := InternalDelete(FRoot, Hash(AKey, ASize), AKey, ASize);
- if Result then
- InvalidateCursor();
+function TX2CustomHash.Delete(const AKey: PX2HashCookie): Boolean;
+var
+ cookie: PX2HashCookie;
+
+begin
+ try
+ Result := False;
+ if not Assigned(FRoot) then
+ exit;
+
+ Result := InternalDelete(FRoot, KeyManager.Hash(AKey), AKey);
+ if Result then
+ InvalidateCursor;
+ finally
+ cookie := AKey;
+ KeyManager.FreeCookie(cookie);
+ end;
end;
procedure TX2CustomHash.SetValue(const AValue: PX2HashValue;
const AData: Pointer);
begin
- ValueManager.Finalize(AValue^.Value);
+ ValueManager.FreeCookie(AValue^.Value);
AValue^.Value := AData;
end;
-
-procedure TX2CustomHash.First();
+procedure TX2CustomHash.First;
begin
if not CursorRequired(False) then
exit;
- Cursor.First();
+ Cursor.First;
end;
-function TX2CustomHash.Next(): Boolean;
+
+function TX2CustomHash.Next: Boolean;
begin
- Result := False;
+ Result := False;
if not CursorRequired(False) then
exit;
- Result := Cursor.Next();
+ Result := Cursor.Next;
end;
{$IFDEF D2005PLUS}
{$ENDREGION}
@@ -1320,62 +1486,68 @@ end;
constructor TX2HashEnumerator.Create(const AHash: TX2CustomHash;
const AEnumKeys: Boolean);
begin
- inherited Create();
+ inherited Create;
FEnumKeys := AEnumKeys;
if AEnumKeys then
- FManager := AHash.KeyManager
+ FManager := AHash.KeyManager
else
- FManager := AHash.ValueManager;
+ FManager := AHash.ValueManager;
- FCursor := AHash.CreateCursor();
+ FCursor := AHash.CreateCursor;
end;
-destructor TX2HashEnumerator.Destroy();
+
+destructor TX2HashEnumerator.Destroy;
begin
FreeAndNil(FCursor);
inherited;
end;
-function TX2HashEnumerator.GetCursor(): Pointer;
+
+function TX2HashEnumerator.GetCursor: PX2HashCookie;
begin
if FEnumKeys then
- Result := FCursor.Current^.Key
+ Result := FCursor.Current^.Key
else
- Result := FCursor.Current^.Value;
+ Result := FCursor.Current^.Value;
end;
-function TX2HashEnumerator.MoveNext(): Boolean;
+
+function TX2HashEnumerator.MoveNext: Boolean;
begin
- Result := False;
+ Result := False;
if Assigned(FCursor) then
- Result := FCursor.Next();
+ Result := FCursor.Next;
end;
{ TX2HashPointerEnumerator }
-function TX2HashPointerEnumerator.GetCurrent(): Pointer;
+function TX2HashPointerEnumerator.GetCurrent: Pointer;
begin
- Result := TX2HashPointerManager(Manager).ToValue(Cursor);
+ Result := TX2HashPointerManager(Manager).GetValue(Cursor);
end;
+
{ TX2HashIntegerEnumerator }
-function TX2HashIntegerEnumerator.GetCurrent(): Integer;
+function TX2HashIntegerEnumerator.GetCurrent: Integer;
begin
- Result := TX2HashIntegerManager(Manager).ToValue(Cursor);
+ Result := TX2HashIntegerManager(Manager).GetValue(Cursor);
end;
+
{ TX2HashObjectEnumerator }
-function TX2HashObjectEnumerator.GetCurrent(): TObject;
+function TX2HashObjectEnumerator.GetCurrent: TObject;
begin
- Result := TX2HashObjectManager(Manager).ToValue(Cursor);
+ Result := TX2HashObjectManager(Manager).GetValue(Cursor);
end;
+
{ TX2HashStringEnumerator }
-function TX2HashStringEnumerator.GetCurrent(): String;
+function TX2HashStringEnumerator.GetCurrent: String;
begin
- Result := TX2HashStringManager(Manager).ToValue(Cursor);
+ Result := TX2HashStringManager(Manager).GetValue(Cursor);
end;
{$IFDEF D2005PLUS}
{$ENDREGION}
@@ -1386,145 +1558,188 @@ end;
{========================================
TX2CustomPointerHash
========================================}
-function TX2CustomPointerHash.CreateKeyManager(): TX2CustomHashManager;
+function TX2CustomPointerHash.CreateKeyManager: TX2CustomHashManager;
begin
- Result := TX2HashPointerManager.Create();
+ Result := TX2HashPointerManager.Create;
end;
-function TX2CustomPointerHash.GetCurrentKey(): Pointer;
+
+function TX2CustomPointerHash.GetCurrentKey: Pointer;
begin
- CursorRequired();
- Result := TX2HashPointerManager(KeyManager).ToValue(Cursor.Current^.Key);
+ CursorRequired;
+ Result := KeyManager.GetValue(Cursor.Current^.Key);
end;
-function TX2CustomPointerHash.GetEnumerator(): TX2HashPointerEnumerator;
+
+function TX2CustomPointerHash.GetEnumerator: TX2HashPointerEnumerator;
begin
- Result := TX2HashPointerEnumerator.Create(Self, True);
+ Result := TX2HashPointerEnumerator.Create(Self, True);
end;
+
function TX2CustomPointerHash.Find(const AKey: Pointer;
const AAllowCreate: Boolean): PX2HashValue;
begin
- Result := inherited Find(@AKey, SizeOf(Pointer), AAllowCreate);
+ Result := inherited Find(KeyManager.CreateCookie(AKey), AAllowCreate);
end;
+
function TX2CustomPointerHash.Exists(const AKey: Pointer): Boolean;
begin
- Result := inherited Exists(@AKey, SizeOf(Pointer));
+ Result := inherited Exists(KeyManager.CreateCookie(AKey));
end;
+
function TX2CustomPointerHash.Delete(const AKey: Pointer): Boolean;
begin
- Result := inherited Delete(@AKey, SizeOf(Pointer));
+ Result := inherited Delete(KeyManager.CreateCookie(AKey));
+end;
+
+
+function TX2CustomPointerHash.GetKeyManager: TX2HashPointerManager;
+begin
+ Result := TX2HashPointerManager(inherited KeyManager);
end;
{========================================
TX2CustomIntegerHash
========================================}
-function TX2CustomIntegerHash.CreateKeyManager(): TX2CustomHashManager;
+function TX2CustomIntegerHash.CreateKeyManager: TX2CustomHashManager;
begin
- Result := TX2HashIntegerManager.Create();
+ Result := TX2HashIntegerManager.Create;
end;
-function TX2CustomIntegerHash.GetCurrentKey(): Integer;
+
+function TX2CustomIntegerHash.GetCurrentKey: Integer;
begin
- CursorRequired();
- Result := TX2HashIntegerManager(KeyManager).ToValue(Cursor.Current^.Key);
+ CursorRequired;
+ Result := KeyManager.GetValue(Cursor.Current^.Key);
end;
-function TX2CustomIntegerHash.GetEnumerator(): TX2HashIntegerEnumerator;
+
+function TX2CustomIntegerHash.GetEnumerator: TX2HashIntegerEnumerator;
begin
- Result := TX2HashIntegerEnumerator.Create(Self, True);
+ Result := TX2HashIntegerEnumerator.Create(Self, True);
end;
+
function TX2CustomIntegerHash.Find(const AKey: Integer;
const AAllowCreate: Boolean): PX2HashValue;
begin
- Result := inherited Find(@AKey, SizeOf(Pointer), AAllowCreate);
+ Result := inherited Find(KeyManager.CreateCookie(AKey), AAllowCreate);
end;
+
function TX2CustomIntegerHash.Exists(const AKey: Integer): Boolean;
begin
- Result := inherited Exists(@AKey, SizeOf(Pointer));
+ Result := inherited Exists(KeyManager.CreateCookie(AKey));
end;
+
function TX2CustomIntegerHash.Delete(const AKey: Integer): Boolean;
begin
- Result := inherited Delete(@AKey, SizeOf(Pointer));
+ Result := inherited Delete(KeyManager.CreateCookie(AKey));
+end;
+
+
+function TX2CustomIntegerHash.GetKeyManager: TX2HashIntegerManager;
+begin
+ Result := TX2HashIntegerManager(inherited KeyManager);
end;
{========================================
TX2CustomObjectHash
========================================}
-function TX2CustomObjectHash.CreateKeyManager(): TX2CustomHashManager;
+function TX2CustomObjectHash.CreateKeyManager: TX2CustomHashManager;
begin
- Result := TX2HashObjectManager.Create();
+ Result := TX2HashObjectManager.Create;
end;
-function TX2CustomObjectHash.GetCurrentKey(): TObject;
+
+function TX2CustomObjectHash.GetCurrentKey: TObject;
begin
- CursorRequired();
- Result := TX2HashObjectManager(KeyManager).ToValue(Cursor.Current^.Key);
+ CursorRequired;
+ Result := KeyManager.GetValue(Cursor.Current^.Key);
end;
-function TX2CustomObjectHash.GetEnumerator(): TX2HashObjectEnumerator;
+
+function TX2CustomObjectHash.GetEnumerator: TX2HashObjectEnumerator;
begin
- Result := TX2HashObjectEnumerator.Create(Self, True);
+ Result := TX2HashObjectEnumerator.Create(Self, True);
end;
+
function TX2CustomObjectHash.Find(const AKey: TObject;
const AAllowCreate: Boolean): PX2HashValue;
begin
- Result := inherited Find(@AKey, SizeOf(Pointer), AAllowCreate);
+ Result := inherited Find(KeyManager.CreateCookie(AKey), AAllowCreate);
end;
+
function TX2CustomObjectHash.Exists(const AKey: TObject): Boolean;
begin
- Result := inherited Exists(@AKey, SizeOf(Pointer));
+ Result := inherited Exists(KeyManager.CreateCookie(AKey));
end;
+
function TX2CustomObjectHash.Delete(const AKey: TObject): Boolean;
begin
- Result := inherited Delete(@AKey, SizeOf(Pointer));
+ Result := inherited Delete(KeyManager.CreateCookie(AKey));
+end;
+
+
+function TX2CustomObjectHash.GetKeyManager: TX2HashObjectManager;
+begin
+ Result := TX2HashObjectManager(inherited KeyManager);
end;
{========================================
TX2CustomStringHash
========================================}
-function TX2CustomStringHash.CreateKeyManager(): TX2CustomHashManager;
+function TX2CustomStringHash.CreateKeyManager: TX2CustomHashManager;
begin
- Result := TX2HashStringManager.Create();
-end;
-
-function TX2CustomStringHash.GetCurrentKey(): String;
-begin
- CursorRequired();
- Result := TX2HashStringManager(KeyManager).ToValue(Cursor.Current^.Key);
+ Result := TX2HashStringManager.Create;
end;
-function TX2CustomStringHash.GetEnumerator(): TX2HashStringEnumerator;
+function TX2CustomStringHash.GetCurrentKey: String;
begin
- Result := TX2HashStringEnumerator.Create(Self, True);
+ CursorRequired;
+ Result := TX2HashStringManager(KeyManager).GetValue(Cursor.Current^.Key);
end;
+
+function TX2CustomStringHash.GetEnumerator: TX2HashStringEnumerator;
+begin
+ Result := TX2HashStringEnumerator.Create(Self, True);
+end;
+
+
function TX2CustomStringHash.Find(const AKey: String;
const AAllowCreate: Boolean): PX2HashValue;
begin
- Result := inherited Find(PChar(AKey), Length(AKey), AAllowCreate);
+ Result := inherited Find(KeyManager.CreateCookie(AKey), AAllowCreate);
end;
+
function TX2CustomStringHash.Exists(const AKey: String): Boolean;
begin
- Result := inherited Exists(PChar(AKey), Length(AKey));
+ Result := inherited Exists(KeyManager.CreateCookie(AKey));
end;
+
function TX2CustomStringHash.Delete(const AKey: String): Boolean;
begin
- Result := inherited Delete(PChar(AKey), Length(AKey));
+ Result := inherited Delete(KeyManager.CreateCookie(AKey));
+end;
+
+
+function TX2CustomStringHash.GetKeyManager: TX2HashStringManager;
+begin
+ Result := TX2HashStringManager(inherited KeyManager);
end;
{$IFDEF D2005PLUS}
{$ENDREGION}
@@ -1535,557 +1750,707 @@ end;
{========================================
TX2PPHash
========================================}
-function TX2PPHash.CreateValueManager(): TX2CustomHashManager;
+function TX2PPHash.CreateValueManager: TX2CustomHashManager;
begin
- Result := TX2HashPointerManager.Create();
+ Result := TX2HashPointerManager.Create;
end;
-function TX2PPHash.GetCurrentValue(): Pointer;
+
+function TX2PPHash.GetCurrentValue: Pointer;
begin
- CursorRequired();
- Result := TX2HashPointerManager(ValueManager).ToValue(Cursor.Current^.Value);
+ CursorRequired;
+ Result := ValueManager.GetValue(Cursor.Current^.Value);
end;
+
function TX2PPHash.GetValue(Key: Pointer): Pointer;
var
- pItem: PX2HashValue;
+ item: PX2HashValue;
begin
- Result := nil;
- pItem := Find(Key, False);
- if Assigned(pItem) then
- Result := TX2HashPointerManager(ValueManager).ToValue(pItem^.Value);
+ Result := nil;
+ item := Find(Key, False);
+ if Assigned(item) then
+ Result := ValueManager.GetValue(item^.Value);
end;
+
procedure TX2PPHash.SetValue(Key: Pointer; const Value: Pointer);
begin
- inherited SetValue(Find(Key, True),
- TX2HashPointerManager(ValueManager).ToPointer(Value));
+ inherited SetValue(Find(Key, True), ValueManager.CreateCookie(Value));
end;
+
+function TX2PPHash.GetValueManager: TX2HashPointerManager;
+begin
+ Result := TX2HashPointerManager(inherited ValueManager);
+end;
+
+
{========================================
TX2PIHash
========================================}
-function TX2PIHash.CreateValueManager(): TX2CustomHashManager;
+function TX2PIHash.CreateValueManager: TX2CustomHashManager;
begin
- Result := TX2HashIntegerManager.Create();
+ Result := TX2HashIntegerManager.Create;
end;
-function TX2PIHash.GetCurrentValue(): Integer;
+
+function TX2PIHash.GetCurrentValue: Integer;
begin
- CursorRequired();
- Result := TX2HashIntegerManager(ValueManager).ToValue(Cursor.Current^.Value);
+ CursorRequired;
+ Result := ValueManager.GetValue(Cursor.Current^.Value);
end;
+
function TX2PIHash.GetValue(Key: Pointer): Integer;
var
- pItem: PX2HashValue;
+ item: PX2HashValue;
begin
- Result := 0;
- pItem := Find(Key, False);
- if Assigned(pItem) then
- Result := TX2HashIntegerManager(ValueManager).ToValue(pItem^.Value);
+ Result := 0;
+ item := Find(Key, False);
+ if Assigned(item) then
+ Result := ValueManager.GetValue(item^.Value);
end;
+
procedure TX2PIHash.SetValue(Key: Pointer; const Value: Integer);
begin
- inherited SetValue(Find(Key, True),
- TX2HashIntegerManager(ValueManager).ToPointer(Value));
+ inherited SetValue(Find(Key, True), ValueManager.CreateCookie(Value));
end;
+
+function TX2PIHash.GetValueManager: TX2HashIntegerManager;
+begin
+ Result := TX2HashIntegerManager(inherited ValueManager);
+end;
+
+
{========================================
TX2POHash
========================================}
constructor TX2POHash.Create(const AOwnsObjects: Boolean);
begin
- inherited Create();
+ inherited Create;
OwnsObjects := AOwnsObjects;
end;
-function TX2POHash.CreateValueManager(): TX2CustomHashManager;
+
+function TX2POHash.CreateValueManager: TX2CustomHashManager;
begin
- Result := TX2HashObjectManager.Create();
+ Result := TX2HashObjectManager.Create;
end;
-function TX2POHash.GetCurrentValue(): TObject;
+
+function TX2POHash.GetCurrentValue: TObject;
begin
- Result := TX2HashObjectManager(ValueManager).ToValue(Cursor.Current^.Value);
+ Result := ValueManager.GetValue(Cursor.Current^.Value);
end;
-function TX2POHash.GetOwnsObjects(): Boolean;
+
+function TX2POHash.GetOwnsObjects: Boolean;
begin
- Result := TX2HashObjectManager(ValueManager).OwnsObjects;
+ Result := ValueManager.OwnsObjects;
end;
+
procedure TX2POHash.SetOwnsObjects(const Value: Boolean);
begin
- TX2HashObjectManager(ValueManager).OwnsObjects := Value;
+ ValueManager.OwnsObjects := Value;
end;
+
function TX2POHash.GetValue(Key: Pointer): TObject;
var
- pItem: PX2HashValue;
+ item: PX2HashValue;
begin
- Result := nil;
- pItem := Find(Key, False);
- if Assigned(pItem) then
- Result := TX2HashObjectManager(ValueManager).ToValue(pItem^.Value);
+ Result := nil;
+ item := Find(Key, False);
+ if Assigned(item) then
+ Result := ValueManager.GetValue(item^.Value);
end;
+
procedure TX2POHash.SetValue(Key: Pointer; const Value: TObject);
begin
- inherited SetValue(Find(Key, True),
- TX2HashObjectManager(ValueManager).ToPointer(Value));
+ inherited SetValue(Find(Key, True), ValueManager.CreateCookie(Value));
+end;
+
+
+function TX2POHash.GetValueManager: TX2HashObjectManager;
+begin
+ Result := TX2HashObjectManager(inherited ValueManager);
end;
{========================================
TX2PSHash
========================================}
-function TX2PSHash.CreateValueManager(): TX2CustomHashManager;
+function TX2PSHash.CreateValueManager: TX2CustomHashManager;
begin
- Result := TX2HashStringManager.Create();
+ Result := TX2HashStringManager.Create;
end;
-function TX2PSHash.GetCurrentValue(): String;
+
+function TX2PSHash.GetCurrentValue: String;
begin
- Result := TX2HashStringManager(ValueManager).ToValue(Cursor.Current^.Value);
+ Result := ValueManager.GetValue(Cursor.Current^.Value);
end;
+
function TX2PSHash.GetValue(Key: Pointer): String;
var
- pItem: PX2HashValue;
+ item: PX2HashValue;
begin
- Result := '';
- pItem := Find(Key, False);
- if Assigned(pItem) then
- Result := TX2HashStringManager(ValueManager).ToValue(pItem^.Value);
+ Result := '';
+ item := Find(Key, False);
+ if Assigned(item) then
+ Result := ValueManager.GetValue(item^.Value);
end;
+
procedure TX2PSHash.SetValue(Key: Pointer; const Value: String);
begin
- inherited SetValue(Find(Key, True),
- TX2HashStringManager(ValueManager).ToPointer(Value));
+ inherited SetValue(Find(Key, True), ValueManager.CreateCookie(Value));
end;
+
+function TX2PSHash.GetValueManager: TX2HashStringManager;
+begin
+ Result := TX2HashStringManager(inherited ValueManager);
+end;
+
+
{========================================
TX2IPHash
========================================}
-function TX2IPHash.CreateValueManager(): TX2CustomHashManager;
+function TX2IPHash.CreateValueManager: TX2CustomHashManager;
begin
- Result := TX2HashPointerManager.Create();
+ Result := TX2HashPointerManager.Create;
end;
-function TX2IPHash.GetCurrentValue(): Pointer;
+
+function TX2IPHash.GetCurrentValue: Pointer;
begin
- CursorRequired();
- Result := TX2HashPointerManager(ValueManager).ToValue(Cursor.Current^.Value);
+ CursorRequired;
+ Result := ValueManager.GetValue(Cursor.Current^.Value);
end;
+
function TX2IPHash.GetValue(Key: Integer): Pointer;
var
- pItem: PX2HashValue;
+ item: PX2HashValue;
begin
- Result := nil;
- pItem := Find(Key, False);
- if Assigned(pItem) then
- Result := TX2HashPointerManager(ValueManager).ToValue(pItem^.Value);
+ Result := nil;
+ item := Find(Key, False);
+ if Assigned(item) then
+ Result := ValueManager.GetValue(item^.Value);
end;
+
procedure TX2IPHash.SetValue(Key: Integer; const Value: Pointer);
begin
- inherited SetValue(Find(Key, True),
- TX2HashPointerManager(ValueManager).ToPointer(Value));
+ inherited SetValue(Find(Key, True), ValueManager.CreateCookie(Value));
end;
+
+function TX2IPHash.GetValueManager: TX2HashPointerManager;
+begin
+ Result := TX2HashPointerManager(inherited ValueManager);
+end;
+
+
{========================================
TX2IIHash
========================================}
-function TX2IIHash.CreateValueManager(): TX2CustomHashManager;
+function TX2IIHash.CreateValueManager: TX2CustomHashManager;
begin
- Result := TX2HashIntegerManager.Create();
+ Result := TX2HashIntegerManager.Create;
end;
-function TX2IIHash.GetCurrentValue(): Integer;
+
+function TX2IIHash.GetCurrentValue: Integer;
begin
- CursorRequired();
- Result := TX2HashIntegerManager(ValueManager).ToValue(Cursor.Current^.Value);
+ CursorRequired;
+ Result := ValueManager.GetValue(Cursor.Current^.Value);
end;
+
function TX2IIHash.GetValue(Key: Integer): Integer;
var
- pItem: PX2HashValue;
+ item: PX2HashValue;
begin
- Result := 0;
- pItem := Find(Key, False);
- if Assigned(pItem) then
- Result := TX2HashIntegerManager(ValueManager).ToValue(pItem^.Value);
+ Result := 0;
+ item := Find(Key, False);
+ if Assigned(item) then
+ Result := ValueManager.GetValue(item^.Value);
end;
+
procedure TX2IIHash.SetValue(Key: Integer; const Value: Integer);
begin
- inherited SetValue(Find(Key, True),
- TX2HashIntegerManager(ValueManager).ToPointer(Value));
+ inherited SetValue(Find(Key, True), ValueManager.CreateCookie(Value));
end;
+
+function TX2IIHash.GetValueManager: TX2HashIntegerManager;
+begin
+ Result := TX2HashIntegerManager(inherited ValueManager);
+end;
+
+
{========================================
TX2IOHash
========================================}
constructor TX2IOHash.Create(const AOwnsObjects: Boolean);
begin
- inherited Create();
+ inherited Create;
OwnsObjects := AOwnsObjects;
end;
-function TX2IOHash.CreateValueManager(): TX2CustomHashManager;
+
+function TX2IOHash.CreateValueManager: TX2CustomHashManager;
begin
- Result := TX2HashObjectManager.Create();
+ Result := TX2HashObjectManager.Create;
end;
-function TX2IOHash.GetCurrentValue(): TObject;
+function TX2IOHash.GetCurrentValue: TObject;
begin
- Result := TX2HashObjectManager(ValueManager).ToValue(Cursor.Current^.Value);
+ Result := ValueManager.GetValue(Cursor.Current^.Value);
end;
-function TX2IOHash.GetOwnsObjects(): Boolean;
+
+function TX2IOHash.GetOwnsObjects: Boolean;
begin
- Result := TX2HashObjectManager(ValueManager).OwnsObjects;
+ Result := ValueManager.OwnsObjects;
end;
+
procedure TX2IOHash.SetOwnsObjects(const Value: Boolean);
begin
- TX2HashObjectManager(ValueManager).OwnsObjects := Value;
+ ValueManager.OwnsObjects := Value;
end;
+
function TX2IOHash.GetValue(Key: Integer): TObject;
var
- pItem: PX2HashValue;
+ item: PX2HashValue;
begin
- Result := nil;
- pItem := Find(Key, False);
- if Assigned(pItem) then
- Result := TX2HashObjectManager(ValueManager).ToValue(pItem^.Value);
+ Result := nil;
+ item := Find(Key, False);
+ if Assigned(item) then
+ Result := ValueManager.GetValue(item^.Value);
end;
+
procedure TX2IOHash.SetValue(Key: Integer; const Value: TObject);
begin
- inherited SetValue(Find(Key, True),
- TX2HashObjectManager(ValueManager).ToPointer(Value));
+ inherited SetValue(Find(Key, True), ValueManager.CreateCookie(Value));
+end;
+
+
+function TX2IOHash.GetValueManager: TX2HashObjectManager;
+begin
+ Result := TX2HashObjectManager(inherited ValueManager);
end;
{========================================
TX2ISHash
========================================}
-function TX2ISHash.CreateValueManager(): TX2CustomHashManager;
+function TX2ISHash.CreateValueManager: TX2CustomHashManager;
begin
- Result := TX2HashStringManager.Create();
+ Result := TX2HashStringManager.Create;
end;
-function TX2ISHash.GetCurrentValue(): String;
+
+function TX2ISHash.GetCurrentValue: String;
begin
- Result := TX2HashStringManager(ValueManager).ToValue(Cursor.Current^.Value);
+ Result := TX2HashStringManager(ValueManager).GetValue(Cursor.Current^.Value);
end;
+
function TX2ISHash.GetValue(Key: Integer): String;
var
- pItem: PX2HashValue;
+ item: PX2HashValue;
begin
- Result := '';
- pItem := Find(Key, False);
- if Assigned(pItem) then
- Result := TX2HashStringManager(ValueManager).ToValue(pItem^.Value);
+ Result := '';
+ item := Find(Key, False);
+ if Assigned(item) then
+ Result := ValueManager.GetValue(item^.Value);
end;
+
procedure TX2ISHash.SetValue(Key: Integer; const Value: String);
begin
- inherited SetValue(Find(Key, True),
- TX2HashStringManager(ValueManager).ToPointer(Value));
+ inherited SetValue(Find(Key, True), ValueManager.CreateCookie(Value));
end;
+
+function TX2ISHash.GetValueManager: TX2HashStringManager;
+begin
+ Result := TX2HashStringManager(inherited ValueManager);
+end;
+
+
{========================================
TX2OPHash
========================================}
-function TX2OPHash.CreateValueManager(): TX2CustomHashManager;
+function TX2OPHash.CreateValueManager: TX2CustomHashManager;
begin
- Result := TX2HashPointerManager.Create();
+ Result := TX2HashPointerManager.Create;
end;
-function TX2OPHash.GetCurrentValue(): Pointer;
+
+function TX2OPHash.GetCurrentValue: Pointer;
begin
- CursorRequired();
- Result := TX2HashPointerManager(ValueManager).ToValue(Cursor.Current^.Value);
+ CursorRequired;
+ Result := ValueManager.GetValue(Cursor.Current^.Value);
end;
+
function TX2OPHash.GetValue(Key: TObject): Pointer;
var
- pItem: PX2HashValue;
+ item: PX2HashValue;
begin
- Result := nil;
- pItem := Find(Key, False);
- if Assigned(pItem) then
- Result := TX2HashPointerManager(ValueManager).ToValue(pItem^.Value);
+ Result := nil;
+ item := Find(Key, False);
+ if Assigned(item) then
+ Result := ValueManager.GetValue(item^.Value);
end;
+
procedure TX2OPHash.SetValue(Key: TObject; const Value: Pointer);
begin
- inherited SetValue(Find(Key, True),
- TX2HashPointerManager(ValueManager).ToPointer(Value));
+ inherited SetValue(Find(Key, True), ValueManager.CreateCookie(Value));
end;
+
+function TX2OPHash.GetValueManager: TX2HashPointerManager;
+begin
+ Result := TX2HashPointerManager(inherited ValueManager);
+end;
+
+
{========================================
TX2OIHash
========================================}
-function TX2OIHash.CreateValueManager(): TX2CustomHashManager;
+function TX2OIHash.CreateValueManager: TX2CustomHashManager;
begin
- Result := TX2HashIntegerManager.Create();
+ Result := TX2HashIntegerManager.Create;
end;
-function TX2OIHash.GetCurrentValue(): Integer;
+
+function TX2OIHash.GetCurrentValue: Integer;
begin
- CursorRequired();
- Result := TX2HashIntegerManager(ValueManager).ToValue(Cursor.Current^.Value);
+ CursorRequired;
+ Result := ValueManager.GetValue(Cursor.Current^.Value);
end;
+
function TX2OIHash.GetValue(Key: TObject): Integer;
var
- pItem: PX2HashValue;
+ item: PX2HashValue;
begin
- Result := 0;
- pItem := Find(Key, False);
- if Assigned(pItem) then
- Result := TX2HashIntegerManager(ValueManager).ToValue(pItem^.Value);
+ Result := 0;
+ item := Find(Key, False);
+ if Assigned(item) then
+ Result := ValueManager.GetValue(item^.Value);
end;
+
procedure TX2OIHash.SetValue(Key: TObject; const Value: Integer);
begin
- inherited SetValue(Find(Key, True),
- TX2HashIntegerManager(ValueManager).ToPointer(Value));
+ inherited SetValue(Find(Key, True), ValueManager.CreateCookie(Value));
end;
+
+function TX2OIHash.GetValueManager: TX2HashIntegerManager;
+begin
+ Result := TX2HashIntegerManager(inherited ValueManager);
+end;
+
+
{========================================
TX2OOHash
========================================}
constructor TX2OOHash.Create(const AOwnsObjects: Boolean);
begin
- inherited Create();
+ inherited Create;
OwnsObjects := AOwnsObjects;
end;
-function TX2OOHash.CreateValueManager(): TX2CustomHashManager;
+
+function TX2OOHash.CreateValueManager: TX2CustomHashManager;
begin
- Result := TX2HashObjectManager.Create();
+ Result := TX2HashObjectManager.Create;
end;
-function TX2OOHash.GetCurrentValue(): TObject;
+
+function TX2OOHash.GetCurrentValue: TObject;
begin
- Result := TX2HashObjectManager(ValueManager).ToValue(Cursor.Current^.Value);
+ Result := ValueManager.GetValue(Cursor.Current^.Value);
end;
-function TX2OOHash.GetOwnsObjects(): Boolean;
+
+function TX2OOHash.GetOwnsObjects: Boolean;
begin
- Result := TX2HashObjectManager(ValueManager).OwnsObjects;
+ Result := ValueManager.OwnsObjects;
end;
+
procedure TX2OOHash.SetOwnsObjects(const Value: Boolean);
begin
- TX2HashObjectManager(ValueManager).OwnsObjects := Value;
+ TX2HashObjectManager(ValueManager).OwnsObjects := Value;
end;
+
function TX2OOHash.GetValue(Key: TObject): TObject;
var
- pItem: PX2HashValue;
+ item: PX2HashValue;
begin
- Result := nil;
- pItem := Find(Key, False);
- if Assigned(pItem) then
- Result := TX2HashObjectManager(ValueManager).ToValue(pItem^.Value);
+ Result := nil;
+ item := Find(Key, False);
+ if Assigned(item) then
+ Result := ValueManager.GetValue(item^.Value);
end;
+
procedure TX2OOHash.SetValue(Key: TObject; const Value: TObject);
begin
- inherited SetValue(Find(Key, True),
- TX2HashObjectManager(ValueManager).ToPointer(Value));
+ inherited SetValue(Find(Key, True), ValueManager.CreateCookie(Value));
+end;
+
+
+function TX2OOHash.GetValueManager: TX2HashObjectManager;
+begin
+ Result := TX2HashObjectManager(inherited ValueManager);
end;
{========================================
TX2OSHash
========================================}
-function TX2OSHash.CreateValueManager(): TX2CustomHashManager;
+function TX2OSHash.CreateValueManager: TX2CustomHashManager;
begin
- Result := TX2HashStringManager.Create();
+ Result := TX2HashStringManager.Create;
end;
-function TX2OSHash.GetCurrentValue(): String;
+
+function TX2OSHash.GetCurrentValue: String;
begin
- Result := TX2HashStringManager(ValueManager).ToValue(Cursor.Current^.Value);
+ Result := ValueManager.GetValue(Cursor.Current^.Value);
end;
+
function TX2OSHash.GetValue(Key: TObject): String;
var
- pItem: PX2HashValue;
+ item: PX2HashValue;
begin
- Result := '';
- pItem := Find(Key, False);
- if Assigned(pItem) then
- Result := TX2HashStringManager(ValueManager).ToValue(pItem^.Value);
+ Result := '';
+ item := Find(Key, False);
+ if Assigned(item) then
+ Result := ValueManager.GetValue(item^.Value);
end;
+
procedure TX2OSHash.SetValue(Key: TObject; const Value: String);
begin
- inherited SetValue(Find(Key, True),
- TX2HashStringManager(ValueManager).ToPointer(Value));
+ inherited SetValue(Find(Key, True), ValueManager.CreateCookie(Value));
end;
+
+function TX2OSHash.GetValueManager: TX2HashStringManager;
+begin
+ Result := TX2HashStringManager(inherited ValueManager);
+end;
+
+
{========================================
TX2SPHash
========================================}
-function TX2SPHash.CreateValueManager(): TX2CustomHashManager;
+function TX2SPHash.CreateValueManager: TX2CustomHashManager;
begin
- Result := TX2HashPointerManager.Create();
+ Result := TX2HashPointerManager.Create;
end;
-function TX2SPHash.GetCurrentValue(): Pointer;
+
+function TX2SPHash.GetCurrentValue: Pointer;
begin
- CursorRequired();
- Result := TX2HashPointerManager(ValueManager).ToValue(Cursor.Current^.Value);
+ CursorRequired;
+ Result := ValueManager.GetValue(Cursor.Current^.Value);
end;
+
function TX2SPHash.GetValue(Key: String): Pointer;
var
- pItem: PX2HashValue;
+ item: PX2HashValue;
begin
- Result := nil;
- pItem := Find(Key, False);
- if Assigned(pItem) then
- Result := TX2HashPointerManager(ValueManager).ToValue(pItem^.Value);
+ Result := nil;
+ item := Find(Key, False);
+ if Assigned(item) then
+ Result := ValueManager.GetValue(item^.Value);
end;
+
procedure TX2SPHash.SetValue(Key: String; const Value: Pointer);
begin
- inherited SetValue(Find(Key, True),
- TX2HashPointerManager(ValueManager).ToPointer(Value));
+ inherited SetValue(Find(Key, True), ValueManager.CreateCookie(Value));
end;
+
+function TX2SPHash.GetValueManager: TX2HashPointerManager;
+begin
+ Result := TX2HashPointerManager(inherited ValueManager);
+end;
+
+
{========================================
TX2SIHash
========================================}
-function TX2SIHash.CreateValueManager(): TX2CustomHashManager;
+function TX2SIHash.CreateValueManager: TX2CustomHashManager;
begin
- Result := TX2HashIntegerManager.Create();
+ Result := TX2HashIntegerManager.Create;
end;
-function TX2SIHash.GetCurrentValue(): Integer;
+
+function TX2SIHash.GetCurrentValue: Integer;
begin
- CursorRequired();
- Result := TX2HashIntegerManager(ValueManager).ToValue(Cursor.Current^.Value);
+ CursorRequired;
+ Result := ValueManager.GetValue(Cursor.Current^.Value);
end;
+
function TX2SIHash.GetValue(Key: String): Integer;
var
- pItem: PX2HashValue;
+ item: PX2HashValue;
begin
- Result := 0;
- pItem := Find(Key, False);
- if Assigned(pItem) then
- Result := TX2HashIntegerManager(ValueManager).ToValue(pItem^.Value);
+ Result := 0;
+ item := Find(Key, False);
+ if Assigned(item) then
+ Result := ValueManager.GetValue(item^.Value);
end;
+
procedure TX2SIHash.SetValue(Key: String; const Value: Integer);
begin
- inherited SetValue(Find(Key, True),
- TX2HashIntegerManager(ValueManager).ToPointer(Value));
+ inherited SetValue(Find(Key, True), ValueManager.CreateCookie(Value));
end;
+
+function TX2SIHash.GetValueManager: TX2HashIntegerManager;
+begin
+ Result := TX2HashIntegerManager(inherited ValueManager);
+end;
+
+
{========================================
TX2SOHash
========================================}
constructor TX2SOHash.Create(const AOwnsObjects: Boolean);
begin
- inherited Create();
+ inherited Create;
OwnsObjects := AOwnsObjects;
end;
-function TX2SOHash.CreateValueManager(): TX2CustomHashManager;
+
+function TX2SOHash.CreateValueManager: TX2CustomHashManager;
begin
- Result := TX2HashObjectManager.Create();
+ Result := TX2HashObjectManager.Create;
end;
-function TX2SOHash.GetCurrentValue(): TObject;
+
+function TX2SOHash.GetCurrentValue: TObject;
begin
- Result := TX2HashObjectManager(ValueManager).ToValue(Cursor.Current^.Value);
+ Result := ValueManager.GetValue(Cursor.Current^.Value);
end;
-function TX2SOHash.GetOwnsObjects(): Boolean;
+
+function TX2SOHash.GetOwnsObjects: Boolean;
begin
- Result := TX2HashObjectManager(ValueManager).OwnsObjects;
+ Result := ValueManager.OwnsObjects;
end;
+
procedure TX2SOHash.SetOwnsObjects(const Value: Boolean);
begin
- TX2HashObjectManager(ValueManager).OwnsObjects := Value;
+ TX2HashObjectManager(ValueManager).OwnsObjects := Value;
end;
+
function TX2SOHash.GetValue(Key: String): TObject;
var
- pItem: PX2HashValue;
+ item: PX2HashValue;
begin
- Result := nil;
- pItem := Find(Key, False);
- if Assigned(pItem) then
- Result := TX2HashObjectManager(ValueManager).ToValue(pItem^.Value);
+ Result := nil;
+ item := Find(Key, False);
+ if Assigned(item) then
+ Result := ValueManager.GetValue(item^.Value);
end;
+
procedure TX2SOHash.SetValue(Key: String; const Value: TObject);
begin
- inherited SetValue(Find(Key, True),
- TX2HashObjectManager(ValueManager).ToPointer(Value));
+ inherited SetValue(Find(Key, True), ValueManager.CreateCookie(Value));
+end;
+
+
+function TX2SOHash.GetValueManager: TX2HashObjectManager;
+begin
+ Result := TX2HashObjectManager(inherited ValueManager);
end;
{========================================
TX2SSHash
========================================}
-function TX2SSHash.CreateValueManager(): TX2CustomHashManager;
+function TX2SSHash.CreateValueManager: TX2CustomHashManager;
begin
- Result := TX2HashStringManager.Create();
+ Result := TX2HashStringManager.Create;
end;
-function TX2SSHash.GetCurrentValue(): String;
+
+function TX2SSHash.GetCurrentValue: String;
begin
- Result := TX2HashStringManager(ValueManager).ToValue(Cursor.Current^.Value);
+ Result := ValueManager.GetValue(Cursor.Current^.Value);
end;
+
function TX2SSHash.GetValue(Key: String): String;
var
- pItem: PX2HashValue;
+ item: PX2HashValue;
begin
- Result := '';
- pItem := Find(Key, False);
- if Assigned(pItem) then
- Result := TX2HashStringManager(ValueManager).ToValue(pItem^.Value);
+ Result := '';
+ item := Find(Key, False);
+ if Assigned(item) then
+ Result := ValueManager.GetValue(item^.Value);
end;
+
procedure TX2SSHash.SetValue(Key: String; const Value: String);
begin
- inherited SetValue(Find(Key, True),
- TX2HashStringManager(ValueManager).ToPointer(Value));
+ inherited SetValue(Find(Key, True), ValueManager.CreateCookie(Value));
+end;
+
+
+function TX2SSHash.GetValueManager: TX2HashStringManager;
+begin
+ Result := TX2HashStringManager(inherited ValueManager);
end;
{$IFDEF D2005PLUS}
{$ENDREGION}
@@ -2093,6 +2458,7 @@ end;
initialization
- CRC32Init();
+ CRC32Init;
end.
+
diff --git a/X2UtHashesVariants.pas b/X2UtHashesVariants.pas
index 83a9232..b7410a6 100644
--- a/X2UtHashesVariants.pas
+++ b/X2UtHashesVariants.pas
@@ -13,244 +13,332 @@ uses
X2UtHashes;
+
type
{
:$ Variant value class.
}
TX2HashVariantManager = class(TX2CustomHashManager)
public
- procedure Finalize(var AData: Pointer); override;
+ procedure FreeCookie(var ACookie: PX2HashCookie); override;
- function DataSize(const AData: Pointer): Cardinal; override;
+ function CreateCookie(const AValue: Variant): PX2HashCookie; overload;
+ function GetValue(const ACookie: PX2HashCookie): Variant; overload;
- function ToPointer(const AValue: Variant): Pointer; overload;
- function ToValue(const AData: Pointer): Variant; overload;
-
- function Compare(const AData: Pointer; const AValue: Pointer;
- const ASize: Cardinal): Boolean; override;
+ function Hash(ACookie: PX2HashCookie): Cardinal; override;
+ function Compare(const ACookie1, ACookie2: PX2HashCookie): Boolean; override;
+ function Clone(const ACookie: PX2HashCookie): PX2HashCookie; override;
end;
+
{
:$ Pointer-to-Variant hash.
}
TX2PVHash = class(TX2CustomPointerHash)
private
- function GetCurrentValue(): Variant;
+ function GetCurrentValue: Variant;
function GetValue(Key: Pointer): Variant;
procedure SetValue(Key: Pointer; const Value: Variant);
+ function GetValueManager: TX2HashVariantManager;
protected
- function CreateValueManager(): TX2CustomHashManager; override;
+ function CreateValueManager: TX2CustomHashManager; override;
+
+ property ValueManager: TX2HashVariantManager read GetValueManager;
public
property CurrentValue: Variant read GetCurrentValue;
property Values[Key: Pointer]: Variant read GetValue write SetValue; default;
end;
+
{
:$ Integer-to-Variant hash.
}
TX2IVHash = class(TX2CustomIntegerHash)
private
- function GetCurrentValue(): Variant;
+ function GetCurrentValue: Variant;
function GetValue(Key: Integer): Variant;
procedure SetValue(Key: Integer; const Value: Variant);
+ function GetValueManager: TX2HashVariantManager;
protected
- function CreateValueManager(): TX2CustomHashManager; override;
+ function CreateValueManager: TX2CustomHashManager; override;
+
+ property ValueManager: TX2HashVariantManager read GetValueManager;
public
property CurrentValue: Variant read GetCurrentValue;
property Values[Key: Integer]: Variant read GetValue write SetValue; default;
end;
+
{
:$ Object-to-Variant hash.
}
TX2OVHash = class(TX2CustomObjectHash)
private
- function GetCurrentValue(): Variant;
+ function GetCurrentValue: Variant;
function GetValue(Key: TObject): Variant;
procedure SetValue(Key: TObject; const Value: Variant);
+ function GetValueManager: TX2HashVariantManager;
protected
- function CreateValueManager(): TX2CustomHashManager; override;
+ function CreateValueManager: TX2CustomHashManager; override;
+
+ property ValueManager: TX2HashVariantManager read GetValueManager;
public
property CurrentValue: Variant read GetCurrentValue;
property Values[Key: TObject]: Variant read GetValue write SetValue; default;
end;
+
{
:$ String-to-Variant hash.
}
TX2SVHash = class(TX2CustomStringHash)
private
- function GetCurrentValue(): Variant;
+ function GetCurrentValue: Variant;
function GetValue(Key: String): Variant;
procedure SetValue(Key: String; const Value: Variant);
+ function GetValueManager: TX2HashVariantManager;
protected
- function CreateValueManager(): TX2CustomHashManager; override;
+ function CreateValueManager: TX2CustomHashManager; override;
+
+ property ValueManager: TX2HashVariantManager read GetValueManager;
public
property CurrentValue: Variant read GetCurrentValue;
property Values[Key: String]: Variant read GetValue write SetValue; default;
end;
+
implementation
+uses
+ SysUtils;
+
{========================================
TX2HashVariantManager
========================================}
-function TX2HashVariantManager.DataSize(const AData: Pointer): Cardinal;
-begin
- Result := SizeOf(Variant);
-end;
+procedure TX2HashVariantManager.FreeCookie(var ACookie: PX2HashCookie);
+var
+ variantCookie: PVariant;
-procedure TX2HashVariantManager.Finalize(var AData: Pointer);
begin
- if AData <> nil then
- Dispose(PVariant(AData));
+ if Assigned(ACookie) then
+ begin
+ variantCookie := ACookie;
+ VarClear(variantCookie^);
+
+ Dispose(variantCookie);
+ end;
inherited;
end;
-function TX2HashVariantManager.ToPointer(const AValue: Variant): Pointer;
+
+function TX2HashVariantManager.CreateCookie(const AValue: Variant): PX2HashCookie;
+var
+ variantCookie: PVariant;
+
begin
- New(PVariant(Result));
- PVariant(Result)^ := AValue;
+ New(variantCookie);
+ VarCopy(variantCookie^, AValue);
+
+ Result := variantCookie;
end;
-function TX2HashVariantManager.ToValue(const AData: Pointer): Variant;
+
+function TX2HashVariantManager.GetValue(const ACookie: PX2HashCookie): Variant;
begin
- Result := PVariant(AData)^;
+ VarCopy(Result, PVariant(ACookie)^);
end;
-function TX2HashVariantManager.Compare(const AData, AValue: Pointer;
- const ASize: Cardinal): Boolean;
+
+function TX2HashVariantManager.Hash(ACookie: PX2HashCookie): Cardinal;
begin
- Result := (VarCompareValue(PVariant(AData)^, PVariant(AValue)^) = vrEqual);
+ { For now, this manager is only used for Values, which aren't hashed. }
+ raise Exception.Create('Hash method is not supported for Variants');
end;
+function TX2HashVariantManager.Compare(const ACookie1, ACookie2: PX2HashCookie): Boolean;
+begin
+ Result := (VarCompareValue(PVariant(ACookie1)^, PVariant(ACookie2)^) = vrEqual);
+end;
+
+
+function TX2HashVariantManager.Clone(const ACookie: PX2HashCookie): PX2HashCookie;
+begin
+ Result := CreateCookie(PVariant(ACookie)^);
+end;
+
+//
+//function TX2HashVariantManager.ToValue(const AData: Pointer): Variant;
+//begin
+// Result := PVariant(AData)^;
+//end;
+//
+//
+//function TX2HashVariantManager.Compare(const AData, AValue: Pointer;
+// const ASize: Cardinal): Boolean;
+//begin
+// Result := (VarCompareValue(PVariant(AData)^, PVariant(AValue)^) = vrEqual);
+//end;
+
+
{========================================
TX2PVHash
========================================}
-function TX2PVHash.CreateValueManager(): TX2CustomHashManager;
+function TX2PVHash.CreateValueManager: TX2CustomHashManager;
begin
- Result := TX2HashVariantManager.Create();
+ Result := TX2HashVariantManager.Create;
end;
-function TX2PVHash.GetCurrentValue(): Variant;
+
+function TX2PVHash.GetCurrentValue: Variant;
begin
- CursorRequired();
- Result := TX2HashVariantManager(ValueManager).ToValue(Cursor.Current^.Value);
+ CursorRequired;
+ Result := ValueManager.GetValue(Cursor.Current^.Value);
end;
+
function TX2PVHash.GetValue(Key: Pointer): Variant;
var
- pItem: PX2HashValue;
+ item: PX2HashValue;
begin
- Result := Unassigned;
- pItem := Find(Key, False);
- if Assigned(pItem) then
- Result := TX2HashVariantManager(ValueManager).ToValue(pItem^.Value);
+ Result := Unassigned;
+ item := Find(Key, False);
+ if Assigned(item) then
+ Result := ValueManager.GetValue(item^.Value);
end;
+
procedure TX2PVHash.SetValue(Key: Pointer; const Value: Variant);
begin
- inherited SetValue(Find(Key, True),
- TX2HashVariantManager(ValueManager).ToPointer(Value));
+ inherited SetValue(Find(Key, True), ValueManager.CreateCookie(Value));
+end;
+
+
+function TX2PVHash.GetValueManager: TX2HashVariantManager;
+begin
+ Result := TX2HashVariantManager(inherited ValueManager);
end;
{========================================
TX2IVHash
========================================}
-function TX2IVHash.CreateValueManager(): TX2CustomHashManager;
+function TX2IVHash.CreateValueManager: TX2CustomHashManager;
begin
- Result := TX2HashVariantManager.Create();
+ Result := TX2HashVariantManager.Create;
end;
-function TX2IVHash.GetCurrentValue(): Variant;
+
+function TX2IVHash.GetCurrentValue: Variant;
begin
- CursorRequired();
- Result := TX2HashVariantManager(ValueManager).ToValue(Cursor.Current^.Value);
+ CursorRequired;
+ Result := ValueManager.GetValue(Cursor.Current^.Value);
end;
+
function TX2IVHash.GetValue(Key: Integer): Variant;
var
- pItem: PX2HashValue;
+ item: PX2HashValue;
begin
- Result := Unassigned;
- pItem := Find(Key, False);
- if Assigned(pItem) then
- Result := TX2HashVariantManager(ValueManager).ToValue(pItem^.Value);
+ Result := Unassigned;
+ item := Find(Key, False);
+ if Assigned(item) then
+ Result := ValueManager.GetValue(item^.Value);
end;
+
procedure TX2IVHash.SetValue(Key: Integer; const Value: Variant);
begin
- inherited SetValue(Find(Key, True),
- TX2HashVariantManager(ValueManager).ToPointer(Value));
+ inherited SetValue(Find(Key, True), ValueManager.CreateCookie(Value));
+end;
+
+
+function TX2IVHash.GetValueManager: TX2HashVariantManager;
+begin
+ Result := TX2HashVariantManager(inherited ValueManager);
end;
{========================================
TX2OVHash
========================================}
-function TX2OVHash.CreateValueManager(): TX2CustomHashManager;
+function TX2OVHash.CreateValueManager: TX2CustomHashManager;
begin
- Result := TX2HashVariantManager.Create();
+ Result := TX2HashVariantManager.Create;
end;
-function TX2OVHash.GetCurrentValue(): Variant;
+
+function TX2OVHash.GetCurrentValue: Variant;
begin
- CursorRequired();
- Result := TX2HashVariantManager(ValueManager).ToValue(Cursor.Current^.Value);
+ CursorRequired;
+ Result := ValueManager.GetValue(Cursor.Current^.Value);
end;
+
function TX2OVHash.GetValue(Key: TObject): Variant;
var
- pItem: PX2HashValue;
+ item: PX2HashValue;
begin
- Result := Unassigned;
- pItem := Find(Key, False);
- if Assigned(pItem) then
- Result := TX2HashVariantManager(ValueManager).ToValue(pItem^.Value);
+ Result := Unassigned;
+ item := Find(Key, False);
+ if Assigned(item) then
+ Result := ValueManager.GetValue(item^.Value);
end;
+
procedure TX2OVHash.SetValue(Key: TObject; const Value: Variant);
begin
- inherited SetValue(Find(Key, True),
- TX2HashVariantManager(ValueManager).ToPointer(Value));
+ inherited SetValue(Find(Key, True), ValueManager.CreateCookie(Value));
+end;
+
+
+function TX2OVHash.GetValueManager: TX2HashVariantManager;
+begin
+ Result := TX2HashVariantManager(inherited ValueManager);
end;
{========================================
TX2SVHash
========================================}
-function TX2SVHash.CreateValueManager(): TX2CustomHashManager;
+function TX2SVHash.CreateValueManager: TX2CustomHashManager;
begin
- Result := TX2HashVariantManager.Create();
+ Result := TX2HashVariantManager.Create;
end;
-function TX2SVHash.GetCurrentValue(): Variant;
+
+function TX2SVHash.GetCurrentValue: Variant;
begin
- CursorRequired();
- Result := TX2HashVariantManager(ValueManager).ToValue(Cursor.Current^.Value);
+ CursorRequired;
+ Result := ValueManager.GetValue(Cursor.Current^.Value);
end;
+
function TX2SVHash.GetValue(Key: String): Variant;
var
- pItem: PX2HashValue;
+ item: PX2HashValue;
begin
- Result := Unassigned;
- pItem := Find(Key, False);
- if Assigned(pItem) then
- Result := TX2HashVariantManager(ValueManager).ToValue(pItem^.Value);
+ Result := Unassigned;
+ item := Find(Key, False);
+ if Assigned(item) then
+ Result := ValueManager.GetValue(item^.Value);
end;
+
procedure TX2SVHash.SetValue(Key: String; const Value: Variant);
begin
- inherited SetValue(Find(Key, True),
- TX2HashVariantManager(ValueManager).ToPointer(Value));
+ inherited SetValue(Find(Key, True), ValueManager.CreateCookie(Value));
+end;
+
+
+function TX2SVHash.GetValueManager: TX2HashVariantManager;
+begin
+ Result := TX2HashVariantManager(inherited ValueManager);
end;
end.