contnrs.pp 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144
  1. {
  2. This file is part of the Free Component Library (FCL)
  3. Copyright (c) 2002 by Florian Klaempfl
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. {$ifdef fpc}
  11. {$mode objfpc}
  12. {$endif}
  13. {$H+}
  14. unit contnrs;
  15. interface
  16. uses
  17. SysUtils,Classes;
  18. Type
  19. {$inline on}
  20. TFPObjectList = class(TObject)
  21. private
  22. FFreeObjects : Boolean;
  23. FList: TFPList;
  24. function GetCount: integer;
  25. procedure SetCount(const AValue: integer);
  26. protected
  27. function GetItem(Index: Integer): TObject; {$ifdef HASINLINE} inline;{$endif}
  28. procedure SetItem(Index: Integer; AObject: TObject); {$ifdef HASINLINE} inline;{$endif}
  29. procedure SetCapacity(NewCapacity: Integer);
  30. function GetCapacity: integer;
  31. public
  32. constructor Create;
  33. constructor Create(FreeObjects : Boolean);
  34. destructor Destroy; override;
  35. procedure Clear;
  36. function Add(AObject: TObject): Integer; {$ifdef HASINLINE} inline;{$endif}
  37. procedure Delete(Index: Integer); {$ifdef HASINLINE} inline;{$endif}
  38. procedure Exchange(Index1, Index2: Integer);
  39. function Expand: TFPObjectList;
  40. function Extract(Item: TObject): TObject;
  41. function Remove(AObject: TObject): Integer;
  42. function IndexOf(AObject: TObject): Integer;
  43. function FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt: Integer): Integer;
  44. procedure Insert(Index: Integer; AObject: TObject); {$ifdef HASINLINE} inline;{$endif}
  45. function First: TObject;
  46. function Last: TObject;
  47. procedure Move(CurIndex, NewIndex: Integer);
  48. procedure Assign(Obj:TFPObjectList);
  49. procedure Pack;
  50. procedure Sort(Compare: TListSortCompare);
  51. property Capacity: Integer read GetCapacity write SetCapacity;
  52. property Count: Integer read GetCount write SetCount;
  53. property OwnsObjects: Boolean read FFreeObjects write FFreeObjects;
  54. property Items[Index: Integer]: TObject read GetItem write SetItem; default;
  55. property List: TFPList read FList;
  56. end;
  57. TObjectList = class(TList)
  58. private
  59. ffreeobjects : boolean;
  60. Protected
  61. Procedure Notify(Ptr: Pointer; Action: TListNotification); override;
  62. function GetItem(Index: Integer): TObject;
  63. Procedure SetItem(Index: Integer; AObject: TObject);
  64. public
  65. constructor create;
  66. constructor create(freeobjects : boolean);
  67. function Add(AObject: TObject): Integer;
  68. function Extract(Item: TObject): TObject;
  69. function Remove(AObject: TObject): Integer;
  70. function IndexOf(AObject: TObject): Integer;
  71. function FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt: Integer): Integer;
  72. Procedure Insert(Index: Integer; AObject: TObject);
  73. function First: TObject;
  74. Function Last: TObject;
  75. property OwnsObjects: Boolean read FFreeObjects write FFreeObjects;
  76. property Items[Index: Integer]: TObject read GetItem write SetItem; default;
  77. end;
  78. TComponentList = class(TObjectList)
  79. Private
  80. FNotifier : TComponent;
  81. Protected
  82. Procedure Notify(Ptr: Pointer; Action: TListNotification); override;
  83. Function GetItems(Index: Integer): TComponent;
  84. Procedure SetItems(Index: Integer; AComponent: TComponent);
  85. Procedure HandleFreeNotify(Sender: TObject; AComponent: TComponent);
  86. public
  87. destructor Destroy; override;
  88. Function Add(AComponent: TComponent): Integer;
  89. Function Extract(Item: TComponent): TComponent;
  90. Function Remove(AComponent: TComponent): Integer;
  91. Function IndexOf(AComponent: TComponent): Integer;
  92. Function First: TComponent;
  93. Function Last: TComponent;
  94. Procedure Insert(Index: Integer; AComponent: TComponent);
  95. property Items[Index: Integer]: TComponent read GetItems write SetItems; default;
  96. end;
  97. TClassList = class(TList)
  98. protected
  99. Function GetItems(Index: Integer): TClass;
  100. Procedure SetItems(Index: Integer; AClass: TClass);
  101. public
  102. Function Add(AClass: TClass): Integer;
  103. Function Extract(Item: TClass): TClass;
  104. Function Remove(AClass: TClass): Integer;
  105. Function IndexOf(AClass: TClass): Integer;
  106. Function First: TClass;
  107. Function Last: TClass;
  108. Procedure Insert(Index: Integer; AClass: TClass);
  109. property Items[Index: Integer]: TClass read GetItems write SetItems; default;
  110. end;
  111. TOrderedList = class(TObject)
  112. private
  113. FList: TList;
  114. protected
  115. Procedure PushItem(AItem: Pointer); virtual; abstract;
  116. Function PopItem: Pointer; virtual;
  117. Function PeekItem: Pointer; virtual;
  118. property List: TList read FList;
  119. public
  120. constructor Create;
  121. destructor Destroy; override;
  122. Function Count: Integer;
  123. Function AtLeast(ACount: Integer): Boolean;
  124. Function Push(AItem: Pointer): Pointer;
  125. Function Pop: Pointer;
  126. Function Peek: Pointer;
  127. end;
  128. { TStack class }
  129. TStack = class(TOrderedList)
  130. protected
  131. Procedure PushItem(AItem: Pointer); override;
  132. end;
  133. { TObjectStack class }
  134. TObjectStack = class(TStack)
  135. public
  136. Function Push(AObject: TObject): TObject;
  137. Function Pop: TObject;
  138. Function Peek: TObject;
  139. end;
  140. { TQueue class }
  141. TQueue = class(TOrderedList)
  142. protected
  143. Procedure PushItem(AItem: Pointer); override;
  144. end;
  145. { TObjectQueue class }
  146. TObjectQueue = class(TQueue)
  147. public
  148. Function Push(AObject: TObject): TObject;
  149. Function Pop: TObject;
  150. Function Peek: TObject;
  151. end;
  152. { ---------------------------------------------------------------------
  153. Hash support, implemented by Dean Zobec
  154. ---------------------------------------------------------------------}
  155. { Must return a Longword value in the range 0..TableSize,
  156. usually via a mod operator; }
  157. THashFunction = function(const S: string; const TableSize: Longword): Longword;
  158. TIteratorMethod = procedure(Item: Pointer; const Key: string;
  159. var Continue: Boolean) of object;
  160. { THTNode }
  161. THTNode = class(TObject)
  162. private
  163. FData: pointer;
  164. FKey: string;
  165. public
  166. constructor CreateWith(const AString: String);
  167. function HasKey(const AKey: string): boolean;
  168. property Key: string read FKey;
  169. property Data: pointer read FData write FData;
  170. end;
  171. { TFPHashTable }
  172. TFPHashTable = class(TObject)
  173. private
  174. FHashTable: TFPObjectList;
  175. FHashTableSize: Longword;
  176. FHashFunction: THashFunction;
  177. FCount: Int64;
  178. function GetDensity: Longword;
  179. function GetNumberOfCollisions: Int64;
  180. procedure SetHashTableSize(const Value: Longword);
  181. procedure InitializeHashTable;
  182. function GetVoidSlots: Longword;
  183. function GetLoadFactor: double;
  184. function GetAVGChainLen: double;
  185. function GetMaxChainLength: Int64;
  186. function Chain(const index: Longword):TFPObjectList;
  187. protected
  188. function ChainLength(const ChainIndex: Longword): Longword; virtual;
  189. procedure SetData(const index: string; const AValue: Pointer); virtual;
  190. function GetData(const index: string):Pointer; virtual;
  191. function FindOrCreateNew(const aKey: string): THTNode; virtual;
  192. function ForEachCall(aMethod: TIteratorMethod): THTNode; virtual;
  193. procedure SetHashFunction(AHashFunction: THashFunction); virtual;
  194. public
  195. constructor Create;
  196. constructor CreateWith(AHashTableSize: Longword; aHashFunc: THashFunction);
  197. destructor Destroy; override;
  198. procedure ChangeTableSize(const ANewSize: Longword); virtual;
  199. procedure Clear; virtual;
  200. procedure Add(const aKey: string; AItem: pointer); virtual;
  201. procedure Delete(const aKey: string); virtual;
  202. function Find(const aKey: string): THTNode;
  203. function IsEmpty: boolean;
  204. property HashFunction: THashFunction read FHashFunction write SetHashFunction;
  205. property Count: Int64 read FCount;
  206. property HashTableSize: Longword read FHashTableSize write SetHashTableSize;
  207. property Items[const index: string]: Pointer read GetData write SetData; default;
  208. property HashTable: TFPObjectList read FHashTable;
  209. property VoidSlots: Longword read GetVoidSlots;
  210. property LoadFactor: double read GetLoadFactor;
  211. property AVGChainLen: double read GetAVGChainLen;
  212. property MaxChainLength: Int64 read GetMaxChainLength;
  213. property NumberOfCollisions: Int64 read GetNumberOfCollisions;
  214. property Density: Longword read GetDensity;
  215. end;
  216. EDuplicate = class(Exception);
  217. EKeyNotFound = class(Exception);
  218. function RSHash(const S: string; const TableSize: Longword): Longword;
  219. implementation
  220. ResourceString
  221. DuplicateMsg = 'An item with key %0:s already exists';
  222. KeyNotFoundMsg = 'Method: %0:s key [''%1:s''] not found in container';
  223. NotEmptyMsg = 'Hash table not empty.';
  224. const
  225. NPRIMES = 28;
  226. PRIMELIST: array[0 .. NPRIMES-1] of Longword =
  227. ( 53, 97, 193, 389, 769,
  228. 1543, 3079, 6151, 12289, 24593,
  229. 49157, 98317, 196613, 393241, 786433,
  230. 1572869, 3145739, 6291469, 12582917, 25165843,
  231. 50331653, 100663319, 201326611, 402653189, 805306457,
  232. 1610612741, 3221225473, 4294967291 );
  233. constructor TFPObjectList.Create(FreeObjects : boolean);
  234. begin
  235. Create;
  236. FFreeObjects := Freeobjects;
  237. end;
  238. destructor TFPObjectList.Destroy;
  239. begin
  240. if (FList <> nil) then
  241. begin
  242. Clear;
  243. FList.Destroy;
  244. end;
  245. inherited Destroy;
  246. end;
  247. procedure TFPObjectList.Clear;
  248. var
  249. i: integer;
  250. begin
  251. if FFreeObjects then
  252. for i := 0 to FList.Count - 1 do
  253. TObject(FList[i]).Free;
  254. FList.Clear;
  255. end;
  256. constructor TFPObjectList.Create;
  257. begin
  258. inherited Create;
  259. FList := TFPList.Create;
  260. FFreeObjects := True;
  261. end;
  262. function TFPObjectList.GetCount: integer;
  263. begin
  264. Result := FList.Count;
  265. end;
  266. procedure TFPObjectList.SetCount(const AValue: integer);
  267. begin
  268. if FList.Count <> AValue then
  269. FList.Count := AValue;
  270. end;
  271. function TFPObjectList.GetItem(Index: Integer): TObject; {$ifdef HASINLINE} inline;{$endif}
  272. begin
  273. Result := TObject(FList[Index]);
  274. end;
  275. procedure TFPObjectList.SetItem(Index: Integer; AObject: TObject); {$ifdef HASINLINE} inline;{$endif}
  276. begin
  277. if OwnsObjects then
  278. TObject(FList[Index]).Free;
  279. FList[index] := AObject;
  280. end;
  281. procedure TFPObjectList.SetCapacity(NewCapacity: Integer);
  282. begin
  283. FList.Capacity := NewCapacity;
  284. end;
  285. function TFPObjectList.GetCapacity: integer;
  286. begin
  287. Result := FList.Capacity;
  288. end;
  289. function TFPObjectList.Add(AObject: TObject): Integer; {$ifdef HASINLINE} inline;{$endif}
  290. begin
  291. Result := FList.Add(AObject);
  292. end;
  293. procedure TFPObjectList.Delete(Index: Integer); {$ifdef HASINLINE} inline;{$endif}
  294. begin
  295. if OwnsObjects then
  296. TObject(FList[Index]).Free;
  297. FList.Delete(Index);
  298. end;
  299. procedure TFPObjectList.Exchange(Index1, Index2: Integer);
  300. begin
  301. FList.Exchange(Index1, Index2);
  302. end;
  303. function TFPObjectList.Expand: TFPObjectList;
  304. begin
  305. FList.Expand;
  306. Result := Self;
  307. end;
  308. function TFPObjectList.Extract(Item: TObject): TObject;
  309. begin
  310. Result := TObject(FList.Extract(Item));
  311. end;
  312. function TFPObjectList.Remove(AObject: TObject): Integer;
  313. begin
  314. Result := IndexOf(AObject);
  315. if (Result <> -1) then
  316. begin
  317. if OwnsObjects then
  318. TObject(FList[Result]).Free;
  319. FList.Delete(Result);
  320. end;
  321. end;
  322. function TFPObjectList.IndexOf(AObject: TObject): Integer;
  323. begin
  324. Result := FList.IndexOf(Pointer(AObject));
  325. end;
  326. function TFPObjectList.FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt : Integer): Integer;
  327. var
  328. I : Integer;
  329. begin
  330. I:=AStartAt;
  331. Result:=-1;
  332. If AExact then
  333. while (I<Count) and (Result=-1) do
  334. If Items[i].ClassType=AClass then
  335. Result:=I
  336. else
  337. Inc(I)
  338. else
  339. while (I<Count) and (Result=-1) do
  340. If Items[i].InheritsFrom(AClass) then
  341. Result:=I
  342. else
  343. Inc(I);
  344. end;
  345. procedure TFPObjectList.Insert(Index: Integer; AObject: TObject); {$ifdef HASINLINE} inline;{$endif}
  346. begin
  347. FList.Insert(Index, Pointer(AObject));
  348. end;
  349. procedure TFPObjectList.Move(CurIndex, NewIndex: Integer);
  350. begin
  351. FList.Move(CurIndex, NewIndex);
  352. end;
  353. procedure TFPObjectList.Assign(Obj: TFPObjectList);
  354. var
  355. i: Integer;
  356. begin
  357. Clear;
  358. for I := 0 to Obj.Count - 1 do
  359. Add(Obj[i]);
  360. end;
  361. procedure TFPObjectList.Pack;
  362. begin
  363. FList.Pack;
  364. end;
  365. procedure TFPObjectList.Sort(Compare: TListSortCompare);
  366. begin
  367. FList.Sort(Compare);
  368. end;
  369. function TFPObjectList.First: TObject;
  370. begin
  371. Result := TObject(FList.First);
  372. end;
  373. function TFPObjectList.Last: TObject;
  374. begin
  375. Result := TObject(FList.Last);
  376. end;
  377. { TObjectList }
  378. constructor tobjectlist.create(freeobjects : boolean);
  379. begin
  380. inherited create;
  381. ffreeobjects:=freeobjects;
  382. end;
  383. Constructor tobjectlist.create;
  384. begin
  385. inherited create;
  386. ffreeobjects:=True;
  387. end;
  388. Procedure TObjectList.Notify(Ptr: Pointer; Action: TListNotification);
  389. begin
  390. if FFreeObjects then
  391. if (Action=lnDeleted) then
  392. TObject(Ptr).Free;
  393. inherited Notify(Ptr,Action);
  394. end;
  395. Function TObjectList.GetItem(Index: Integer): TObject;
  396. begin
  397. Result:=TObject(Inherited Get(Index));
  398. end;
  399. Procedure TObjectList.SetItem(Index: Integer; AObject: TObject);
  400. Var
  401. O : TObject;
  402. begin
  403. if OwnsObjects then
  404. begin
  405. O:=GetItem(Index);
  406. O.Free;
  407. end;
  408. Put(Index,Pointer(AObject));
  409. end;
  410. Function TObjectList.Add(AObject: TObject): Integer;
  411. begin
  412. Result:=Inherited Add(Pointer(AObject));
  413. end;
  414. Function TObjectList.Extract(Item: TObject): TObject;
  415. begin
  416. Result:=Tobject(Inherited Extract(Pointer(Item)));
  417. end;
  418. Function TObjectList.Remove(AObject: TObject): Integer;
  419. begin
  420. Result:=Inherited Remove(Pointer(AObject));
  421. end;
  422. Function TObjectList.IndexOf(AObject: TObject): Integer;
  423. begin
  424. Result:=Inherited indexOF(Pointer(AObject));
  425. end;
  426. Function TObjectList.FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt : Integer): Integer;
  427. Var
  428. I : Integer;
  429. begin
  430. I:=AStartAt;
  431. Result:=-1;
  432. If AExact then
  433. While (I<Count) and (Result=-1) do
  434. If Items[i].ClassType=AClass then
  435. Result:=I
  436. else
  437. Inc(I)
  438. else
  439. While (I<Count) and (Result=-1) do
  440. If Items[i].InheritsFrom(AClass) then
  441. Result:=I
  442. else
  443. Inc(I);
  444. end;
  445. procedure TObjectList.Insert(Index: Integer; AObject: TObject);
  446. begin
  447. Inherited Insert(Index,Pointer(AObject));
  448. end;
  449. function TObjectList.First: TObject;
  450. begin
  451. Result := TObject(Inherited First);
  452. end;
  453. function TObjectList.Last: TObject;
  454. begin
  455. Result := TObject(Inherited Last);
  456. end;
  457. { TListComponent }
  458. Type
  459. TlistComponent = Class(TComponent)
  460. Private
  461. Flist : TComponentList;
  462. Public
  463. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  464. end;
  465. procedure TlistComponent.Notification(AComponent: TComponent;
  466. Operation: TOperation);
  467. begin
  468. If (Operation=opremove) then
  469. Flist.HandleFreeNotify(Self,AComponent);
  470. inherited;
  471. end;
  472. { TComponentList }
  473. Function TComponentList.Add(AComponent: TComponent): Integer;
  474. begin
  475. Result:=Inherited Add(AComponent);
  476. end;
  477. destructor TComponentList.Destroy;
  478. begin
  479. FNotifier.Free;
  480. inherited;
  481. end;
  482. Function TComponentList.Extract(Item: TComponent): TComponent;
  483. begin
  484. Result:=TComponent(Inherited Extract(Item));
  485. end;
  486. Function TComponentList.First: TComponent;
  487. begin
  488. Result:=TComponent(Inherited First);
  489. end;
  490. Function TComponentList.GetItems(Index: Integer): TComponent;
  491. begin
  492. Result:=TComponent(Inherited Items[Index]);
  493. end;
  494. Procedure TComponentList.HandleFreeNotify(Sender: TObject;
  495. AComponent: TComponent);
  496. begin
  497. Extract(Acomponent);
  498. end;
  499. Function TComponentList.IndexOf(AComponent: TComponent): Integer;
  500. begin
  501. Result:=Inherited IndexOf(AComponent);
  502. end;
  503. Procedure TComponentList.Insert(Index: Integer; AComponent: TComponent);
  504. begin
  505. Inherited Insert(Index,Acomponent)
  506. end;
  507. Function TComponentList.Last: TComponent;
  508. begin
  509. Result:=TComponent(Inherited Last);
  510. end;
  511. Procedure TComponentList.Notify(Ptr: Pointer; Action: TListNotification);
  512. begin
  513. If FNotifier=NIl then
  514. begin
  515. FNotifier:=TlistComponent.Create(nil);
  516. TlistComponent(FNotifier).FList:=Self;
  517. end;
  518. If Assigned(Ptr) then
  519. With TComponent(Ptr) do
  520. case Action of
  521. lnAdded : FreeNotification(FNotifier);
  522. lnExtracted, lnDeleted: RemoveFreeNotification(FNotifier);
  523. end;
  524. inherited Notify(Ptr, Action);
  525. end;
  526. Function TComponentList.Remove(AComponent: TComponent): Integer;
  527. begin
  528. Result:=Inherited Remove(AComponent);
  529. end;
  530. Procedure TComponentList.SetItems(Index: Integer; AComponent: TComponent);
  531. begin
  532. Put(Index,AComponent);
  533. end;
  534. { TClassList }
  535. Function TClassList.Add(AClass: TClass): Integer;
  536. begin
  537. Result:=Inherited Add(Pointer(AClass));
  538. end;
  539. Function TClassList.Extract(Item: TClass): TClass;
  540. begin
  541. Result:=TClass(Inherited Extract(Pointer(Item)));
  542. end;
  543. Function TClassList.First: TClass;
  544. begin
  545. Result:=TClass(Inherited First);
  546. end;
  547. Function TClassList.GetItems(Index: Integer): TClass;
  548. begin
  549. Result:=TClass(Inherited Items[Index]);
  550. end;
  551. Function TClassList.IndexOf(AClass: TClass): Integer;
  552. begin
  553. Result:=Inherited IndexOf(Pointer(AClass));
  554. end;
  555. Procedure TClassList.Insert(Index: Integer; AClass: TClass);
  556. begin
  557. Inherited Insert(index,Pointer(AClass));
  558. end;
  559. Function TClassList.Last: TClass;
  560. begin
  561. Result:=TClass(Inherited Last);
  562. end;
  563. Function TClassList.Remove(AClass: TClass): Integer;
  564. begin
  565. Result:=Inherited Remove(Pointer(AClass));
  566. end;
  567. Procedure TClassList.SetItems(Index: Integer; AClass: TClass);
  568. begin
  569. Put(Index,Pointer(Aclass));
  570. end;
  571. { TOrderedList }
  572. Function TOrderedList.AtLeast(ACount: Integer): Boolean;
  573. begin
  574. Result:=(FList.Count>=Acount)
  575. end;
  576. Function TOrderedList.Count: Integer;
  577. begin
  578. Result:=FList.Count;
  579. end;
  580. constructor TOrderedList.Create;
  581. begin
  582. FList:=Tlist.Create;
  583. end;
  584. destructor TOrderedList.Destroy;
  585. begin
  586. FList.Free;
  587. end;
  588. Function TOrderedList.Peek: Pointer;
  589. begin
  590. If AtLeast(1) then
  591. Result:=PeekItem
  592. else
  593. Result:=Nil;
  594. end;
  595. Function TOrderedList.PeekItem: Pointer;
  596. begin
  597. With Flist do
  598. Result:=Items[Count-1]
  599. end;
  600. Function TOrderedList.Pop: Pointer;
  601. begin
  602. If Atleast(1) then
  603. Result:=PopItem
  604. else
  605. Result:=Nil;
  606. end;
  607. Function TOrderedList.PopItem: Pointer;
  608. begin
  609. With FList do
  610. If Count>0 then
  611. begin
  612. Result:=Items[Count-1];
  613. Delete(Count-1);
  614. end
  615. else
  616. Result:=Nil;
  617. end;
  618. Function TOrderedList.Push(AItem: Pointer): Pointer;
  619. begin
  620. PushItem(Aitem);
  621. Result:=AItem;
  622. end;
  623. { TStack }
  624. Procedure TStack.PushItem(AItem: Pointer);
  625. begin
  626. FList.Add(Aitem);
  627. end;
  628. { TObjectStack }
  629. Function TObjectStack.Peek: TObject;
  630. begin
  631. Result:=TObject(Inherited Peek);
  632. end;
  633. Function TObjectStack.Pop: TObject;
  634. begin
  635. Result:=TObject(Inherited Pop);
  636. end;
  637. Function TObjectStack.Push(AObject: TObject): TObject;
  638. begin
  639. Result:=TObject(Inherited Push(Pointer(AObject)));
  640. end;
  641. { TQueue }
  642. Procedure TQueue.PushItem(AItem: Pointer);
  643. begin
  644. With Flist Do
  645. Insert(0,AItem);
  646. end;
  647. { TObjectQueue }
  648. Function TObjectQueue.Peek: TObject;
  649. begin
  650. Result:=TObject(Inherited Peek);
  651. end;
  652. Function TObjectQueue.Pop: TObject;
  653. begin
  654. Result:=TObject(Inherited Pop);
  655. end;
  656. Function TObjectQueue.Push(AObject: TObject): TObject;
  657. begin
  658. Result:=TObject(Inherited Push(Pointer(Aobject)));
  659. end;
  660. { ---------------------------------------------------------------------
  661. Hash support, by Dean Zobec
  662. ---------------------------------------------------------------------}
  663. { Default hash function }
  664. function RSHash(const S: string; const TableSize: Longword): Longword;
  665. const
  666. b = 378551;
  667. var
  668. a: Longword;
  669. i: Longword;
  670. begin
  671. a := 63689;
  672. Result := 0;
  673. for i := 1 to Length(S) do
  674. begin
  675. Result := Result * a + Ord(S[i]);
  676. a := a * b;
  677. end;
  678. Result := (Result and $7FFFFFFF) mod TableSize;
  679. end;
  680. { THTNode }
  681. constructor THTNode.CreateWith(const AString: string);
  682. begin
  683. inherited Create;
  684. FKey := AString;
  685. end;
  686. function THTNode.HasKey(const AKey: string): boolean;
  687. begin
  688. if Length(AKey) <> Length(FKey) then
  689. begin
  690. Result := false;
  691. exit;
  692. end
  693. else
  694. Result := CompareMem(PChar(FKey), PChar(AKey), length(AKey));
  695. end;
  696. { TFPHashTable }
  697. constructor TFPHashTable.Create;
  698. begin
  699. Inherited Create;
  700. FHashTable := TFPObjectList.Create(True);
  701. HashTableSize := 196613;
  702. FHashFunction := @RSHash;
  703. end;
  704. constructor TFPHashTable.CreateWith(AHashTableSize: Longword;
  705. aHashFunc: THashFunction);
  706. begin
  707. Inherited Create;
  708. FHashTable := TFPObjectList.Create(True);
  709. HashTableSize := AHashTableSize;
  710. FHashFunction := aHashFunc;
  711. end;
  712. destructor TFPHashTable.Destroy;
  713. begin
  714. FHashTable.Free;
  715. inherited Destroy;
  716. end;
  717. function TFPHashTable.GetDensity: Longword;
  718. begin
  719. Result := FHashTableSize - VoidSlots
  720. end;
  721. function TFPHashTable.GetNumberOfCollisions: Int64;
  722. begin
  723. Result := FCount -(FHashTableSize - VoidSlots)
  724. end;
  725. procedure TFPHashTable.SetData(const index: string; const AValue: Pointer);
  726. begin
  727. FindOrCreateNew(index).Data := AValue;
  728. end;
  729. procedure TFPHashTable.SetHashTableSize(const Value: Longword);
  730. var
  731. i: Longword;
  732. newSize: Longword;
  733. begin
  734. if Value <> FHashTableSize then
  735. begin
  736. i := 0;
  737. while (PRIMELIST[i] < Value) and (i < 27) do
  738. inc(i);
  739. newSize := PRIMELIST[i];
  740. if Count = 0 then
  741. begin
  742. FHashTableSize := newSize;
  743. InitializeHashTable;
  744. end
  745. else
  746. ChangeTableSize(newSize);
  747. end;
  748. end;
  749. procedure TFPHashTable.InitializeHashTable;
  750. var
  751. i: LongWord;
  752. begin
  753. for i := 0 to FHashTableSize-1 do
  754. FHashTable.Add(nil);
  755. FCount := 0;
  756. end;
  757. procedure TFPHashTable.ChangeTableSize(const ANewSize: Longword);
  758. var
  759. SavedTable: TFPObjectList;
  760. SavedTableSize: Longword;
  761. i, j: Longword;
  762. temp: THTNode;
  763. begin
  764. SavedTable := FHashTable;
  765. SavedTableSize := FHashTableSize;
  766. FHashTableSize := ANewSize;
  767. FHashTable := TFPObjectList.Create(True);
  768. InitializeHashTable;
  769. for i := 0 to SavedTableSize-1 do
  770. begin
  771. if Assigned(SavedTable[i]) then
  772. for j := 0 to TFPObjectList(SavedTable[i]).Count -1 do
  773. begin
  774. temp := THTNode(TFPObjectList(SavedTable[i])[j]);
  775. Add(temp.Key, temp.Data);
  776. end;
  777. end;
  778. SavedTable.Free;
  779. end;
  780. procedure TFPHashTable.SetHashFunction(AHashFunction: THashFunction);
  781. begin
  782. if IsEmpty then
  783. FHashFunction := AHashFunction
  784. else
  785. raise Exception.Create(NotEmptyMsg);
  786. end;
  787. function TFPHashTable.Find(const aKey: string): THTNode;
  788. var
  789. hashCode: Longword;
  790. chn: TFPObjectList;
  791. i: Longword;
  792. begin
  793. hashCode := FHashFunction(aKey, FHashTableSize);
  794. chn := Chain(hashCode);
  795. if Assigned(chn) then
  796. begin
  797. for i := 0 to chn.Count - 1 do
  798. if THTNode(chn[i]).HasKey(aKey) then
  799. begin
  800. result := THTNode(chn[i]);
  801. exit;
  802. end;
  803. end;
  804. Result := nil;
  805. end;
  806. function TFPHashTable.GetData(const Index: string): Pointer;
  807. var
  808. node: THTNode;
  809. begin
  810. node := Find(Index);
  811. if Assigned(node) then
  812. Result := node.Data
  813. else
  814. Result := nil;
  815. end;
  816. function TFPHashTable.FindOrCreateNew(const aKey: string): THTNode;
  817. var
  818. hashCode: Longword;
  819. chn: TFPObjectList;
  820. i: Longword;
  821. begin
  822. hashCode := FHashFunction(aKey, FHashTableSize);
  823. chn := Chain(hashCode);
  824. if Assigned(chn) then
  825. begin
  826. for i := 0 to chn.Count - 1 do
  827. if THTNode(chn[i]).HasKey(aKey) then
  828. begin
  829. Result := THTNode(chn[i]);
  830. exit;
  831. end
  832. end
  833. else
  834. begin
  835. FHashTable[hashcode] := TFPObjectList.Create(true);
  836. chn := Chain(hashcode);
  837. end;
  838. inc(FCount);
  839. Result := THTNode.CreateWith(aKey);
  840. chn.Add(Result);
  841. end;
  842. function TFPHashTable.ChainLength(const ChainIndex: Longword): Longword;
  843. begin
  844. if Assigned(Chain(ChainIndex)) then
  845. Result := Chain(ChainIndex).Count
  846. else
  847. Result := 0;
  848. end;
  849. procedure TFPHashTable.Clear;
  850. var
  851. i: Longword;
  852. begin
  853. for i := 0 to FHashTableSize - 1 do
  854. begin
  855. if Assigned(Chain(i)) then
  856. Chain(i).Clear;
  857. end;
  858. FCount := 0;
  859. end;
  860. function TFPHashTable.ForEachCall(aMethod: TIteratorMethod): THTNode;
  861. var
  862. i, j: Longword;
  863. continue: boolean;
  864. begin
  865. Result := nil;
  866. continue := true;
  867. for i := 0 to FHashTableSize-1 do
  868. begin
  869. if assigned(Chain(i)) then
  870. begin
  871. for j := 0 to Chain(i).Count-1 do
  872. begin
  873. aMethod(THTNode(Chain(i)[j]).Data, THTNode(Chain(i)[j]).Key, continue);
  874. if not continue then
  875. begin
  876. Result := THTNode(Chain(i)[j]);
  877. Exit;
  878. end;
  879. end;
  880. end;
  881. end;
  882. end;
  883. procedure TFPHashTable.Add(const aKey: string; aItem: pointer);
  884. var
  885. hashCode: Longword;
  886. chn: TFPObjectList;
  887. i: Longword;
  888. NewNode: THtNode;
  889. begin
  890. hashCode := FHashFunction(aKey, FHashTableSize);
  891. chn := Chain(hashCode);
  892. if Assigned(chn) then
  893. begin
  894. for i := 0 to chn.Count - 1 do
  895. if THTNode(chn[i]).HasKey(aKey) then
  896. Raise EDuplicate.CreateFmt(DuplicateMsg, [aKey]);
  897. end
  898. else
  899. begin
  900. FHashTable[hashcode] := TFPObjectList.Create(true);
  901. chn := Chain(hashcode);
  902. end;
  903. inc(FCount);
  904. NewNode := THTNode.CreateWith(aKey);
  905. NewNode.Data := aItem;
  906. chn.Add(NewNode);
  907. end;
  908. procedure TFPHashTable.Delete(const aKey: string);
  909. var
  910. hashCode: Longword;
  911. chn: TFPObjectList;
  912. i: Longword;
  913. begin
  914. hashCode := FHashFunction(aKey, FHashTableSize);
  915. chn := Chain(hashCode);
  916. if Assigned(chn) then
  917. begin
  918. for i := 0 to chn.Count - 1 do
  919. if THTNode(chn[i]).HasKey(aKey) then
  920. begin
  921. chn.Delete(i);
  922. dec(FCount);
  923. exit;
  924. end;
  925. end;
  926. raise EKeyNotFound.CreateFmt(KeyNotFoundMsg, ['Delete', aKey]);
  927. end;
  928. function TFPHashTable.IsEmpty: boolean;
  929. begin
  930. Result := (FCount = 0);
  931. end;
  932. function TFPHashTable.Chain(const index: Longword): TFPObjectList;
  933. begin
  934. Result := TFPObjectList(FHashTable[index]);
  935. end;
  936. function TFPHashTable.GetVoidSlots: Longword;
  937. var
  938. i: Longword;
  939. num: Longword;
  940. begin
  941. num := 0;
  942. for i:= 0 to FHashTableSize-1 do
  943. if Not Assigned(Chain(i)) then
  944. inc(num);
  945. result := num;
  946. end;
  947. function TFPHashTable.GetLoadFactor: double;
  948. begin
  949. Result := Count / FHashTableSize;
  950. end;
  951. function TFPHashTable.GetAVGChainLen: double;
  952. begin
  953. result := Count / (FHashTableSize - VoidSlots);
  954. end;
  955. function TFPHashTable.GetMaxChainLength: Int64;
  956. var
  957. i: Longword;
  958. begin
  959. Result := 0;
  960. for i := 0 to FHashTableSize-1 do
  961. if ChainLength(i) > Result then
  962. Result := ChainLength(i);
  963. end;
  964. end.