contnrs.pp 26 KB

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