1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155 |
- {
- This file is part of the Free Component Library (FCL)
- Copyright (c) 2002 by Florian Klaempfl
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- {$ifdef fpc}
- {$mode objfpc}
- {$endif}
- {$H+}
- {$ifdef CLASSESINLINE}{$inline on}{$endif}
- unit contnrs;
- interface
- uses
- SysUtils,Classes;
- Type
- TObjectListCallback = procedure(data:TObject;arg:pointer) of object;
- TObjectListStaticCallback = procedure(data:TObject;arg:pointer);
- TFPObjectList = class(TObject)
- private
- FFreeObjects : Boolean;
- FList: TFPList;
- function GetCount: integer;
- procedure SetCount(const AValue: integer);
- protected
- function GetItem(Index: Integer): TObject; {$ifdef CLASSESINLINE}inline;{$endif}
- procedure SetItem(Index: Integer; AObject: TObject); {$ifdef CLASSESINLINE}inline;{$endif}
- procedure SetCapacity(NewCapacity: Integer);
- function GetCapacity: integer;
- public
- constructor Create;
- constructor Create(FreeObjects : Boolean);
- destructor Destroy; override;
- procedure Clear;
- function Add(AObject: TObject): Integer; {$ifdef CLASSESINLINE}inline;{$endif}
- procedure Delete(Index: Integer); {$ifdef CLASSESINLINE}inline;{$endif}
- procedure Exchange(Index1, Index2: Integer);
- function Expand: TFPObjectList;
- function Extract(Item: TObject): TObject;
- function Remove(AObject: TObject): Integer;
- function IndexOf(AObject: TObject): Integer;
- function FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt: Integer): Integer;
- procedure Insert(Index: Integer; AObject: TObject); {$ifdef CLASSESINLINE}inline;{$endif}
- function First: TObject;
- function Last: TObject;
- procedure Move(CurIndex, NewIndex: Integer);
- procedure Assign(Obj:TFPObjectList);
- procedure Pack;
- procedure Sort(Compare: TListSortCompare);
- procedure ForEachCall(proc2call:TObjectListCallback;arg:pointer);
- procedure ForEachCall(proc2call:TObjectListStaticCallback;arg:pointer);
- property Capacity: Integer read GetCapacity write SetCapacity;
- property Count: Integer read GetCount write SetCount;
- property OwnsObjects: Boolean read FFreeObjects write FFreeObjects;
- property Items[Index: Integer]: TObject read GetItem write SetItem; default;
- property List: TFPList read FList;
- end;
- TObjectList = class(TList)
- private
- ffreeobjects : boolean;
- Protected
- Procedure Notify(Ptr: Pointer; Action: TListNotification); override;
- function GetItem(Index: Integer): TObject;
- Procedure SetItem(Index: Integer; AObject: TObject);
- public
- constructor create;
- constructor create(freeobjects : boolean);
- function Add(AObject: TObject): Integer;
- function Extract(Item: TObject): TObject;
- function Remove(AObject: TObject): Integer;
- function IndexOf(AObject: TObject): Integer;
- function FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt: Integer): Integer;
- Procedure Insert(Index: Integer; AObject: TObject);
- function First: TObject;
- Function Last: TObject;
- property OwnsObjects: Boolean read FFreeObjects write FFreeObjects;
- property Items[Index: Integer]: TObject read GetItem write SetItem; default;
- end;
- TComponentList = class(TObjectList)
- Private
- FNotifier : TComponent;
- Protected
- Procedure Notify(Ptr: Pointer; Action: TListNotification); override;
- Function GetItems(Index: Integer): TComponent;
- Procedure SetItems(Index: Integer; AComponent: TComponent);
- Procedure HandleFreeNotify(Sender: TObject; AComponent: TComponent);
- public
- destructor Destroy; override;
- Function Add(AComponent: TComponent): Integer;
- Function Extract(Item: TComponent): TComponent;
- Function Remove(AComponent: TComponent): Integer;
- Function IndexOf(AComponent: TComponent): Integer;
- Function First: TComponent;
- Function Last: TComponent;
- Procedure Insert(Index: Integer; AComponent: TComponent);
- property Items[Index: Integer]: TComponent read GetItems write SetItems; default;
- end;
- TClassList = class(TList)
- protected
- Function GetItems(Index: Integer): TClass;
- Procedure SetItems(Index: Integer; AClass: TClass);
- public
- Function Add(AClass: TClass): Integer;
- Function Extract(Item: TClass): TClass;
- Function Remove(AClass: TClass): Integer;
- Function IndexOf(AClass: TClass): Integer;
- Function First: TClass;
- Function Last: TClass;
- Procedure Insert(Index: Integer; AClass: TClass);
- property Items[Index: Integer]: TClass read GetItems write SetItems; default;
- end;
- TOrderedList = class(TObject)
- private
- FList: TList;
- protected
- Procedure PushItem(AItem: Pointer); virtual; abstract;
- Function PopItem: Pointer; virtual;
- Function PeekItem: Pointer; virtual;
- property List: TList read FList;
- public
- constructor Create;
- destructor Destroy; override;
- Function Count: Integer;
- Function AtLeast(ACount: Integer): Boolean;
- Function Push(AItem: Pointer): Pointer;
- Function Pop: Pointer;
- Function Peek: Pointer;
- end;
- { TStack class }
- TStack = class(TOrderedList)
- protected
- Procedure PushItem(AItem: Pointer); override;
- end;
- { TObjectStack class }
- TObjectStack = class(TStack)
- public
- Function Push(AObject: TObject): TObject;
- Function Pop: TObject;
- Function Peek: TObject;
- end;
- { TQueue class }
- TQueue = class(TOrderedList)
- protected
- Procedure PushItem(AItem: Pointer); override;
- end;
- { TObjectQueue class }
- TObjectQueue = class(TQueue)
- public
- Function Push(AObject: TObject): TObject;
- Function Pop: TObject;
- Function Peek: TObject;
- end;
- { ---------------------------------------------------------------------
- TPList with Hash support
- ---------------------------------------------------------------------}
- type
- THashItem=record
- HashValue : LongWord;
- StrIndex : Integer;
- NextIndex : Integer;
- Data : Pointer;
- end;
- PHashItem=^THashItem;
- const
- MaxHashListSize = Maxint div 16;
- MaxHashStrSize = Maxint;
- MaxHashTableSize = Maxint div 4;
- MaxItemsPerHash = 3;
- type
- PHashItemList = ^THashItemList;
- THashItemList = array[0..MaxHashListSize - 1] of THashItem;
- PHashTable = ^THashTable;
- THashTable = array[0..MaxHashTableSize - 1] of Integer;
- { TFPHashList class }
- TFPHashList = class(TObject)
- private
- { ItemList }
- FHashList : PHashItemList;
- FCount,
- FCapacity : Integer;
- { Hash }
- FHashTable : PHashTable;
- FHashCapacity : Integer;
- { Strings }
- FStrs : PChar;
- FStrCount,
- FStrCapacity : Integer;
- protected
- function Get(Index: Integer): Pointer;
- procedure SetCapacity(NewCapacity: Integer);
- procedure SetCount(NewCount: Integer);
- Procedure RaiseIndexError(Index : Integer);
- function AddStr(const s:shortstring): Integer;
- procedure AddToHashTable(Index: Integer);
- procedure StrExpand(MinIncSize:Integer);
- procedure SetStrCapacity(NewCapacity: Integer);
- procedure SetHashCapacity(NewCapacity: Integer);
- procedure ReHash;
- public
- constructor Create;
- destructor Destroy; override;
- function Add(const AName:shortstring;Item: Pointer): Integer;
- procedure Clear;
- function NameOfIndex(Index: Integer): String;
- procedure Delete(Index: Integer);
- class procedure Error(const Msg: string; Data: PtrInt);
- function Expand: TFPHashList;
- function Extract(item: Pointer): Pointer;
- function IndexOf(Item: Pointer): Integer;
- function Find(const s:shortstring): Pointer;
- function Remove(Item: Pointer): Integer;
- procedure Pack;
- procedure ShowStatistics;
- procedure ForEachCall(proc2call:TListCallback;arg:pointer);
- procedure ForEachCall(proc2call:TListStaticCallback;arg:pointer);
- property Capacity: Integer read FCapacity write SetCapacity;
- property Count: Integer read FCount write SetCount;
- property Items[Index: Integer]: Pointer read Get; default;
- property List: PHashItemList read FHashList;
- property Strs: PChar read FStrs;
- end;
- { TFPHashObjectList class }
- TFPHashObjectList = class;
- TFPHashObject = class
- private
- FOwner : TFPHashObjectList;
- FCachedStr : pshortstring;
- FStrIndex : Integer;
- protected
- function GetName:shortstring;
- public
- constructor Create(HashObjectList:TFPHashObjectList;const s:shortstring);
- property Name:shortstring read GetName;
- end;
- TFPHashObjectList = class(TObject)
- private
- FFreeObjects : Boolean;
- FHashList: TFPHashList;
- function GetCount: integer;
- procedure SetCount(const AValue: integer);
- protected
- function GetItem(Index: Integer): TObject;
- procedure SetCapacity(NewCapacity: Integer);
- function GetCapacity: integer;
- public
- constructor Create(FreeObjects : boolean = True);
- destructor Destroy; override;
- procedure Clear;
- function Add(const AName:shortstring;AObject: TObject): Integer;
- function NameOfIndex(Index: Integer): shortstring;
- procedure Delete(Index: Integer);
- function Expand: TFPHashObjectList;
- function Extract(Item: TObject): TObject;
- function Remove(AObject: TObject): Integer;
- function IndexOf(AObject: TObject): Integer;
- function Find(const s:shortstring): TObject;
- function FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt: Integer): Integer;
- procedure Pack;
- procedure ShowStatistics;
- procedure ForEachCall(proc2call:TObjectListCallback;arg:pointer);
- procedure ForEachCall(proc2call:TObjectListStaticCallback;arg:pointer);
- property Capacity: Integer read GetCapacity write SetCapacity;
- property Count: Integer read GetCount write SetCount;
- property OwnsObjects: Boolean read FFreeObjects write FFreeObjects;
- property Items[Index: Integer]: TObject read GetItem; default;
- property List: TFPHashList read FHashList;
- end;
- { ---------------------------------------------------------------------
- Hash support, implemented by Dean Zobec
- ---------------------------------------------------------------------}
- { Must return a Longword value in the range 0..TableSize,
- usually via a mod operator; }
- THashFunction = function(const S: string; const TableSize: Longword): Longword;
-
- { THTNode }
- THTCustomNode = class(TObject)
- private
- FKey: string;
- public
- constructor CreateWith(const AString: String);
- function HasKey(const AKey: string): boolean;
- property Key: string read FKey;
- end;
- THTCustomNodeClass = Class of THTCustomNode;
-
- { TFPCustomHashTable }
- TFPCustomHashTable = class(TObject)
- private
- FHashTable: TFPObjectList;
- FHashTableSize: Longword;
- FHashFunction: THashFunction;
- FCount: Longword;
- function GetDensity: Longword;
- function GetNumberOfCollisions: Longword;
- procedure SetHashTableSize(const Value: Longword);
- procedure InitializeHashTable;
- function GetVoidSlots: Longword;
- function GetLoadFactor: double;
- function GetAVGChainLen: double;
- function GetMaxChainLength: Longword;
- function Chain(const index: Longword):TFPObjectList;
- protected
- Function CreateNewNode(const aKey : string) : THTCustomNode; virtual; abstract;
- Procedure AddNode(ANode : THTCustomNode); virtual; abstract;
- function ChainLength(const ChainIndex: Longword): Longword; virtual;
- function FindOrCreateNew(const aKey: string): THTCustomNode; virtual;
- procedure SetHashFunction(AHashFunction: THashFunction); virtual;
- Function FindChainForAdd(Const aKey : String) : TFPObjectList;
- public
- constructor Create;
- constructor CreateWith(AHashTableSize: Longword; aHashFunc: THashFunction);
- destructor Destroy; override;
- procedure ChangeTableSize(const ANewSize: Longword); virtual;
- procedure Clear; virtual;
- procedure Delete(const aKey: string); virtual;
- function Find(const aKey: string): THTCustomNode;
- function IsEmpty: boolean;
- property HashFunction: THashFunction read FHashFunction write SetHashFunction;
- property Count: Longword read FCount;
- property HashTableSize: Longword read FHashTableSize write SetHashTableSize;
- property HashTable: TFPObjectList read FHashTable;
- property VoidSlots: Longword read GetVoidSlots;
- property LoadFactor: double read GetLoadFactor;
- property AVGChainLen: double read GetAVGChainLen;
- property MaxChainLength: Longword read GetMaxChainLength;
- property NumberOfCollisions: Longword read GetNumberOfCollisions;
- property Density: Longword read GetDensity;
- end;
- { TFPDataHashTable : Hash table with simple data pointers }
- THTDataNode = Class(THTCustomNode)
- Private
- FData: pointer;
- public
- property Data: pointer read FData write FData;
- end;
- // For compatibility
- THTNode = THTDataNode;
- TDataIteratorMethod = procedure(Item: Pointer; const Key: string; var Continue: Boolean) of object;
- // For compatibility
- TIteratorMethod = TDataIteratorMethod;
-
- TFPDataHashTable = Class(TFPCustomHashTable)
- Protected
- Function CreateNewNode(const aKey : String) : THTCustomNode; override;
- Procedure AddNode(ANode : THTCustomNode); override;
- procedure SetData(const index: string; const AValue: Pointer); virtual;
- function GetData(const index: string):Pointer; virtual;
- function ForEachCall(aMethod: TDataIteratorMethod): THTDataNode; virtual;
- Public
- procedure Add(const aKey: string; AItem: pointer); virtual;
- property Items[const index: string]: Pointer read GetData write SetData; default;
- end;
- { TFPStringHashTable : Hash table with simple strings as data }
- THTStringNode = Class(THTCustomNode)
- Private
- FData : String;
- public
- property Data: String read FData write FData;
- end;
- TStringIteratorMethod = procedure(Item: String; const Key: string; var Continue: Boolean) of object;
- TFPStringHashTable = Class(TFPCustomHashTable)
- Protected
- Function CreateNewNode(const aKey : String) : THTCustomNode; override;
- Procedure AddNode(ANode : THTCustomNode); override;
- procedure SetData(const Index, AValue: string); virtual;
- function GetData(const index: string): String; virtual;
- function ForEachCall(aMethod: TStringIteratorMethod): THTStringNode; virtual;
- Public
- procedure Add(const aKey,aItem: string); virtual;
- property Items[const index: string]: String read GetData write SetData; default;
- end;
-
- { TFPStringHashTable : Hash table with simple strings as data }
-
- THTObjectNode = Class(THTCustomNode)
- Private
- FData : TObject;
- public
- property Data: TObject read FData write FData;
- end;
- THTOwnedObjectNode = Class(THTObjectNode)
- public
- Destructor Destroy; override;
- end;
- TObjectIteratorMethod = procedure(Item: TObject; const Key: string; var Continue: Boolean) of object;
- TFPObjectHashTable = Class(TFPCustomHashTable)
- Private
- FOwnsObjects : Boolean;
- Protected
- Function CreateNewNode(const aKey : String) : THTCustomNode; override;
- Procedure AddNode(ANode : THTCustomNode); override;
- procedure SetData(const Index: string; AObject : TObject); virtual;
- function GetData(const index: string): TObject; virtual;
- function ForEachCall(aMethod: TObjectIteratorMethod): THTObjectNode; virtual;
- Public
- constructor Create(AOwnsObjects : Boolean = True);
- constructor CreateWith(AHashTableSize: Longword; aHashFunc: THashFunction; AOwnsObjects : Boolean = True);
- procedure Add(const aKey: string; AItem : TObject); virtual;
- property Items[const index: string]: TObject read GetData write SetData; default;
- Property OwnsObjects : Boolean Read FOwnsObjects Write FOwnsObjects;
- end;
- EDuplicate = class(Exception);
- EKeyNotFound = class(Exception);
- function RSHash(const S: string; const TableSize: Longword): Longword;
- implementation
- uses
- RtlConsts;
- ResourceString
- DuplicateMsg = 'An item with key %0:s already exists';
- KeyNotFoundMsg = 'Method: %0:s key [''%1:s''] not found in container';
- NotEmptyMsg = 'Hash table not empty.';
- const
- NPRIMES = 28;
- PRIMELIST: array[0 .. NPRIMES-1] of Longword =
- ( 53, 97, 193, 389, 769,
- 1543, 3079, 6151, 12289, 24593,
- 49157, 98317, 196613, 393241, 786433,
- 1572869, 3145739, 6291469, 12582917, 25165843,
- 50331653, 100663319, 201326611, 402653189, 805306457,
- 1610612741, 3221225473, 4294967291 );
- constructor TFPObjectList.Create(FreeObjects : boolean);
- begin
- Create;
- FFreeObjects := Freeobjects;
- end;
- destructor TFPObjectList.Destroy;
- begin
- if (FList <> nil) then
- begin
- Clear;
- FList.Destroy;
- end;
- inherited Destroy;
- end;
- procedure TFPObjectList.Clear;
- var
- i: integer;
- begin
- if FFreeObjects then
- for i := 0 to FList.Count - 1 do
- TObject(FList[i]).Free;
- FList.Clear;
- end;
- constructor TFPObjectList.Create;
- begin
- inherited Create;
- FList := TFPList.Create;
- FFreeObjects := True;
- end;
- function TFPObjectList.GetCount: integer;
- begin
- Result := FList.Count;
- end;
- procedure TFPObjectList.SetCount(const AValue: integer);
- begin
- if FList.Count <> AValue then
- FList.Count := AValue;
- end;
- function TFPObjectList.GetItem(Index: Integer): TObject; {$ifdef CLASSESINLINE}inline;{$endif}
- begin
- Result := TObject(FList[Index]);
- end;
- procedure TFPObjectList.SetItem(Index: Integer; AObject: TObject); {$ifdef CLASSESINLINE}inline;{$endif}
- begin
- if OwnsObjects then
- TObject(FList[Index]).Free;
- FList[index] := AObject;
- end;
- procedure TFPObjectList.SetCapacity(NewCapacity: Integer);
- begin
- FList.Capacity := NewCapacity;
- end;
- function TFPObjectList.GetCapacity: integer;
- begin
- Result := FList.Capacity;
- end;
- function TFPObjectList.Add(AObject: TObject): Integer; {$ifdef CLASSESINLINE}inline;{$endif}
- begin
- Result := FList.Add(AObject);
- end;
- procedure TFPObjectList.Delete(Index: Integer); {$ifdef CLASSESINLINE}inline;{$endif}
- begin
- if OwnsObjects then
- TObject(FList[Index]).Free;
- FList.Delete(Index);
- end;
- procedure TFPObjectList.Exchange(Index1, Index2: Integer);
- begin
- FList.Exchange(Index1, Index2);
- end;
- function TFPObjectList.Expand: TFPObjectList;
- begin
- FList.Expand;
- Result := Self;
- end;
- function TFPObjectList.Extract(Item: TObject): TObject;
- begin
- Result := TObject(FList.Extract(Item));
- end;
- function TFPObjectList.Remove(AObject: TObject): Integer;
- begin
- Result := IndexOf(AObject);
- if (Result <> -1) then
- begin
- if OwnsObjects then
- TObject(FList[Result]).Free;
- FList.Delete(Result);
- end;
- end;
- function TFPObjectList.IndexOf(AObject: TObject): Integer;
- begin
- Result := FList.IndexOf(Pointer(AObject));
- end;
- function TFPObjectList.FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt : Integer): Integer;
- var
- I : Integer;
- begin
- I:=AStartAt;
- Result:=-1;
- If AExact then
- while (I<Count) and (Result=-1) do
- If Items[i].ClassType=AClass then
- Result:=I
- else
- Inc(I)
- else
- while (I<Count) and (Result=-1) do
- If Items[i].InheritsFrom(AClass) then
- Result:=I
- else
- Inc(I);
- end;
- procedure TFPObjectList.Insert(Index: Integer; AObject: TObject); {$ifdef CLASSESINLINE}inline;{$endif}
- begin
- FList.Insert(Index, Pointer(AObject));
- end;
- procedure TFPObjectList.Move(CurIndex, NewIndex: Integer);
- begin
- FList.Move(CurIndex, NewIndex);
- end;
- procedure TFPObjectList.Assign(Obj: TFPObjectList);
- var
- i: Integer;
- begin
- Clear;
- for I := 0 to Obj.Count - 1 do
- Add(Obj[i]);
- end;
- procedure TFPObjectList.Pack;
- begin
- FList.Pack;
- end;
- procedure TFPObjectList.Sort(Compare: TListSortCompare);
- begin
- FList.Sort(Compare);
- end;
- function TFPObjectList.First: TObject;
- begin
- Result := TObject(FList.First);
- end;
- function TFPObjectList.Last: TObject;
- begin
- Result := TObject(FList.Last);
- end;
- procedure TFPObjectList.ForEachCall(proc2call:TObjectListCallback;arg:pointer);
- begin
- FList.ForEachCall(TListCallBack(proc2call),arg);
- end;
- procedure TFPObjectList.ForEachCall(proc2call:TObjectListStaticCallback;arg:pointer);
- begin
- FList.ForEachCall(TListStaticCallBack(proc2call),arg);
- end;
- { TObjectList }
- constructor tobjectlist.create(freeobjects : boolean);
- begin
- inherited create;
- ffreeobjects:=freeobjects;
- end;
- Constructor tobjectlist.create;
- begin
- inherited create;
- ffreeobjects:=True;
- end;
- Procedure TObjectList.Notify(Ptr: Pointer; Action: TListNotification);
- begin
- if FFreeObjects then
- if (Action=lnDeleted) then
- TObject(Ptr).Free;
- inherited Notify(Ptr,Action);
- end;
- Function TObjectList.GetItem(Index: Integer): TObject;
- begin
- Result:=TObject(Inherited Get(Index));
- end;
- Procedure TObjectList.SetItem(Index: Integer; AObject: TObject);
- Var
- O : TObject;
- begin
- if OwnsObjects then
- begin
- O:=GetItem(Index);
- O.Free;
- end;
- Put(Index,Pointer(AObject));
- end;
- Function TObjectList.Add(AObject: TObject): Integer;
- begin
- Result:=Inherited Add(Pointer(AObject));
- end;
- Function TObjectList.Extract(Item: TObject): TObject;
- begin
- Result:=Tobject(Inherited Extract(Pointer(Item)));
- end;
- Function TObjectList.Remove(AObject: TObject): Integer;
- begin
- Result:=Inherited Remove(Pointer(AObject));
- end;
- Function TObjectList.IndexOf(AObject: TObject): Integer;
- begin
- Result:=Inherited indexOF(Pointer(AObject));
- end;
- Function TObjectList.FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt : Integer): Integer;
- Var
- I : Integer;
- begin
- I:=AStartAt;
- Result:=-1;
- If AExact then
- While (I<Count) and (Result=-1) do
- If Items[i].ClassType=AClass then
- Result:=I
- else
- Inc(I)
- else
- While (I<Count) and (Result=-1) do
- If Items[i].InheritsFrom(AClass) then
- Result:=I
- else
- Inc(I);
- end;
- procedure TObjectList.Insert(Index: Integer; AObject: TObject);
- begin
- Inherited Insert(Index,Pointer(AObject));
- end;
- function TObjectList.First: TObject;
- begin
- Result := TObject(Inherited First);
- end;
- function TObjectList.Last: TObject;
- begin
- Result := TObject(Inherited Last);
- end;
- { TListComponent }
- Type
- TlistComponent = Class(TComponent)
- Private
- Flist : TComponentList;
- Public
- procedure Notification(AComponent: TComponent; Operation: TOperation); override;
- end;
- procedure TlistComponent.Notification(AComponent: TComponent;
- Operation: TOperation);
- begin
- If (Operation=opremove) then
- Flist.HandleFreeNotify(Self,AComponent);
- inherited;
- end;
- { TComponentList }
- Function TComponentList.Add(AComponent: TComponent): Integer;
- begin
- Result:=Inherited Add(AComponent);
- end;
- destructor TComponentList.Destroy;
- begin
- inherited;
- FreeAndNil(FNotifier);
- end;
- Function TComponentList.Extract(Item: TComponent): TComponent;
- begin
- Result:=TComponent(Inherited Extract(Item));
- end;
- Function TComponentList.First: TComponent;
- begin
- Result:=TComponent(Inherited First);
- end;
- Function TComponentList.GetItems(Index: Integer): TComponent;
- begin
- Result:=TComponent(Inherited Items[Index]);
- end;
- Procedure TComponentList.HandleFreeNotify(Sender: TObject;
- AComponent: TComponent);
- begin
- Extract(Acomponent);
- end;
- Function TComponentList.IndexOf(AComponent: TComponent): Integer;
- begin
- Result:=Inherited IndexOf(AComponent);
- end;
- Procedure TComponentList.Insert(Index: Integer; AComponent: TComponent);
- begin
- Inherited Insert(Index,Acomponent)
- end;
- Function TComponentList.Last: TComponent;
- begin
- Result:=TComponent(Inherited Last);
- end;
- Procedure TComponentList.Notify(Ptr: Pointer; Action: TListNotification);
- begin
- If FNotifier=NIl then
- begin
- FNotifier:=TlistComponent.Create(nil);
- TlistComponent(FNotifier).FList:=Self;
- end;
- If Assigned(Ptr) then
- With TComponent(Ptr) do
- case Action of
- lnAdded : FreeNotification(FNotifier);
- lnExtracted, lnDeleted: RemoveFreeNotification(FNotifier);
- end;
- inherited Notify(Ptr, Action);
- end;
- Function TComponentList.Remove(AComponent: TComponent): Integer;
- begin
- Result:=Inherited Remove(AComponent);
- end;
- Procedure TComponentList.SetItems(Index: Integer; AComponent: TComponent);
- begin
- Put(Index,AComponent);
- end;
- { TClassList }
- Function TClassList.Add(AClass: TClass): Integer;
- begin
- Result:=Inherited Add(Pointer(AClass));
- end;
- Function TClassList.Extract(Item: TClass): TClass;
- begin
- Result:=TClass(Inherited Extract(Pointer(Item)));
- end;
- Function TClassList.First: TClass;
- begin
- Result:=TClass(Inherited First);
- end;
- Function TClassList.GetItems(Index: Integer): TClass;
- begin
- Result:=TClass(Inherited Items[Index]);
- end;
- Function TClassList.IndexOf(AClass: TClass): Integer;
- begin
- Result:=Inherited IndexOf(Pointer(AClass));
- end;
- Procedure TClassList.Insert(Index: Integer; AClass: TClass);
- begin
- Inherited Insert(index,Pointer(AClass));
- end;
- Function TClassList.Last: TClass;
- begin
- Result:=TClass(Inherited Last);
- end;
- Function TClassList.Remove(AClass: TClass): Integer;
- begin
- Result:=Inherited Remove(Pointer(AClass));
- end;
- Procedure TClassList.SetItems(Index: Integer; AClass: TClass);
- begin
- Put(Index,Pointer(Aclass));
- end;
- { TOrderedList }
- Function TOrderedList.AtLeast(ACount: Integer): Boolean;
- begin
- Result:=(FList.Count>=Acount)
- end;
- Function TOrderedList.Count: Integer;
- begin
- Result:=FList.Count;
- end;
- constructor TOrderedList.Create;
- begin
- FList:=Tlist.Create;
- end;
- destructor TOrderedList.Destroy;
- begin
- FList.Free;
- end;
- Function TOrderedList.Peek: Pointer;
- begin
- If AtLeast(1) then
- Result:=PeekItem
- else
- Result:=Nil;
- end;
- Function TOrderedList.PeekItem: Pointer;
- begin
- With Flist do
- Result:=Items[Count-1]
- end;
- Function TOrderedList.Pop: Pointer;
- begin
- If Atleast(1) then
- Result:=PopItem
- else
- Result:=Nil;
- end;
- Function TOrderedList.PopItem: Pointer;
- begin
- With FList do
- If Count>0 then
- begin
- Result:=Items[Count-1];
- Delete(Count-1);
- end
- else
- Result:=Nil;
- end;
- Function TOrderedList.Push(AItem: Pointer): Pointer;
- begin
- PushItem(Aitem);
- Result:=AItem;
- end;
- { TStack }
- Procedure TStack.PushItem(AItem: Pointer);
- begin
- FList.Add(Aitem);
- end;
- { TObjectStack }
- Function TObjectStack.Peek: TObject;
- begin
- Result:=TObject(Inherited Peek);
- end;
- Function TObjectStack.Pop: TObject;
- begin
- Result:=TObject(Inherited Pop);
- end;
- Function TObjectStack.Push(AObject: TObject): TObject;
- begin
- Result:=TObject(Inherited Push(Pointer(AObject)));
- end;
- { TQueue }
- Procedure TQueue.PushItem(AItem: Pointer);
- begin
- With Flist Do
- Insert(0,AItem);
- end;
- { TObjectQueue }
- Function TObjectQueue.Peek: TObject;
- begin
- Result:=TObject(Inherited Peek);
- end;
- Function TObjectQueue.Pop: TObject;
- begin
- Result:=TObject(Inherited Pop);
- end;
- Function TObjectQueue.Push(AObject: TObject): TObject;
- begin
- Result:=TObject(Inherited Push(Pointer(Aobject)));
- end;
- {*****************************************************************************
- TFPHashList
- *****************************************************************************}
- function FPHash1(const s:string):LongWord;
- Var
- g : LongWord;
- p,pmax : pchar;
- begin
- result:=0;
- p:=@s[1];
- pmax:=@s[length(s)+1];
- while (p<pmax) do
- begin
- result:=result shl 4 + LongWord(p^);
- g:=result and LongWord($F0000000);
- if g<>0 then
- result:=result xor (g shr 24) xor g;
- inc(p);
- end;
- If result=0 then
- result:=$ffffffff;
- end;
- function FPHash(const s:string):LongWord;
- Var
- p,pmax : pchar;
- begin
- {$ifopt Q+}
- {$define overflowon}
- {$Q-}
- {$endif}
- result:=0;
- p:=@s[1];
- pmax:=@s[length(s)+1];
- while (p<pmax) do
- begin
- result:=LongWord((result shl 5) - result) xor LongWord(P^);
- inc(p);
- end;
- {$ifdef overflowon}
- {$Q+}
- {$undef overflowon}
- {$endif}
- end;
- procedure TFPHashList.RaiseIndexError(Index : Integer);
- begin
- Error(SListIndexError, Index);
- end;
- function TFPHashList.Get(Index: Integer): Pointer;
- begin
- If (Index < 0) or (Index >= FCount) then
- RaiseIndexError(Index);
- Result:=FHashList^[Index].Data;
- end;
- function TFPHashList.NameOfIndex(Index: Integer): String;
- begin
- If (Index < 0) or (Index >= FCount) then
- RaiseIndexError(Index);
- with FHashList^[Index] do
- begin
- if StrIndex>=0 then
- Result:=PShortString(@FStrs[StrIndex])^
- else
- Result:='';
- end;
- end;
- function TFPHashList.Extract(item: Pointer): Pointer;
- var
- i : Integer;
- begin
- result := nil;
- i := IndexOf(item);
- if i >= 0 then
- begin
- Result := item;
- Delete(i);
- end;
- end;
- procedure TFPHashList.SetCapacity(NewCapacity: Integer);
- begin
- If (NewCapacity < FCount) or (NewCapacity > MaxHashListSize) then
- Error (SListCapacityError, NewCapacity);
- if NewCapacity = FCapacity then
- exit;
- ReallocMem(FHashList, NewCapacity*SizeOf(THashItem));
- FCapacity := NewCapacity;
- end;
- procedure TFPHashList.SetCount(NewCount: Integer);
- begin
- if (NewCount < 0) or (NewCount > MaxHashListSize)then
- Error(SListCountError, NewCount);
- If NewCount > FCount then
- begin
- If NewCount > FCapacity then
- SetCapacity(NewCount);
- If FCount < NewCount then
- FillChar(FHashList^[FCount], (NewCount-FCount) div Sizeof(THashItem), 0);
- end;
- FCount := Newcount;
- end;
- procedure TFPHashList.SetStrCapacity(NewCapacity: Integer);
- begin
- If (NewCapacity < FStrCount) or (NewCapacity > MaxHashStrSize) then
- Error (SListCapacityError, NewCapacity);
- if NewCapacity = FStrCapacity then
- exit;
- ReallocMem(FStrs, NewCapacity);
- FStrCapacity := NewCapacity;
- end;
- procedure TFPHashList.SetHashCapacity(NewCapacity: Integer);
- begin
- If (NewCapacity < 1) then
- Error (SListCapacityError, NewCapacity);
- if FHashCapacity=NewCapacity then
- exit;
- FHashCapacity:=NewCapacity;
- ReallocMem(FHashTable, FHashCapacity*sizeof(Integer));
- ReHash;
- end;
- procedure TFPHashList.ReHash;
- var
- i : Integer;
- begin
- FillDword(FHashTable^,FHashCapacity,LongWord(-1));
- For i:=0 To FCount-1 Do
- AddToHashTable(i);
- end;
- constructor TFPHashList.Create;
- begin
- SetHashCapacity(1);
- end;
- destructor TFPHashList.Destroy;
- begin
- Clear;
- if assigned(FHashTable) then
- FreeMem(FHashTable);
- inherited Destroy;
- end;
- function TFPHashList.AddStr(const s:shortstring): Integer;
- var
- Len : Integer;
- begin
- len:=length(s)+1;
- if FStrCount+Len >= FStrCapacity then
- StrExpand(Len);
- System.Move(s[0],FStrs[FStrCount],Len);
- result:=FStrCount;
- inc(FStrCount,Len);
- end;
- procedure TFPHashList.AddToHashTable(Index: Integer);
- var
- HashIndex : Integer;
- begin
- with FHashList^[Index] do
- begin
- if not assigned(Data) then
- exit;
- HashIndex:=HashValue mod LongWord(FHashCapacity);
- NextIndex:=FHashTable^[HashIndex];
- FHashTable^[HashIndex]:=Index;
- end;
- end;
- function TFPHashList.Add(const AName:shortstring;Item: Pointer): Integer;
- begin
- if FCount = FCapacity then
- Expand;
- with FHashList^[FCount] do
- begin
- HashValue:=FPHash(AName);
- Data:=Item;
- StrIndex:=AddStr(AName);
- end;
- AddToHashTable(FCount);
- Result := FCount;
- inc(FCount);
- end;
- procedure TFPHashList.Clear;
- begin
- if Assigned(FHashList) then
- begin
- FCount:=0;
- SetCapacity(0);
- FHashList := nil;
- end;
- SetHashCapacity(1);
- if Assigned(FStrs) then
- begin
- FStrCount:=0;
- SetStrCapacity(0);
- FStrs := nil;
- end;
- end;
- procedure TFPHashList.Delete(Index: Integer);
- begin
- If (Index<0) or (Index>=FCount) then
- Error (SListIndexError, Index);
- with FHashList^[Index] do
- begin
- Data:=nil;
- StrIndex:=-1;
- end;
- end;
- class procedure TFPHashList.Error(const Msg: string; Data: PtrInt);
- begin
- Raise EListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame);
- end;
- function TFPHashList.Expand: TFPHashList;
- var
- IncSize : Longint;
- begin
- Result := Self;
- if FCount < FCapacity then
- exit;
- IncSize := 4;
- if FCapacity > 127 then
- Inc(IncSize, FCapacity shr 2)
- else if FCapacity > 8 then
- inc(IncSize,8)
- else if FCapacity > 3 then
- inc(IncSize,4);
- SetCapacity(FCapacity + IncSize);
- { Maybe expand hash also }
- if FCount>FHashCapacity*MaxItemsPerHash then
- SetHashCapacity(FCount div MaxItemsPerHash);
- end;
- procedure TFPHashList.StrExpand(MinIncSize:Integer);
- var
- IncSize : Longint;
- begin
- if FStrCount+MinIncSize < FStrCapacity then
- exit;
- IncSize := 64+MinIncSize;
- if FStrCapacity > 255 then
- Inc(IncSize, FStrCapacity shr 2);
- SetStrCapacity(FStrCapacity + IncSize);
- end;
- function TFPHashList.IndexOf(Item: Pointer): Integer;
- begin
- Result := 0;
- while(Result < FCount) and (FHashList^[Result].Data <> Item) do
- inc(Result);
- If Result = FCount then
- Result := -1;
- end;
- function TFPHashList.Find(const s:shortstring): Pointer;
- var
- CurrHash : LongWord;
- Index,
- HashIndex : Integer;
- Len,
- LastChar : Char;
- begin
- CurrHash:=FPHash(s);
- HashIndex:=CurrHash mod LongWord(FHashCapacity);
- Index:=FHashTable^[HashIndex];
- Len:=Char(Length(s));
- LastChar:=s[Byte(Len)];
- while Index<>-1 do
- begin
- with FHashList^[Index] do
- begin
- if assigned(Data) and
- (HashValue=CurrHash) and
- (Len=FStrs[StrIndex]) and
- (LastChar=FStrs[StrIndex+Byte(Len)]) and
- (s=PShortString(@FStrs[StrIndex])^) then
- begin
- Result:=Data;
- exit;
- end;
- Index:=NextIndex;
- end;
- end;
- Result:=nil;
- end;
- function TFPHashList.Remove(Item: Pointer): Integer;
- begin
- Result := IndexOf(Item);
- If Result <> -1 then
- Self.Delete(Result);
- end;
- procedure TFPHashList.Pack;
- var
- NewCount,
- i : integer;
- pdest,
- psrc : PHashItem;
- begin
- NewCount:=0;
- psrc:=FHashList[0];
- pdest:=psrc;
- For I:=0 To FCount-1 Do
- begin
- if assigned(psrc^.Data) then
- begin
- pdest^:=psrc^;
- inc(pdest);
- inc(NewCount);
- end;
- inc(psrc);
- end;
- FCount:=NewCount;
- { We need to ReHash to update the IndexNext }
- ReHash;
- { Release over-capacity }
- SetCapacity(FCount);
- SetStrCapacity(FStrCount);
- end;
- procedure TFPHashList.ShowStatistics;
- var
- HashMean,
- HashStdDev : Double;
- Index,
- i,j : Integer;
- begin
- { Calculate Mean and StdDev }
- HashMean:=0;
- HashStdDev:=0;
- for i:=0 to FHashCapacity-1 do
- begin
- j:=0;
- Index:=FHashTable^[i];
- while (Index<>-1) do
- begin
- inc(j);
- Index:=FHashList^[Index].NextIndex;
- end;
- HashMean:=HashMean+j;
- HashStdDev:=HashStdDev+Sqr(j);
- end;
- HashMean:=HashMean/FHashCapacity;
- HashStdDev:=(HashStdDev-FHashCapacity*Sqr(HashMean));
- If FHashCapacity>1 then
- HashStdDev:=Sqrt(HashStdDev/(FHashCapacity-1))
- else
- HashStdDev:=0;
- { Print info to stdout }
- Writeln('HashSize : ',FHashCapacity);
- Writeln('HashMean : ',HashMean:1:4);
- Writeln('HashStdDev : ',HashStdDev:1:4);
- Writeln('ListSize : ',FCount,'/',FCapacity);
- Writeln('StringSize : ',FStrCount,'/',FStrCapacity);
- end;
- procedure TFPHashList.ForEachCall(proc2call:TListCallback;arg:pointer);
- var
- i : integer;
- p : pointer;
- begin
- For I:=0 To Count-1 Do
- begin
- p:=FHashList^[i].Data;
- if assigned(p) then
- proc2call(p,arg);
- end;
- end;
- procedure TFPHashList.ForEachCall(proc2call:TListStaticCallback;arg:pointer);
- var
- i : integer;
- p : pointer;
- begin
- For I:=0 To Count-1 Do
- begin
- p:=FHashList^[i].Data;
- if assigned(p) then
- proc2call(p,arg);
- end;
- end;
- {*****************************************************************************
- TFPHashObject
- *****************************************************************************}
- constructor TFPHashObject.Create(HashObjectList:TFPHashObjectList;const s:shortstring);
- var
- Index : Integer;
- begin
- FOwner:=HashObjectList;
- Index:=HashObjectList.Add(s,Self);
- FStrIndex:=HashObjectList.List.List^[Index].StrIndex;
- FCachedStr:=PShortString(@FOwner.List.Strs[FStrIndex]);
- end;
- function TFPHashObject.GetName:shortstring;
- begin
- FCachedStr:=PShortString(@FOwner.List.Strs[FStrIndex]);
- Result:=FCachedStr^;
- end;
- {*****************************************************************************
- TFPHashObjectList (Copied from rtl/objpas/classes/lists.inc)
- *****************************************************************************}
- constructor TFPHashObjectList.Create(FreeObjects : boolean = True);
- begin
- inherited Create;
- FHashList := TFPHashList.Create;
- FFreeObjects := Freeobjects;
- end;
- destructor TFPHashObjectList.Destroy;
- begin
- if (FHashList <> nil) then
- begin
- Clear;
- FHashList.Destroy;
- end;
- inherited Destroy;
- end;
- procedure TFPHashObjectList.Clear;
- var
- i: integer;
- begin
- if FFreeObjects then
- for i := 0 to FHashList.Count - 1 do
- TObject(FHashList[i]).Free;
- FHashList.Clear;
- end;
- function TFPHashObjectList.GetCount: integer;
- begin
- Result := FHashList.Count;
- end;
- procedure TFPHashObjectList.SetCount(const AValue: integer);
- begin
- if FHashList.Count <> AValue then
- FHashList.Count := AValue;
- end;
- function TFPHashObjectList.GetItem(Index: Integer): TObject;
- begin
- Result := TObject(FHashList[Index]);
- end;
- procedure TFPHashObjectList.SetCapacity(NewCapacity: Integer);
- begin
- FHashList.Capacity := NewCapacity;
- end;
- function TFPHashObjectList.GetCapacity: integer;
- begin
- Result := FHashList.Capacity;
- end;
- function TFPHashObjectList.Add(const AName:shortstring;AObject: TObject): Integer;
- begin
- Result := FHashList.Add(AName,AObject);
- end;
- function TFPHashObjectList.NameOfIndex(Index: Integer): shortString;
- begin
- Result := FHashList.NameOfIndex(Index);
- end;
- procedure TFPHashObjectList.Delete(Index: Integer);
- begin
- if OwnsObjects then
- TObject(FHashList[Index]).Free;
- FHashList.Delete(Index);
- end;
- function TFPHashObjectList.Expand: TFPHashObjectList;
- begin
- FHashList.Expand;
- Result := Self;
- end;
- function TFPHashObjectList.Extract(Item: TObject): TObject;
- begin
- Result := TObject(FHashList.Extract(Item));
- end;
- function TFPHashObjectList.Remove(AObject: TObject): Integer;
- begin
- Result := IndexOf(AObject);
- if (Result <> -1) then
- begin
- if OwnsObjects then
- TObject(FHashList[Result]).Free;
- FHashList.Delete(Result);
- end;
- end;
- function TFPHashObjectList.IndexOf(AObject: TObject): Integer;
- begin
- Result := FHashList.IndexOf(Pointer(AObject));
- end;
- function TFPHashObjectList.Find(const s:shortstring): TObject;
- begin
- result:=TObject(FHashList.Find(s));
- end;
- function TFPHashObjectList.FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt : Integer): Integer;
- var
- I : Integer;
- begin
- I:=AStartAt;
- Result:=-1;
- If AExact then
- while (I<Count) and (Result=-1) do
- If Items[i].ClassType=AClass then
- Result:=I
- else
- Inc(I)
- else
- while (I<Count) and (Result=-1) do
- If Items[i].InheritsFrom(AClass) then
- Result:=I
- else
- Inc(I);
- end;
- procedure TFPHashObjectList.Pack;
- begin
- FHashList.Pack;
- end;
- procedure TFPHashObjectList.ShowStatistics;
- begin
- FHashList.ShowStatistics;
- end;
- procedure TFPHashObjectList.ForEachCall(proc2call:TObjectListCallback;arg:pointer);
- begin
- FHashList.ForEachCall(TListCallBack(proc2call),arg);
- end;
- procedure TFPHashObjectList.ForEachCall(proc2call:TObjectListStaticCallback;arg:pointer);
- begin
- FHashList.ForEachCall(TListStaticCallBack(proc2call),arg);
- end;
- { ---------------------------------------------------------------------
- Hash support, by Dean Zobec
- ---------------------------------------------------------------------}
- { Default hash function }
- function RSHash(const S: string; const TableSize: Longword): Longword;
- const
- b = 378551;
- var
- a: Longword;
- i: Longword;
- begin
- a := 63689;
- Result := 0;
- if length(s)>0 then
- for i := 1 to Length(S) do
- begin
- Result := Result * a + Ord(S[i]);
- a := a * b;
- end;
- Result := (Result and $7FFFFFFF) mod TableSize;
- end;
- { THTNode }
- constructor THTCustomNode.CreateWith(const AString: string);
- begin
- inherited Create;
- FKey := AString;
- end;
- function THTCustomNode.HasKey(const AKey: string): boolean;
- begin
- if Length(AKey) <> Length(FKey) then
- begin
- Result := false;
- exit;
- end
- else
- Result := CompareMem(PChar(FKey), PChar(AKey), length(AKey));
- end;
- { TFPCustomHashTable }
- constructor TFPCustomHashTable.Create;
- begin
- CreateWith(196613,@RSHash);
- end;
- constructor TFPCustomHashTable.CreateWith(AHashTableSize: Longword;
- aHashFunc: THashFunction);
- begin
- Inherited Create;
- FHashTable := TFPObjectList.Create(True);
- HashTableSize := AHashTableSize;
- FHashFunction := aHashFunc;
- end;
- destructor TFPCustomHashTable.Destroy;
- begin
- FHashTable.Free;
- inherited Destroy;
- end;
- function TFPCustomHashTable.GetDensity: Longword;
- begin
- Result := FHashTableSize - VoidSlots
- end;
- function TFPCustomHashTable.GetNumberOfCollisions: Longword;
- begin
- Result := FCount -(FHashTableSize - VoidSlots)
- end;
- procedure TFPCustomHashTable.SetHashTableSize(const Value: Longword);
- var
- i: Longword;
- newSize: Longword;
- begin
- if Value <> FHashTableSize then
- begin
- i := 0;
- while (PRIMELIST[i] < Value) and (i < 27) do
- inc(i);
- newSize := PRIMELIST[i];
- if Count = 0 then
- begin
- FHashTableSize := newSize;
- InitializeHashTable;
- end
- else
- ChangeTableSize(newSize);
- end;
- end;
- procedure TFPCustomHashTable.InitializeHashTable;
- var
- i: LongWord;
- begin
- if FHashTableSize>0 Then
- for i := 0 to FHashTableSize-1 do
- FHashTable.Add(nil);
- FCount := 0;
- end;
- procedure TFPCustomHashTable.ChangeTableSize(const ANewSize: Longword);
- var
- SavedTable: TFPObjectList;
- SavedTableSize: Longword;
- i, j: Longword;
- temp: THTCustomNode;
- begin
- SavedTable := FHashTable;
- SavedTableSize := FHashTableSize;
- FHashTableSize := ANewSize;
- FHashTable := TFPObjectList.Create(True);
- InitializeHashTable;
- If SavedTableSize>0 Then
- for i := 0 to SavedTableSize-1 do
- begin
- if Assigned(SavedTable[i]) then
- for j := 0 to TFPObjectList(SavedTable[i]).Count -1 do
- begin
- temp := THTCustomNode(TFPObjectList(SavedTable[i])[j]);
- AddNode(temp);
- end;
- end;
- SavedTable.Free;
- end;
- procedure TFPCustomHashTable.SetHashFunction(AHashFunction: THashFunction);
- begin
- if IsEmpty then
- FHashFunction := AHashFunction
- else
- raise Exception.Create(NotEmptyMsg);
- end;
- function TFPCustomHashTable.Find(const aKey: string): THTCustomNode;
- var
- hashCode: Longword;
- chn: TFPObjectList;
- i: Longword;
- begin
- hashCode := FHashFunction(aKey, FHashTableSize);
- chn := Chain(hashCode);
- if Assigned(chn) then
- begin
- if chn.count>0 then
- for i := 0 to chn.Count - 1 do
- if THTCustomNode(chn[i]).HasKey(aKey) then
- begin
- result := THTCustomNode(chn[i]);
- exit;
- end;
- end;
- Result := nil;
- end;
- Function TFPCustomHashTable.FindChainForAdd(Const aKey : String) : TFPObjectList;
- var
- hashCode: Longword;
- i: Longword;
- begin
- hashCode := FHashFunction(aKey, FHashTableSize);
- Result := Chain(hashCode);
- if Assigned(Result) then
- begin
- if Result.count>0 then
- for i := 0 to Result.Count - 1 do
- if THTCustomNode(Result[i]).HasKey(aKey) then
- Raise EDuplicate.CreateFmt(DuplicateMsg, [aKey]);
- end
- else
- begin
- FHashTable[hashcode] := TFPObjectList.Create(true);
- Result := Chain(hashcode);
- end;
- inc(FCount);
- end;
- procedure TFPCustomHashTable.Delete(const aKey: string);
- var
- hashCode: Longword;
- chn: TFPObjectList;
- i: Longword;
- begin
- hashCode := FHashFunction(aKey, FHashTableSize);
- chn := Chain(hashCode);
- if Assigned(chn) then
- begin
- if chn.count>0 then
- for i := 0 to chn.Count - 1 do
- if THTCustomNode(chn[i]).HasKey(aKey) then
- begin
- chn.Delete(i);
- dec(FCount);
- exit;
- end;
- end;
- raise EKeyNotFound.CreateFmt(KeyNotFoundMsg, ['Delete', aKey]);
- end;
- function TFPCustomHashTable.IsEmpty: boolean;
- begin
- Result := (FCount = 0);
- end;
- function TFPCustomHashTable.Chain(const index: Longword): TFPObjectList;
- begin
- Result := TFPObjectList(FHashTable[index]);
- end;
- function TFPCustomHashTable.GetVoidSlots: Longword;
- var
- i: Longword;
- num: Longword;
- begin
- num := 0;
- if FHashTableSize>0 Then
- for i:= 0 to FHashTableSize-1 do
- if Not Assigned(Chain(i)) then
- inc(num);
- result := num;
- end;
- function TFPCustomHashTable.GetLoadFactor: double;
- begin
- Result := Count / FHashTableSize;
- end;
- function TFPCustomHashTable.GetAVGChainLen: double;
- begin
- result := Count / (FHashTableSize - VoidSlots);
- end;
- function TFPCustomHashTable.GetMaxChainLength: Longword;
- var
- i: Longword;
- begin
- Result := 0;
- if FHashTableSize>0 Then
- for i := 0 to FHashTableSize-1 do
- if ChainLength(i) > Result then
- Result := ChainLength(i);
- end;
- function TFPCustomHashTable.FindOrCreateNew(const aKey: string): THTCustomNode;
- var
- hashCode: Longword;
- chn: TFPObjectList;
- i: Longword;
- begin
- hashCode := FHashFunction(aKey, FHashTableSize);
- chn := Chain(hashCode);
- if Assigned(chn) then
- begin
- if chn.count>0 then
- for i := 0 to chn.Count - 1 do
- if THTCustomNode(chn[i]).HasKey(aKey) then
- begin
- Result := THTNode(chn[i]);
- exit;
- end
- end
- else
- begin
- FHashTable[hashcode] := TFPObjectList.Create(true);
- chn := Chain(hashcode);
- end;
- inc(FCount);
- Result := CreateNewNode(aKey);
- chn.Add(Result);
- end;
- function TFPCustomHashTable.ChainLength(const ChainIndex: Longword): Longword;
- begin
- if Assigned(Chain(ChainIndex)) then
- Result := Chain(ChainIndex).Count
- else
- Result := 0;
- end;
- procedure TFPCustomHashTable.Clear;
- var
- i: Longword;
- begin
- if FHashTableSize>0 Then
- for i := 0 to FHashTableSize - 1 do
- begin
- if Assigned(Chain(i)) then
- Chain(i).Clear;
- end;
- FCount := 0;
- end;
- { TFPDataHashTable }
- procedure TFPDataHashTable.Add(const aKey: string; aItem: pointer);
- var
- chn: TFPObjectList;
- NewNode: THtDataNode;
- begin
- chn:=FindChainForAdd(akey);
- NewNode := THtDataNode(CreateNewNode(aKey));
- NewNode.Data := aItem;
- chn.Add(NewNode);
- end;
- function TFPDataHashTable.GetData(const Index: string): Pointer;
- var
- node: THTDataNode;
- begin
- node := THTDataNode(Find(Index));
- if Assigned(node) then
- Result := node.Data
- else
- Result := nil;
- end;
- procedure TFPDataHashTable.SetData(const index: string; const AValue: Pointer);
- begin
- THTDataNode(FindOrCreateNew(index)).Data := AValue;
- end;
- Function TFPDataHashTable.CreateNewNode(const aKey : string) : THTCustomNode;
- begin
- Result:=THTDataNode.CreateWith(aKey);
- end;
- function TFPDataHashTable.ForEachCall(aMethod: TDataIteratorMethod): THTDataNode;
- var
- i, j: Longword;
- continue: boolean;
- begin
- Result := nil;
- continue := true;
- if FHashTableSize>0 then
- for i := 0 to FHashTableSize-1 do
- begin
- if assigned(Chain(i)) then
- begin
- if chain(i).count>0 then
- for j := 0 to Chain(i).Count-1 do
- begin
- aMethod(THTDataNode(Chain(i)[j]).Data, THTDataNode(Chain(i)[j]).Key, continue);
- if not continue then
- begin
- Result := THTDataNode(Chain(i)[j]);
- Exit;
- end;
- end;
- end;
- end;
- end;
- Procedure TFPDataHashTable.AddNode(ANode : THTCustomNode);
- begin
- With THTDataNode(ANode) do
- Add(Key,Data);
- end;
- { TFPStringHashTable }
- Procedure TFPStringHashTable.AddNode(ANode : THTCustomNode);
- begin
- With THTStringNode(ANode) do
- Add(Key,Data);
- end;
- function TFPStringHashTable.GetData(const Index: string): String;
- var
- node: THTStringNode;
- begin
- node := THTStringNode(Find(Index));
- if Assigned(node) then
- Result := node.Data
- else
- Result := '';
- end;
- procedure TFPStringHashTable.SetData(const index, AValue: string);
- begin
- THTStringNode(FindOrCreateNew(index)).Data := AValue;
- end;
- procedure TFPStringHashTable.Add(const aKey, aItem: string);
- var
- chn: TFPObjectList;
- NewNode: THtStringNode;
-
- begin
- chn:=FindChainForAdd(akey);
- NewNode := THtStringNode(CreateNewNode(aKey));
- NewNode.Data := aItem;
- chn.Add(NewNode);
- end;
- Function TFPStringHashTable.CreateNewNode(const aKey : string) : THTCustomNode;
- begin
- Result:=THTStringNode.CreateWith(aKey);
- end;
- function TFPStringHashTable.ForEachCall(aMethod: TStringIteratorMethod): THTStringNode;
- var
- i, j: Longword;
- continue: boolean;
- begin
- Result := nil;
- continue := true;
- if FHashTableSize>0 then
- for i := 0 to FHashTableSize-1 do
- begin
- if assigned(Chain(i)) then
- begin
- if chain(i).count>0 then
- for j := 0 to Chain(i).Count-1 do
- begin
- aMethod(THTStringNode(Chain(i)[j]).Data, THTStringNode(Chain(i)[j]).Key, continue);
- if not continue then
- begin
- Result := THTStringNode(Chain(i)[j]);
- Exit;
- end;
- end;
- end;
- end;
- end;
- { TFPObjectHashTable }
- Procedure TFPObjectHashTable.AddNode(ANode : THTCustomNode);
- begin
- With THTObjectNode(ANode) do
- Add(Key,Data);
- end;
- function TFPObjectHashTable.GetData(const Index: string): TObject;
- var
- node: THTObjectNode;
- begin
- node := THTObjectNode(Find(Index));
- if Assigned(node) then
- Result := node.Data
- else
- Result := Nil;
- end;
- procedure TFPObjectHashTable.SetData(const index : string; AObject : TObject);
- begin
- THTObjectNode(FindOrCreateNew(index)).Data := AObject;
- end;
- procedure TFPObjectHashTable.Add(const aKey: string; AItem : TObject);
- var
- chn: TFPObjectList;
- NewNode: THTObjectNode;
-
- begin
- chn:=FindChainForAdd(akey);
- NewNode := THTObjectNode(CreateNewNode(aKey));
- NewNode.Data := aItem;
- chn.Add(NewNode);
- end;
- Function TFPObjectHashTable.CreateNewNode(const aKey : string) : THTCustomNode;
- begin
- If OwnsObjects then
- Result:=THTOwnedObjectNode.CreateWith(aKey)
- else
- Result:=THTObjectNode.CreateWith(aKey);
- end;
- function TFPObjectHashTable.ForEachCall(aMethod: TObjectIteratorMethod): THTObjectNode;
- var
- i, j: Longword;
- continue: boolean;
- begin
- Result := nil;
- continue := true;
- if FHashTableSize>0 then
- for i := 0 to FHashTableSize-1 do
- begin
- if assigned(Chain(i)) then
- begin
- if chain(i).count>0 then
- for j := 0 to Chain(i).Count-1 do
- begin
- aMethod(THTObjectNode(Chain(i)[j]).Data, THTObjectNode(Chain(i)[j]).Key, continue);
- if not continue then
- begin
- Result := THTObjectNode(Chain(i)[j]);
- Exit;
- end;
- end;
- end;
- end;
- end;
- constructor TFPObjectHashTable.Create(AOwnsObjects : Boolean = True);
- begin
- Inherited Create;
- FOwnsObjects:=AOwnsObjects;
- end;
-
- constructor TFPObjectHashTable.CreateWith(AHashTableSize: Longword; aHashFunc: THashFunction; AOwnsObjects : Boolean = True);
- begin
- Inherited CreateWith(AHashTableSize,AHashFunc);
- FOwnsObjects:=AOwnsObjects;
- end;
- Destructor THTOwnedObjectNode.Destroy;
- begin
- FreeAndNil(FData);
- Inherited;
- end;
-
- end.
|