home *** CD-ROM | disk | FTP | other *** search
- {$INCLUDE ..\cDefines.inc}
- unit cDictionaries;
-
- { }
- { Data structures: Dictionaries v3.10 }
- { }
- { This unit is copyright ⌐ 1999-2002 by David Butler (david@e.co.za) }
- { }
- { This unit is part of Delphi Fundamentals. }
- { Its original file name is cDictionaries.pas }
- { It was generated 29 Oct 2002 02:22. }
- { The latest version is available from the Fundamentals home page }
- { http://fundementals.sourceforge.net/ }
- { }
- { I invite you to use this unit, free of charge. }
- { I invite you to distibute this unit, but it must be for free. }
- { I also invite you to contribute to its development, }
- { but do not distribute a modified copy of this file. }
- { }
- { A forum is available on SourceForge for general discussion }
- { http://sourceforge.net/forum/forum.php?forum_id=2117 }
- { }
- { }
- { Revision history: }
- { [ cDataStructs ] }
- { 1999/11/12 0.01 Split cTypes from cDataStruct and cHolder. }
- { 2000/06/16 1.02 Added ADictionary. }
- { 2000/06/14 1.03 Converted cDataStructs to template. }
- { 2000/06/16 1.04 Added dictionaries stored in AArrays. }
- { 2000/07/07 1.05 Added ATypeDictionary. }
- { 2001/01/19 1.06 Added THashedStringDictionary. }
- { 2001/04/13 1.07 Added TObjectDictionary. }
- { 2001/08/20 2.08 Merged cTypes and cDataStructs to allow object }
- { interface implementation in base classes. }
- { 2002/01/14 2.09 Replaced AllowDuplicates property with DuplicatesAction }
- { property. }
- { [ cDictionaries ] }
- { 2002/05/15 3.10 Created cDictionaries unit from cDataStructs. }
- { Refactored for Fundamentals 3. }
- { }
-
- interface
-
- uses
- // Delphi
- SysUtils,
-
- // Fundamentals
- cUtils,
- cTypes,
- cArrays;
-
- const
- UnitName = 'cDictionaries';
- UnitVersion = '3.10';
- UnitDesc = 'Data structures: Dictionaries';
- UnitCopyright = '(c) 1999-2002 David Butler';
-
-
-
- { }
- { DICTIONARY BASE CLASSES }
- { Classes with the A-prefix are Abstract base classes. They define the }
- { interface for the type and must never be instanciated. }
- { Instead, create one of the implementation classes (T-prefix). }
- { }
-
-
-
- { }
- { ADictionary }
- { Base class for a dictionary (key-value pair where the key is a string). }
- { }
- type
- TDictionaryDuplicatesAction = (ddError, // raises an exception on duplicate keys
- ddAccept, // allow duplicate keys
- ddIgnore); // silently discard duplicates
- ADictionary = class (AType)
- protected
- Procedure DictionaryError (const Msg : String);
- Procedure KeyNotFoundError (const Key : String);
-
- Function GetAddOnSet : Boolean; virtual; abstract;
- Procedure SetAddOnSet (const AddOnSet : Boolean); virtual; abstract;
- Function GetDuplicatesAction : TDictionaryDuplicatesAction; virtual; abstract;
- Procedure SetDuplicatesAction (const DuplicatesAction : TDictionaryDuplicatesAction); virtual; abstract;
- Function GetKeysCaseSensitive : Boolean; virtual; abstract;
-
- public
- Procedure Delete (const Key : String); virtual; abstract;
- Function HasKey (const Key : String) : Boolean; virtual; abstract;
- Procedure Rename (const Key, NewKey : String); virtual; abstract;
-
- Function Count : Integer; virtual; abstract;
- Function GetKeyByIndex (const Idx : Integer) : String; virtual; abstract;
-
- Property AddOnSet : Boolean read GetAddOnSet write SetAddOnSet;
- Property DuplicatesAction : TDictionaryDuplicatesAction read GetDuplicatesAction write SetDuplicatesAction;
- Property KeysCaseSensitive : Boolean read GetKeysCaseSensitive;
- end;
- EDictionary = class (EType);
-
-
-
- { }
- { ALongIntDictionary }
- { A Dictionary with LongInt values and String keys. }
- { }
- type
- ALongIntDictionary = class (ADictionary)
- protected
- Function GetAsString : String; override;
-
- Function GetItem (const Key : String) : LongInt; virtual;
- Procedure SetItem (const Key : String; const Value : LongInt); virtual; abstract;
-
- public
- { AType implementations }
- Procedure Assign (const Source : TObject); override;
-
- { ALongIntDictionary interface }
- Property Item [const Key : String] : LongInt read GetItem write SetItem; default;
- Procedure Add (const Key : String; const Value : LongInt); virtual; abstract;
-
- Function GetItemByIndex (const Idx : Integer) : LongInt; virtual; abstract;
- Function LocateItem (const Key : String; var Value : LongInt) : Integer; virtual; abstract;
- Function LocateNext (const Key : String; const Idx : Integer;
- var Value : LongInt) : Integer; virtual; abstract;
- end;
- ELongIntDictionary = class (EDictionary);
-
-
-
- { }
- { AIntegerDictionary }
- { }
- type
- AIntegerDictionary = ALongIntDictionary;
-
-
-
- { }
- { ALongWordDictionary }
- { A Dictionary with LongWord values and String keys. }
- { }
- type
- ALongWordDictionary = class (ADictionary)
- protected
- Function GetAsString : String; override;
-
- Function GetItem (const Key : String) : LongWord; virtual;
- Procedure SetItem (const Key : String; const Value : LongWord); virtual; abstract;
-
- public
- { AType implementations }
- Procedure Assign (const Source : TObject); override;
-
- { ALongWordDictionary interface }
- Property Item [const Key : String] : LongWord read GetItem write SetItem; default;
- Procedure Add (const Key : String; const Value : LongWord); virtual; abstract;
-
- Function GetItemByIndex (const Idx : Integer) : LongWord; virtual; abstract;
- Function LocateItem (const Key : String; var Value : LongWord) : Integer; virtual; abstract;
- Function LocateNext (const Key : String; const Idx : Integer;
- var Value : LongWord) : Integer; virtual; abstract;
- end;
- ELongWordDictionary = class (EDictionary);
-
-
-
- { }
- { ACardinalArray }
- { }
- type
- ACardinalDictionary = ALongWordDictionary;
-
-
-
- { }
- { AInt64Dictionary }
- { A Dictionary with Int64 values and String keys. }
- { }
- type
- AInt64Dictionary = class (ADictionary)
- protected
- Function GetAsString : String; override;
-
- Function GetItem (const Key : String) : Int64; virtual;
- Procedure SetItem (const Key : String; const Value : Int64); virtual; abstract;
-
- public
- { AType implementations }
- Procedure Assign (const Source : TObject); override;
-
- { AInt64Dictionary interface }
- Property Item [const Key : String] : Int64 read GetItem write SetItem; default;
- Procedure Add (const Key : String; const Value : Int64); virtual; abstract;
-
- Function GetItemByIndex (const Idx : Integer) : Int64; virtual; abstract;
- Function LocateItem (const Key : String; var Value : Int64) : Integer; virtual; abstract;
- Function LocateNext (const Key : String; const Idx : Integer;
- var Value : Int64) : Integer; virtual; abstract;
- end;
- EInt64Dictionary = class (EDictionary);
-
-
-
- { }
- { ASingleDictionary }
- { A Dictionary with Single values and String keys. }
- { }
- type
- ASingleDictionary = class (ADictionary)
- protected
- Function GetAsString : String; override;
-
- Function GetItem (const Key : String) : Single; virtual;
- Procedure SetItem (const Key : String; const Value : Single); virtual; abstract;
-
- public
- { AType implementations }
- Procedure Assign (const Source : TObject); override;
-
- { ASingleDictionary interface }
- Property Item [const Key : String] : Single read GetItem write SetItem; default;
- Procedure Add (const Key : String; const Value : Single); virtual; abstract;
-
- Function GetItemByIndex (const Idx : Integer) : Single; virtual; abstract;
- Function LocateItem (const Key : String; var Value : Single) : Integer; virtual; abstract;
- Function LocateNext (const Key : String; const Idx : Integer;
- var Value : Single) : Integer; virtual; abstract;
- end;
- ESingleDictionary = class (EDictionary);
-
-
-
- { }
- { ADoubleDictionary }
- { A Dictionary with Double values and String keys. }
- { }
- type
- ADoubleDictionary = class (ADictionary)
- protected
- Function GetAsString : String; override;
-
- Function GetItem (const Key : String) : Double; virtual;
- Procedure SetItem (const Key : String; const Value : Double); virtual; abstract;
-
- public
- { AType implementations }
- Procedure Assign (const Source : TObject); override;
-
- { ADoubleDictionary interface }
- Property Item [const Key : String] : Double read GetItem write SetItem; default;
- Procedure Add (const Key : String; const Value : Double); virtual; abstract;
-
- Function GetItemByIndex (const Idx : Integer) : Double; virtual; abstract;
- Function LocateItem (const Key : String; var Value : Double) : Integer; virtual; abstract;
- Function LocateNext (const Key : String; const Idx : Integer;
- var Value : Double) : Integer; virtual; abstract;
- end;
- EDoubleDictionary = class (EDictionary);
-
-
-
- { }
- { AExtendedDictionary }
- { A Dictionary with Extended values and String keys. }
- { }
- type
- AExtendedDictionary = class (ADictionary)
- protected
- Function GetAsString : String; override;
-
- Function GetItem (const Key : String) : Extended; virtual;
- Procedure SetItem (const Key : String; const Value : Extended); virtual; abstract;
-
- public
- { AType implementations }
- Procedure Assign (const Source : TObject); override;
-
- { AExtendedDictionary interface }
- Property Item [const Key : String] : Extended read GetItem write SetItem; default;
- Procedure Add (const Key : String; const Value : Extended); virtual; abstract;
-
- Function GetItemByIndex (const Idx : Integer) : Extended; virtual; abstract;
- Function LocateItem (const Key : String; var Value : Extended) : Integer; virtual; abstract;
- Function LocateNext (const Key : String; const Idx : Integer;
- var Value : Extended) : Integer; virtual; abstract;
- end;
- EExtendedDictionary = class (EDictionary);
-
-
-
- { }
- { APointerDictionary }
- { A Dictionary with Pointer values and String keys. }
- { }
- type
- APointerDictionary = class (ADictionary)
- protected
- Function GetAsString : String; override;
-
- Function GetItem (const Key : String) : Pointer; virtual;
- Procedure SetItem (const Key : String; const Value : Pointer); virtual; abstract;
-
- public
- { AType implementations }
- Procedure Assign (const Source : TObject); override;
-
- { APointerDictionary interface }
- Property Item [const Key : String] : Pointer read GetItem write SetItem; default;
- Procedure Add (const Key : String; const Value : Pointer); virtual; abstract;
-
- Function GetItemByIndex (const Idx : Integer) : Pointer; virtual; abstract;
- Function LocateItem (const Key : String; var Value : Pointer) : Integer; virtual; abstract;
- Function LocateNext (const Key : String; const Idx : Integer;
- var Value : Pointer) : Integer; virtual; abstract;
- end;
- EPointerDictionary = class (EDictionary);
-
-
-
- { }
- { AStringDictionary }
- { A Dictionary with String values and String keys. }
- { }
- type
- AStringDictionary = class (ADictionary)
- protected
- Function GetAsString : String; override;
-
- Function GetItem (const Key : String) : String; virtual;
- Procedure SetItem (const Key : String; const Value : String); virtual; abstract;
-
- public
- { AType implementations }
- Procedure Assign (const Source : TObject); override;
-
- { AStringDictionary interface }
- Property Item [const Key : String] : String read GetItem write SetItem; default;
- Procedure Add (const Key : String; const Value : String); virtual; abstract;
-
- Function GetItemByIndex (const Idx : Integer) : String; virtual; abstract;
- Function LocateItem (const Key : String; var Value : String) : Integer; virtual; abstract;
- Function LocateNext (const Key : String; const Idx : Integer;
- var Value : String) : Integer; virtual; abstract;
-
- Function GetItemLength (const Key : String) : Integer; virtual;
- Function GetTotalLength : Int64; virtual;
- end;
- EStringDictionary = class (EDictionary);
-
-
-
-
-
-
- { }
- { AObjectDictionary }
- { }
- type
- AObjectDictionary = class (ADictionary)
- protected
- Function GetItem (const Key : String) : TObject; virtual;
- Procedure SetItem (const Key : String; const Value : TObject); virtual; abstract;
- Function GetIsItemOwner : Boolean; virtual; abstract;
- Procedure SetIsItemOwner (const IsItemOwner : Boolean); virtual; abstract;
-
- public
- { AType implementation }
- Function GetAsString : String; override;
- Procedure Clear; override;
- Procedure Assign (const Source : TObject); reintroduce; overload; override;
-
- { AObjectDictionary interface }
- Procedure Add (const Key : String; const Value : TObject); virtual; abstract;
- Property Item [const Key : String] : TObject read GetItem write SetItem; default;
-
- Function GetItemByIndex (const Idx : Integer) : TObject; virtual; abstract;
- Function LocateItem (const Key : String; var Value : TObject) : Integer; virtual; abstract;
- Function LocateNext (const Key : String; const Idx : Integer;
- var Value : TObject) : Integer; virtual; abstract;
-
- Property IsItemOwner : Boolean read GetIsItemOwner write SetIsItemOwner;
- Function ReleaseItem (const Key : String) : TObject; virtual; abstract;
- Procedure ReleaseItems; virtual; abstract;
- Procedure FreeItems; virtual; abstract;
- end;
- EObjectDictionary = class (EDictionary);
-
-
-
- { }
- { DICTIONARY IMPLEMENTATIONS }
- { }
-
-
-
- { }
- { TLongIntDictionary }
- { Implements ALongIntDictionary using arrays. }
- { A 'chained-hash' lookup table is used for quick access. }
- { }
- type
- TLongIntDictionary = class (ALongIntDictionary)
- protected
- FKeys : AStringArray;
- FValues : ALongIntArray;
- FLookup : Array of IntegerArray;
- FCaseSensitive : Boolean;
- FAddOnSet : Boolean;
- FDuplicatesAction : TDictionaryDuplicatesAction;
-
- Function LocateKey (const Key : String; var LookupIdx : Integer;
- const ErrorIfNotFound : Boolean) : Integer;
- Function KeyIndex (const Key : String; const ErrorIfNotFound : Boolean) : Integer;
- Procedure DeleteByIndex (const Idx : Integer; const Hash : Integer = -1);
- Procedure Rehash;
- Function GetHashTableSize : Integer;
- Procedure IndexError;
-
- { ADictionary implementations }
- Function GetKeysCaseSensitive : Boolean; override;
- Function GetAddOnSet : Boolean; override;
- Procedure SetAddOnSet (const AddOnSet : Boolean); override;
- Function GetDuplicatesAction : TDictionaryDuplicatesAction; override;
- Procedure SetDuplicatesAction (const DuplicatesAction : TDictionaryDuplicatesAction); override;
-
- { ALongIntDictionary implementations }
- Procedure SetItem (const Key : String; const Value : LongInt); override;
-
- public
- { TLongIntDictionary interface }
- Constructor Create;
- Constructor CreateEx (const Keys : AStringArray = nil; const Values : ALongIntArray = nil;
- const KeysCaseSensitive : Boolean = True;
- const AddOnSet : Boolean = True;
- const DuplicatesAction : TDictionaryDuplicatesAction = ddAccept);
- Destructor Destroy; override;
-
- { AType implementations }
- class Function CreateInstance : AType; override;
- Procedure Clear; override;
-
- { ADictionary implementations }
- Procedure Delete (const Key : String); override;
- Function HasKey (const Key : String) : Boolean; override;
- Procedure Rename (const Key : String; const NewKey : String); override;
- Function Count : Integer; override;
- Function GetKeyByIndex (const Idx : Integer) : String; override;
-
- { ALongIntDictionary implementations }
- Procedure Add (const Key : String; const Value : LongInt); override;
- Function GetItemByIndex (const Idx : Integer) : LongInt; override;
- Procedure SetItemByIndex (const Idx : Integer; const Value : LongInt);
- Function LocateItem (const Key : String; var Value : LongInt) : Integer; override;
- Function LocateNext (const Key : String; const Idx : Integer;
- var Value : LongInt) : Integer; override;
-
- { TLongIntDictionary interface }
- Property HashTableSize : Integer read GetHashTableSize;
- Procedure DeleteItemByIndex (const Idx : Integer);
- end;
-
-
-
- { }
- { TIntegerDictionary }
- { }
- type
- TIntegerDictionary = TLongIntDictionary;
-
-
-
- { }
- { TLongWordDictionary }
- { Implements ALongWordDictionary using arrays. }
- { A 'chained-hash' lookup table is used for quick access. }
- { }
- type
- TLongWordDictionary = class (ALongWordDictionary)
- protected
- FKeys : AStringArray;
- FValues : ALongWordArray;
- FLookup : Array of IntegerArray;
- FCaseSensitive : Boolean;
- FAddOnSet : Boolean;
- FDuplicatesAction : TDictionaryDuplicatesAction;
-
- Function LocateKey (const Key : String; var LookupIdx : Integer;
- const ErrorIfNotFound : Boolean) : Integer;
- Function KeyIndex (const Key : String; const ErrorIfNotFound : Boolean) : Integer;
- Procedure DeleteByIndex (const Idx : Integer; const Hash : Integer = -1);
- Procedure Rehash;
- Function GetHashTableSize : Integer;
- Procedure IndexError;
-
- { ADictionary implementations }
- Function GetKeysCaseSensitive : Boolean; override;
- Function GetAddOnSet : Boolean; override;
- Procedure SetAddOnSet (const AddOnSet : Boolean); override;
- Function GetDuplicatesAction : TDictionaryDuplicatesAction; override;
- Procedure SetDuplicatesAction (const DuplicatesAction : TDictionaryDuplicatesAction); override;
-
- { ALongWordDictionary implementations }
- Procedure SetItem (const Key : String; const Value : LongWord); override;
-
- public
- { TLongWordDictionary interface }
- Constructor Create;
- Constructor CreateEx (const Keys : AStringArray = nil; const Values : ALongWordArray = nil;
- const KeysCaseSensitive : Boolean = True;
- const AddOnSet : Boolean = True;
- const DuplicatesAction : TDictionaryDuplicatesAction = ddAccept);
- Destructor Destroy; override;
-
- { AType implementations }
- class Function CreateInstance : AType; override;
- Procedure Clear; override;
-
- { ADictionary implementations }
- Procedure Delete (const Key : String); override;
- Function HasKey (const Key : String) : Boolean; override;
- Procedure Rename (const Key : String; const NewKey : String); override;
- Function Count : Integer; override;
- Function GetKeyByIndex (const Idx : Integer) : String; override;
-
- { ALongWordDictionary implementations }
- Procedure Add (const Key : String; const Value : LongWord); override;
- Function GetItemByIndex (const Idx : Integer) : LongWord; override;
- Procedure SetItemByIndex (const Idx : Integer; const Value : LongWord);
- Function LocateItem (const Key : String; var Value : LongWord) : Integer; override;
- Function LocateNext (const Key : String; const Idx : Integer;
- var Value : LongWord) : Integer; override;
-
- { TLongWordDictionary interface }
- Property HashTableSize : Integer read GetHashTableSize;
- Procedure DeleteItemByIndex (const Idx : Integer);
- end;
-
-
-
- { }
- { TCardinalDictionary }
- { }
- type
- TCardinalDictionary = TLongWordDictionary;
-
-
-
- { }
- { TInt64Dictionary }
- { Implements AInt64Dictionary using arrays. }
- { A 'chained-hash' lookup table is used for quick access. }
- { }
- type
- TInt64Dictionary = class (AInt64Dictionary)
- protected
- FKeys : AStringArray;
- FValues : AInt64Array;
- FLookup : Array of IntegerArray;
- FCaseSensitive : Boolean;
- FAddOnSet : Boolean;
- FDuplicatesAction : TDictionaryDuplicatesAction;
-
- Function LocateKey (const Key : String; var LookupIdx : Integer;
- const ErrorIfNotFound : Boolean) : Integer;
- Function KeyIndex (const Key : String; const ErrorIfNotFound : Boolean) : Integer;
- Procedure DeleteByIndex (const Idx : Integer; const Hash : Integer = -1);
- Procedure Rehash;
- Function GetHashTableSize : Integer;
- Procedure IndexError;
-
- { ADictionary implementations }
- Function GetKeysCaseSensitive : Boolean; override;
- Function GetAddOnSet : Boolean; override;
- Procedure SetAddOnSet (const AddOnSet : Boolean); override;
- Function GetDuplicatesAction : TDictionaryDuplicatesAction; override;
- Procedure SetDuplicatesAction (const DuplicatesAction : TDictionaryDuplicatesAction); override;
-
- { AInt64Dictionary implementations }
- Procedure SetItem (const Key : String; const Value : Int64); override;
-
- public
- { TInt64Dictionary interface }
- Constructor Create;
- Constructor CreateEx (const Keys : AStringArray = nil; const Values : AInt64Array = nil;
- const KeysCaseSensitive : Boolean = True;
- const AddOnSet : Boolean = True;
- const DuplicatesAction : TDictionaryDuplicatesAction = ddAccept);
- Destructor Destroy; override;
-
- { AType implementations }
- class Function CreateInstance : AType; override;
- Procedure Clear; override;
-
- { ADictionary implementations }
- Procedure Delete (const Key : String); override;
- Function HasKey (const Key : String) : Boolean; override;
- Procedure Rename (const Key : String; const NewKey : String); override;
- Function Count : Integer; override;
- Function GetKeyByIndex (const Idx : Integer) : String; override;
-
- { AInt64Dictionary implementations }
- Procedure Add (const Key : String; const Value : Int64); override;
- Function GetItemByIndex (const Idx : Integer) : Int64; override;
- Procedure SetItemByIndex (const Idx : Integer; const Value : Int64);
- Function LocateItem (const Key : String; var Value : Int64) : Integer; override;
- Function LocateNext (const Key : String; const Idx : Integer;
- var Value : Int64) : Integer; override;
-
- { TInt64Dictionary interface }
- Property HashTableSize : Integer read GetHashTableSize;
- Procedure DeleteItemByIndex (const Idx : Integer);
- end;
-
-
-
- { }
- { TSingleDictionary }
- { Implements ASingleDictionary using arrays. }
- { A 'chained-hash' lookup table is used for quick access. }
- { }
- type
- TSingleDictionary = class (ASingleDictionary)
- protected
- FKeys : AStringArray;
- FValues : ASingleArray;
- FLookup : Array of IntegerArray;
- FCaseSensitive : Boolean;
- FAddOnSet : Boolean;
- FDuplicatesAction : TDictionaryDuplicatesAction;
-
- Function LocateKey (const Key : String; var LookupIdx : Integer;
- const ErrorIfNotFound : Boolean) : Integer;
- Function KeyIndex (const Key : String; const ErrorIfNotFound : Boolean) : Integer;
- Procedure DeleteByIndex (const Idx : Integer; const Hash : Integer = -1);
- Procedure Rehash;
- Function GetHashTableSize : Integer;
- Procedure IndexError;
-
- { ADictionary implementations }
- Function GetKeysCaseSensitive : Boolean; override;
- Function GetAddOnSet : Boolean; override;
- Procedure SetAddOnSet (const AddOnSet : Boolean); override;
- Function GetDuplicatesAction : TDictionaryDuplicatesAction; override;
- Procedure SetDuplicatesAction (const DuplicatesAction : TDictionaryDuplicatesAction); override;
-
- { ASingleDictionary implementations }
- Procedure SetItem (const Key : String; const Value : Single); override;
-
- public
- { TSingleDictionary interface }
- Constructor Create;
- Constructor CreateEx (const Keys : AStringArray = nil; const Values : ASingleArray = nil;
- const KeysCaseSensitive : Boolean = True;
- const AddOnSet : Boolean = True;
- const DuplicatesAction : TDictionaryDuplicatesAction = ddAccept);
- Destructor Destroy; override;
-
- { AType implementations }
- class Function CreateInstance : AType; override;
- Procedure Clear; override;
-
- { ADictionary implementations }
- Procedure Delete (const Key : String); override;
- Function HasKey (const Key : String) : Boolean; override;
- Procedure Rename (const Key : String; const NewKey : String); override;
- Function Count : Integer; override;
- Function GetKeyByIndex (const Idx : Integer) : String; override;
-
- { ASingleDictionary implementations }
- Procedure Add (const Key : String; const Value : Single); override;
- Function GetItemByIndex (const Idx : Integer) : Single; override;
- Procedure SetItemByIndex (const Idx : Integer; const Value : Single);
- Function LocateItem (const Key : String; var Value : Single) : Integer; override;
- Function LocateNext (const Key : String; const Idx : Integer;
- var Value : Single) : Integer; override;
-
- { TSingleDictionary interface }
- Property HashTableSize : Integer read GetHashTableSize;
- Procedure DeleteItemByIndex (const Idx : Integer);
- end;
-
-
-
- { }
- { TDoubleDictionary }
- { Implements ADoubleDictionary using arrays. }
- { A 'chained-hash' lookup table is used for quick access. }
- { }
- type
- TDoubleDictionary = class (ADoubleDictionary)
- protected
- FKeys : AStringArray;
- FValues : ADoubleArray;
- FLookup : Array of IntegerArray;
- FCaseSensitive : Boolean;
- FAddOnSet : Boolean;
- FDuplicatesAction : TDictionaryDuplicatesAction;
-
- Function LocateKey (const Key : String; var LookupIdx : Integer;
- const ErrorIfNotFound : Boolean) : Integer;
- Function KeyIndex (const Key : String; const ErrorIfNotFound : Boolean) : Integer;
- Procedure DeleteByIndex (const Idx : Integer; const Hash : Integer = -1);
- Procedure Rehash;
- Function GetHashTableSize : Integer;
- Procedure IndexError;
-
- { ADictionary implementations }
- Function GetKeysCaseSensitive : Boolean; override;
- Function GetAddOnSet : Boolean; override;
- Procedure SetAddOnSet (const AddOnSet : Boolean); override;
- Function GetDuplicatesAction : TDictionaryDuplicatesAction; override;
- Procedure SetDuplicatesAction (const DuplicatesAction : TDictionaryDuplicatesAction); override;
-
- { ADoubleDictionary implementations }
- Procedure SetItem (const Key : String; const Value : Double); override;
-
- public
- { TDoubleDictionary interface }
- Constructor Create;
- Constructor CreateEx (const Keys : AStringArray = nil; const Values : ADoubleArray = nil;
- const KeysCaseSensitive : Boolean = True;
- const AddOnSet : Boolean = True;
- const DuplicatesAction : TDictionaryDuplicatesAction = ddAccept);
- Destructor Destroy; override;
-
- { AType implementations }
- class Function CreateInstance : AType; override;
- Procedure Clear; override;
-
- { ADictionary implementations }
- Procedure Delete (const Key : String); override;
- Function HasKey (const Key : String) : Boolean; override;
- Procedure Rename (const Key : String; const NewKey : String); override;
- Function Count : Integer; override;
- Function GetKeyByIndex (const Idx : Integer) : String; override;
-
- { ADoubleDictionary implementations }
- Procedure Add (const Key : String; const Value : Double); override;
- Function GetItemByIndex (const Idx : Integer) : Double; override;
- Procedure SetItemByIndex (const Idx : Integer; const Value : Double);
- Function LocateItem (const Key : String; var Value : Double) : Integer; override;
- Function LocateNext (const Key : String; const Idx : Integer;
- var Value : Double) : Integer; override;
-
- { TDoubleDictionary interface }
- Property HashTableSize : Integer read GetHashTableSize;
- Procedure DeleteItemByIndex (const Idx : Integer);
- end;
-
-
-
- { }
- { TExtendedDictionary }
- { Implements AExtendedDictionary using arrays. }
- { A 'chained-hash' lookup table is used for quick access. }
- { }
- type
- TExtendedDictionary = class (AExtendedDictionary)
- protected
- FKeys : AStringArray;
- FValues : AExtendedArray;
- FLookup : Array of IntegerArray;
- FCaseSensitive : Boolean;
- FAddOnSet : Boolean;
- FDuplicatesAction : TDictionaryDuplicatesAction;
-
- Function LocateKey (const Key : String; var LookupIdx : Integer;
- const ErrorIfNotFound : Boolean) : Integer;
- Function KeyIndex (const Key : String; const ErrorIfNotFound : Boolean) : Integer;
- Procedure DeleteByIndex (const Idx : Integer; const Hash : Integer = -1);
- Procedure Rehash;
- Function GetHashTableSize : Integer;
- Procedure IndexError;
-
- { ADictionary implementations }
- Function GetKeysCaseSensitive : Boolean; override;
- Function GetAddOnSet : Boolean; override;
- Procedure SetAddOnSet (const AddOnSet : Boolean); override;
- Function GetDuplicatesAction : TDictionaryDuplicatesAction; override;
- Procedure SetDuplicatesAction (const DuplicatesAction : TDictionaryDuplicatesAction); override;
-
- { AExtendedDictionary implementations }
- Procedure SetItem (const Key : String; const Value : Extended); override;
-
- public
- { TExtendedDictionary interface }
- Constructor Create;
- Constructor CreateEx (const Keys : AStringArray = nil; const Values : AExtendedArray = nil;
- const KeysCaseSensitive : Boolean = True;
- const AddOnSet : Boolean = True;
- const DuplicatesAction : TDictionaryDuplicatesAction = ddAccept);
- Destructor Destroy; override;
-
- { AType implementations }
- class Function CreateInstance : AType; override;
- Procedure Clear; override;
-
- { ADictionary implementations }
- Procedure Delete (const Key : String); override;
- Function HasKey (const Key : String) : Boolean; override;
- Procedure Rename (const Key : String; const NewKey : String); override;
- Function Count : Integer; override;
- Function GetKeyByIndex (const Idx : Integer) : String; override;
-
- { AExtendedDictionary implementations }
- Procedure Add (const Key : String; const Value : Extended); override;
- Function GetItemByIndex (const Idx : Integer) : Extended; override;
- Procedure SetItemByIndex (const Idx : Integer; const Value : Extended);
- Function LocateItem (const Key : String; var Value : Extended) : Integer; override;
- Function LocateNext (const Key : String; const Idx : Integer;
- var Value : Extended) : Integer; override;
-
- { TExtendedDictionary interface }
- Property HashTableSize : Integer read GetHashTableSize;
- Procedure DeleteItemByIndex (const Idx : Integer);
- end;
-
-
-
- { }
- { TStringDictionary }
- { Implements AStringDictionary using arrays. }
- { A 'chained-hash' lookup table is used for quick access. }
- { }
- type
- TStringDictionary = class (AStringDictionary)
- protected
- FKeys : AStringArray;
- FValues : AStringArray;
- FLookup : Array of IntegerArray;
- FCaseSensitive : Boolean;
- FAddOnSet : Boolean;
- FDuplicatesAction : TDictionaryDuplicatesAction;
-
- Function LocateKey (const Key : String; var LookupIdx : Integer;
- const ErrorIfNotFound : Boolean) : Integer;
- Function KeyIndex (const Key : String; const ErrorIfNotFound : Boolean) : Integer;
- Procedure DeleteByIndex (const Idx : Integer; const Hash : Integer = -1);
- Procedure Rehash;
- Function GetHashTableSize : Integer;
- Procedure IndexError;
-
- { ADictionary implementations }
- Function GetKeysCaseSensitive : Boolean; override;
- Function GetAddOnSet : Boolean; override;
- Procedure SetAddOnSet (const AddOnSet : Boolean); override;
- Function GetDuplicatesAction : TDictionaryDuplicatesAction; override;
- Procedure SetDuplicatesAction (const DuplicatesAction : TDictionaryDuplicatesAction); override;
-
- { AStringDictionary implementations }
- Procedure SetItem (const Key : String; const Value : String); override;
-
- public
- { TStringDictionary interface }
- Constructor Create;
- Constructor CreateEx (const Keys : AStringArray = nil; const Values : AStringArray = nil;
- const KeysCaseSensitive : Boolean = True;
- const AddOnSet : Boolean = True;
- const DuplicatesAction : TDictionaryDuplicatesAction = ddAccept);
- Destructor Destroy; override;
-
- { AType implementations }
- class Function CreateInstance : AType; override;
- Procedure Clear; override;
-
- { ADictionary implementations }
- Procedure Delete (const Key : String); override;
- Function HasKey (const Key : String) : Boolean; override;
- Procedure Rename (const Key : String; const NewKey : String); override;
- Function Count : Integer; override;
- Function GetKeyByIndex (const Idx : Integer) : String; override;
-
- { AStringDictionary implementations }
- Procedure Add (const Key : String; const Value : String); override;
- Function GetItemByIndex (const Idx : Integer) : String; override;
- Procedure SetItemByIndex (const Idx : Integer; const Value : String);
- Function LocateItem (const Key : String; var Value : String) : Integer; override;
- Function LocateNext (const Key : String; const Idx : Integer;
- var Value : String) : Integer; override;
-
- { TStringDictionary interface }
- Property HashTableSize : Integer read GetHashTableSize;
- Procedure DeleteItemByIndex (const Idx : Integer);
- end;
-
-
-
- { }
- { TObjectDictionary }
- { Implements AObjectDictionary using arrays. }
- { A 'chained-hash' lookup table is used for quick access. }
- { }
- type
- TObjectDictionary = class (AObjectDictionary)
- protected
- FKeys : AStringArray;
- FValues : AObjectArray;
- FLookup : Array of IntegerArray;
- FCaseSensitive : Boolean;
- FAddOnSet : Boolean;
- FDuplicatesAction : TDictionaryDuplicatesAction;
-
- Function LocateKey (const Key : String; var LookupIdx : Integer;
- const ErrorIfNotFound : Boolean) : Integer;
- Function KeyIndex (const Key : String; const ErrorIfNotFound : Boolean) : Integer;
- Procedure DeleteByIndex (const Idx : Integer; const Hash : Integer = -1);
- Procedure Rehash;
- Function GetHashTableSize : Integer;
- Procedure IndexError;
-
- { ADictionary implementations }
- Function GetKeysCaseSensitive : Boolean; override;
- Function GetAddOnSet : Boolean; override;
- Procedure SetAddOnSet (const AddOnSet : Boolean); override;
- Function GetDuplicatesAction : TDictionaryDuplicatesAction; override;
- Procedure SetDuplicatesAction (const DuplicatesAction : TDictionaryDuplicatesAction); override;
-
- { AObjectDictionary implementations }
- Function GetIsItemOwner : Boolean; override;
- Procedure SetIsItemOwner (const IsItemOwner : Boolean); override;
-
- Procedure SetItem (const Key : String; const Value : TObject); override;
-
- public
- { TObjectDictionary interface }
- Constructor Create;
- Constructor CreateEx (const Keys : AStringArray = nil; const Values : AObjectArray = nil;
- const IsItemOwner : Boolean = False;
- const KeysCaseSensitive : Boolean = True;
- const AddOnSet : Boolean = True;
- const DuplicatesAction : TDictionaryDuplicatesAction = ddAccept);
- Destructor Destroy; override;
-
- { AType implementations }
- class Function CreateInstance : AType; override;
- Procedure Clear; override;
-
- { ADictionary implementations }
- Procedure Delete (const Key : String); override;
- Function HasKey (const Key : String) : Boolean; override;
- Procedure Rename (const Key : String; const NewKey : String); override;
- Function Count : Integer; override;
- Function GetKeyByIndex (const Idx : Integer) : String; override;
-
- { AObjectDictionary implementations }
- Procedure Add (const Key : String; const Value : TObject); override;
- Function GetItemByIndex (const Idx : Integer) : TObject; override;
- Procedure SetItemByIndex (const Idx : Integer; const Value : TObject);
- Function LocateItem (const Key : String; var Value : TObject) : Integer; override;
- Function LocateNext (const Key : String; const Idx : Integer;
- var Value : TObject) : Integer; override;
-
- Function ReleaseItem (const Key : String) : TObject; override;
- Procedure ReleaseItems; override;
- Procedure FreeItems; override;
-
- { TObjectDictionary interface }
- Property HashTableSize : Integer read GetHashTableSize;
- Procedure DeleteItemByIndex (const Idx : Integer);
- end;
-
-
-
- { }
- { Dictionary functions }
- { }
- const
- AverageHashChainSize = 4;
-
- Function DictionaryRehashSize (const Count : Integer) : Integer;
-
-
-
- { }
- { Self testing code }
- { }
- Procedure SelfTest;
-
-
-
- implementation
-
- uses
- // Fundamentals
- cStrings;
-
-
-
- { }
- { DICTIONARY BASE CLASSES }
- { }
-
-
-
- { }
- { ADictionary }
- { }
- Procedure ADictionary.DictionaryError (const Msg : String);
- Begin
- TypeError (Msg, nil, EDictionary);
- End;
-
- Procedure ADictionary.KeyNotFoundError (const Key : String);
- Begin
- DictionaryError ('Key not found: ' + Key);
- End;
-
-
-
- { }
- { ALongIntDictionary }
- { }
- Function ALongIntDictionary.GetItem (const Key : String) : LongInt;
- Begin
- if LocateItem (Key, Result) < 0 then
- KeyNotFoundError (Key);
- End;
-
- Procedure ALongIntDictionary.Assign (const Source : TObject);
- var I : Integer;
- Begin
- if Source is ALongIntDictionary then
- begin
- Clear;
- For I := 0 to ALongIntDictionary (Source).Count - 1 do
- Add (ALongIntDictionary (Source).GetKeyByIndex (I),
- ALongIntDictionary (Source).GetItemByIndex (I));
- end else
- inherited Assign (Source);
- End;
-
- Function ALongIntDictionary.GetAsString : String;
- var I, L : Integer;
- Begin
- L := Count - 1;
- For I := 0 to L do
- begin
- Result := Result + GetKeyByIndex (I) + ':' + IntToStr (GetItemByIndex (I));
- if I < L then
- Result := Result + ',';
- end;
- End;
-
-
-
- { }
- { ALongWordDictionary }
- { }
- Function ALongWordDictionary.GetItem (const Key : String) : LongWord;
- Begin
- if LocateItem (Key, Result) < 0 then
- KeyNotFoundError (Key);
- End;
-
- Procedure ALongWordDictionary.Assign (const Source : TObject);
- var I : Integer;
- Begin
- if Source is ALongWordDictionary then
- begin
- Clear;
- For I := 0 to ALongWordDictionary (Source).Count - 1 do
- Add (ALongWordDictionary (Source).GetKeyByIndex (I),
- ALongWordDictionary (Source).GetItemByIndex (I));
- end else
- inherited Assign (Source);
- End;
-
- Function ALongWordDictionary.GetAsString : String;
- var I, L : Integer;
- Begin
- L := Count - 1;
- For I := 0 to L do
- begin
- Result := Result + GetKeyByIndex (I) + ':' + IntToStr (GetItemByIndex (I));
- if I < L then
- Result := Result + ',';
- end;
- End;
-
-
-
- { }
- { AInt64Dictionary }
- { }
- Function AInt64Dictionary.GetItem (const Key : String) : Int64;
- Begin
- if LocateItem (Key, Result) < 0 then
- KeyNotFoundError (Key);
- End;
-
- Procedure AInt64Dictionary.Assign (const Source : TObject);
- var I : Integer;
- Begin
- if Source is AInt64Dictionary then
- begin
- Clear;
- For I := 0 to AInt64Dictionary (Source).Count - 1 do
- Add (AInt64Dictionary (Source).GetKeyByIndex (I),
- AInt64Dictionary (Source).GetItemByIndex (I));
- end else
- inherited Assign (Source);
- End;
-
- Function AInt64Dictionary.GetAsString : String;
- var I, L : Integer;
- Begin
- L := Count - 1;
- For I := 0 to L do
- begin
- Result := Result + GetKeyByIndex (I) + ':' + IntToStr (GetItemByIndex (I));
- if I < L then
- Result := Result + ',';
- end;
- End;
-
-
-
- { }
- { ASingleDictionary }
- { }
- Function ASingleDictionary.GetItem (const Key : String) : Single;
- Begin
- if LocateItem (Key, Result) < 0 then
- KeyNotFoundError (Key);
- End;
-
- Procedure ASingleDictionary.Assign (const Source : TObject);
- var I : Integer;
- Begin
- if Source is ASingleDictionary then
- begin
- Clear;
- For I := 0 to ASingleDictionary (Source).Count - 1 do
- Add (ASingleDictionary (Source).GetKeyByIndex (I),
- ASingleDictionary (Source).GetItemByIndex (I));
- end else
- inherited Assign (Source);
- End;
-
- Function ASingleDictionary.GetAsString : String;
- var I, L : Integer;
- Begin
- L := Count - 1;
- For I := 0 to L do
- begin
- Result := Result + GetKeyByIndex (I) + ':' + FloatToStr (GetItemByIndex (I));
- if I < L then
- Result := Result + ',';
- end;
- End;
-
-
-
- { }
- { ADoubleDictionary }
- { }
- Function ADoubleDictionary.GetItem (const Key : String) : Double;
- Begin
- if LocateItem (Key, Result) < 0 then
- KeyNotFoundError (Key);
- End;
-
- Procedure ADoubleDictionary.Assign (const Source : TObject);
- var I : Integer;
- Begin
- if Source is ADoubleDictionary then
- begin
- Clear;
- For I := 0 to ADoubleDictionary (Source).Count - 1 do
- Add (ADoubleDictionary (Source).GetKeyByIndex (I),
- ADoubleDictionary (Source).GetItemByIndex (I));
- end else
- inherited Assign (Source);
- End;
-
- Function ADoubleDictionary.GetAsString : String;
- var I, L : Integer;
- Begin
- L := Count - 1;
- For I := 0 to L do
- begin
- Result := Result + GetKeyByIndex (I) + ':' + FloatToStr (GetItemByIndex (I));
- if I < L then
- Result := Result + ',';
- end;
- End;
-
-
-
- { }
- { AExtendedDictionary }
- { }
- Function AExtendedDictionary.GetItem (const Key : String) : Extended;
- Begin
- if LocateItem (Key, Result) < 0 then
- KeyNotFoundError (Key);
- End;
-
- Procedure AExtendedDictionary.Assign (const Source : TObject);
- var I : Integer;
- Begin
- if Source is AExtendedDictionary then
- begin
- Clear;
- For I := 0 to AExtendedDictionary (Source).Count - 1 do
- Add (AExtendedDictionary (Source).GetKeyByIndex (I),
- AExtendedDictionary (Source).GetItemByIndex (I));
- end else
- inherited Assign (Source);
- End;
-
- Function AExtendedDictionary.GetAsString : String;
- var I, L : Integer;
- Begin
- L := Count - 1;
- For I := 0 to L do
- begin
- Result := Result + GetKeyByIndex (I) + ':' + FloatToStr (GetItemByIndex (I));
- if I < L then
- Result := Result + ',';
- end;
- End;
-
-
-
- { }
- { AStringDictionary }
- { }
- Function AStringDictionary.GetItem (const Key : String) : String;
- Begin
- if LocateItem (Key, Result) < 0 then
- KeyNotFoundError (Key);
- End;
-
- Procedure AStringDictionary.Assign (const Source : TObject);
- var I : Integer;
- Begin
- if Source is AStringDictionary then
- begin
- Clear;
- For I := 0 to AStringDictionary (Source).Count - 1 do
- Add (AStringDictionary (Source).GetKeyByIndex (I),
- AStringDictionary (Source).GetItemByIndex (I));
- end else
- inherited Assign (Source);
- End;
-
- Function AStringDictionary.GetAsString : String;
- var I, L : Integer;
- Begin
- L := Count - 1;
- For I := 0 to L do
- begin
- Result := Result + GetKeyByIndex (I) + ':' + QuoteText (GetItemByIndex (I));
- if I < L then
- Result := Result + ',';
- end;
- End;
-
- Function AStringDictionary.GetItemLength (const Key : String) : Integer;
- Begin
- Result := Length (GetItem (Key));
- End;
-
- Function AStringDictionary.GetTotalLength : Int64;
- var I : Integer;
- Begin
- Result := 0;
- For I := 0 to Count - 1 do
- Inc (Result, Length (GetItemByIndex (I)));
- End;
-
-
-
- { }
- { APointerDictionary }
- { }
- Function APointerDictionary.GetItem (const Key : String) : Pointer;
- Begin
- if LocateItem (Key, Result) < 0 then
- KeyNotFoundError (Key);
- End;
-
- Procedure APointerDictionary.Assign (const Source : TObject);
- var I : Integer;
- Begin
- if Source is APointerDictionary then
- begin
- Clear;
- For I := 0 to APointerDictionary (Source).Count - 1 do
- Add (APointerDictionary (Source).GetKeyByIndex (I),
- APointerDictionary (Source).GetItemByIndex (I));
- end else
- inherited Assign (Source);
- End;
-
- Function APointerDictionary.GetAsString : String;
- var I, L : Integer;
- Begin
- L := Count - 1;
- For I := 0 to L do
- begin
- Result := Result + GetKeyByIndex (I) + ':' + PointerToStr (GetItemByIndex (I));
- if I < L then
- Result := Result + ',';
- end;
- End;
-
-
-
- { }
- { AObjectDictionary }
- { }
- Function AObjectDictionary.GetItem (const Key : String) : TObject;
- Begin
- if LocateItem (Key, Result) < 0 then
- KeyNotFoundError (Key);
- End;
-
- Function AObjectDictionary.GetAsString : String;
- var I, L : Integer;
- Begin
- L := Count - 1;
- For I := 0 to L do
- begin
- Result := Result + GetKeyByIndex (I) + ':' + ObjectClassName (GetItemByIndex (I));
- if I < L then
- Result := Result + ',';
- end;
- End;
-
- Procedure AObjectDictionary.Clear;
- Begin
- if IsItemOwner then
- FreeItems else
- ReleaseItems;
- End;
-
- Procedure AObjectDictionary.Assign (const Source : TObject);
- var I : Integer;
- Begin
- if Source is AObjectDictionary then
- begin
- Clear;
- For I := 0 to AObjectDictionary (Source).Count - 1 do
- Add (AObjectDictionary (Source).GetKeyByIndex (I),
- AObjectDictionary (Source).GetItemByIndex (I));
- end else
- inherited Assign (Source);
- End;
-
-
-
- { }
- { DICTIONARY IMPLEMENTATIONS }
- { }
-
-
-
- { Dictionary helper functions }
- Function DictionaryRehashSize (const Count : Integer) : Integer;
- var L : Integer;
- Begin
- L := Count div AverageHashChainSize; // Number of slots
- if L <= 16 then // Rehash in powers of 16
- Result := 16 else
- if L <= 256 then
- Result := 256 else
- if L <= 4096 then
- Result := 4096 else
- if L <= 65536 then
- Result := 65536 else
- if L <= 1048576 then
- Result := 1048576 else
- if L <= 16777216 then
- Result := 16777216 else
- Result := 268435456;
- End;
-
- { }
- { TLongIntDictionary }
- { }
- Constructor TLongIntDictionary.Create;
- Begin
- inherited Create;
- FCaseSensitive := True;
- FDuplicatesAction := ddAccept;
- FAddOnSet := True;
- FKeys := TStringArray.Create;
- FValues := TLongIntArray.Create;
- End;
-
- Constructor TLongIntDictionary.CreateEx (const Keys : AStringArray; const Values : ALongIntArray; const KeysCaseSensitive : Boolean; const AddOnSet : Boolean; const DuplicatesAction : TDictionaryDuplicatesAction);
- Begin
- inherited Create;
- if Assigned (Keys) then
- FKeys := Keys else
- FKeys := TStringArray.Create;
- if Assigned (Values) then
- FValues := Values else
- FValues := TLongIntArray.Create;
- Assert (FKeys.Count = FValues.Count, 'Keys and Values must be equal length');
- FAddOnSet := AddOnSet;
- FDuplicatesAction := DuplicatesAction;
- Rehash;
- End;
-
- Destructor TLongIntDictionary.Destroy;
- Begin
- FreeAndNil (FValues);
- FreeAndNil (FKeys);
- inherited Destroy;
- End;
-
- Function TLongIntDictionary.GetKeysCaseSensitive : Boolean;
- Begin
- Result := FCaseSensitive;
- End;
-
- Function TLongIntDictionary.GetAddOnSet : Boolean;
- Begin
- Result := FAddOnSet;
- End;
-
- Procedure TLongIntDictionary.SetAddOnSet (const AddOnSet : Boolean);
- Begin
- FAddOnSet := AddOnSet;
- End;
-
- Function TLongIntDictionary.GetHashTableSize : Integer;
- Begin
- Result := Length (FLookup);
- End;
-
- Procedure TLongIntDictionary.Rehash;
- var I, C, L : Integer;
- Begin
- C := FKeys.Count;
- L := DictionaryRehashSize (C);
- FLookup := nil;
- SetLength (FLookup, L);
- For I := 0 to C - 1 do
- Append (FLookup [HashStr (FKeys [I], L, FCaseSensitive)], I);
- End;
-
- class Function TLongIntDictionary.CreateInstance : AType;
- Begin
- Result := TLongIntDictionary.Create;
- End;
-
- Function TLongIntDictionary.LocateKey (const Key : String; var LookupIdx : Integer; const ErrorIfNotFound : Boolean) : Integer;
- var H, I, J, L : Integer;
- Begin
- Result := -1;
- L := Length (FLookup);
- if L > 0 then
- begin
- H := HashStr (Key, L, FCaseSensitive);
- LookupIdx := H;
- For I := 0 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, I];
- if cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- begin
- Result := J;
- break;
- end;
- end;
- end;
- if ErrorIfNotFound and (Result = -1) then
- KeyNotFoundError (Key);
- End;
-
- Function TLongIntDictionary.KeyIndex (const Key : String; const ErrorIfNotFound : Boolean) : Integer;
- var H : Integer;
- Begin
- Result := LocateKey (Key, H, ErrorIfNotFound);
- End;
-
- Procedure TLongIntDictionary.Add (const Key : String; const Value : LongInt);
- var H, L, I : Integer;
- Begin
- if FDuplicatesAction in [ddIgnore, ddError] then
- if LocateKey (Key, H, False) >= 0 then
- if FDuplicatesAction = ddIgnore then
- exit else
- DictionaryError ('Duplicate key: ' + QuoteText (Key));
- L := Length (FLookup);
- if L = 0 then
- begin
- Rehash;
- L := Length (FLookup);
- end;
- H := Integer (HashStr (Key, LongWord (L), FCaseSensitive));
- I := FKeys.AddItem (Key);
- Append (FLookup [H], I);
- FValues.AddItem (Value);
-
- if (I + 1) div AverageHashChainSize > L then
- Rehash;
- End;
-
- Procedure TLongIntDictionary.DeleteByIndex (const Idx : Integer; const Hash : Integer);
- var I, J, H : Integer;
- Begin
- if Hash = -1 then
- H := HashStr (FKeys [Idx], Length (FLookup), FCaseSensitive) else
- H := Hash;
- FKeys.Delete (Idx);
- FValues.Delete (Idx);
- J := PosNext (Idx, FLookup [H]);
- Assert (J >= 0, 'Invalid hash value/lookup table');
- Remove (FLookup [H], J, 1);
-
- For I := 0 to Length (FLookup) - 1 do
- For J := 0 to Length (FLookup [I]) - 1 do
- if FLookup [I][J] > Idx then
- Dec (FLookup [I][J]);
- End;
-
- Procedure TLongIntDictionary.Delete (const Key : String);
- var I, H : Integer;
- Begin
- I := LocateKey (Key, H, True);
- DeleteByIndex (I, H);
- End;
-
- Function TLongIntDictionary.HasKey (const Key : String) : Boolean;
- Begin
- Result := KeyIndex (Key, False) >= 0;
- End;
-
- Procedure TLongIntDictionary.Rename (const Key, NewKey : String);
- var I, J, H : Integer;
- Begin
- I := LocateKey (Key, H, True);
- FKeys [I] := NewKey;
- J := PosNext (I, FLookup [H]);
- Assert (J >= 0, 'Invalid hash value/lookup table');
- Remove (FLookup [H], J, 1);
- Append (FLookup [HashStr (NewKey, Length (FLookup), FCaseSensitive)], I);
- End;
-
- Function TLongIntDictionary.GetDuplicatesAction : TDictionaryDuplicatesAction;
- Begin
- Result := FDuplicatesAction;
- End;
-
- Procedure TLongIntDictionary.SetDuplicatesAction (const DuplicatesAction : TDictionaryDuplicatesAction);
- Begin
- FDuplicatesAction := DuplicatesAction;
- End;
-
- Function TLongIntDictionary.LocateItem (const Key : String; var Value : LongInt) : Integer;
- Begin
- Result := KeyIndex (Key, False);
- if Result >= 0 then
- Value := FValues [Result] else
- Value := 0;
- End;
-
- Function TLongIntDictionary.LocateNext (const Key : String; const Idx : Integer; var Value : LongInt) : Integer;
- var L, H, I, J, K : Integer;
- Begin
- Result := -1;
- L := Length (FLookup);
- if L = 0 then
- DictionaryError ('Item not found');
- H := HashStr (Key, L, FCaseSensitive);
- For I := 0 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, I];
- if J = Idx then
- begin
- if not cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- DictionaryError ('Item not found');
- For K := I + 1 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, K];
- if cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- begin
- Value := FValues [J];
- Result := J;
- exit;
- end;
- end;
- Result := -1;
- exit;
- end;
- end;
- DictionaryError ('Item not found');
- End;
-
- Procedure TLongIntDictionary.SetItem (const Key : String; const Value : LongInt);
- var I : Integer;
- Begin
- I := KeyIndex (Key, False);
- if I >= 0 then
- FValues [I] := Value else
- if AddOnSet then
- Add (Key, Value) else
- KeyNotFoundError (Key);
- End;
-
- Procedure TLongIntDictionary.IndexError;
- Begin
- DictionaryError ('Index out of range');
- End;
-
- Function TLongIntDictionary.Count : Integer;
- Begin
- Result := FKeys.Count;
- Assert (FValues.Count = Result, 'Key/Value count mismatch');
- End;
-
- Function TLongIntDictionary.GetKeyByIndex (const Idx : Integer) : String;
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FKeys.Count) then
- IndexError;
- {$ENDIF}
- Result := FKeys [Idx];
- End;
-
- Procedure TLongIntDictionary.DeleteItemByIndex (const Idx : Integer);
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- DeleteByIndex (Idx, -1);
- End;
-
- Function TLongIntDictionary.GetItemByIndex (const Idx : Integer) : LongInt;
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- Result := FValues [Idx];
- End;
-
- Procedure TLongIntDictionary.SetItemByIndex (const Idx : Integer; const Value : LongInt);
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- FValues [Idx] := Value;
- End;
-
- Procedure TLongIntDictionary.Clear;
- Begin
- FKeys.Clear;
- FValues.Clear;
- Rehash;
- End;
-
-
-
- { }
- { TLongWordDictionary }
- { }
- Constructor TLongWordDictionary.Create;
- Begin
- inherited Create;
- FCaseSensitive := True;
- FDuplicatesAction := ddAccept;
- FAddOnSet := True;
- FKeys := TStringArray.Create;
- FValues := TLongWordArray.Create;
- End;
-
- Constructor TLongWordDictionary.CreateEx (const Keys : AStringArray; const Values : ALongWordArray; const KeysCaseSensitive : Boolean; const AddOnSet : Boolean; const DuplicatesAction : TDictionaryDuplicatesAction);
- Begin
- inherited Create;
- if Assigned (Keys) then
- FKeys := Keys else
- FKeys := TStringArray.Create;
- if Assigned (Values) then
- FValues := Values else
- FValues := TLongWordArray.Create;
- Assert (FKeys.Count = FValues.Count, 'Keys and Values must be equal length');
- FAddOnSet := AddOnSet;
- FDuplicatesAction := DuplicatesAction;
- Rehash;
- End;
-
- Destructor TLongWordDictionary.Destroy;
- Begin
- FreeAndNil (FValues);
- FreeAndNil (FKeys);
- inherited Destroy;
- End;
-
- Function TLongWordDictionary.GetKeysCaseSensitive : Boolean;
- Begin
- Result := FCaseSensitive;
- End;
-
- Function TLongWordDictionary.GetAddOnSet : Boolean;
- Begin
- Result := FAddOnSet;
- End;
-
- Procedure TLongWordDictionary.SetAddOnSet (const AddOnSet : Boolean);
- Begin
- FAddOnSet := AddOnSet;
- End;
-
- Function TLongWordDictionary.GetHashTableSize : Integer;
- Begin
- Result := Length (FLookup);
- End;
-
- Procedure TLongWordDictionary.Rehash;
- var I, C, L : Integer;
- Begin
- C := FKeys.Count;
- L := DictionaryRehashSize (C);
- FLookup := nil;
- SetLength (FLookup, L);
- For I := 0 to C - 1 do
- Append (FLookup [HashStr (FKeys [I], L, FCaseSensitive)], I);
- End;
-
- class Function TLongWordDictionary.CreateInstance : AType;
- Begin
- Result := TLongWordDictionary.Create;
- End;
-
- Function TLongWordDictionary.LocateKey (const Key : String; var LookupIdx : Integer; const ErrorIfNotFound : Boolean) : Integer;
- var H, I, J, L : Integer;
- Begin
- Result := -1;
- L := Length (FLookup);
- if L > 0 then
- begin
- H := HashStr (Key, L, FCaseSensitive);
- LookupIdx := H;
- For I := 0 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, I];
- if cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- begin
- Result := J;
- break;
- end;
- end;
- end;
- if ErrorIfNotFound and (Result = -1) then
- KeyNotFoundError (Key);
- End;
-
- Function TLongWordDictionary.KeyIndex (const Key : String; const ErrorIfNotFound : Boolean) : Integer;
- var H : Integer;
- Begin
- Result := LocateKey (Key, H, ErrorIfNotFound);
- End;
-
- Procedure TLongWordDictionary.Add (const Key : String; const Value : LongWord);
- var H, L, I : Integer;
- Begin
- if FDuplicatesAction in [ddIgnore, ddError] then
- if LocateKey (Key, H, False) >= 0 then
- if FDuplicatesAction = ddIgnore then
- exit else
- DictionaryError ('Duplicate key: ' + QuoteText (Key));
- L := Length (FLookup);
- if L = 0 then
- begin
- Rehash;
- L := Length (FLookup);
- end;
- H := Integer (HashStr (Key, LongWord (L), FCaseSensitive));
- I := FKeys.AddItem (Key);
- Append (FLookup [H], I);
- FValues.AddItem (Value);
-
- if (I + 1) div AverageHashChainSize > L then
- Rehash;
- End;
-
- Procedure TLongWordDictionary.DeleteByIndex (const Idx : Integer; const Hash : Integer);
- var I, J, H : Integer;
- Begin
- if Hash = -1 then
- H := HashStr (FKeys [Idx], Length (FLookup), FCaseSensitive) else
- H := Hash;
- FKeys.Delete (Idx);
- FValues.Delete (Idx);
- J := PosNext (Idx, FLookup [H]);
- Assert (J >= 0, 'Invalid hash value/lookup table');
- Remove (FLookup [H], J, 1);
-
- For I := 0 to Length (FLookup) - 1 do
- For J := 0 to Length (FLookup [I]) - 1 do
- if FLookup [I][J] > Idx then
- Dec (FLookup [I][J]);
- End;
-
- Procedure TLongWordDictionary.Delete (const Key : String);
- var I, H : Integer;
- Begin
- I := LocateKey (Key, H, True);
- DeleteByIndex (I, H);
- End;
-
- Function TLongWordDictionary.HasKey (const Key : String) : Boolean;
- Begin
- Result := KeyIndex (Key, False) >= 0;
- End;
-
- Procedure TLongWordDictionary.Rename (const Key, NewKey : String);
- var I, J, H : Integer;
- Begin
- I := LocateKey (Key, H, True);
- FKeys [I] := NewKey;
- J := PosNext (I, FLookup [H]);
- Assert (J >= 0, 'Invalid hash value/lookup table');
- Remove (FLookup [H], J, 1);
- Append (FLookup [HashStr (NewKey, Length (FLookup), FCaseSensitive)], I);
- End;
-
- Function TLongWordDictionary.GetDuplicatesAction : TDictionaryDuplicatesAction;
- Begin
- Result := FDuplicatesAction;
- End;
-
- Procedure TLongWordDictionary.SetDuplicatesAction (const DuplicatesAction : TDictionaryDuplicatesAction);
- Begin
- FDuplicatesAction := DuplicatesAction;
- End;
-
- Function TLongWordDictionary.LocateItem (const Key : String; var Value : LongWord) : Integer;
- Begin
- Result := KeyIndex (Key, False);
- if Result >= 0 then
- Value := FValues [Result] else
- Value := 0;
- End;
-
- Function TLongWordDictionary.LocateNext (const Key : String; const Idx : Integer; var Value : LongWord) : Integer;
- var L, H, I, J, K : Integer;
- Begin
- Result := -1;
- L := Length (FLookup);
- if L = 0 then
- DictionaryError ('Item not found');
- H := HashStr (Key, L, FCaseSensitive);
- For I := 0 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, I];
- if J = Idx then
- begin
- if not cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- DictionaryError ('Item not found');
- For K := I + 1 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, K];
- if cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- begin
- Value := FValues [J];
- Result := J;
- exit;
- end;
- end;
- Result := -1;
- exit;
- end;
- end;
- DictionaryError ('Item not found');
- End;
-
- Procedure TLongWordDictionary.SetItem (const Key : String; const Value : LongWord);
- var I : Integer;
- Begin
- I := KeyIndex (Key, False);
- if I >= 0 then
- FValues [I] := Value else
- if AddOnSet then
- Add (Key, Value) else
- KeyNotFoundError (Key);
- End;
-
- Procedure TLongWordDictionary.IndexError;
- Begin
- DictionaryError ('Index out of range');
- End;
-
- Function TLongWordDictionary.Count : Integer;
- Begin
- Result := FKeys.Count;
- Assert (FValues.Count = Result, 'Key/Value count mismatch');
- End;
-
- Function TLongWordDictionary.GetKeyByIndex (const Idx : Integer) : String;
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FKeys.Count) then
- IndexError;
- {$ENDIF}
- Result := FKeys [Idx];
- End;
-
- Procedure TLongWordDictionary.DeleteItemByIndex (const Idx : Integer);
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- DeleteByIndex (Idx, -1);
- End;
-
- Function TLongWordDictionary.GetItemByIndex (const Idx : Integer) : LongWord;
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- Result := FValues [Idx];
- End;
-
- Procedure TLongWordDictionary.SetItemByIndex (const Idx : Integer; const Value : LongWord);
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- FValues [Idx] := Value;
- End;
-
- Procedure TLongWordDictionary.Clear;
- Begin
- FKeys.Clear;
- FValues.Clear;
- Rehash;
- End;
-
-
-
- { }
- { TInt64Dictionary }
- { }
- Constructor TInt64Dictionary.Create;
- Begin
- inherited Create;
- FCaseSensitive := True;
- FDuplicatesAction := ddAccept;
- FAddOnSet := True;
- FKeys := TStringArray.Create;
- FValues := TInt64Array.Create;
- End;
-
- Constructor TInt64Dictionary.CreateEx (const Keys : AStringArray; const Values : AInt64Array; const KeysCaseSensitive : Boolean; const AddOnSet : Boolean; const DuplicatesAction : TDictionaryDuplicatesAction);
- Begin
- inherited Create;
- if Assigned (Keys) then
- FKeys := Keys else
- FKeys := TStringArray.Create;
- if Assigned (Values) then
- FValues := Values else
- FValues := TInt64Array.Create;
- Assert (FKeys.Count = FValues.Count, 'Keys and Values must be equal length');
- FAddOnSet := AddOnSet;
- FDuplicatesAction := DuplicatesAction;
- Rehash;
- End;
-
- Destructor TInt64Dictionary.Destroy;
- Begin
- FreeAndNil (FValues);
- FreeAndNil (FKeys);
- inherited Destroy;
- End;
-
- Function TInt64Dictionary.GetKeysCaseSensitive : Boolean;
- Begin
- Result := FCaseSensitive;
- End;
-
- Function TInt64Dictionary.GetAddOnSet : Boolean;
- Begin
- Result := FAddOnSet;
- End;
-
- Procedure TInt64Dictionary.SetAddOnSet (const AddOnSet : Boolean);
- Begin
- FAddOnSet := AddOnSet;
- End;
-
- Function TInt64Dictionary.GetHashTableSize : Integer;
- Begin
- Result := Length (FLookup);
- End;
-
- Procedure TInt64Dictionary.Rehash;
- var I, C, L : Integer;
- Begin
- C := FKeys.Count;
- L := DictionaryRehashSize (C);
- FLookup := nil;
- SetLength (FLookup, L);
- For I := 0 to C - 1 do
- Append (FLookup [HashStr (FKeys [I], L, FCaseSensitive)], I);
- End;
-
- class Function TInt64Dictionary.CreateInstance : AType;
- Begin
- Result := TInt64Dictionary.Create;
- End;
-
- Function TInt64Dictionary.LocateKey (const Key : String; var LookupIdx : Integer; const ErrorIfNotFound : Boolean) : Integer;
- var H, I, J, L : Integer;
- Begin
- Result := -1;
- L := Length (FLookup);
- if L > 0 then
- begin
- H := HashStr (Key, L, FCaseSensitive);
- LookupIdx := H;
- For I := 0 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, I];
- if cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- begin
- Result := J;
- break;
- end;
- end;
- end;
- if ErrorIfNotFound and (Result = -1) then
- KeyNotFoundError (Key);
- End;
-
- Function TInt64Dictionary.KeyIndex (const Key : String; const ErrorIfNotFound : Boolean) : Integer;
- var H : Integer;
- Begin
- Result := LocateKey (Key, H, ErrorIfNotFound);
- End;
-
- Procedure TInt64Dictionary.Add (const Key : String; const Value : Int64);
- var H, L, I : Integer;
- Begin
- if FDuplicatesAction in [ddIgnore, ddError] then
- if LocateKey (Key, H, False) >= 0 then
- if FDuplicatesAction = ddIgnore then
- exit else
- DictionaryError ('Duplicate key: ' + QuoteText (Key));
- L := Length (FLookup);
- if L = 0 then
- begin
- Rehash;
- L := Length (FLookup);
- end;
- H := Integer (HashStr (Key, LongWord (L), FCaseSensitive));
- I := FKeys.AddItem (Key);
- Append (FLookup [H], I);
- FValues.AddItem (Value);
-
- if (I + 1) div AverageHashChainSize > L then
- Rehash;
- End;
-
- Procedure TInt64Dictionary.DeleteByIndex (const Idx : Integer; const Hash : Integer);
- var I, J, H : Integer;
- Begin
- if Hash = -1 then
- H := HashStr (FKeys [Idx], Length (FLookup), FCaseSensitive) else
- H := Hash;
- FKeys.Delete (Idx);
- FValues.Delete (Idx);
- J := PosNext (Idx, FLookup [H]);
- Assert (J >= 0, 'Invalid hash value/lookup table');
- Remove (FLookup [H], J, 1);
-
- For I := 0 to Length (FLookup) - 1 do
- For J := 0 to Length (FLookup [I]) - 1 do
- if FLookup [I][J] > Idx then
- Dec (FLookup [I][J]);
- End;
-
- Procedure TInt64Dictionary.Delete (const Key : String);
- var I, H : Integer;
- Begin
- I := LocateKey (Key, H, True);
- DeleteByIndex (I, H);
- End;
-
- Function TInt64Dictionary.HasKey (const Key : String) : Boolean;
- Begin
- Result := KeyIndex (Key, False) >= 0;
- End;
-
- Procedure TInt64Dictionary.Rename (const Key, NewKey : String);
- var I, J, H : Integer;
- Begin
- I := LocateKey (Key, H, True);
- FKeys [I] := NewKey;
- J := PosNext (I, FLookup [H]);
- Assert (J >= 0, 'Invalid hash value/lookup table');
- Remove (FLookup [H], J, 1);
- Append (FLookup [HashStr (NewKey, Length (FLookup), FCaseSensitive)], I);
- End;
-
- Function TInt64Dictionary.GetDuplicatesAction : TDictionaryDuplicatesAction;
- Begin
- Result := FDuplicatesAction;
- End;
-
- Procedure TInt64Dictionary.SetDuplicatesAction (const DuplicatesAction : TDictionaryDuplicatesAction);
- Begin
- FDuplicatesAction := DuplicatesAction;
- End;
-
- Function TInt64Dictionary.LocateItem (const Key : String; var Value : Int64) : Integer;
- Begin
- Result := KeyIndex (Key, False);
- if Result >= 0 then
- Value := FValues [Result] else
- Value := 0;
- End;
-
- Function TInt64Dictionary.LocateNext (const Key : String; const Idx : Integer; var Value : Int64) : Integer;
- var L, H, I, J, K : Integer;
- Begin
- Result := -1;
- L := Length (FLookup);
- if L = 0 then
- DictionaryError ('Item not found');
- H := HashStr (Key, L, FCaseSensitive);
- For I := 0 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, I];
- if J = Idx then
- begin
- if not cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- DictionaryError ('Item not found');
- For K := I + 1 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, K];
- if cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- begin
- Value := FValues [J];
- Result := J;
- exit;
- end;
- end;
- Result := -1;
- exit;
- end;
- end;
- DictionaryError ('Item not found');
- End;
-
- Procedure TInt64Dictionary.SetItem (const Key : String; const Value : Int64);
- var I : Integer;
- Begin
- I := KeyIndex (Key, False);
- if I >= 0 then
- FValues [I] := Value else
- if AddOnSet then
- Add (Key, Value) else
- KeyNotFoundError (Key);
- End;
-
- Procedure TInt64Dictionary.IndexError;
- Begin
- DictionaryError ('Index out of range');
- End;
-
- Function TInt64Dictionary.Count : Integer;
- Begin
- Result := FKeys.Count;
- Assert (FValues.Count = Result, 'Key/Value count mismatch');
- End;
-
- Function TInt64Dictionary.GetKeyByIndex (const Idx : Integer) : String;
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FKeys.Count) then
- IndexError;
- {$ENDIF}
- Result := FKeys [Idx];
- End;
-
- Procedure TInt64Dictionary.DeleteItemByIndex (const Idx : Integer);
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- DeleteByIndex (Idx, -1);
- End;
-
- Function TInt64Dictionary.GetItemByIndex (const Idx : Integer) : Int64;
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- Result := FValues [Idx];
- End;
-
- Procedure TInt64Dictionary.SetItemByIndex (const Idx : Integer; const Value : Int64);
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- FValues [Idx] := Value;
- End;
-
- Procedure TInt64Dictionary.Clear;
- Begin
- FKeys.Clear;
- FValues.Clear;
- Rehash;
- End;
-
-
-
- { }
- { TSingleDictionary }
- { }
- Constructor TSingleDictionary.Create;
- Begin
- inherited Create;
- FCaseSensitive := True;
- FDuplicatesAction := ddAccept;
- FAddOnSet := True;
- FKeys := TStringArray.Create;
- FValues := TSingleArray.Create;
- End;
-
- Constructor TSingleDictionary.CreateEx (const Keys : AStringArray; const Values : ASingleArray; const KeysCaseSensitive : Boolean; const AddOnSet : Boolean; const DuplicatesAction : TDictionaryDuplicatesAction);
- Begin
- inherited Create;
- if Assigned (Keys) then
- FKeys := Keys else
- FKeys := TStringArray.Create;
- if Assigned (Values) then
- FValues := Values else
- FValues := TSingleArray.Create;
- Assert (FKeys.Count = FValues.Count, 'Keys and Values must be equal length');
- FAddOnSet := AddOnSet;
- FDuplicatesAction := DuplicatesAction;
- Rehash;
- End;
-
- Destructor TSingleDictionary.Destroy;
- Begin
- FreeAndNil (FValues);
- FreeAndNil (FKeys);
- inherited Destroy;
- End;
-
- Function TSingleDictionary.GetKeysCaseSensitive : Boolean;
- Begin
- Result := FCaseSensitive;
- End;
-
- Function TSingleDictionary.GetAddOnSet : Boolean;
- Begin
- Result := FAddOnSet;
- End;
-
- Procedure TSingleDictionary.SetAddOnSet (const AddOnSet : Boolean);
- Begin
- FAddOnSet := AddOnSet;
- End;
-
- Function TSingleDictionary.GetHashTableSize : Integer;
- Begin
- Result := Length (FLookup);
- End;
-
- Procedure TSingleDictionary.Rehash;
- var I, C, L : Integer;
- Begin
- C := FKeys.Count;
- L := DictionaryRehashSize (C);
- FLookup := nil;
- SetLength (FLookup, L);
- For I := 0 to C - 1 do
- Append (FLookup [HashStr (FKeys [I], L, FCaseSensitive)], I);
- End;
-
- class Function TSingleDictionary.CreateInstance : AType;
- Begin
- Result := TSingleDictionary.Create;
- End;
-
- Function TSingleDictionary.LocateKey (const Key : String; var LookupIdx : Integer; const ErrorIfNotFound : Boolean) : Integer;
- var H, I, J, L : Integer;
- Begin
- Result := -1;
- L := Length (FLookup);
- if L > 0 then
- begin
- H := HashStr (Key, L, FCaseSensitive);
- LookupIdx := H;
- For I := 0 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, I];
- if cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- begin
- Result := J;
- break;
- end;
- end;
- end;
- if ErrorIfNotFound and (Result = -1) then
- KeyNotFoundError (Key);
- End;
-
- Function TSingleDictionary.KeyIndex (const Key : String; const ErrorIfNotFound : Boolean) : Integer;
- var H : Integer;
- Begin
- Result := LocateKey (Key, H, ErrorIfNotFound);
- End;
-
- Procedure TSingleDictionary.Add (const Key : String; const Value : Single);
- var H, L, I : Integer;
- Begin
- if FDuplicatesAction in [ddIgnore, ddError] then
- if LocateKey (Key, H, False) >= 0 then
- if FDuplicatesAction = ddIgnore then
- exit else
- DictionaryError ('Duplicate key: ' + QuoteText (Key));
- L := Length (FLookup);
- if L = 0 then
- begin
- Rehash;
- L := Length (FLookup);
- end;
- H := Integer (HashStr (Key, LongWord (L), FCaseSensitive));
- I := FKeys.AddItem (Key);
- Append (FLookup [H], I);
- FValues.AddItem (Value);
-
- if (I + 1) div AverageHashChainSize > L then
- Rehash;
- End;
-
- Procedure TSingleDictionary.DeleteByIndex (const Idx : Integer; const Hash : Integer);
- var I, J, H : Integer;
- Begin
- if Hash = -1 then
- H := HashStr (FKeys [Idx], Length (FLookup), FCaseSensitive) else
- H := Hash;
- FKeys.Delete (Idx);
- FValues.Delete (Idx);
- J := PosNext (Idx, FLookup [H]);
- Assert (J >= 0, 'Invalid hash value/lookup table');
- Remove (FLookup [H], J, 1);
-
- For I := 0 to Length (FLookup) - 1 do
- For J := 0 to Length (FLookup [I]) - 1 do
- if FLookup [I][J] > Idx then
- Dec (FLookup [I][J]);
- End;
-
- Procedure TSingleDictionary.Delete (const Key : String);
- var I, H : Integer;
- Begin
- I := LocateKey (Key, H, True);
- DeleteByIndex (I, H);
- End;
-
- Function TSingleDictionary.HasKey (const Key : String) : Boolean;
- Begin
- Result := KeyIndex (Key, False) >= 0;
- End;
-
- Procedure TSingleDictionary.Rename (const Key, NewKey : String);
- var I, J, H : Integer;
- Begin
- I := LocateKey (Key, H, True);
- FKeys [I] := NewKey;
- J := PosNext (I, FLookup [H]);
- Assert (J >= 0, 'Invalid hash value/lookup table');
- Remove (FLookup [H], J, 1);
- Append (FLookup [HashStr (NewKey, Length (FLookup), FCaseSensitive)], I);
- End;
-
- Function TSingleDictionary.GetDuplicatesAction : TDictionaryDuplicatesAction;
- Begin
- Result := FDuplicatesAction;
- End;
-
- Procedure TSingleDictionary.SetDuplicatesAction (const DuplicatesAction : TDictionaryDuplicatesAction);
- Begin
- FDuplicatesAction := DuplicatesAction;
- End;
-
- Function TSingleDictionary.LocateItem (const Key : String; var Value : Single) : Integer;
- Begin
- Result := KeyIndex (Key, False);
- if Result >= 0 then
- Value := FValues [Result] else
- Value := 0.0;
- End;
-
- Function TSingleDictionary.LocateNext (const Key : String; const Idx : Integer; var Value : Single) : Integer;
- var L, H, I, J, K : Integer;
- Begin
- Result := -1;
- L := Length (FLookup);
- if L = 0 then
- DictionaryError ('Item not found');
- H := HashStr (Key, L, FCaseSensitive);
- For I := 0 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, I];
- if J = Idx then
- begin
- if not cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- DictionaryError ('Item not found');
- For K := I + 1 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, K];
- if cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- begin
- Value := FValues [J];
- Result := J;
- exit;
- end;
- end;
- Result := -1;
- exit;
- end;
- end;
- DictionaryError ('Item not found');
- End;
-
- Procedure TSingleDictionary.SetItem (const Key : String; const Value : Single);
- var I : Integer;
- Begin
- I := KeyIndex (Key, False);
- if I >= 0 then
- FValues [I] := Value else
- if AddOnSet then
- Add (Key, Value) else
- KeyNotFoundError (Key);
- End;
-
- Procedure TSingleDictionary.IndexError;
- Begin
- DictionaryError ('Index out of range');
- End;
-
- Function TSingleDictionary.Count : Integer;
- Begin
- Result := FKeys.Count;
- Assert (FValues.Count = Result, 'Key/Value count mismatch');
- End;
-
- Function TSingleDictionary.GetKeyByIndex (const Idx : Integer) : String;
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FKeys.Count) then
- IndexError;
- {$ENDIF}
- Result := FKeys [Idx];
- End;
-
- Procedure TSingleDictionary.DeleteItemByIndex (const Idx : Integer);
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- DeleteByIndex (Idx, -1);
- End;
-
- Function TSingleDictionary.GetItemByIndex (const Idx : Integer) : Single;
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- Result := FValues [Idx];
- End;
-
- Procedure TSingleDictionary.SetItemByIndex (const Idx : Integer; const Value : Single);
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- FValues [Idx] := Value;
- End;
-
- Procedure TSingleDictionary.Clear;
- Begin
- FKeys.Clear;
- FValues.Clear;
- Rehash;
- End;
-
-
-
- { }
- { TDoubleDictionary }
- { }
- Constructor TDoubleDictionary.Create;
- Begin
- inherited Create;
- FCaseSensitive := True;
- FDuplicatesAction := ddAccept;
- FAddOnSet := True;
- FKeys := TStringArray.Create;
- FValues := TDoubleArray.Create;
- End;
-
- Constructor TDoubleDictionary.CreateEx (const Keys : AStringArray; const Values : ADoubleArray; const KeysCaseSensitive : Boolean; const AddOnSet : Boolean; const DuplicatesAction : TDictionaryDuplicatesAction);
- Begin
- inherited Create;
- if Assigned (Keys) then
- FKeys := Keys else
- FKeys := TStringArray.Create;
- if Assigned (Values) then
- FValues := Values else
- FValues := TDoubleArray.Create;
- Assert (FKeys.Count = FValues.Count, 'Keys and Values must be equal length');
- FAddOnSet := AddOnSet;
- FDuplicatesAction := DuplicatesAction;
- Rehash;
- End;
-
- Destructor TDoubleDictionary.Destroy;
- Begin
- FreeAndNil (FValues);
- FreeAndNil (FKeys);
- inherited Destroy;
- End;
-
- Function TDoubleDictionary.GetKeysCaseSensitive : Boolean;
- Begin
- Result := FCaseSensitive;
- End;
-
- Function TDoubleDictionary.GetAddOnSet : Boolean;
- Begin
- Result := FAddOnSet;
- End;
-
- Procedure TDoubleDictionary.SetAddOnSet (const AddOnSet : Boolean);
- Begin
- FAddOnSet := AddOnSet;
- End;
-
- Function TDoubleDictionary.GetHashTableSize : Integer;
- Begin
- Result := Length (FLookup);
- End;
-
- Procedure TDoubleDictionary.Rehash;
- var I, C, L : Integer;
- Begin
- C := FKeys.Count;
- L := DictionaryRehashSize (C);
- FLookup := nil;
- SetLength (FLookup, L);
- For I := 0 to C - 1 do
- Append (FLookup [HashStr (FKeys [I], L, FCaseSensitive)], I);
- End;
-
- class Function TDoubleDictionary.CreateInstance : AType;
- Begin
- Result := TDoubleDictionary.Create;
- End;
-
- Function TDoubleDictionary.LocateKey (const Key : String; var LookupIdx : Integer; const ErrorIfNotFound : Boolean) : Integer;
- var H, I, J, L : Integer;
- Begin
- Result := -1;
- L := Length (FLookup);
- if L > 0 then
- begin
- H := HashStr (Key, L, FCaseSensitive);
- LookupIdx := H;
- For I := 0 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, I];
- if cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- begin
- Result := J;
- break;
- end;
- end;
- end;
- if ErrorIfNotFound and (Result = -1) then
- KeyNotFoundError (Key);
- End;
-
- Function TDoubleDictionary.KeyIndex (const Key : String; const ErrorIfNotFound : Boolean) : Integer;
- var H : Integer;
- Begin
- Result := LocateKey (Key, H, ErrorIfNotFound);
- End;
-
- Procedure TDoubleDictionary.Add (const Key : String; const Value : Double);
- var H, L, I : Integer;
- Begin
- if FDuplicatesAction in [ddIgnore, ddError] then
- if LocateKey (Key, H, False) >= 0 then
- if FDuplicatesAction = ddIgnore then
- exit else
- DictionaryError ('Duplicate key: ' + QuoteText (Key));
- L := Length (FLookup);
- if L = 0 then
- begin
- Rehash;
- L := Length (FLookup);
- end;
- H := Integer (HashStr (Key, LongWord (L), FCaseSensitive));
- I := FKeys.AddItem (Key);
- Append (FLookup [H], I);
- FValues.AddItem (Value);
-
- if (I + 1) div AverageHashChainSize > L then
- Rehash;
- End;
-
- Procedure TDoubleDictionary.DeleteByIndex (const Idx : Integer; const Hash : Integer);
- var I, J, H : Integer;
- Begin
- if Hash = -1 then
- H := HashStr (FKeys [Idx], Length (FLookup), FCaseSensitive) else
- H := Hash;
- FKeys.Delete (Idx);
- FValues.Delete (Idx);
- J := PosNext (Idx, FLookup [H]);
- Assert (J >= 0, 'Invalid hash value/lookup table');
- Remove (FLookup [H], J, 1);
-
- For I := 0 to Length (FLookup) - 1 do
- For J := 0 to Length (FLookup [I]) - 1 do
- if FLookup [I][J] > Idx then
- Dec (FLookup [I][J]);
- End;
-
- Procedure TDoubleDictionary.Delete (const Key : String);
- var I, H : Integer;
- Begin
- I := LocateKey (Key, H, True);
- DeleteByIndex (I, H);
- End;
-
- Function TDoubleDictionary.HasKey (const Key : String) : Boolean;
- Begin
- Result := KeyIndex (Key, False) >= 0;
- End;
-
- Procedure TDoubleDictionary.Rename (const Key, NewKey : String);
- var I, J, H : Integer;
- Begin
- I := LocateKey (Key, H, True);
- FKeys [I] := NewKey;
- J := PosNext (I, FLookup [H]);
- Assert (J >= 0, 'Invalid hash value/lookup table');
- Remove (FLookup [H], J, 1);
- Append (FLookup [HashStr (NewKey, Length (FLookup), FCaseSensitive)], I);
- End;
-
- Function TDoubleDictionary.GetDuplicatesAction : TDictionaryDuplicatesAction;
- Begin
- Result := FDuplicatesAction;
- End;
-
- Procedure TDoubleDictionary.SetDuplicatesAction (const DuplicatesAction : TDictionaryDuplicatesAction);
- Begin
- FDuplicatesAction := DuplicatesAction;
- End;
-
- Function TDoubleDictionary.LocateItem (const Key : String; var Value : Double) : Integer;
- Begin
- Result := KeyIndex (Key, False);
- if Result >= 0 then
- Value := FValues [Result] else
- Value := 0.0;
- End;
-
- Function TDoubleDictionary.LocateNext (const Key : String; const Idx : Integer; var Value : Double) : Integer;
- var L, H, I, J, K : Integer;
- Begin
- Result := -1;
- L := Length (FLookup);
- if L = 0 then
- DictionaryError ('Item not found');
- H := HashStr (Key, L, FCaseSensitive);
- For I := 0 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, I];
- if J = Idx then
- begin
- if not cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- DictionaryError ('Item not found');
- For K := I + 1 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, K];
- if cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- begin
- Value := FValues [J];
- Result := J;
- exit;
- end;
- end;
- Result := -1;
- exit;
- end;
- end;
- DictionaryError ('Item not found');
- End;
-
- Procedure TDoubleDictionary.SetItem (const Key : String; const Value : Double);
- var I : Integer;
- Begin
- I := KeyIndex (Key, False);
- if I >= 0 then
- FValues [I] := Value else
- if AddOnSet then
- Add (Key, Value) else
- KeyNotFoundError (Key);
- End;
-
- Procedure TDoubleDictionary.IndexError;
- Begin
- DictionaryError ('Index out of range');
- End;
-
- Function TDoubleDictionary.Count : Integer;
- Begin
- Result := FKeys.Count;
- Assert (FValues.Count = Result, 'Key/Value count mismatch');
- End;
-
- Function TDoubleDictionary.GetKeyByIndex (const Idx : Integer) : String;
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FKeys.Count) then
- IndexError;
- {$ENDIF}
- Result := FKeys [Idx];
- End;
-
- Procedure TDoubleDictionary.DeleteItemByIndex (const Idx : Integer);
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- DeleteByIndex (Idx, -1);
- End;
-
- Function TDoubleDictionary.GetItemByIndex (const Idx : Integer) : Double;
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- Result := FValues [Idx];
- End;
-
- Procedure TDoubleDictionary.SetItemByIndex (const Idx : Integer; const Value : Double);
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- FValues [Idx] := Value;
- End;
-
- Procedure TDoubleDictionary.Clear;
- Begin
- FKeys.Clear;
- FValues.Clear;
- Rehash;
- End;
-
-
-
- { }
- { TExtendedDictionary }
- { }
- Constructor TExtendedDictionary.Create;
- Begin
- inherited Create;
- FCaseSensitive := True;
- FDuplicatesAction := ddAccept;
- FAddOnSet := True;
- FKeys := TStringArray.Create;
- FValues := TExtendedArray.Create;
- End;
-
- Constructor TExtendedDictionary.CreateEx (const Keys : AStringArray; const Values : AExtendedArray; const KeysCaseSensitive : Boolean; const AddOnSet : Boolean; const DuplicatesAction : TDictionaryDuplicatesAction);
- Begin
- inherited Create;
- if Assigned (Keys) then
- FKeys := Keys else
- FKeys := TStringArray.Create;
- if Assigned (Values) then
- FValues := Values else
- FValues := TExtendedArray.Create;
- Assert (FKeys.Count = FValues.Count, 'Keys and Values must be equal length');
- FAddOnSet := AddOnSet;
- FDuplicatesAction := DuplicatesAction;
- Rehash;
- End;
-
- Destructor TExtendedDictionary.Destroy;
- Begin
- FreeAndNil (FValues);
- FreeAndNil (FKeys);
- inherited Destroy;
- End;
-
- Function TExtendedDictionary.GetKeysCaseSensitive : Boolean;
- Begin
- Result := FCaseSensitive;
- End;
-
- Function TExtendedDictionary.GetAddOnSet : Boolean;
- Begin
- Result := FAddOnSet;
- End;
-
- Procedure TExtendedDictionary.SetAddOnSet (const AddOnSet : Boolean);
- Begin
- FAddOnSet := AddOnSet;
- End;
-
- Function TExtendedDictionary.GetHashTableSize : Integer;
- Begin
- Result := Length (FLookup);
- End;
-
- Procedure TExtendedDictionary.Rehash;
- var I, C, L : Integer;
- Begin
- C := FKeys.Count;
- L := DictionaryRehashSize (C);
- FLookup := nil;
- SetLength (FLookup, L);
- For I := 0 to C - 1 do
- Append (FLookup [HashStr (FKeys [I], L, FCaseSensitive)], I);
- End;
-
- class Function TExtendedDictionary.CreateInstance : AType;
- Begin
- Result := TExtendedDictionary.Create;
- End;
-
- Function TExtendedDictionary.LocateKey (const Key : String; var LookupIdx : Integer; const ErrorIfNotFound : Boolean) : Integer;
- var H, I, J, L : Integer;
- Begin
- Result := -1;
- L := Length (FLookup);
- if L > 0 then
- begin
- H := HashStr (Key, L, FCaseSensitive);
- LookupIdx := H;
- For I := 0 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, I];
- if cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- begin
- Result := J;
- break;
- end;
- end;
- end;
- if ErrorIfNotFound and (Result = -1) then
- KeyNotFoundError (Key);
- End;
-
- Function TExtendedDictionary.KeyIndex (const Key : String; const ErrorIfNotFound : Boolean) : Integer;
- var H : Integer;
- Begin
- Result := LocateKey (Key, H, ErrorIfNotFound);
- End;
-
- Procedure TExtendedDictionary.Add (const Key : String; const Value : Extended);
- var H, L, I : Integer;
- Begin
- if FDuplicatesAction in [ddIgnore, ddError] then
- if LocateKey (Key, H, False) >= 0 then
- if FDuplicatesAction = ddIgnore then
- exit else
- DictionaryError ('Duplicate key: ' + QuoteText (Key));
- L := Length (FLookup);
- if L = 0 then
- begin
- Rehash;
- L := Length (FLookup);
- end;
- H := Integer (HashStr (Key, LongWord (L), FCaseSensitive));
- I := FKeys.AddItem (Key);
- Append (FLookup [H], I);
- FValues.AddItem (Value);
-
- if (I + 1) div AverageHashChainSize > L then
- Rehash;
- End;
-
- Procedure TExtendedDictionary.DeleteByIndex (const Idx : Integer; const Hash : Integer);
- var I, J, H : Integer;
- Begin
- if Hash = -1 then
- H := HashStr (FKeys [Idx], Length (FLookup), FCaseSensitive) else
- H := Hash;
- FKeys.Delete (Idx);
- FValues.Delete (Idx);
- J := PosNext (Idx, FLookup [H]);
- Assert (J >= 0, 'Invalid hash value/lookup table');
- Remove (FLookup [H], J, 1);
-
- For I := 0 to Length (FLookup) - 1 do
- For J := 0 to Length (FLookup [I]) - 1 do
- if FLookup [I][J] > Idx then
- Dec (FLookup [I][J]);
- End;
-
- Procedure TExtendedDictionary.Delete (const Key : String);
- var I, H : Integer;
- Begin
- I := LocateKey (Key, H, True);
- DeleteByIndex (I, H);
- End;
-
- Function TExtendedDictionary.HasKey (const Key : String) : Boolean;
- Begin
- Result := KeyIndex (Key, False) >= 0;
- End;
-
- Procedure TExtendedDictionary.Rename (const Key, NewKey : String);
- var I, J, H : Integer;
- Begin
- I := LocateKey (Key, H, True);
- FKeys [I] := NewKey;
- J := PosNext (I, FLookup [H]);
- Assert (J >= 0, 'Invalid hash value/lookup table');
- Remove (FLookup [H], J, 1);
- Append (FLookup [HashStr (NewKey, Length (FLookup), FCaseSensitive)], I);
- End;
-
- Function TExtendedDictionary.GetDuplicatesAction : TDictionaryDuplicatesAction;
- Begin
- Result := FDuplicatesAction;
- End;
-
- Procedure TExtendedDictionary.SetDuplicatesAction (const DuplicatesAction : TDictionaryDuplicatesAction);
- Begin
- FDuplicatesAction := DuplicatesAction;
- End;
-
- Function TExtendedDictionary.LocateItem (const Key : String; var Value : Extended) : Integer;
- Begin
- Result := KeyIndex (Key, False);
- if Result >= 0 then
- Value := FValues [Result] else
- Value := 0.0;
- End;
-
- Function TExtendedDictionary.LocateNext (const Key : String; const Idx : Integer; var Value : Extended) : Integer;
- var L, H, I, J, K : Integer;
- Begin
- Result := -1;
- L := Length (FLookup);
- if L = 0 then
- DictionaryError ('Item not found');
- H := HashStr (Key, L, FCaseSensitive);
- For I := 0 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, I];
- if J = Idx then
- begin
- if not cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- DictionaryError ('Item not found');
- For K := I + 1 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, K];
- if cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- begin
- Value := FValues [J];
- Result := J;
- exit;
- end;
- end;
- Result := -1;
- exit;
- end;
- end;
- DictionaryError ('Item not found');
- End;
-
- Procedure TExtendedDictionary.SetItem (const Key : String; const Value : Extended);
- var I : Integer;
- Begin
- I := KeyIndex (Key, False);
- if I >= 0 then
- FValues [I] := Value else
- if AddOnSet then
- Add (Key, Value) else
- KeyNotFoundError (Key);
- End;
-
- Procedure TExtendedDictionary.IndexError;
- Begin
- DictionaryError ('Index out of range');
- End;
-
- Function TExtendedDictionary.Count : Integer;
- Begin
- Result := FKeys.Count;
- Assert (FValues.Count = Result, 'Key/Value count mismatch');
- End;
-
- Function TExtendedDictionary.GetKeyByIndex (const Idx : Integer) : String;
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FKeys.Count) then
- IndexError;
- {$ENDIF}
- Result := FKeys [Idx];
- End;
-
- Procedure TExtendedDictionary.DeleteItemByIndex (const Idx : Integer);
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- DeleteByIndex (Idx, -1);
- End;
-
- Function TExtendedDictionary.GetItemByIndex (const Idx : Integer) : Extended;
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- Result := FValues [Idx];
- End;
-
- Procedure TExtendedDictionary.SetItemByIndex (const Idx : Integer; const Value : Extended);
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- FValues [Idx] := Value;
- End;
-
- Procedure TExtendedDictionary.Clear;
- Begin
- FKeys.Clear;
- FValues.Clear;
- Rehash;
- End;
-
-
-
- { }
- { TStringDictionary }
- { }
- Constructor TStringDictionary.Create;
- Begin
- inherited Create;
- FCaseSensitive := True;
- FDuplicatesAction := ddAccept;
- FAddOnSet := True;
- FKeys := TStringArray.Create;
- FValues := TStringArray.Create;
- End;
-
- Constructor TStringDictionary.CreateEx (const Keys : AStringArray; const Values : AStringArray; const KeysCaseSensitive : Boolean; const AddOnSet : Boolean; const DuplicatesAction : TDictionaryDuplicatesAction);
- Begin
- inherited Create;
- if Assigned (Keys) then
- FKeys := Keys else
- FKeys := TStringArray.Create;
- if Assigned (Values) then
- FValues := Values else
- FValues := TStringArray.Create;
- Assert (FKeys.Count = FValues.Count, 'Keys and Values must be equal length');
- FAddOnSet := AddOnSet;
- FDuplicatesAction := DuplicatesAction;
- Rehash;
- End;
-
- Destructor TStringDictionary.Destroy;
- Begin
- FreeAndNil (FValues);
- FreeAndNil (FKeys);
- inherited Destroy;
- End;
-
- Function TStringDictionary.GetKeysCaseSensitive : Boolean;
- Begin
- Result := FCaseSensitive;
- End;
-
- Function TStringDictionary.GetAddOnSet : Boolean;
- Begin
- Result := FAddOnSet;
- End;
-
- Procedure TStringDictionary.SetAddOnSet (const AddOnSet : Boolean);
- Begin
- FAddOnSet := AddOnSet;
- End;
-
- Function TStringDictionary.GetHashTableSize : Integer;
- Begin
- Result := Length (FLookup);
- End;
-
- Procedure TStringDictionary.Rehash;
- var I, C, L : Integer;
- Begin
- C := FKeys.Count;
- L := DictionaryRehashSize (C);
- FLookup := nil;
- SetLength (FLookup, L);
- For I := 0 to C - 1 do
- Append (FLookup [HashStr (FKeys [I], L, FCaseSensitive)], I);
- End;
-
- class Function TStringDictionary.CreateInstance : AType;
- Begin
- Result := TStringDictionary.Create;
- End;
-
- Function TStringDictionary.LocateKey (const Key : String; var LookupIdx : Integer; const ErrorIfNotFound : Boolean) : Integer;
- var H, I, J, L : Integer;
- Begin
- Result := -1;
- L := Length (FLookup);
- if L > 0 then
- begin
- H := HashStr (Key, L, FCaseSensitive);
- LookupIdx := H;
- For I := 0 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, I];
- if cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- begin
- Result := J;
- break;
- end;
- end;
- end;
- if ErrorIfNotFound and (Result = -1) then
- KeyNotFoundError (Key);
- End;
-
- Function TStringDictionary.KeyIndex (const Key : String; const ErrorIfNotFound : Boolean) : Integer;
- var H : Integer;
- Begin
- Result := LocateKey (Key, H, ErrorIfNotFound);
- End;
-
- Procedure TStringDictionary.Add (const Key : String; const Value : String);
- var H, L, I : Integer;
- Begin
- if FDuplicatesAction in [ddIgnore, ddError] then
- if LocateKey (Key, H, False) >= 0 then
- if FDuplicatesAction = ddIgnore then
- exit else
- DictionaryError ('Duplicate key: ' + QuoteText (Key));
- L := Length (FLookup);
- if L = 0 then
- begin
- Rehash;
- L := Length (FLookup);
- end;
- H := Integer (HashStr (Key, LongWord (L), FCaseSensitive));
- I := FKeys.AddItem (Key);
- Append (FLookup [H], I);
- FValues.AddItem (Value);
-
- if (I + 1) div AverageHashChainSize > L then
- Rehash;
- End;
-
- Procedure TStringDictionary.DeleteByIndex (const Idx : Integer; const Hash : Integer);
- var I, J, H : Integer;
- Begin
- if Hash = -1 then
- H := HashStr (FKeys [Idx], Length (FLookup), FCaseSensitive) else
- H := Hash;
- FKeys.Delete (Idx);
- FValues.Delete (Idx);
- J := PosNext (Idx, FLookup [H]);
- Assert (J >= 0, 'Invalid hash value/lookup table');
- Remove (FLookup [H], J, 1);
-
- For I := 0 to Length (FLookup) - 1 do
- For J := 0 to Length (FLookup [I]) - 1 do
- if FLookup [I][J] > Idx then
- Dec (FLookup [I][J]);
- End;
-
- Procedure TStringDictionary.Delete (const Key : String);
- var I, H : Integer;
- Begin
- I := LocateKey (Key, H, True);
- DeleteByIndex (I, H);
- End;
-
- Function TStringDictionary.HasKey (const Key : String) : Boolean;
- Begin
- Result := KeyIndex (Key, False) >= 0;
- End;
-
- Procedure TStringDictionary.Rename (const Key, NewKey : String);
- var I, J, H : Integer;
- Begin
- I := LocateKey (Key, H, True);
- FKeys [I] := NewKey;
- J := PosNext (I, FLookup [H]);
- Assert (J >= 0, 'Invalid hash value/lookup table');
- Remove (FLookup [H], J, 1);
- Append (FLookup [HashStr (NewKey, Length (FLookup), FCaseSensitive)], I);
- End;
-
- Function TStringDictionary.GetDuplicatesAction : TDictionaryDuplicatesAction;
- Begin
- Result := FDuplicatesAction;
- End;
-
- Procedure TStringDictionary.SetDuplicatesAction (const DuplicatesAction : TDictionaryDuplicatesAction);
- Begin
- FDuplicatesAction := DuplicatesAction;
- End;
-
- Function TStringDictionary.LocateItem (const Key : String; var Value : String) : Integer;
- Begin
- Result := KeyIndex (Key, False);
- if Result >= 0 then
- Value := FValues [Result] else
- Value := '';
- End;
-
- Function TStringDictionary.LocateNext (const Key : String; const Idx : Integer; var Value : String) : Integer;
- var L, H, I, J, K : Integer;
- Begin
- Result := -1;
- L := Length (FLookup);
- if L = 0 then
- DictionaryError ('Item not found');
- H := HashStr (Key, L, FCaseSensitive);
- For I := 0 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, I];
- if J = Idx then
- begin
- if not cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- DictionaryError ('Item not found');
- For K := I + 1 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, K];
- if cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- begin
- Value := FValues [J];
- Result := J;
- exit;
- end;
- end;
- Result := -1;
- exit;
- end;
- end;
- DictionaryError ('Item not found');
- End;
-
- Procedure TStringDictionary.SetItem (const Key : String; const Value : String);
- var I : Integer;
- Begin
- I := KeyIndex (Key, False);
- if I >= 0 then
- FValues [I] := Value else
- if AddOnSet then
- Add (Key, Value) else
- KeyNotFoundError (Key);
- End;
-
- Procedure TStringDictionary.IndexError;
- Begin
- DictionaryError ('Index out of range');
- End;
-
- Function TStringDictionary.Count : Integer;
- Begin
- Result := FKeys.Count;
- Assert (FValues.Count = Result, 'Key/Value count mismatch');
- End;
-
- Function TStringDictionary.GetKeyByIndex (const Idx : Integer) : String;
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FKeys.Count) then
- IndexError;
- {$ENDIF}
- Result := FKeys [Idx];
- End;
-
- Procedure TStringDictionary.DeleteItemByIndex (const Idx : Integer);
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- DeleteByIndex (Idx, -1);
- End;
-
- Function TStringDictionary.GetItemByIndex (const Idx : Integer) : String;
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- Result := FValues [Idx];
- End;
-
- Procedure TStringDictionary.SetItemByIndex (const Idx : Integer; const Value : String);
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- FValues [Idx] := Value;
- End;
-
- Procedure TStringDictionary.Clear;
- Begin
- FKeys.Clear;
- FValues.Clear;
- Rehash;
- End;
-
-
-
- { }
- { TObjectDictionary }
- { }
- Constructor TObjectDictionary.Create;
- Begin
- inherited Create;
- FCaseSensitive := True;
- FDuplicatesAction := ddAccept;
- FAddOnSet := True;
- FKeys := TStringArray.Create;
- FValues := TObjectArray.Create;
- End;
-
- Constructor TObjectDictionary.CreateEx (const Keys : AStringArray; const Values : AObjectArray; const IsItemOwner : Boolean; const KeysCaseSensitive : Boolean; const AddOnSet : Boolean; const DuplicatesAction : TDictionaryDuplicatesAction);
- Begin
- inherited Create;
- if Assigned (Keys) then
- FKeys := Keys else
- FKeys := TStringArray.Create;
- if Assigned (Values) then
- FValues := Values else
- FValues := TObjectArray.Create;
- Assert (FKeys.Count = FValues.Count, 'Keys and Values must be equal length');
- FAddOnSet := AddOnSet;
- FValues.IsItemOwner := IsItemOwner;
- FCaseSensitive := KeysCaseSensitive;
- FDuplicatesAction := DuplicatesAction;
- Rehash;
- End;
-
- Destructor TObjectDictionary.Destroy;
- Begin
- FreeAndNil (FValues);
- FreeAndNil (FKeys);
- inherited Destroy;
- End;
-
- Function TObjectDictionary.GetKeysCaseSensitive : Boolean;
- Begin
- Result := FCaseSensitive;
- End;
-
- Function TObjectDictionary.GetAddOnSet : Boolean;
- Begin
- Result := FAddOnSet;
- End;
-
- Procedure TObjectDictionary.SetAddOnSet (const AddOnSet : Boolean);
- Begin
- FAddOnSet := AddOnSet;
- End;
-
- Function TObjectDictionary.GetHashTableSize : Integer;
- Begin
- Result := Length (FLookup);
- End;
-
- Function TObjectDictionary.GetIsItemOwner : Boolean;
- Begin
- Result := FValues.IsItemOwner;
- End;
-
- Procedure TObjectDictionary.SetIsItemOwner (const IsItemOwner : Boolean);
- Begin
- FValues.IsItemOwner := IsItemOwner;
- End;
-
- Procedure TObjectDictionary.Rehash;
- var I, C, L : Integer;
- Begin
- C := FKeys.Count;
- L := DictionaryRehashSize (C);
- FLookup := nil;
- SetLength (FLookup, L);
- For I := 0 to C - 1 do
- Append (FLookup [HashStr (FKeys [I], L, FCaseSensitive)], I);
- End;
-
- class Function TObjectDictionary.CreateInstance : AType;
- Begin
- Result := TObjectDictionary.Create;
- End;
-
- Function TObjectDictionary.LocateKey (const Key : String; var LookupIdx : Integer; const ErrorIfNotFound : Boolean) : Integer;
- var H, I, J, L : Integer;
- Begin
- Result := -1;
- L := Length (FLookup);
- if L > 0 then
- begin
- H := HashStr (Key, L, FCaseSensitive);
- LookupIdx := H;
- For I := 0 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, I];
- if cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- begin
- Result := J;
- break;
- end;
- end;
- end;
- if ErrorIfNotFound and (Result = -1) then
- KeyNotFoundError (Key);
- End;
-
- Function TObjectDictionary.KeyIndex (const Key : String; const ErrorIfNotFound : Boolean) : Integer;
- var H : Integer;
- Begin
- Result := LocateKey (Key, H, ErrorIfNotFound);
- End;
-
- Procedure TObjectDictionary.Add (const Key : String; const Value : TObject);
- var H, L, I : Integer;
- Begin
- if FDuplicatesAction in [ddIgnore, ddError] then
- if LocateKey (Key, H, False) >= 0 then
- if FDuplicatesAction = ddIgnore then
- exit else
- DictionaryError ('Duplicate key: ' + QuoteText (Key));
- L := Length (FLookup);
- if L = 0 then
- begin
- Rehash;
- L := Length (FLookup);
- end;
- H := Integer (HashStr (Key, LongWord (L), FCaseSensitive));
- I := FKeys.AddItem (Key);
- Append (FLookup [H], I);
- FValues.AddItem (Value);
-
- if (I + 1) div AverageHashChainSize > L then
- Rehash;
- End;
-
- Procedure TObjectDictionary.DeleteByIndex (const Idx : Integer; const Hash : Integer);
- var I, J, H : Integer;
- Begin
- if Hash = -1 then
- H := HashStr (FKeys [Idx], Length (FLookup), FCaseSensitive) else
- H := Hash;
- FKeys.Delete (Idx);
- FValues.Delete (Idx);
- J := PosNext (Idx, FLookup [H]);
- Assert (J >= 0, 'Invalid hash value/lookup table');
- Remove (FLookup [H], J, 1);
-
- For I := 0 to Length (FLookup) - 1 do
- For J := 0 to Length (FLookup [I]) - 1 do
- if FLookup [I][J] > Idx then
- Dec (FLookup [I][J]);
- End;
-
- Procedure TObjectDictionary.Delete (const Key : String);
- var I, H : Integer;
- Begin
- I := LocateKey (Key, H, True);
- DeleteByIndex (I, H);
- End;
-
- Function TObjectDictionary.HasKey (const Key : String) : Boolean;
- Begin
- Result := KeyIndex (Key, False) >= 0;
- End;
-
- Procedure TObjectDictionary.Rename (const Key, NewKey : String);
- var I, J, H : Integer;
- Begin
- I := LocateKey (Key, H, True);
- FKeys [I] := NewKey;
- J := PosNext (I, FLookup [H]);
- Assert (J >= 0, 'Invalid hash value/lookup table');
- Remove (FLookup [H], J, 1);
- Append (FLookup [HashStr (NewKey, Length (FLookup), FCaseSensitive)], I);
- End;
-
- Function TObjectDictionary.GetDuplicatesAction : TDictionaryDuplicatesAction;
- Begin
- Result := FDuplicatesAction;
- End;
-
- Procedure TObjectDictionary.SetDuplicatesAction (const DuplicatesAction : TDictionaryDuplicatesAction);
- Begin
- FDuplicatesAction := DuplicatesAction;
- End;
-
- Function TObjectDictionary.LocateItem (const Key : String; var Value : TObject) : Integer;
- Begin
- Result := KeyIndex (Key, False);
- if Result >= 0 then
- Value := FValues [Result] else
- Value := nil;
- End;
-
- Function TObjectDictionary.LocateNext (const Key : String; const Idx : Integer; var Value : TObject) : Integer;
- var L, H, I, J, K : Integer;
- Begin
- Result := -1;
- L := Length (FLookup);
- if L = 0 then
- DictionaryError ('Item not found');
- H := HashStr (Key, L, FCaseSensitive);
- For I := 0 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, I];
- if J = Idx then
- begin
- if not cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- DictionaryError ('Item not found');
- For K := I + 1 to Length (FLookup [H]) - 1 do
- begin
- J := FLookup [H, K];
- if cStrings.IsEqual (Key, FKeys [J], FCaseSensitive) then
- begin
- Value := FValues [J];
- Result := J;
- exit;
- end;
- end;
- Result := -1;
- exit;
- end;
- end;
- DictionaryError ('Item not found');
- End;
-
- Procedure TObjectDictionary.SetItem (const Key : String; const Value : TObject);
- var I : Integer;
- Begin
- I := KeyIndex (Key, False);
- if I >= 0 then
- FValues [I] := Value else
- if AddOnSet then
- Add (Key, Value) else
- KeyNotFoundError (Key);
- End;
-
- Procedure TObjectDictionary.IndexError;
- Begin
- DictionaryError ('Index out of range');
- End;
-
- Function TObjectDictionary.Count : Integer;
- Begin
- Result := FKeys.Count;
- Assert (FValues.Count = Result, 'Key/Value count mismatch');
- End;
-
- Function TObjectDictionary.GetKeyByIndex (const Idx : Integer) : String;
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FKeys.Count) then
- IndexError;
- {$ENDIF}
- Result := FKeys [Idx];
- End;
-
- Procedure TObjectDictionary.DeleteItemByIndex (const Idx : Integer);
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- DeleteByIndex (Idx, -1);
- End;
-
- Function TObjectDictionary.GetItemByIndex (const Idx : Integer) : TObject;
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- Result := FValues [Idx];
- End;
-
- Procedure TObjectDictionary.SetItemByIndex (const Idx : Integer; const Value : TObject);
- Begin
- {$IFOPT R+}
- if (Idx < 0) or (Idx >= FValues.Count) then
- IndexError;
- {$ENDIF}
- FValues [Idx] := Value;
- End;
-
- Function TObjectDictionary.ReleaseItem (const Key : String) : TObject;
- var I : Integer;
- Begin
- I := KeyIndex (Key, True);
- Result := FValues.ReleaseItem (I);
- End;
-
- Procedure TObjectDictionary.ReleaseItems;
- Begin
- FKeys.Clear;
- FValues.ReleaseItems;
- Rehash;
- End;
-
- Procedure TObjectDictionary.FreeItems;
- Begin
- FKeys.Clear;
- FValues.FreeItems;
- Rehash;
- End;
-
- Procedure TObjectDictionary.Clear;
- Begin
- FKeys.Clear;
- FValues.Clear;
- Rehash;
- End;
-
-
-
- { }
- { Self testing code }
- { }
- Procedure SelfTest;
- var F : TIntegerDictionary;
- G : TStringDictionary;
- I : Integer;
- Begin
- F := TIntegerDictionary.Create;
- For I := 0 to 16384 do
- F.Add (IntToStr (I), I);
- Assert (F.Count = 16385, 'Dictionary.Count');
- For I := 0 to 16384 do
- Assert (F.GetKeyByIndex (I) = IntToStr (I), 'Dictionary.GetKeyByIndex');
- Assert (F ['0'] = 0, 'Dictionary.GetItem');
- Assert (F ['5'] = 5, 'Dictionary.GetItem');
- Assert (F ['16384'] = 16384, 'Dictionary.GetItem');
- For I := 0 to 16384 do
- Assert (F.GetItemByIndex (I) = I, 'Dictionary.GetItemByIndex');
- Assert (F.HasKey ('5'), 'Dictionary.HasKey');
- Assert (not F.HasKey ('X'), 'Dictionary.HasKey');
- F.Rename ('5', 'X');
- Assert (not F.HasKey ('5'), 'Dictionary.Rename');
- Assert (F.HasKey ('X'), 'Dictionary.Rename');
- Assert (F ['X'] = 5, 'Dictionary.Rename');
- F.Delete ('X');
- Assert (not F.HasKey ('X'), 'Dictionary.Delete');
- Assert (F.Count = 16384, 'Dictionary.Delete');
- F.Delete ('0');
- Assert (not F.HasKey ('0'), 'Dictionary.Delete');
- Assert (F.Count = 16383, 'Dictionary.Delete');
- F.DeleteItemByIndex (0);
- Assert (not F.HasKey ('1'), 'Dictionary.DeleteItemByIndex');
- Assert (F.Count = 16382, 'Dictionary.DeleteItemByIndex');
- F.Free;
-
- G := TStringDictionary.Create;
- For I := 0 to 16384 do
- G.Add (IntToStr (I), IntToStr (I));
- Assert (G.Count = 16385, 'Dictionary.Count');
- For I := 0 to 16384 do
- Assert (G.GetKeyByIndex (I) = IntToStr (I), 'Dictionary.GetKeyByIndex');
- Assert (G ['0'] = '0', 'Dictionary.GetItem');
- Assert (G ['5'] = '5', 'Dictionary.GetItem');
- Assert (G ['16384'] = '16384', 'Dictionary.GetItem');
- For I := 0 to 16384 do
- Assert (G.GetItemByIndex (I) = IntToStr (I), 'Dictionary.GetItemByIndex');
- Assert (G.HasKey ('5'), 'Dictionary.HasKey');
- Assert (not G.HasKey ('X'), 'Dictionary.HasKey');
- G.Rename ('5', 'X');
- Assert (not G.HasKey ('5'), 'Dictionary.Rename');
- Assert (G.HasKey ('X'), 'Dictionary.Rename');
- Assert (G ['X'] = '5', 'Dictionary.Rename');
- G.Delete ('X');
- Assert (not G.HasKey ('X'), 'Dictionary.Delete');
- Assert (G.Count = 16384, 'Dictionary.Delete');
- G.Delete ('0');
- Assert (not G.HasKey ('0'), 'Dictionary.Delete');
- Assert (G.Count = 16383, 'Dictionary.Delete');
- G.DeleteItemByIndex (0);
- Assert (not G.HasKey ('1'), 'Dictionary.DeleteItemByIndex');
- Assert (G.Count = 16382, 'Dictionary.DeleteItemByIndex');
- G.Free;
- End;
-
-
-
- end.
-
-