2
0

contnrs.pp 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155
  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. TPList with Hash support
  158. ---------------------------------------------------------------------}
  159. type
  160. THashItem=record
  161. HashValue : LongWord;
  162. StrIndex : Integer;
  163. NextIndex : Integer;
  164. Data : Pointer;
  165. end;
  166. PHashItem=^THashItem;
  167. const
  168. MaxHashListSize = Maxint div 16;
  169. MaxHashStrSize = Maxint;
  170. MaxHashTableSize = Maxint div 4;
  171. MaxItemsPerHash = 3;
  172. type
  173. PHashItemList = ^THashItemList;
  174. THashItemList = array[0..MaxHashListSize - 1] of THashItem;
  175. PHashTable = ^THashTable;
  176. THashTable = array[0..MaxHashTableSize - 1] of Integer;
  177. { TFPHashList class }
  178. TFPHashList = class(TObject)
  179. private
  180. { ItemList }
  181. FHashList : PHashItemList;
  182. FCount,
  183. FCapacity : Integer;
  184. { Hash }
  185. FHashTable : PHashTable;
  186. FHashCapacity : Integer;
  187. { Strings }
  188. FStrs : PChar;
  189. FStrCount,
  190. FStrCapacity : Integer;
  191. protected
  192. function Get(Index: Integer): Pointer;
  193. procedure SetCapacity(NewCapacity: Integer);
  194. procedure SetCount(NewCount: Integer);
  195. Procedure RaiseIndexError(Index : Integer);
  196. function AddStr(const s:shortstring): Integer;
  197. procedure AddToHashTable(Index: Integer);
  198. procedure StrExpand(MinIncSize:Integer);
  199. procedure SetStrCapacity(NewCapacity: Integer);
  200. procedure SetHashCapacity(NewCapacity: Integer);
  201. procedure ReHash;
  202. public
  203. constructor Create;
  204. destructor Destroy; override;
  205. function Add(const AName:shortstring;Item: Pointer): Integer;
  206. procedure Clear;
  207. function NameOfIndex(Index: Integer): String;
  208. procedure Delete(Index: Integer);
  209. class procedure Error(const Msg: string; Data: PtrInt);
  210. function Expand: TFPHashList;
  211. function Extract(item: Pointer): Pointer;
  212. function IndexOf(Item: Pointer): Integer;
  213. function Find(const s:shortstring): Pointer;
  214. function Remove(Item: Pointer): Integer;
  215. procedure Pack;
  216. procedure ShowStatistics;
  217. procedure ForEachCall(proc2call:TListCallback;arg:pointer);
  218. procedure ForEachCall(proc2call:TListStaticCallback;arg:pointer);
  219. property Capacity: Integer read FCapacity write SetCapacity;
  220. property Count: Integer read FCount write SetCount;
  221. property Items[Index: Integer]: Pointer read Get; default;
  222. property List: PHashItemList read FHashList;
  223. property Strs: PChar read FStrs;
  224. end;
  225. { TFPHashObjectList class }
  226. TFPHashObjectList = class;
  227. TFPHashObject = class
  228. private
  229. FOwner : TFPHashObjectList;
  230. FCachedStr : pshortstring;
  231. FStrIndex : Integer;
  232. protected
  233. function GetName:shortstring;
  234. public
  235. constructor Create(HashObjectList:TFPHashObjectList;const s:shortstring);
  236. property Name:shortstring read GetName;
  237. end;
  238. TFPHashObjectList = class(TObject)
  239. private
  240. FFreeObjects : Boolean;
  241. FHashList: TFPHashList;
  242. function GetCount: integer;
  243. procedure SetCount(const AValue: integer);
  244. protected
  245. function GetItem(Index: Integer): TObject;
  246. procedure SetCapacity(NewCapacity: Integer);
  247. function GetCapacity: integer;
  248. public
  249. constructor Create(FreeObjects : boolean = True);
  250. destructor Destroy; override;
  251. procedure Clear;
  252. function Add(const AName:shortstring;AObject: TObject): Integer;
  253. function NameOfIndex(Index: Integer): shortstring;
  254. procedure Delete(Index: Integer);
  255. function Expand: TFPHashObjectList;
  256. function Extract(Item: TObject): TObject;
  257. function Remove(AObject: TObject): Integer;
  258. function IndexOf(AObject: TObject): Integer;
  259. function Find(const s:shortstring): TObject;
  260. function FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt: Integer): Integer;
  261. procedure Pack;
  262. procedure ShowStatistics;
  263. procedure ForEachCall(proc2call:TObjectListCallback;arg:pointer);
  264. procedure ForEachCall(proc2call:TObjectListStaticCallback;arg:pointer);
  265. property Capacity: Integer read GetCapacity write SetCapacity;
  266. property Count: Integer read GetCount write SetCount;
  267. property OwnsObjects: Boolean read FFreeObjects write FFreeObjects;
  268. property Items[Index: Integer]: TObject read GetItem; default;
  269. property List: TFPHashList read FHashList;
  270. end;
  271. { ---------------------------------------------------------------------
  272. Hash support, implemented by Dean Zobec
  273. ---------------------------------------------------------------------}
  274. { Must return a Longword value in the range 0..TableSize,
  275. usually via a mod operator; }
  276. THashFunction = function(const S: string; const TableSize: Longword): Longword;
  277. { THTNode }
  278. THTCustomNode = class(TObject)
  279. private
  280. FKey: string;
  281. public
  282. constructor CreateWith(const AString: String);
  283. function HasKey(const AKey: string): boolean;
  284. property Key: string read FKey;
  285. end;
  286. THTCustomNodeClass = Class of THTCustomNode;
  287. { TFPCustomHashTable }
  288. TFPCustomHashTable = class(TObject)
  289. private
  290. FHashTable: TFPObjectList;
  291. FHashTableSize: Longword;
  292. FHashFunction: THashFunction;
  293. FCount: Longword;
  294. function GetDensity: Longword;
  295. function GetNumberOfCollisions: Longword;
  296. procedure SetHashTableSize(const Value: Longword);
  297. procedure InitializeHashTable;
  298. function GetVoidSlots: Longword;
  299. function GetLoadFactor: double;
  300. function GetAVGChainLen: double;
  301. function GetMaxChainLength: Longword;
  302. function Chain(const index: Longword):TFPObjectList;
  303. protected
  304. Function CreateNewNode(const aKey : string) : THTCustomNode; virtual; abstract;
  305. Procedure AddNode(ANode : THTCustomNode); virtual; abstract;
  306. function ChainLength(const ChainIndex: Longword): Longword; virtual;
  307. function FindOrCreateNew(const aKey: string): THTCustomNode; virtual;
  308. procedure SetHashFunction(AHashFunction: THashFunction); virtual;
  309. Function FindChainForAdd(Const aKey : String) : TFPObjectList;
  310. public
  311. constructor Create;
  312. constructor CreateWith(AHashTableSize: Longword; aHashFunc: THashFunction);
  313. destructor Destroy; override;
  314. procedure ChangeTableSize(const ANewSize: Longword); virtual;
  315. procedure Clear; virtual;
  316. procedure Delete(const aKey: string); virtual;
  317. function Find(const aKey: string): THTCustomNode;
  318. function IsEmpty: boolean;
  319. property HashFunction: THashFunction read FHashFunction write SetHashFunction;
  320. property Count: Longword read FCount;
  321. property HashTableSize: Longword read FHashTableSize write SetHashTableSize;
  322. property HashTable: TFPObjectList read FHashTable;
  323. property VoidSlots: Longword read GetVoidSlots;
  324. property LoadFactor: double read GetLoadFactor;
  325. property AVGChainLen: double read GetAVGChainLen;
  326. property MaxChainLength: Longword read GetMaxChainLength;
  327. property NumberOfCollisions: Longword read GetNumberOfCollisions;
  328. property Density: Longword read GetDensity;
  329. end;
  330. { TFPDataHashTable : Hash table with simple data pointers }
  331. THTDataNode = Class(THTCustomNode)
  332. Private
  333. FData: pointer;
  334. public
  335. property Data: pointer read FData write FData;
  336. end;
  337. // For compatibility
  338. THTNode = THTDataNode;
  339. TDataIteratorMethod = procedure(Item: Pointer; const Key: string; var Continue: Boolean) of object;
  340. // For compatibility
  341. TIteratorMethod = TDataIteratorMethod;
  342. TFPDataHashTable = Class(TFPCustomHashTable)
  343. Protected
  344. Function CreateNewNode(const aKey : String) : THTCustomNode; override;
  345. Procedure AddNode(ANode : THTCustomNode); override;
  346. procedure SetData(const index: string; const AValue: Pointer); virtual;
  347. function GetData(const index: string):Pointer; virtual;
  348. function ForEachCall(aMethod: TDataIteratorMethod): THTDataNode; virtual;
  349. Public
  350. procedure Add(const aKey: string; AItem: pointer); virtual;
  351. property Items[const index: string]: Pointer read GetData write SetData; default;
  352. end;
  353. { TFPStringHashTable : Hash table with simple strings as data }
  354. THTStringNode = Class(THTCustomNode)
  355. Private
  356. FData : String;
  357. public
  358. property Data: String read FData write FData;
  359. end;
  360. TStringIteratorMethod = procedure(Item: String; const Key: string; var Continue: Boolean) of object;
  361. TFPStringHashTable = Class(TFPCustomHashTable)
  362. Protected
  363. Function CreateNewNode(const aKey : String) : THTCustomNode; override;
  364. Procedure AddNode(ANode : THTCustomNode); override;
  365. procedure SetData(const Index, AValue: string); virtual;
  366. function GetData(const index: string): String; virtual;
  367. function ForEachCall(aMethod: TStringIteratorMethod): THTStringNode; virtual;
  368. Public
  369. procedure Add(const aKey,aItem: string); virtual;
  370. property Items[const index: string]: String read GetData write SetData; default;
  371. end;
  372. { TFPStringHashTable : Hash table with simple strings as data }
  373. THTObjectNode = Class(THTCustomNode)
  374. Private
  375. FData : TObject;
  376. public
  377. property Data: TObject read FData write FData;
  378. end;
  379. THTOwnedObjectNode = Class(THTObjectNode)
  380. public
  381. Destructor Destroy; override;
  382. end;
  383. TObjectIteratorMethod = procedure(Item: TObject; const Key: string; var Continue: Boolean) of object;
  384. TFPObjectHashTable = Class(TFPCustomHashTable)
  385. Private
  386. FOwnsObjects : Boolean;
  387. Protected
  388. Function CreateNewNode(const aKey : String) : THTCustomNode; override;
  389. Procedure AddNode(ANode : THTCustomNode); override;
  390. procedure SetData(const Index: string; AObject : TObject); virtual;
  391. function GetData(const index: string): TObject; virtual;
  392. function ForEachCall(aMethod: TObjectIteratorMethod): THTObjectNode; virtual;
  393. Public
  394. constructor Create(AOwnsObjects : Boolean = True);
  395. constructor CreateWith(AHashTableSize: Longword; aHashFunc: THashFunction; AOwnsObjects : Boolean = True);
  396. procedure Add(const aKey: string; AItem : TObject); virtual;
  397. property Items[const index: string]: TObject read GetData write SetData; default;
  398. Property OwnsObjects : Boolean Read FOwnsObjects Write FOwnsObjects;
  399. end;
  400. EDuplicate = class(Exception);
  401. EKeyNotFound = class(Exception);
  402. function RSHash(const S: string; const TableSize: Longword): Longword;
  403. implementation
  404. uses
  405. RtlConsts;
  406. ResourceString
  407. DuplicateMsg = 'An item with key %0:s already exists';
  408. KeyNotFoundMsg = 'Method: %0:s key [''%1:s''] not found in container';
  409. NotEmptyMsg = 'Hash table not empty.';
  410. const
  411. NPRIMES = 28;
  412. PRIMELIST: array[0 .. NPRIMES-1] of Longword =
  413. ( 53, 97, 193, 389, 769,
  414. 1543, 3079, 6151, 12289, 24593,
  415. 49157, 98317, 196613, 393241, 786433,
  416. 1572869, 3145739, 6291469, 12582917, 25165843,
  417. 50331653, 100663319, 201326611, 402653189, 805306457,
  418. 1610612741, 3221225473, 4294967291 );
  419. constructor TFPObjectList.Create(FreeObjects : boolean);
  420. begin
  421. Create;
  422. FFreeObjects := Freeobjects;
  423. end;
  424. destructor TFPObjectList.Destroy;
  425. begin
  426. if (FList <> nil) then
  427. begin
  428. Clear;
  429. FList.Destroy;
  430. end;
  431. inherited Destroy;
  432. end;
  433. procedure TFPObjectList.Clear;
  434. var
  435. i: integer;
  436. begin
  437. if FFreeObjects then
  438. for i := 0 to FList.Count - 1 do
  439. TObject(FList[i]).Free;
  440. FList.Clear;
  441. end;
  442. constructor TFPObjectList.Create;
  443. begin
  444. inherited Create;
  445. FList := TFPList.Create;
  446. FFreeObjects := True;
  447. end;
  448. function TFPObjectList.GetCount: integer;
  449. begin
  450. Result := FList.Count;
  451. end;
  452. procedure TFPObjectList.SetCount(const AValue: integer);
  453. begin
  454. if FList.Count <> AValue then
  455. FList.Count := AValue;
  456. end;
  457. function TFPObjectList.GetItem(Index: Integer): TObject; {$ifdef CLASSESINLINE}inline;{$endif}
  458. begin
  459. Result := TObject(FList[Index]);
  460. end;
  461. procedure TFPObjectList.SetItem(Index: Integer; AObject: TObject); {$ifdef CLASSESINLINE}inline;{$endif}
  462. begin
  463. if OwnsObjects then
  464. TObject(FList[Index]).Free;
  465. FList[index] := AObject;
  466. end;
  467. procedure TFPObjectList.SetCapacity(NewCapacity: Integer);
  468. begin
  469. FList.Capacity := NewCapacity;
  470. end;
  471. function TFPObjectList.GetCapacity: integer;
  472. begin
  473. Result := FList.Capacity;
  474. end;
  475. function TFPObjectList.Add(AObject: TObject): Integer; {$ifdef CLASSESINLINE}inline;{$endif}
  476. begin
  477. Result := FList.Add(AObject);
  478. end;
  479. procedure TFPObjectList.Delete(Index: Integer); {$ifdef CLASSESINLINE}inline;{$endif}
  480. begin
  481. if OwnsObjects then
  482. TObject(FList[Index]).Free;
  483. FList.Delete(Index);
  484. end;
  485. procedure TFPObjectList.Exchange(Index1, Index2: Integer);
  486. begin
  487. FList.Exchange(Index1, Index2);
  488. end;
  489. function TFPObjectList.Expand: TFPObjectList;
  490. begin
  491. FList.Expand;
  492. Result := Self;
  493. end;
  494. function TFPObjectList.Extract(Item: TObject): TObject;
  495. begin
  496. Result := TObject(FList.Extract(Item));
  497. end;
  498. function TFPObjectList.Remove(AObject: TObject): Integer;
  499. begin
  500. Result := IndexOf(AObject);
  501. if (Result <> -1) then
  502. begin
  503. if OwnsObjects then
  504. TObject(FList[Result]).Free;
  505. FList.Delete(Result);
  506. end;
  507. end;
  508. function TFPObjectList.IndexOf(AObject: TObject): Integer;
  509. begin
  510. Result := FList.IndexOf(Pointer(AObject));
  511. end;
  512. function TFPObjectList.FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt : Integer): Integer;
  513. var
  514. I : Integer;
  515. begin
  516. I:=AStartAt;
  517. Result:=-1;
  518. If AExact then
  519. while (I<Count) and (Result=-1) do
  520. If Items[i].ClassType=AClass then
  521. Result:=I
  522. else
  523. Inc(I)
  524. else
  525. while (I<Count) and (Result=-1) do
  526. If Items[i].InheritsFrom(AClass) then
  527. Result:=I
  528. else
  529. Inc(I);
  530. end;
  531. procedure TFPObjectList.Insert(Index: Integer; AObject: TObject); {$ifdef CLASSESINLINE}inline;{$endif}
  532. begin
  533. FList.Insert(Index, Pointer(AObject));
  534. end;
  535. procedure TFPObjectList.Move(CurIndex, NewIndex: Integer);
  536. begin
  537. FList.Move(CurIndex, NewIndex);
  538. end;
  539. procedure TFPObjectList.Assign(Obj: TFPObjectList);
  540. var
  541. i: Integer;
  542. begin
  543. Clear;
  544. for I := 0 to Obj.Count - 1 do
  545. Add(Obj[i]);
  546. end;
  547. procedure TFPObjectList.Pack;
  548. begin
  549. FList.Pack;
  550. end;
  551. procedure TFPObjectList.Sort(Compare: TListSortCompare);
  552. begin
  553. FList.Sort(Compare);
  554. end;
  555. function TFPObjectList.First: TObject;
  556. begin
  557. Result := TObject(FList.First);
  558. end;
  559. function TFPObjectList.Last: TObject;
  560. begin
  561. Result := TObject(FList.Last);
  562. end;
  563. procedure TFPObjectList.ForEachCall(proc2call:TObjectListCallback;arg:pointer);
  564. begin
  565. FList.ForEachCall(TListCallBack(proc2call),arg);
  566. end;
  567. procedure TFPObjectList.ForEachCall(proc2call:TObjectListStaticCallback;arg:pointer);
  568. begin
  569. FList.ForEachCall(TListStaticCallBack(proc2call),arg);
  570. end;
  571. { TObjectList }
  572. constructor tobjectlist.create(freeobjects : boolean);
  573. begin
  574. inherited create;
  575. ffreeobjects:=freeobjects;
  576. end;
  577. Constructor tobjectlist.create;
  578. begin
  579. inherited create;
  580. ffreeobjects:=True;
  581. end;
  582. Procedure TObjectList.Notify(Ptr: Pointer; Action: TListNotification);
  583. begin
  584. if FFreeObjects then
  585. if (Action=lnDeleted) then
  586. TObject(Ptr).Free;
  587. inherited Notify(Ptr,Action);
  588. end;
  589. Function TObjectList.GetItem(Index: Integer): TObject;
  590. begin
  591. Result:=TObject(Inherited Get(Index));
  592. end;
  593. Procedure TObjectList.SetItem(Index: Integer; AObject: TObject);
  594. Var
  595. O : TObject;
  596. begin
  597. if OwnsObjects then
  598. begin
  599. O:=GetItem(Index);
  600. O.Free;
  601. end;
  602. Put(Index,Pointer(AObject));
  603. end;
  604. Function TObjectList.Add(AObject: TObject): Integer;
  605. begin
  606. Result:=Inherited Add(Pointer(AObject));
  607. end;
  608. Function TObjectList.Extract(Item: TObject): TObject;
  609. begin
  610. Result:=Tobject(Inherited Extract(Pointer(Item)));
  611. end;
  612. Function TObjectList.Remove(AObject: TObject): Integer;
  613. begin
  614. Result:=Inherited Remove(Pointer(AObject));
  615. end;
  616. Function TObjectList.IndexOf(AObject: TObject): Integer;
  617. begin
  618. Result:=Inherited indexOF(Pointer(AObject));
  619. end;
  620. Function TObjectList.FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt : Integer): Integer;
  621. Var
  622. I : Integer;
  623. begin
  624. I:=AStartAt;
  625. Result:=-1;
  626. If AExact then
  627. While (I<Count) and (Result=-1) do
  628. If Items[i].ClassType=AClass then
  629. Result:=I
  630. else
  631. Inc(I)
  632. else
  633. While (I<Count) and (Result=-1) do
  634. If Items[i].InheritsFrom(AClass) then
  635. Result:=I
  636. else
  637. Inc(I);
  638. end;
  639. procedure TObjectList.Insert(Index: Integer; AObject: TObject);
  640. begin
  641. Inherited Insert(Index,Pointer(AObject));
  642. end;
  643. function TObjectList.First: TObject;
  644. begin
  645. Result := TObject(Inherited First);
  646. end;
  647. function TObjectList.Last: TObject;
  648. begin
  649. Result := TObject(Inherited Last);
  650. end;
  651. { TListComponent }
  652. Type
  653. TlistComponent = Class(TComponent)
  654. Private
  655. Flist : TComponentList;
  656. Public
  657. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  658. end;
  659. procedure TlistComponent.Notification(AComponent: TComponent;
  660. Operation: TOperation);
  661. begin
  662. If (Operation=opremove) then
  663. Flist.HandleFreeNotify(Self,AComponent);
  664. inherited;
  665. end;
  666. { TComponentList }
  667. Function TComponentList.Add(AComponent: TComponent): Integer;
  668. begin
  669. Result:=Inherited Add(AComponent);
  670. end;
  671. destructor TComponentList.Destroy;
  672. begin
  673. inherited;
  674. FreeAndNil(FNotifier);
  675. end;
  676. Function TComponentList.Extract(Item: TComponent): TComponent;
  677. begin
  678. Result:=TComponent(Inherited Extract(Item));
  679. end;
  680. Function TComponentList.First: TComponent;
  681. begin
  682. Result:=TComponent(Inherited First);
  683. end;
  684. Function TComponentList.GetItems(Index: Integer): TComponent;
  685. begin
  686. Result:=TComponent(Inherited Items[Index]);
  687. end;
  688. Procedure TComponentList.HandleFreeNotify(Sender: TObject;
  689. AComponent: TComponent);
  690. begin
  691. Extract(Acomponent);
  692. end;
  693. Function TComponentList.IndexOf(AComponent: TComponent): Integer;
  694. begin
  695. Result:=Inherited IndexOf(AComponent);
  696. end;
  697. Procedure TComponentList.Insert(Index: Integer; AComponent: TComponent);
  698. begin
  699. Inherited Insert(Index,Acomponent)
  700. end;
  701. Function TComponentList.Last: TComponent;
  702. begin
  703. Result:=TComponent(Inherited Last);
  704. end;
  705. Procedure TComponentList.Notify(Ptr: Pointer; Action: TListNotification);
  706. begin
  707. If FNotifier=NIl then
  708. begin
  709. FNotifier:=TlistComponent.Create(nil);
  710. TlistComponent(FNotifier).FList:=Self;
  711. end;
  712. If Assigned(Ptr) then
  713. With TComponent(Ptr) do
  714. case Action of
  715. lnAdded : FreeNotification(FNotifier);
  716. lnExtracted, lnDeleted: RemoveFreeNotification(FNotifier);
  717. end;
  718. inherited Notify(Ptr, Action);
  719. end;
  720. Function TComponentList.Remove(AComponent: TComponent): Integer;
  721. begin
  722. Result:=Inherited Remove(AComponent);
  723. end;
  724. Procedure TComponentList.SetItems(Index: Integer; AComponent: TComponent);
  725. begin
  726. Put(Index,AComponent);
  727. end;
  728. { TClassList }
  729. Function TClassList.Add(AClass: TClass): Integer;
  730. begin
  731. Result:=Inherited Add(Pointer(AClass));
  732. end;
  733. Function TClassList.Extract(Item: TClass): TClass;
  734. begin
  735. Result:=TClass(Inherited Extract(Pointer(Item)));
  736. end;
  737. Function TClassList.First: TClass;
  738. begin
  739. Result:=TClass(Inherited First);
  740. end;
  741. Function TClassList.GetItems(Index: Integer): TClass;
  742. begin
  743. Result:=TClass(Inherited Items[Index]);
  744. end;
  745. Function TClassList.IndexOf(AClass: TClass): Integer;
  746. begin
  747. Result:=Inherited IndexOf(Pointer(AClass));
  748. end;
  749. Procedure TClassList.Insert(Index: Integer; AClass: TClass);
  750. begin
  751. Inherited Insert(index,Pointer(AClass));
  752. end;
  753. Function TClassList.Last: TClass;
  754. begin
  755. Result:=TClass(Inherited Last);
  756. end;
  757. Function TClassList.Remove(AClass: TClass): Integer;
  758. begin
  759. Result:=Inherited Remove(Pointer(AClass));
  760. end;
  761. Procedure TClassList.SetItems(Index: Integer; AClass: TClass);
  762. begin
  763. Put(Index,Pointer(Aclass));
  764. end;
  765. { TOrderedList }
  766. Function TOrderedList.AtLeast(ACount: Integer): Boolean;
  767. begin
  768. Result:=(FList.Count>=Acount)
  769. end;
  770. Function TOrderedList.Count: Integer;
  771. begin
  772. Result:=FList.Count;
  773. end;
  774. constructor TOrderedList.Create;
  775. begin
  776. FList:=Tlist.Create;
  777. end;
  778. destructor TOrderedList.Destroy;
  779. begin
  780. FList.Free;
  781. end;
  782. Function TOrderedList.Peek: Pointer;
  783. begin
  784. If AtLeast(1) then
  785. Result:=PeekItem
  786. else
  787. Result:=Nil;
  788. end;
  789. Function TOrderedList.PeekItem: Pointer;
  790. begin
  791. With Flist do
  792. Result:=Items[Count-1]
  793. end;
  794. Function TOrderedList.Pop: Pointer;
  795. begin
  796. If Atleast(1) then
  797. Result:=PopItem
  798. else
  799. Result:=Nil;
  800. end;
  801. Function TOrderedList.PopItem: Pointer;
  802. begin
  803. With FList do
  804. If Count>0 then
  805. begin
  806. Result:=Items[Count-1];
  807. Delete(Count-1);
  808. end
  809. else
  810. Result:=Nil;
  811. end;
  812. Function TOrderedList.Push(AItem: Pointer): Pointer;
  813. begin
  814. PushItem(Aitem);
  815. Result:=AItem;
  816. end;
  817. { TStack }
  818. Procedure TStack.PushItem(AItem: Pointer);
  819. begin
  820. FList.Add(Aitem);
  821. end;
  822. { TObjectStack }
  823. Function TObjectStack.Peek: TObject;
  824. begin
  825. Result:=TObject(Inherited Peek);
  826. end;
  827. Function TObjectStack.Pop: TObject;
  828. begin
  829. Result:=TObject(Inherited Pop);
  830. end;
  831. Function TObjectStack.Push(AObject: TObject): TObject;
  832. begin
  833. Result:=TObject(Inherited Push(Pointer(AObject)));
  834. end;
  835. { TQueue }
  836. Procedure TQueue.PushItem(AItem: Pointer);
  837. begin
  838. With Flist Do
  839. Insert(0,AItem);
  840. end;
  841. { TObjectQueue }
  842. Function TObjectQueue.Peek: TObject;
  843. begin
  844. Result:=TObject(Inherited Peek);
  845. end;
  846. Function TObjectQueue.Pop: TObject;
  847. begin
  848. Result:=TObject(Inherited Pop);
  849. end;
  850. Function TObjectQueue.Push(AObject: TObject): TObject;
  851. begin
  852. Result:=TObject(Inherited Push(Pointer(Aobject)));
  853. end;
  854. {*****************************************************************************
  855. TFPHashList
  856. *****************************************************************************}
  857. function FPHash1(const s:string):LongWord;
  858. Var
  859. g : LongWord;
  860. p,pmax : pchar;
  861. begin
  862. result:=0;
  863. p:=@s[1];
  864. pmax:=@s[length(s)+1];
  865. while (p<pmax) do
  866. begin
  867. result:=result shl 4 + LongWord(p^);
  868. g:=result and LongWord($F0000000);
  869. if g<>0 then
  870. result:=result xor (g shr 24) xor g;
  871. inc(p);
  872. end;
  873. If result=0 then
  874. result:=$ffffffff;
  875. end;
  876. function FPHash(const s:string):LongWord;
  877. Var
  878. p,pmax : pchar;
  879. begin
  880. {$ifopt Q+}
  881. {$define overflowon}
  882. {$Q-}
  883. {$endif}
  884. result:=0;
  885. p:=@s[1];
  886. pmax:=@s[length(s)+1];
  887. while (p<pmax) do
  888. begin
  889. result:=LongWord((result shl 5) - result) xor LongWord(P^);
  890. inc(p);
  891. end;
  892. {$ifdef overflowon}
  893. {$Q+}
  894. {$undef overflowon}
  895. {$endif}
  896. end;
  897. procedure TFPHashList.RaiseIndexError(Index : Integer);
  898. begin
  899. Error(SListIndexError, Index);
  900. end;
  901. function TFPHashList.Get(Index: Integer): Pointer;
  902. begin
  903. If (Index < 0) or (Index >= FCount) then
  904. RaiseIndexError(Index);
  905. Result:=FHashList^[Index].Data;
  906. end;
  907. function TFPHashList.NameOfIndex(Index: Integer): String;
  908. begin
  909. If (Index < 0) or (Index >= FCount) then
  910. RaiseIndexError(Index);
  911. with FHashList^[Index] do
  912. begin
  913. if StrIndex>=0 then
  914. Result:=PShortString(@FStrs[StrIndex])^
  915. else
  916. Result:='';
  917. end;
  918. end;
  919. function TFPHashList.Extract(item: Pointer): Pointer;
  920. var
  921. i : Integer;
  922. begin
  923. result := nil;
  924. i := IndexOf(item);
  925. if i >= 0 then
  926. begin
  927. Result := item;
  928. Delete(i);
  929. end;
  930. end;
  931. procedure TFPHashList.SetCapacity(NewCapacity: Integer);
  932. begin
  933. If (NewCapacity < FCount) or (NewCapacity > MaxHashListSize) then
  934. Error (SListCapacityError, NewCapacity);
  935. if NewCapacity = FCapacity then
  936. exit;
  937. ReallocMem(FHashList, NewCapacity*SizeOf(THashItem));
  938. FCapacity := NewCapacity;
  939. end;
  940. procedure TFPHashList.SetCount(NewCount: Integer);
  941. begin
  942. if (NewCount < 0) or (NewCount > MaxHashListSize)then
  943. Error(SListCountError, NewCount);
  944. If NewCount > FCount then
  945. begin
  946. If NewCount > FCapacity then
  947. SetCapacity(NewCount);
  948. If FCount < NewCount then
  949. FillChar(FHashList^[FCount], (NewCount-FCount) div Sizeof(THashItem), 0);
  950. end;
  951. FCount := Newcount;
  952. end;
  953. procedure TFPHashList.SetStrCapacity(NewCapacity: Integer);
  954. begin
  955. If (NewCapacity < FStrCount) or (NewCapacity > MaxHashStrSize) then
  956. Error (SListCapacityError, NewCapacity);
  957. if NewCapacity = FStrCapacity then
  958. exit;
  959. ReallocMem(FStrs, NewCapacity);
  960. FStrCapacity := NewCapacity;
  961. end;
  962. procedure TFPHashList.SetHashCapacity(NewCapacity: Integer);
  963. begin
  964. If (NewCapacity < 1) then
  965. Error (SListCapacityError, NewCapacity);
  966. if FHashCapacity=NewCapacity then
  967. exit;
  968. FHashCapacity:=NewCapacity;
  969. ReallocMem(FHashTable, FHashCapacity*sizeof(Integer));
  970. ReHash;
  971. end;
  972. procedure TFPHashList.ReHash;
  973. var
  974. i : Integer;
  975. begin
  976. FillDword(FHashTable^,FHashCapacity,LongWord(-1));
  977. For i:=0 To FCount-1 Do
  978. AddToHashTable(i);
  979. end;
  980. constructor TFPHashList.Create;
  981. begin
  982. SetHashCapacity(1);
  983. end;
  984. destructor TFPHashList.Destroy;
  985. begin
  986. Clear;
  987. if assigned(FHashTable) then
  988. FreeMem(FHashTable);
  989. inherited Destroy;
  990. end;
  991. function TFPHashList.AddStr(const s:shortstring): Integer;
  992. var
  993. Len : Integer;
  994. begin
  995. len:=length(s)+1;
  996. if FStrCount+Len >= FStrCapacity then
  997. StrExpand(Len);
  998. System.Move(s[0],FStrs[FStrCount],Len);
  999. result:=FStrCount;
  1000. inc(FStrCount,Len);
  1001. end;
  1002. procedure TFPHashList.AddToHashTable(Index: Integer);
  1003. var
  1004. HashIndex : Integer;
  1005. begin
  1006. with FHashList^[Index] do
  1007. begin
  1008. if not assigned(Data) then
  1009. exit;
  1010. HashIndex:=HashValue mod LongWord(FHashCapacity);
  1011. NextIndex:=FHashTable^[HashIndex];
  1012. FHashTable^[HashIndex]:=Index;
  1013. end;
  1014. end;
  1015. function TFPHashList.Add(const AName:shortstring;Item: Pointer): Integer;
  1016. begin
  1017. if FCount = FCapacity then
  1018. Expand;
  1019. with FHashList^[FCount] do
  1020. begin
  1021. HashValue:=FPHash(AName);
  1022. Data:=Item;
  1023. StrIndex:=AddStr(AName);
  1024. end;
  1025. AddToHashTable(FCount);
  1026. Result := FCount;
  1027. inc(FCount);
  1028. end;
  1029. procedure TFPHashList.Clear;
  1030. begin
  1031. if Assigned(FHashList) then
  1032. begin
  1033. FCount:=0;
  1034. SetCapacity(0);
  1035. FHashList := nil;
  1036. end;
  1037. SetHashCapacity(1);
  1038. if Assigned(FStrs) then
  1039. begin
  1040. FStrCount:=0;
  1041. SetStrCapacity(0);
  1042. FStrs := nil;
  1043. end;
  1044. end;
  1045. procedure TFPHashList.Delete(Index: Integer);
  1046. begin
  1047. If (Index<0) or (Index>=FCount) then
  1048. Error (SListIndexError, Index);
  1049. with FHashList^[Index] do
  1050. begin
  1051. Data:=nil;
  1052. StrIndex:=-1;
  1053. end;
  1054. end;
  1055. class procedure TFPHashList.Error(const Msg: string; Data: PtrInt);
  1056. begin
  1057. Raise EListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame);
  1058. end;
  1059. function TFPHashList.Expand: TFPHashList;
  1060. var
  1061. IncSize : Longint;
  1062. begin
  1063. Result := Self;
  1064. if FCount < FCapacity then
  1065. exit;
  1066. IncSize := 4;
  1067. if FCapacity > 127 then
  1068. Inc(IncSize, FCapacity shr 2)
  1069. else if FCapacity > 8 then
  1070. inc(IncSize,8)
  1071. else if FCapacity > 3 then
  1072. inc(IncSize,4);
  1073. SetCapacity(FCapacity + IncSize);
  1074. { Maybe expand hash also }
  1075. if FCount>FHashCapacity*MaxItemsPerHash then
  1076. SetHashCapacity(FCount div MaxItemsPerHash);
  1077. end;
  1078. procedure TFPHashList.StrExpand(MinIncSize:Integer);
  1079. var
  1080. IncSize : Longint;
  1081. begin
  1082. if FStrCount+MinIncSize < FStrCapacity then
  1083. exit;
  1084. IncSize := 64+MinIncSize;
  1085. if FStrCapacity > 255 then
  1086. Inc(IncSize, FStrCapacity shr 2);
  1087. SetStrCapacity(FStrCapacity + IncSize);
  1088. end;
  1089. function TFPHashList.IndexOf(Item: Pointer): Integer;
  1090. begin
  1091. Result := 0;
  1092. while(Result < FCount) and (FHashList^[Result].Data <> Item) do
  1093. inc(Result);
  1094. If Result = FCount then
  1095. Result := -1;
  1096. end;
  1097. function TFPHashList.Find(const s:shortstring): Pointer;
  1098. var
  1099. CurrHash : LongWord;
  1100. Index,
  1101. HashIndex : Integer;
  1102. Len,
  1103. LastChar : Char;
  1104. begin
  1105. CurrHash:=FPHash(s);
  1106. HashIndex:=CurrHash mod LongWord(FHashCapacity);
  1107. Index:=FHashTable^[HashIndex];
  1108. Len:=Char(Length(s));
  1109. LastChar:=s[Byte(Len)];
  1110. while Index<>-1 do
  1111. begin
  1112. with FHashList^[Index] do
  1113. begin
  1114. if assigned(Data) and
  1115. (HashValue=CurrHash) and
  1116. (Len=FStrs[StrIndex]) and
  1117. (LastChar=FStrs[StrIndex+Byte(Len)]) and
  1118. (s=PShortString(@FStrs[StrIndex])^) then
  1119. begin
  1120. Result:=Data;
  1121. exit;
  1122. end;
  1123. Index:=NextIndex;
  1124. end;
  1125. end;
  1126. Result:=nil;
  1127. end;
  1128. function TFPHashList.Remove(Item: Pointer): Integer;
  1129. begin
  1130. Result := IndexOf(Item);
  1131. If Result <> -1 then
  1132. Self.Delete(Result);
  1133. end;
  1134. procedure TFPHashList.Pack;
  1135. var
  1136. NewCount,
  1137. i : integer;
  1138. pdest,
  1139. psrc : PHashItem;
  1140. begin
  1141. NewCount:=0;
  1142. psrc:=FHashList[0];
  1143. pdest:=psrc;
  1144. For I:=0 To FCount-1 Do
  1145. begin
  1146. if assigned(psrc^.Data) then
  1147. begin
  1148. pdest^:=psrc^;
  1149. inc(pdest);
  1150. inc(NewCount);
  1151. end;
  1152. inc(psrc);
  1153. end;
  1154. FCount:=NewCount;
  1155. { We need to ReHash to update the IndexNext }
  1156. ReHash;
  1157. { Release over-capacity }
  1158. SetCapacity(FCount);
  1159. SetStrCapacity(FStrCount);
  1160. end;
  1161. procedure TFPHashList.ShowStatistics;
  1162. var
  1163. HashMean,
  1164. HashStdDev : Double;
  1165. Index,
  1166. i,j : Integer;
  1167. begin
  1168. { Calculate Mean and StdDev }
  1169. HashMean:=0;
  1170. HashStdDev:=0;
  1171. for i:=0 to FHashCapacity-1 do
  1172. begin
  1173. j:=0;
  1174. Index:=FHashTable^[i];
  1175. while (Index<>-1) do
  1176. begin
  1177. inc(j);
  1178. Index:=FHashList^[Index].NextIndex;
  1179. end;
  1180. HashMean:=HashMean+j;
  1181. HashStdDev:=HashStdDev+Sqr(j);
  1182. end;
  1183. HashMean:=HashMean/FHashCapacity;
  1184. HashStdDev:=(HashStdDev-FHashCapacity*Sqr(HashMean));
  1185. If FHashCapacity>1 then
  1186. HashStdDev:=Sqrt(HashStdDev/(FHashCapacity-1))
  1187. else
  1188. HashStdDev:=0;
  1189. { Print info to stdout }
  1190. Writeln('HashSize : ',FHashCapacity);
  1191. Writeln('HashMean : ',HashMean:1:4);
  1192. Writeln('HashStdDev : ',HashStdDev:1:4);
  1193. Writeln('ListSize : ',FCount,'/',FCapacity);
  1194. Writeln('StringSize : ',FStrCount,'/',FStrCapacity);
  1195. end;
  1196. procedure TFPHashList.ForEachCall(proc2call:TListCallback;arg:pointer);
  1197. var
  1198. i : integer;
  1199. p : pointer;
  1200. begin
  1201. For I:=0 To Count-1 Do
  1202. begin
  1203. p:=FHashList^[i].Data;
  1204. if assigned(p) then
  1205. proc2call(p,arg);
  1206. end;
  1207. end;
  1208. procedure TFPHashList.ForEachCall(proc2call:TListStaticCallback;arg:pointer);
  1209. var
  1210. i : integer;
  1211. p : pointer;
  1212. begin
  1213. For I:=0 To Count-1 Do
  1214. begin
  1215. p:=FHashList^[i].Data;
  1216. if assigned(p) then
  1217. proc2call(p,arg);
  1218. end;
  1219. end;
  1220. {*****************************************************************************
  1221. TFPHashObject
  1222. *****************************************************************************}
  1223. constructor TFPHashObject.Create(HashObjectList:TFPHashObjectList;const s:shortstring);
  1224. var
  1225. Index : Integer;
  1226. begin
  1227. FOwner:=HashObjectList;
  1228. Index:=HashObjectList.Add(s,Self);
  1229. FStrIndex:=HashObjectList.List.List^[Index].StrIndex;
  1230. FCachedStr:=PShortString(@FOwner.List.Strs[FStrIndex]);
  1231. end;
  1232. function TFPHashObject.GetName:shortstring;
  1233. begin
  1234. FCachedStr:=PShortString(@FOwner.List.Strs[FStrIndex]);
  1235. Result:=FCachedStr^;
  1236. end;
  1237. {*****************************************************************************
  1238. TFPHashObjectList (Copied from rtl/objpas/classes/lists.inc)
  1239. *****************************************************************************}
  1240. constructor TFPHashObjectList.Create(FreeObjects : boolean = True);
  1241. begin
  1242. inherited Create;
  1243. FHashList := TFPHashList.Create;
  1244. FFreeObjects := Freeobjects;
  1245. end;
  1246. destructor TFPHashObjectList.Destroy;
  1247. begin
  1248. if (FHashList <> nil) then
  1249. begin
  1250. Clear;
  1251. FHashList.Destroy;
  1252. end;
  1253. inherited Destroy;
  1254. end;
  1255. procedure TFPHashObjectList.Clear;
  1256. var
  1257. i: integer;
  1258. begin
  1259. if FFreeObjects then
  1260. for i := 0 to FHashList.Count - 1 do
  1261. TObject(FHashList[i]).Free;
  1262. FHashList.Clear;
  1263. end;
  1264. function TFPHashObjectList.GetCount: integer;
  1265. begin
  1266. Result := FHashList.Count;
  1267. end;
  1268. procedure TFPHashObjectList.SetCount(const AValue: integer);
  1269. begin
  1270. if FHashList.Count <> AValue then
  1271. FHashList.Count := AValue;
  1272. end;
  1273. function TFPHashObjectList.GetItem(Index: Integer): TObject;
  1274. begin
  1275. Result := TObject(FHashList[Index]);
  1276. end;
  1277. procedure TFPHashObjectList.SetCapacity(NewCapacity: Integer);
  1278. begin
  1279. FHashList.Capacity := NewCapacity;
  1280. end;
  1281. function TFPHashObjectList.GetCapacity: integer;
  1282. begin
  1283. Result := FHashList.Capacity;
  1284. end;
  1285. function TFPHashObjectList.Add(const AName:shortstring;AObject: TObject): Integer;
  1286. begin
  1287. Result := FHashList.Add(AName,AObject);
  1288. end;
  1289. function TFPHashObjectList.NameOfIndex(Index: Integer): shortString;
  1290. begin
  1291. Result := FHashList.NameOfIndex(Index);
  1292. end;
  1293. procedure TFPHashObjectList.Delete(Index: Integer);
  1294. begin
  1295. if OwnsObjects then
  1296. TObject(FHashList[Index]).Free;
  1297. FHashList.Delete(Index);
  1298. end;
  1299. function TFPHashObjectList.Expand: TFPHashObjectList;
  1300. begin
  1301. FHashList.Expand;
  1302. Result := Self;
  1303. end;
  1304. function TFPHashObjectList.Extract(Item: TObject): TObject;
  1305. begin
  1306. Result := TObject(FHashList.Extract(Item));
  1307. end;
  1308. function TFPHashObjectList.Remove(AObject: TObject): Integer;
  1309. begin
  1310. Result := IndexOf(AObject);
  1311. if (Result <> -1) then
  1312. begin
  1313. if OwnsObjects then
  1314. TObject(FHashList[Result]).Free;
  1315. FHashList.Delete(Result);
  1316. end;
  1317. end;
  1318. function TFPHashObjectList.IndexOf(AObject: TObject): Integer;
  1319. begin
  1320. Result := FHashList.IndexOf(Pointer(AObject));
  1321. end;
  1322. function TFPHashObjectList.Find(const s:shortstring): TObject;
  1323. begin
  1324. result:=TObject(FHashList.Find(s));
  1325. end;
  1326. function TFPHashObjectList.FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt : Integer): Integer;
  1327. var
  1328. I : Integer;
  1329. begin
  1330. I:=AStartAt;
  1331. Result:=-1;
  1332. If AExact then
  1333. while (I<Count) and (Result=-1) do
  1334. If Items[i].ClassType=AClass then
  1335. Result:=I
  1336. else
  1337. Inc(I)
  1338. else
  1339. while (I<Count) and (Result=-1) do
  1340. If Items[i].InheritsFrom(AClass) then
  1341. Result:=I
  1342. else
  1343. Inc(I);
  1344. end;
  1345. procedure TFPHashObjectList.Pack;
  1346. begin
  1347. FHashList.Pack;
  1348. end;
  1349. procedure TFPHashObjectList.ShowStatistics;
  1350. begin
  1351. FHashList.ShowStatistics;
  1352. end;
  1353. procedure TFPHashObjectList.ForEachCall(proc2call:TObjectListCallback;arg:pointer);
  1354. begin
  1355. FHashList.ForEachCall(TListCallBack(proc2call),arg);
  1356. end;
  1357. procedure TFPHashObjectList.ForEachCall(proc2call:TObjectListStaticCallback;arg:pointer);
  1358. begin
  1359. FHashList.ForEachCall(TListStaticCallBack(proc2call),arg);
  1360. end;
  1361. { ---------------------------------------------------------------------
  1362. Hash support, by Dean Zobec
  1363. ---------------------------------------------------------------------}
  1364. { Default hash function }
  1365. function RSHash(const S: string; const TableSize: Longword): Longword;
  1366. const
  1367. b = 378551;
  1368. var
  1369. a: Longword;
  1370. i: Longword;
  1371. begin
  1372. a := 63689;
  1373. Result := 0;
  1374. if length(s)>0 then
  1375. for i := 1 to Length(S) do
  1376. begin
  1377. Result := Result * a + Ord(S[i]);
  1378. a := a * b;
  1379. end;
  1380. Result := (Result and $7FFFFFFF) mod TableSize;
  1381. end;
  1382. { THTNode }
  1383. constructor THTCustomNode.CreateWith(const AString: string);
  1384. begin
  1385. inherited Create;
  1386. FKey := AString;
  1387. end;
  1388. function THTCustomNode.HasKey(const AKey: string): boolean;
  1389. begin
  1390. if Length(AKey) <> Length(FKey) then
  1391. begin
  1392. Result := false;
  1393. exit;
  1394. end
  1395. else
  1396. Result := CompareMem(PChar(FKey), PChar(AKey), length(AKey));
  1397. end;
  1398. { TFPCustomHashTable }
  1399. constructor TFPCustomHashTable.Create;
  1400. begin
  1401. CreateWith(196613,@RSHash);
  1402. end;
  1403. constructor TFPCustomHashTable.CreateWith(AHashTableSize: Longword;
  1404. aHashFunc: THashFunction);
  1405. begin
  1406. Inherited Create;
  1407. FHashTable := TFPObjectList.Create(True);
  1408. HashTableSize := AHashTableSize;
  1409. FHashFunction := aHashFunc;
  1410. end;
  1411. destructor TFPCustomHashTable.Destroy;
  1412. begin
  1413. FHashTable.Free;
  1414. inherited Destroy;
  1415. end;
  1416. function TFPCustomHashTable.GetDensity: Longword;
  1417. begin
  1418. Result := FHashTableSize - VoidSlots
  1419. end;
  1420. function TFPCustomHashTable.GetNumberOfCollisions: Longword;
  1421. begin
  1422. Result := FCount -(FHashTableSize - VoidSlots)
  1423. end;
  1424. procedure TFPCustomHashTable.SetHashTableSize(const Value: Longword);
  1425. var
  1426. i: Longword;
  1427. newSize: Longword;
  1428. begin
  1429. if Value <> FHashTableSize then
  1430. begin
  1431. i := 0;
  1432. while (PRIMELIST[i] < Value) and (i < 27) do
  1433. inc(i);
  1434. newSize := PRIMELIST[i];
  1435. if Count = 0 then
  1436. begin
  1437. FHashTableSize := newSize;
  1438. InitializeHashTable;
  1439. end
  1440. else
  1441. ChangeTableSize(newSize);
  1442. end;
  1443. end;
  1444. procedure TFPCustomHashTable.InitializeHashTable;
  1445. var
  1446. i: LongWord;
  1447. begin
  1448. if FHashTableSize>0 Then
  1449. for i := 0 to FHashTableSize-1 do
  1450. FHashTable.Add(nil);
  1451. FCount := 0;
  1452. end;
  1453. procedure TFPCustomHashTable.ChangeTableSize(const ANewSize: Longword);
  1454. var
  1455. SavedTable: TFPObjectList;
  1456. SavedTableSize: Longword;
  1457. i, j: Longword;
  1458. temp: THTCustomNode;
  1459. begin
  1460. SavedTable := FHashTable;
  1461. SavedTableSize := FHashTableSize;
  1462. FHashTableSize := ANewSize;
  1463. FHashTable := TFPObjectList.Create(True);
  1464. InitializeHashTable;
  1465. If SavedTableSize>0 Then
  1466. for i := 0 to SavedTableSize-1 do
  1467. begin
  1468. if Assigned(SavedTable[i]) then
  1469. for j := 0 to TFPObjectList(SavedTable[i]).Count -1 do
  1470. begin
  1471. temp := THTCustomNode(TFPObjectList(SavedTable[i])[j]);
  1472. AddNode(temp);
  1473. end;
  1474. end;
  1475. SavedTable.Free;
  1476. end;
  1477. procedure TFPCustomHashTable.SetHashFunction(AHashFunction: THashFunction);
  1478. begin
  1479. if IsEmpty then
  1480. FHashFunction := AHashFunction
  1481. else
  1482. raise Exception.Create(NotEmptyMsg);
  1483. end;
  1484. function TFPCustomHashTable.Find(const aKey: string): THTCustomNode;
  1485. var
  1486. hashCode: Longword;
  1487. chn: TFPObjectList;
  1488. i: Longword;
  1489. begin
  1490. hashCode := FHashFunction(aKey, FHashTableSize);
  1491. chn := Chain(hashCode);
  1492. if Assigned(chn) then
  1493. begin
  1494. if chn.count>0 then
  1495. for i := 0 to chn.Count - 1 do
  1496. if THTCustomNode(chn[i]).HasKey(aKey) then
  1497. begin
  1498. result := THTCustomNode(chn[i]);
  1499. exit;
  1500. end;
  1501. end;
  1502. Result := nil;
  1503. end;
  1504. Function TFPCustomHashTable.FindChainForAdd(Const aKey : String) : TFPObjectList;
  1505. var
  1506. hashCode: Longword;
  1507. i: Longword;
  1508. begin
  1509. hashCode := FHashFunction(aKey, FHashTableSize);
  1510. Result := Chain(hashCode);
  1511. if Assigned(Result) then
  1512. begin
  1513. if Result.count>0 then
  1514. for i := 0 to Result.Count - 1 do
  1515. if THTCustomNode(Result[i]).HasKey(aKey) then
  1516. Raise EDuplicate.CreateFmt(DuplicateMsg, [aKey]);
  1517. end
  1518. else
  1519. begin
  1520. FHashTable[hashcode] := TFPObjectList.Create(true);
  1521. Result := Chain(hashcode);
  1522. end;
  1523. inc(FCount);
  1524. end;
  1525. procedure TFPCustomHashTable.Delete(const aKey: string);
  1526. var
  1527. hashCode: Longword;
  1528. chn: TFPObjectList;
  1529. i: Longword;
  1530. begin
  1531. hashCode := FHashFunction(aKey, FHashTableSize);
  1532. chn := Chain(hashCode);
  1533. if Assigned(chn) then
  1534. begin
  1535. if chn.count>0 then
  1536. for i := 0 to chn.Count - 1 do
  1537. if THTCustomNode(chn[i]).HasKey(aKey) then
  1538. begin
  1539. chn.Delete(i);
  1540. dec(FCount);
  1541. exit;
  1542. end;
  1543. end;
  1544. raise EKeyNotFound.CreateFmt(KeyNotFoundMsg, ['Delete', aKey]);
  1545. end;
  1546. function TFPCustomHashTable.IsEmpty: boolean;
  1547. begin
  1548. Result := (FCount = 0);
  1549. end;
  1550. function TFPCustomHashTable.Chain(const index: Longword): TFPObjectList;
  1551. begin
  1552. Result := TFPObjectList(FHashTable[index]);
  1553. end;
  1554. function TFPCustomHashTable.GetVoidSlots: Longword;
  1555. var
  1556. i: Longword;
  1557. num: Longword;
  1558. begin
  1559. num := 0;
  1560. if FHashTableSize>0 Then
  1561. for i:= 0 to FHashTableSize-1 do
  1562. if Not Assigned(Chain(i)) then
  1563. inc(num);
  1564. result := num;
  1565. end;
  1566. function TFPCustomHashTable.GetLoadFactor: double;
  1567. begin
  1568. Result := Count / FHashTableSize;
  1569. end;
  1570. function TFPCustomHashTable.GetAVGChainLen: double;
  1571. begin
  1572. result := Count / (FHashTableSize - VoidSlots);
  1573. end;
  1574. function TFPCustomHashTable.GetMaxChainLength: Longword;
  1575. var
  1576. i: Longword;
  1577. begin
  1578. Result := 0;
  1579. if FHashTableSize>0 Then
  1580. for i := 0 to FHashTableSize-1 do
  1581. if ChainLength(i) > Result then
  1582. Result := ChainLength(i);
  1583. end;
  1584. function TFPCustomHashTable.FindOrCreateNew(const aKey: string): THTCustomNode;
  1585. var
  1586. hashCode: Longword;
  1587. chn: TFPObjectList;
  1588. i: Longword;
  1589. begin
  1590. hashCode := FHashFunction(aKey, FHashTableSize);
  1591. chn := Chain(hashCode);
  1592. if Assigned(chn) then
  1593. begin
  1594. if chn.count>0 then
  1595. for i := 0 to chn.Count - 1 do
  1596. if THTCustomNode(chn[i]).HasKey(aKey) then
  1597. begin
  1598. Result := THTNode(chn[i]);
  1599. exit;
  1600. end
  1601. end
  1602. else
  1603. begin
  1604. FHashTable[hashcode] := TFPObjectList.Create(true);
  1605. chn := Chain(hashcode);
  1606. end;
  1607. inc(FCount);
  1608. Result := CreateNewNode(aKey);
  1609. chn.Add(Result);
  1610. end;
  1611. function TFPCustomHashTable.ChainLength(const ChainIndex: Longword): Longword;
  1612. begin
  1613. if Assigned(Chain(ChainIndex)) then
  1614. Result := Chain(ChainIndex).Count
  1615. else
  1616. Result := 0;
  1617. end;
  1618. procedure TFPCustomHashTable.Clear;
  1619. var
  1620. i: Longword;
  1621. begin
  1622. if FHashTableSize>0 Then
  1623. for i := 0 to FHashTableSize - 1 do
  1624. begin
  1625. if Assigned(Chain(i)) then
  1626. Chain(i).Clear;
  1627. end;
  1628. FCount := 0;
  1629. end;
  1630. { TFPDataHashTable }
  1631. procedure TFPDataHashTable.Add(const aKey: string; aItem: pointer);
  1632. var
  1633. chn: TFPObjectList;
  1634. NewNode: THtDataNode;
  1635. begin
  1636. chn:=FindChainForAdd(akey);
  1637. NewNode := THtDataNode(CreateNewNode(aKey));
  1638. NewNode.Data := aItem;
  1639. chn.Add(NewNode);
  1640. end;
  1641. function TFPDataHashTable.GetData(const Index: string): Pointer;
  1642. var
  1643. node: THTDataNode;
  1644. begin
  1645. node := THTDataNode(Find(Index));
  1646. if Assigned(node) then
  1647. Result := node.Data
  1648. else
  1649. Result := nil;
  1650. end;
  1651. procedure TFPDataHashTable.SetData(const index: string; const AValue: Pointer);
  1652. begin
  1653. THTDataNode(FindOrCreateNew(index)).Data := AValue;
  1654. end;
  1655. Function TFPDataHashTable.CreateNewNode(const aKey : string) : THTCustomNode;
  1656. begin
  1657. Result:=THTDataNode.CreateWith(aKey);
  1658. end;
  1659. function TFPDataHashTable.ForEachCall(aMethod: TDataIteratorMethod): THTDataNode;
  1660. var
  1661. i, j: Longword;
  1662. continue: boolean;
  1663. begin
  1664. Result := nil;
  1665. continue := true;
  1666. if FHashTableSize>0 then
  1667. for i := 0 to FHashTableSize-1 do
  1668. begin
  1669. if assigned(Chain(i)) then
  1670. begin
  1671. if chain(i).count>0 then
  1672. for j := 0 to Chain(i).Count-1 do
  1673. begin
  1674. aMethod(THTDataNode(Chain(i)[j]).Data, THTDataNode(Chain(i)[j]).Key, continue);
  1675. if not continue then
  1676. begin
  1677. Result := THTDataNode(Chain(i)[j]);
  1678. Exit;
  1679. end;
  1680. end;
  1681. end;
  1682. end;
  1683. end;
  1684. Procedure TFPDataHashTable.AddNode(ANode : THTCustomNode);
  1685. begin
  1686. With THTDataNode(ANode) do
  1687. Add(Key,Data);
  1688. end;
  1689. { TFPStringHashTable }
  1690. Procedure TFPStringHashTable.AddNode(ANode : THTCustomNode);
  1691. begin
  1692. With THTStringNode(ANode) do
  1693. Add(Key,Data);
  1694. end;
  1695. function TFPStringHashTable.GetData(const Index: string): String;
  1696. var
  1697. node: THTStringNode;
  1698. begin
  1699. node := THTStringNode(Find(Index));
  1700. if Assigned(node) then
  1701. Result := node.Data
  1702. else
  1703. Result := '';
  1704. end;
  1705. procedure TFPStringHashTable.SetData(const index, AValue: string);
  1706. begin
  1707. THTStringNode(FindOrCreateNew(index)).Data := AValue;
  1708. end;
  1709. procedure TFPStringHashTable.Add(const aKey, aItem: string);
  1710. var
  1711. chn: TFPObjectList;
  1712. NewNode: THtStringNode;
  1713. begin
  1714. chn:=FindChainForAdd(akey);
  1715. NewNode := THtStringNode(CreateNewNode(aKey));
  1716. NewNode.Data := aItem;
  1717. chn.Add(NewNode);
  1718. end;
  1719. Function TFPStringHashTable.CreateNewNode(const aKey : string) : THTCustomNode;
  1720. begin
  1721. Result:=THTStringNode.CreateWith(aKey);
  1722. end;
  1723. function TFPStringHashTable.ForEachCall(aMethod: TStringIteratorMethod): THTStringNode;
  1724. var
  1725. i, j: Longword;
  1726. continue: boolean;
  1727. begin
  1728. Result := nil;
  1729. continue := true;
  1730. if FHashTableSize>0 then
  1731. for i := 0 to FHashTableSize-1 do
  1732. begin
  1733. if assigned(Chain(i)) then
  1734. begin
  1735. if chain(i).count>0 then
  1736. for j := 0 to Chain(i).Count-1 do
  1737. begin
  1738. aMethod(THTStringNode(Chain(i)[j]).Data, THTStringNode(Chain(i)[j]).Key, continue);
  1739. if not continue then
  1740. begin
  1741. Result := THTStringNode(Chain(i)[j]);
  1742. Exit;
  1743. end;
  1744. end;
  1745. end;
  1746. end;
  1747. end;
  1748. { TFPObjectHashTable }
  1749. Procedure TFPObjectHashTable.AddNode(ANode : THTCustomNode);
  1750. begin
  1751. With THTObjectNode(ANode) do
  1752. Add(Key,Data);
  1753. end;
  1754. function TFPObjectHashTable.GetData(const Index: string): TObject;
  1755. var
  1756. node: THTObjectNode;
  1757. begin
  1758. node := THTObjectNode(Find(Index));
  1759. if Assigned(node) then
  1760. Result := node.Data
  1761. else
  1762. Result := Nil;
  1763. end;
  1764. procedure TFPObjectHashTable.SetData(const index : string; AObject : TObject);
  1765. begin
  1766. THTObjectNode(FindOrCreateNew(index)).Data := AObject;
  1767. end;
  1768. procedure TFPObjectHashTable.Add(const aKey: string; AItem : TObject);
  1769. var
  1770. chn: TFPObjectList;
  1771. NewNode: THTObjectNode;
  1772. begin
  1773. chn:=FindChainForAdd(akey);
  1774. NewNode := THTObjectNode(CreateNewNode(aKey));
  1775. NewNode.Data := aItem;
  1776. chn.Add(NewNode);
  1777. end;
  1778. Function TFPObjectHashTable.CreateNewNode(const aKey : string) : THTCustomNode;
  1779. begin
  1780. If OwnsObjects then
  1781. Result:=THTOwnedObjectNode.CreateWith(aKey)
  1782. else
  1783. Result:=THTObjectNode.CreateWith(aKey);
  1784. end;
  1785. function TFPObjectHashTable.ForEachCall(aMethod: TObjectIteratorMethod): THTObjectNode;
  1786. var
  1787. i, j: Longword;
  1788. continue: boolean;
  1789. begin
  1790. Result := nil;
  1791. continue := true;
  1792. if FHashTableSize>0 then
  1793. for i := 0 to FHashTableSize-1 do
  1794. begin
  1795. if assigned(Chain(i)) then
  1796. begin
  1797. if chain(i).count>0 then
  1798. for j := 0 to Chain(i).Count-1 do
  1799. begin
  1800. aMethod(THTObjectNode(Chain(i)[j]).Data, THTObjectNode(Chain(i)[j]).Key, continue);
  1801. if not continue then
  1802. begin
  1803. Result := THTObjectNode(Chain(i)[j]);
  1804. Exit;
  1805. end;
  1806. end;
  1807. end;
  1808. end;
  1809. end;
  1810. constructor TFPObjectHashTable.Create(AOwnsObjects : Boolean = True);
  1811. begin
  1812. Inherited Create;
  1813. FOwnsObjects:=AOwnsObjects;
  1814. end;
  1815. constructor TFPObjectHashTable.CreateWith(AHashTableSize: Longword; aHashFunc: THashFunction; AOwnsObjects : Boolean = True);
  1816. begin
  1817. Inherited CreateWith(AHashTableSize,AHashFunc);
  1818. FOwnsObjects:=AOwnsObjects;
  1819. end;
  1820. Destructor THTOwnedObjectNode.Destroy;
  1821. begin
  1822. FreeAndNil(FData);
  1823. Inherited;
  1824. end;
  1825. end.