contnrs.pp 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739
  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. TFPList 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(TObject)
  178. private
  179. { ItemList }
  180. FHashList : PHashItemList;
  181. FCount,
  182. FCapacity : Integer;
  183. { Hash }
  184. FHashTable : PHashTable;
  185. FHashCapacity : Integer;
  186. { Strings }
  187. FStrs : PChar;
  188. FStrCount,
  189. FStrCapacity : Integer;
  190. function InternalFind(AHash:LongWord;const AName:shortstring;out PrevIndex:Integer):Integer;
  191. protected
  192. function Get(Index: Integer): Pointer; {$ifdef CCLASSESINLINE}inline;{$endif}
  193. procedure Put(Index: Integer; Item: Pointer); {$ifdef CCLASSESINLINE}inline;{$endif}
  194. procedure SetCapacity(NewCapacity: Integer);
  195. procedure SetCount(NewCount: Integer);
  196. Procedure RaiseIndexError(Index : Integer);
  197. function AddStr(const s:shortstring): Integer;
  198. procedure AddToHashTable(Index: Integer);
  199. procedure StrExpand(MinIncSize:Integer);
  200. procedure SetStrCapacity(NewCapacity: Integer);
  201. procedure SetHashCapacity(NewCapacity: Integer);
  202. procedure ReHash;
  203. public
  204. constructor Create;
  205. destructor Destroy; override;
  206. function Add(const AName:shortstring;Item: Pointer): Integer;
  207. procedure Clear;
  208. function NameOfIndex(Index: Integer): ShortString; {$ifdef CCLASSESINLINE}inline;{$endif}
  209. function HashOfIndex(Index: Integer): LongWord; {$ifdef CCLASSESINLINE}inline;{$endif}
  210. function GetNextCollision(Index: Integer): Integer;
  211. procedure Delete(Index: Integer);
  212. class procedure Error(const Msg: string; Data: PtrInt);
  213. function Expand: TFPHashList;
  214. function Extract(item: Pointer): Pointer;
  215. function IndexOf(Item: Pointer): Integer;
  216. function Find(const AName:shortstring): Pointer;
  217. function FindIndexOf(const AName:shortstring): Integer;
  218. function FindWithHash(const AName:shortstring;AHash:LongWord): Pointer;
  219. function Rename(const AOldName,ANewName:shortstring): Integer;
  220. function Remove(Item: Pointer): Integer;
  221. procedure Pack;
  222. procedure ShowStatistics;
  223. procedure ForEachCall(proc2call:TListCallback;arg:pointer);
  224. procedure ForEachCall(proc2call:TListStaticCallback;arg:pointer);
  225. property Capacity: Integer read FCapacity write SetCapacity;
  226. property Count: Integer read FCount write SetCount;
  227. property Items[Index: Integer]: Pointer read Get write Put; default;
  228. property List: PHashItemList read FHashList;
  229. property Strs: PChar read FStrs;
  230. end;
  231. {*******************************************************
  232. TFPHashObjectList (From fcl/inc/contnrs.pp)
  233. ********************************************************}
  234. TFPHashObjectList = class;
  235. { TFPHashObject }
  236. TFPHashObject = class
  237. private
  238. FOwner : TFPHashObjectList;
  239. FCachedStr : pshortstring;
  240. FStrIndex : Integer;
  241. procedure InternalChangeOwner(HashObjectList:TFPHashObjectList;const s:shortstring);
  242. protected
  243. function GetName:shortstring;virtual;
  244. function GetHash:Longword;virtual;
  245. public
  246. constructor CreateNotOwned;
  247. constructor Create(HashObjectList:TFPHashObjectList;const s:shortstring);
  248. procedure ChangeOwner(HashObjectList:TFPHashObjectList); {$ifdef CCLASSESINLINE}inline;{$endif}
  249. procedure ChangeOwnerAndName(HashObjectList:TFPHashObjectList;const s:shortstring); {$ifdef CCLASSESINLINE}inline;{$endif}
  250. procedure Rename(const ANewName:shortstring);
  251. property Name:shortstring read GetName;
  252. property Hash:Longword read GetHash;
  253. end;
  254. TFPHashObjectList = class(TObject)
  255. private
  256. FFreeObjects : Boolean;
  257. FHashList: TFPHashList;
  258. function GetCount: integer; {$ifdef CCLASSESINLINE}inline;{$endif}
  259. procedure SetCount(const AValue: integer); {$ifdef CCLASSESINLINE}inline;{$endif}
  260. protected
  261. function GetItem(Index: Integer): TObject; {$ifdef CCLASSESINLINE}inline;{$endif}
  262. procedure SetItem(Index: Integer; AObject: TObject); {$ifdef CCLASSESINLINE}inline;{$endif}
  263. procedure SetCapacity(NewCapacity: Integer); {$ifdef CCLASSESINLINE}inline;{$endif}
  264. function GetCapacity: integer; {$ifdef CCLASSESINLINE}inline;{$endif}
  265. public
  266. constructor Create(FreeObjects : boolean = True);
  267. destructor Destroy; override;
  268. procedure Clear;
  269. function Add(const AName:shortstring;AObject: TObject): Integer; {$ifdef CCLASSESINLINE}inline;{$endif}
  270. function NameOfIndex(Index: Integer): ShortString; {$ifdef CCLASSESINLINE}inline;{$endif}
  271. function HashOfIndex(Index: Integer): LongWord; {$ifdef CCLASSESINLINE}inline;{$endif}
  272. function GetNextCollision(Index: Integer): Integer; {$ifdef CCLASSESINLINE}inline;{$endif}
  273. procedure Delete(Index: Integer);
  274. function Expand: TFPHashObjectList; {$ifdef CCLASSESINLINE}inline;{$endif}
  275. function Extract(Item: TObject): TObject; {$ifdef CCLASSESINLINE}inline;{$endif}
  276. function Remove(AObject: TObject): Integer;
  277. function IndexOf(AObject: TObject): Integer; {$ifdef CCLASSESINLINE}inline;{$endif}
  278. function Find(const s:shortstring): TObject; {$ifdef CCLASSESINLINE}inline;{$endif}
  279. function FindIndexOf(const s:shortstring): Integer; {$ifdef CCLASSESINLINE}inline;{$endif}
  280. function FindWithHash(const AName:shortstring;AHash:LongWord): Pointer;
  281. function Rename(const AOldName,ANewName:shortstring): Integer; {$ifdef CCLASSESINLINE}inline;{$endif}
  282. function FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt: Integer): Integer;
  283. procedure Pack; {$ifdef CCLASSESINLINE}inline;{$endif}
  284. procedure ShowStatistics; {$ifdef CCLASSESINLINE}inline;{$endif}
  285. procedure ForEachCall(proc2call:TObjectListCallback;arg:pointer); {$ifdef CCLASSESINLINE}inline;{$endif}
  286. procedure ForEachCall(proc2call:TObjectListStaticCallback;arg:pointer); {$ifdef CCLASSESINLINE}inline;{$endif}
  287. property Capacity: Integer read GetCapacity write SetCapacity;
  288. property Count: Integer read GetCount write SetCount;
  289. property OwnsObjects: Boolean read FFreeObjects write FFreeObjects;
  290. property Items[Index: Integer]: TObject read GetItem write SetItem; default;
  291. property List: TFPHashList read FHashList;
  292. end;
  293. { ---------------------------------------------------------------------
  294. Hash support, implemented by Dean Zobec
  295. ---------------------------------------------------------------------}
  296. { Must return a Longword value in the range 0..TableSize,
  297. usually via a mod operator; }
  298. THashFunction = function(const S: string; const TableSize: Longword): Longword;
  299. { THTNode }
  300. THTCustomNode = class(TObject)
  301. private
  302. FKey: string;
  303. public
  304. constructor CreateWith(const AString: String);
  305. function HasKey(const AKey: string): boolean;
  306. property Key: string read FKey;
  307. end;
  308. THTCustomNodeClass = Class of THTCustomNode;
  309. { TFPCustomHashTable }
  310. TFPCustomHashTable = class(TObject)
  311. private
  312. FHashTable: TFPObjectList;
  313. FHashTableSize: Longword;
  314. FHashFunction: THashFunction;
  315. FCount: Longword;
  316. function GetDensity: Longword;
  317. function GetNumberOfCollisions: Longword;
  318. procedure SetHashTableSize(const Value: Longword);
  319. procedure InitializeHashTable;
  320. function GetVoidSlots: Longword;
  321. function GetLoadFactor: double;
  322. function GetAVGChainLen: double;
  323. function GetMaxChainLength: Longword;
  324. function Chain(const index: Longword):TFPObjectList;
  325. protected
  326. Function CreateNewNode(const aKey : string) : THTCustomNode; virtual; abstract;
  327. Procedure AddNode(ANode : THTCustomNode); virtual; abstract;
  328. function ChainLength(const ChainIndex: Longword): Longword; virtual;
  329. function FindOrCreateNew(const aKey: string): THTCustomNode; virtual;
  330. procedure SetHashFunction(AHashFunction: THashFunction); virtual;
  331. Function FindChainForAdd(Const aKey : String) : TFPObjectList;
  332. public
  333. constructor Create;
  334. constructor CreateWith(AHashTableSize: Longword; aHashFunc: THashFunction);
  335. destructor Destroy; override;
  336. procedure ChangeTableSize(const ANewSize: Longword); virtual;
  337. procedure Clear; virtual;
  338. procedure Delete(const aKey: string); virtual;
  339. function Find(const aKey: string): THTCustomNode;
  340. function IsEmpty: boolean;
  341. property HashFunction: THashFunction read FHashFunction write SetHashFunction;
  342. property Count: Longword read FCount;
  343. property HashTableSize: Longword read FHashTableSize write SetHashTableSize;
  344. property HashTable: TFPObjectList read FHashTable;
  345. property VoidSlots: Longword read GetVoidSlots;
  346. property LoadFactor: double read GetLoadFactor;
  347. property AVGChainLen: double read GetAVGChainLen;
  348. property MaxChainLength: Longword read GetMaxChainLength;
  349. property NumberOfCollisions: Longword read GetNumberOfCollisions;
  350. property Density: Longword read GetDensity;
  351. end;
  352. { TFPDataHashTable : Hash table with simple data pointers }
  353. THTDataNode = Class(THTCustomNode)
  354. Private
  355. FData: pointer;
  356. public
  357. property Data: pointer read FData write FData;
  358. end;
  359. // For compatibility
  360. THTNode = THTDataNode;
  361. TDataIteratorMethod = procedure(Item: Pointer; const Key: string; var Continue: Boolean) of object;
  362. // For compatibility
  363. TIteratorMethod = TDataIteratorMethod;
  364. TFPDataHashTable = Class(TFPCustomHashTable)
  365. Protected
  366. Function CreateNewNode(const aKey : String) : THTCustomNode; override;
  367. Procedure AddNode(ANode : THTCustomNode); override;
  368. procedure SetData(const index: string; const AValue: Pointer); virtual;
  369. function GetData(const index: string):Pointer; virtual;
  370. function ForEachCall(aMethod: TDataIteratorMethod): THTDataNode; virtual;
  371. Public
  372. procedure Add(const aKey: string; AItem: pointer); virtual;
  373. property Items[const index: string]: Pointer read GetData write SetData; default;
  374. end;
  375. { TFPStringHashTable : Hash table with simple strings as data }
  376. THTStringNode = Class(THTCustomNode)
  377. Private
  378. FData : String;
  379. public
  380. property Data: String read FData write FData;
  381. end;
  382. TStringIteratorMethod = procedure(Item: String; const Key: string; var Continue: Boolean) of object;
  383. TFPStringHashTable = Class(TFPCustomHashTable)
  384. Protected
  385. Function CreateNewNode(const aKey : String) : THTCustomNode; override;
  386. Procedure AddNode(ANode : THTCustomNode); override;
  387. procedure SetData(const Index, AValue: string); virtual;
  388. function GetData(const index: string): String; virtual;
  389. function ForEachCall(aMethod: TStringIteratorMethod): THTStringNode; virtual;
  390. Public
  391. procedure Add(const aKey,aItem: string); virtual;
  392. property Items[const index: string]: String read GetData write SetData; default;
  393. end;
  394. { TFPStringHashTable : Hash table with simple strings as data }
  395. THTObjectNode = Class(THTCustomNode)
  396. Private
  397. FData : TObject;
  398. public
  399. property Data: TObject read FData write FData;
  400. end;
  401. THTOwnedObjectNode = Class(THTObjectNode)
  402. public
  403. Destructor Destroy; override;
  404. end;
  405. TObjectIteratorMethod = procedure(Item: TObject; const Key: string; var Continue: Boolean) of object;
  406. TFPObjectHashTable = Class(TFPCustomHashTable)
  407. Private
  408. FOwnsObjects : Boolean;
  409. Protected
  410. Function CreateNewNode(const aKey : String) : THTCustomNode; override;
  411. Procedure AddNode(ANode : THTCustomNode); override;
  412. procedure SetData(const Index: string; AObject : TObject); virtual;
  413. function GetData(const index: string): TObject; virtual;
  414. function ForEachCall(aMethod: TObjectIteratorMethod): THTObjectNode; virtual;
  415. Public
  416. constructor Create(AOwnsObjects : Boolean = True);
  417. constructor CreateWith(AHashTableSize: Longword; aHashFunc: THashFunction; AOwnsObjects : Boolean = True);
  418. procedure Add(const aKey: string; AItem : TObject); virtual;
  419. property Items[const index: string]: TObject read GetData write SetData; default;
  420. Property OwnsObjects : Boolean Read FOwnsObjects Write FOwnsObjects;
  421. end;
  422. EDuplicate = class(Exception);
  423. EKeyNotFound = class(Exception);
  424. function RSHash(const S: string; const TableSize: Longword): Longword;
  425. { ---------------------------------------------------------------------
  426. Bucket lists as in Delphi
  427. ---------------------------------------------------------------------}
  428. Type
  429. TBucketItem = record
  430. Item, Data: Pointer;
  431. end;
  432. TBucketItemArray = array of TBucketItem;
  433. TBucket = record
  434. Count : Integer;
  435. Items : TBucketItemArray;
  436. end;
  437. PBucket = ^TBucket;
  438. TBucketArray = array of TBucket;
  439. TBucketProc = procedure(AInfo, AItem, AData: Pointer; out AContinue: Boolean);
  440. TBucketProcObject = procedure(AItem, AData: Pointer; out AContinue: Boolean) of Object;
  441. { ---------------------------------------------------------------------
  442. TCustomBucketList
  443. ---------------------------------------------------------------------}
  444. { TCustomBucketList }
  445. TCustomBucketList = class(TObject)
  446. private
  447. FBuckets: TBucketArray;
  448. function GetBucketCount: Integer;
  449. function GetData(AItem: Pointer): Pointer;
  450. procedure SetData(AItem: Pointer; const AData: Pointer);
  451. procedure SetBucketCount(const Value: Integer);
  452. protected
  453. Procedure GetBucketItem(AItem: Pointer; out ABucket, AIndex: Integer);
  454. function AddItem(ABucket: Integer; AItem, AData: Pointer): Pointer; virtual;
  455. function BucketFor(AItem: Pointer): Integer; virtual; abstract;
  456. function DeleteItem(ABucket: Integer; AIndex: Integer): Pointer; virtual;
  457. Procedure Error(Msg : String; Args : Array of Const);
  458. function FindItem(AItem: Pointer; out ABucket, AIndex: Integer): Boolean; virtual;
  459. property Buckets: TBucketArray read FBuckets;
  460. property BucketCount: Integer read GetBucketCount write SetBucketCount;
  461. public
  462. destructor Destroy; override;
  463. procedure Clear;
  464. function Add(AItem, AData: Pointer): Pointer;
  465. procedure Assign(AList: TCustomBucketList);
  466. function Exists(AItem: Pointer): Boolean;
  467. function Find(AItem: Pointer; out AData: Pointer): Boolean;
  468. function ForEach(AProc: TBucketProc; AInfo: Pointer = nil): Boolean;
  469. function ForEach(AProc: TBucketProcObject): Boolean;
  470. function Remove(AItem: Pointer): Pointer;
  471. property Data[AItem: Pointer]: Pointer read GetData write SetData; default;
  472. end;
  473. { ---------------------------------------------------------------------
  474. TBucketList
  475. ---------------------------------------------------------------------}
  476. TBucketListSizes = (bl2, bl4, bl8, bl16, bl32, bl64, bl128, bl256);
  477. { TBucketList }
  478. TBucketList = class(TCustomBucketList)
  479. private
  480. FBucketMask: Byte;
  481. protected
  482. function BucketFor(AItem: Pointer): Integer; override;
  483. public
  484. constructor Create(ABuckets: TBucketListSizes = bl16);
  485. end;
  486. { ---------------------------------------------------------------------
  487. TObjectBucketList
  488. ---------------------------------------------------------------------}
  489. { TObjectBucketList }
  490. TObjectBucketList = class(TBucketList)
  491. protected
  492. function GetData(AItem: TObject): TObject;
  493. procedure SetData(AItem: TObject; const AData: TObject);
  494. public
  495. function Add(AItem, AData: TObject): TObject;
  496. function Remove(AItem: TObject): TObject;
  497. property Data[AItem: TObject]: TObject read GetData write SetData; default;
  498. end;
  499. implementation
  500. uses
  501. RtlConsts;
  502. ResourceString
  503. DuplicateMsg = 'An item with key %0:s already exists';
  504. KeyNotFoundMsg = 'Method: %0:s key [''%1:s''] not found in container';
  505. NotEmptyMsg = 'Hash table not empty.';
  506. SErrNoSuchItem = 'No item in list for %p';
  507. SDuplicateItem = 'Item already exists in list: %p';
  508. const
  509. NPRIMES = 28;
  510. PRIMELIST: array[0 .. NPRIMES-1] of Longword =
  511. ( 53, 97, 193, 389, 769,
  512. 1543, 3079, 6151, 12289, 24593,
  513. 49157, 98317, 196613, 393241, 786433,
  514. 1572869, 3145739, 6291469, 12582917, 25165843,
  515. 50331653, 100663319, 201326611, 402653189, 805306457,
  516. 1610612741, 3221225473, 4294967291 );
  517. constructor TFPObjectList.Create(FreeObjects : boolean);
  518. begin
  519. Create;
  520. FFreeObjects := Freeobjects;
  521. end;
  522. destructor TFPObjectList.Destroy;
  523. begin
  524. if (FList <> nil) then
  525. begin
  526. Clear;
  527. FList.Destroy;
  528. end;
  529. inherited Destroy;
  530. end;
  531. procedure TFPObjectList.Clear;
  532. var
  533. i: integer;
  534. begin
  535. if FFreeObjects then
  536. for i := 0 to FList.Count - 1 do
  537. TObject(FList[i]).Free;
  538. FList.Clear;
  539. end;
  540. constructor TFPObjectList.Create;
  541. begin
  542. inherited Create;
  543. FList := TFPList.Create;
  544. FFreeObjects := True;
  545. end;
  546. function TFPObjectList.GetCount: integer;
  547. begin
  548. Result := FList.Count;
  549. end;
  550. procedure TFPObjectList.SetCount(const AValue: integer);
  551. begin
  552. if FList.Count <> AValue then
  553. FList.Count := AValue;
  554. end;
  555. function TFPObjectList.GetItem(Index: Integer): TObject; {$ifdef CLASSESINLINE}inline;{$endif}
  556. begin
  557. Result := TObject(FList[Index]);
  558. end;
  559. procedure TFPObjectList.SetItem(Index: Integer; AObject: TObject); {$ifdef CLASSESINLINE}inline;{$endif}
  560. begin
  561. if OwnsObjects then
  562. TObject(FList[Index]).Free;
  563. FList[index] := AObject;
  564. end;
  565. procedure TFPObjectList.SetCapacity(NewCapacity: Integer);
  566. begin
  567. FList.Capacity := NewCapacity;
  568. end;
  569. function TFPObjectList.GetCapacity: integer;
  570. begin
  571. Result := FList.Capacity;
  572. end;
  573. function TFPObjectList.Add(AObject: TObject): Integer; {$ifdef CLASSESINLINE}inline;{$endif}
  574. begin
  575. Result := FList.Add(AObject);
  576. end;
  577. procedure TFPObjectList.Delete(Index: Integer); {$ifdef CLASSESINLINE}inline;{$endif}
  578. begin
  579. if OwnsObjects then
  580. TObject(FList[Index]).Free;
  581. FList.Delete(Index);
  582. end;
  583. procedure TFPObjectList.Exchange(Index1, Index2: Integer);
  584. begin
  585. FList.Exchange(Index1, Index2);
  586. end;
  587. function TFPObjectList.Expand: TFPObjectList;
  588. begin
  589. FList.Expand;
  590. Result := Self;
  591. end;
  592. function TFPObjectList.Extract(Item: TObject): TObject;
  593. begin
  594. Result := TObject(FList.Extract(Item));
  595. end;
  596. function TFPObjectList.Remove(AObject: TObject): Integer;
  597. begin
  598. Result := IndexOf(AObject);
  599. if (Result <> -1) then
  600. begin
  601. if OwnsObjects then
  602. TObject(FList[Result]).Free;
  603. FList.Delete(Result);
  604. end;
  605. end;
  606. function TFPObjectList.IndexOf(AObject: TObject): Integer;
  607. begin
  608. Result := FList.IndexOf(Pointer(AObject));
  609. end;
  610. function TFPObjectList.FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt : Integer): Integer;
  611. var
  612. I : Integer;
  613. begin
  614. I:=AStartAt;
  615. Result:=-1;
  616. If AExact then
  617. while (I<Count) and (Result=-1) do
  618. If Items[i].ClassType=AClass then
  619. Result:=I
  620. else
  621. Inc(I)
  622. else
  623. while (I<Count) and (Result=-1) do
  624. If Items[i].InheritsFrom(AClass) then
  625. Result:=I
  626. else
  627. Inc(I);
  628. end;
  629. procedure TFPObjectList.Insert(Index: Integer; AObject: TObject); {$ifdef CLASSESINLINE}inline;{$endif}
  630. begin
  631. FList.Insert(Index, Pointer(AObject));
  632. end;
  633. procedure TFPObjectList.Move(CurIndex, NewIndex: Integer);
  634. begin
  635. FList.Move(CurIndex, NewIndex);
  636. end;
  637. procedure TFPObjectList.Assign(Obj: TFPObjectList);
  638. var
  639. i: Integer;
  640. begin
  641. Clear;
  642. for I := 0 to Obj.Count - 1 do
  643. Add(Obj[i]);
  644. end;
  645. procedure TFPObjectList.Pack;
  646. begin
  647. FList.Pack;
  648. end;
  649. procedure TFPObjectList.Sort(Compare: TListSortCompare);
  650. begin
  651. FList.Sort(Compare);
  652. end;
  653. function TFPObjectList.First: TObject;
  654. begin
  655. Result := TObject(FList.First);
  656. end;
  657. function TFPObjectList.Last: TObject;
  658. begin
  659. Result := TObject(FList.Last);
  660. end;
  661. procedure TFPObjectList.ForEachCall(proc2call:TObjectListCallback;arg:pointer);
  662. begin
  663. FList.ForEachCall(TListCallBack(proc2call),arg);
  664. end;
  665. procedure TFPObjectList.ForEachCall(proc2call:TObjectListStaticCallback;arg:pointer);
  666. begin
  667. FList.ForEachCall(TListStaticCallBack(proc2call),arg);
  668. end;
  669. { TObjectList }
  670. constructor tobjectlist.create(freeobjects : boolean);
  671. begin
  672. inherited create;
  673. ffreeobjects:=freeobjects;
  674. end;
  675. Constructor tobjectlist.create;
  676. begin
  677. inherited create;
  678. ffreeobjects:=True;
  679. end;
  680. Procedure TObjectList.Notify(Ptr: Pointer; Action: TListNotification);
  681. begin
  682. if FFreeObjects then
  683. if (Action=lnDeleted) then
  684. TObject(Ptr).Free;
  685. inherited Notify(Ptr,Action);
  686. end;
  687. Function TObjectList.GetItem(Index: Integer): TObject;
  688. begin
  689. Result:=TObject(Inherited Get(Index));
  690. end;
  691. Procedure TObjectList.SetItem(Index: Integer; AObject: TObject);
  692. Var
  693. O : TObject;
  694. begin
  695. if OwnsObjects then
  696. begin
  697. O:=GetItem(Index);
  698. O.Free;
  699. end;
  700. Put(Index,Pointer(AObject));
  701. end;
  702. Function TObjectList.Add(AObject: TObject): Integer;
  703. begin
  704. Result:=Inherited Add(Pointer(AObject));
  705. end;
  706. Function TObjectList.Extract(Item: TObject): TObject;
  707. begin
  708. Result:=Tobject(Inherited Extract(Pointer(Item)));
  709. end;
  710. Function TObjectList.Remove(AObject: TObject): Integer;
  711. begin
  712. Result:=Inherited Remove(Pointer(AObject));
  713. end;
  714. Function TObjectList.IndexOf(AObject: TObject): Integer;
  715. begin
  716. Result:=Inherited indexOF(Pointer(AObject));
  717. end;
  718. Function TObjectList.FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt : Integer): Integer;
  719. Var
  720. I : Integer;
  721. begin
  722. I:=AStartAt;
  723. Result:=-1;
  724. If AExact then
  725. While (I<Count) and (Result=-1) do
  726. If Items[i].ClassType=AClass then
  727. Result:=I
  728. else
  729. Inc(I)
  730. else
  731. While (I<Count) and (Result=-1) do
  732. If Items[i].InheritsFrom(AClass) then
  733. Result:=I
  734. else
  735. Inc(I);
  736. end;
  737. procedure TObjectList.Insert(Index: Integer; AObject: TObject);
  738. begin
  739. Inherited Insert(Index,Pointer(AObject));
  740. end;
  741. function TObjectList.First: TObject;
  742. begin
  743. Result := TObject(Inherited First);
  744. end;
  745. function TObjectList.Last: TObject;
  746. begin
  747. Result := TObject(Inherited Last);
  748. end;
  749. { TListComponent }
  750. Type
  751. TlistComponent = Class(TComponent)
  752. Private
  753. Flist : TComponentList;
  754. Public
  755. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  756. end;
  757. procedure TlistComponent.Notification(AComponent: TComponent;
  758. Operation: TOperation);
  759. begin
  760. If (Operation=opremove) then
  761. Flist.HandleFreeNotify(Self,AComponent);
  762. inherited;
  763. end;
  764. { TComponentList }
  765. Function TComponentList.Add(AComponent: TComponent): Integer;
  766. begin
  767. Result:=Inherited Add(AComponent);
  768. end;
  769. destructor TComponentList.Destroy;
  770. begin
  771. inherited;
  772. FreeAndNil(FNotifier);
  773. end;
  774. Function TComponentList.Extract(Item: TComponent): TComponent;
  775. begin
  776. Result:=TComponent(Inherited Extract(Item));
  777. end;
  778. Function TComponentList.First: TComponent;
  779. begin
  780. Result:=TComponent(Inherited First);
  781. end;
  782. Function TComponentList.GetItems(Index: Integer): TComponent;
  783. begin
  784. Result:=TComponent(Inherited Items[Index]);
  785. end;
  786. Procedure TComponentList.HandleFreeNotify(Sender: TObject;
  787. AComponent: TComponent);
  788. begin
  789. Extract(Acomponent);
  790. end;
  791. Function TComponentList.IndexOf(AComponent: TComponent): Integer;
  792. begin
  793. Result:=Inherited IndexOf(AComponent);
  794. end;
  795. Procedure TComponentList.Insert(Index: Integer; AComponent: TComponent);
  796. begin
  797. Inherited Insert(Index,Acomponent)
  798. end;
  799. Function TComponentList.Last: TComponent;
  800. begin
  801. Result:=TComponent(Inherited Last);
  802. end;
  803. Procedure TComponentList.Notify(Ptr: Pointer; Action: TListNotification);
  804. begin
  805. If FNotifier=NIl then
  806. begin
  807. FNotifier:=TlistComponent.Create(nil);
  808. TlistComponent(FNotifier).FList:=Self;
  809. end;
  810. If Assigned(Ptr) then
  811. With TComponent(Ptr) do
  812. case Action of
  813. lnAdded : FreeNotification(FNotifier);
  814. lnExtracted, lnDeleted: RemoveFreeNotification(FNotifier);
  815. end;
  816. inherited Notify(Ptr, Action);
  817. end;
  818. Function TComponentList.Remove(AComponent: TComponent): Integer;
  819. begin
  820. Result:=Inherited Remove(AComponent);
  821. end;
  822. Procedure TComponentList.SetItems(Index: Integer; AComponent: TComponent);
  823. begin
  824. Put(Index,AComponent);
  825. end;
  826. { TClassList }
  827. Function TClassList.Add(AClass: TClass): Integer;
  828. begin
  829. Result:=Inherited Add(Pointer(AClass));
  830. end;
  831. Function TClassList.Extract(Item: TClass): TClass;
  832. begin
  833. Result:=TClass(Inherited Extract(Pointer(Item)));
  834. end;
  835. Function TClassList.First: TClass;
  836. begin
  837. Result:=TClass(Inherited First);
  838. end;
  839. Function TClassList.GetItems(Index: Integer): TClass;
  840. begin
  841. Result:=TClass(Inherited Items[Index]);
  842. end;
  843. Function TClassList.IndexOf(AClass: TClass): Integer;
  844. begin
  845. Result:=Inherited IndexOf(Pointer(AClass));
  846. end;
  847. Procedure TClassList.Insert(Index: Integer; AClass: TClass);
  848. begin
  849. Inherited Insert(index,Pointer(AClass));
  850. end;
  851. Function TClassList.Last: TClass;
  852. begin
  853. Result:=TClass(Inherited Last);
  854. end;
  855. Function TClassList.Remove(AClass: TClass): Integer;
  856. begin
  857. Result:=Inherited Remove(Pointer(AClass));
  858. end;
  859. Procedure TClassList.SetItems(Index: Integer; AClass: TClass);
  860. begin
  861. Put(Index,Pointer(Aclass));
  862. end;
  863. { TOrderedList }
  864. Function TOrderedList.AtLeast(ACount: Integer): Boolean;
  865. begin
  866. Result:=(FList.Count>=Acount)
  867. end;
  868. Function TOrderedList.Count: Integer;
  869. begin
  870. Result:=FList.Count;
  871. end;
  872. constructor TOrderedList.Create;
  873. begin
  874. FList:=Tlist.Create;
  875. end;
  876. destructor TOrderedList.Destroy;
  877. begin
  878. FList.Free;
  879. end;
  880. Function TOrderedList.Peek: Pointer;
  881. begin
  882. If AtLeast(1) then
  883. Result:=PeekItem
  884. else
  885. Result:=Nil;
  886. end;
  887. Function TOrderedList.PeekItem: Pointer;
  888. begin
  889. With Flist do
  890. Result:=Items[Count-1]
  891. end;
  892. Function TOrderedList.Pop: Pointer;
  893. begin
  894. If Atleast(1) then
  895. Result:=PopItem
  896. else
  897. Result:=Nil;
  898. end;
  899. Function TOrderedList.PopItem: Pointer;
  900. begin
  901. With FList do
  902. If Count>0 then
  903. begin
  904. Result:=Items[Count-1];
  905. Delete(Count-1);
  906. end
  907. else
  908. Result:=Nil;
  909. end;
  910. Function TOrderedList.Push(AItem: Pointer): Pointer;
  911. begin
  912. PushItem(Aitem);
  913. Result:=AItem;
  914. end;
  915. { TStack }
  916. Procedure TStack.PushItem(AItem: Pointer);
  917. begin
  918. FList.Add(Aitem);
  919. end;
  920. { TObjectStack }
  921. Function TObjectStack.Peek: TObject;
  922. begin
  923. Result:=TObject(Inherited Peek);
  924. end;
  925. Function TObjectStack.Pop: TObject;
  926. begin
  927. Result:=TObject(Inherited Pop);
  928. end;
  929. Function TObjectStack.Push(AObject: TObject): TObject;
  930. begin
  931. Result:=TObject(Inherited Push(Pointer(AObject)));
  932. end;
  933. { TQueue }
  934. Procedure TQueue.PushItem(AItem: Pointer);
  935. begin
  936. With Flist Do
  937. Insert(0,AItem);
  938. end;
  939. { TObjectQueue }
  940. Function TObjectQueue.Peek: TObject;
  941. begin
  942. Result:=TObject(Inherited Peek);
  943. end;
  944. Function TObjectQueue.Pop: TObject;
  945. begin
  946. Result:=TObject(Inherited Pop);
  947. end;
  948. Function TObjectQueue.Push(AObject: TObject): TObject;
  949. begin
  950. Result:=TObject(Inherited Push(Pointer(Aobject)));
  951. end;
  952. {*****************************************************************************
  953. TFPHashList
  954. *****************************************************************************}
  955. function FPHash(const s:shortstring):LongWord;
  956. Var
  957. p,pmax : pchar;
  958. begin
  959. {$ifopt Q+}
  960. {$define overflowon}
  961. {$Q-}
  962. {$endif}
  963. result:=0;
  964. p:=@s[1];
  965. pmax:=@s[length(s)+1];
  966. while (p<pmax) do
  967. begin
  968. result:=LongWord(LongInt(result shl 5) - LongInt(result)) xor LongWord(P^);
  969. inc(p);
  970. end;
  971. {$ifdef overflowon}
  972. {$Q+}
  973. {$undef overflowon}
  974. {$endif}
  975. end;
  976. function FPHash(P: PChar; Len: Integer): LongWord;
  977. Var
  978. pmax : pchar;
  979. begin
  980. {$ifopt Q+}
  981. {$define overflowon}
  982. {$Q-}
  983. {$endif}
  984. result:=0;
  985. pmax:=p+len;
  986. while (p<pmax) do
  987. begin
  988. result:=LongWord(LongInt(result shl 5) - LongInt(result)) xor LongWord(P^);
  989. inc(p);
  990. end;
  991. {$ifdef overflowon}
  992. {$Q+}
  993. {$undef overflowon}
  994. {$endif}
  995. end;
  996. procedure TFPHashList.RaiseIndexError(Index : Integer);
  997. begin
  998. Error(SListIndexError, Index);
  999. end;
  1000. function TFPHashList.Get(Index: Integer): Pointer;
  1001. begin
  1002. If (Index < 0) or (Index >= FCount) then
  1003. RaiseIndexError(Index);
  1004. Result:=FHashList^[Index].Data;
  1005. end;
  1006. procedure TFPHashList.Put(Index: Integer; Item: Pointer);
  1007. begin
  1008. if (Index < 0) or (Index >= FCount) then
  1009. RaiseIndexError(Index);
  1010. FHashList^[Index].Data:=Item;
  1011. end;
  1012. function TFPHashList.NameOfIndex(Index: Integer): shortstring;
  1013. begin
  1014. If (Index < 0) or (Index >= FCount) then
  1015. RaiseIndexError(Index);
  1016. with FHashList^[Index] do
  1017. begin
  1018. if StrIndex>=0 then
  1019. Result:=PShortString(@FStrs[StrIndex])^
  1020. else
  1021. Result:='';
  1022. end;
  1023. end;
  1024. function TFPHashList.HashOfIndex(Index: Integer): LongWord;
  1025. begin
  1026. If (Index < 0) or (Index >= FCount) then
  1027. RaiseIndexError(Index);
  1028. Result:=FHashList^[Index].HashValue;
  1029. end;
  1030. function TFPHashList.GetNextCollision(Index: Integer): Integer;
  1031. begin
  1032. Result:=-1;
  1033. if ((Index > -1) and (Index < FCount)) then
  1034. Result:=FHashList^[Index].NextIndex;
  1035. end;
  1036. function TFPHashList.Extract(item: Pointer): Pointer;
  1037. var
  1038. i : Integer;
  1039. begin
  1040. result := nil;
  1041. i := IndexOf(item);
  1042. if i >= 0 then
  1043. begin
  1044. Result := item;
  1045. Delete(i);
  1046. end;
  1047. end;
  1048. procedure TFPHashList.SetCapacity(NewCapacity: Integer);
  1049. begin
  1050. If (NewCapacity < FCount) or (NewCapacity > MaxHashListSize) then
  1051. Error (SListCapacityError, NewCapacity);
  1052. if NewCapacity = FCapacity then
  1053. exit;
  1054. ReallocMem(FHashList, NewCapacity*SizeOf(THashItem));
  1055. FCapacity := NewCapacity;
  1056. { Maybe expand hash also }
  1057. if FCapacity>FHashCapacity*MaxItemsPerHash then
  1058. SetHashCapacity(FCapacity div MaxItemsPerHash);
  1059. end;
  1060. procedure TFPHashList.SetCount(NewCount: Integer);
  1061. begin
  1062. if (NewCount < 0) or (NewCount > MaxHashListSize)then
  1063. Error(SListCountError, NewCount);
  1064. If NewCount > FCount then
  1065. begin
  1066. If NewCount > FCapacity then
  1067. SetCapacity(NewCount);
  1068. If FCount < NewCount then
  1069. FillChar(FHashList^[FCount], (NewCount-FCount) div Sizeof(THashItem), 0);
  1070. end;
  1071. FCount := Newcount;
  1072. end;
  1073. procedure TFPHashList.SetStrCapacity(NewCapacity: Integer);
  1074. begin
  1075. If (NewCapacity < FStrCount) or (NewCapacity > MaxHashStrSize) then
  1076. Error (SListCapacityError, NewCapacity);
  1077. if NewCapacity = FStrCapacity then
  1078. exit;
  1079. ReallocMem(FStrs, NewCapacity);
  1080. FStrCapacity := NewCapacity;
  1081. end;
  1082. procedure TFPHashList.SetHashCapacity(NewCapacity: Integer);
  1083. begin
  1084. If (NewCapacity < 1) then
  1085. Error (SListCapacityError, NewCapacity);
  1086. if FHashCapacity=NewCapacity then
  1087. exit;
  1088. FHashCapacity:=NewCapacity;
  1089. ReallocMem(FHashTable, FHashCapacity*sizeof(Integer));
  1090. ReHash;
  1091. end;
  1092. procedure TFPHashList.ReHash;
  1093. var
  1094. i : Integer;
  1095. begin
  1096. FillDword(FHashTable^,FHashCapacity,LongWord(-1));
  1097. For i:=0 To FCount-1 Do
  1098. AddToHashTable(i);
  1099. end;
  1100. constructor TFPHashList.Create;
  1101. begin
  1102. SetHashCapacity(1);
  1103. end;
  1104. destructor TFPHashList.Destroy;
  1105. begin
  1106. Clear;
  1107. if assigned(FHashTable) then
  1108. FreeMem(FHashTable);
  1109. inherited Destroy;
  1110. end;
  1111. function TFPHashList.AddStr(const s:shortstring): Integer;
  1112. var
  1113. Len : Integer;
  1114. begin
  1115. len:=length(s)+1;
  1116. if FStrCount+Len >= FStrCapacity then
  1117. StrExpand(Len);
  1118. System.Move(s[0],FStrs[FStrCount],Len);
  1119. result:=FStrCount;
  1120. inc(FStrCount,Len);
  1121. end;
  1122. procedure TFPHashList.AddToHashTable(Index: Integer);
  1123. var
  1124. HashIndex : Integer;
  1125. begin
  1126. with FHashList^[Index] do
  1127. begin
  1128. if not assigned(Data) then
  1129. exit;
  1130. HashIndex:=HashValue mod LongWord(FHashCapacity);
  1131. NextIndex:=FHashTable^[HashIndex];
  1132. FHashTable^[HashIndex]:=Index;
  1133. end;
  1134. end;
  1135. function TFPHashList.Add(const AName:shortstring;Item: Pointer): Integer;
  1136. begin
  1137. if FCount = FCapacity then
  1138. Expand;
  1139. with FHashList^[FCount] do
  1140. begin
  1141. HashValue:=FPHash(AName);
  1142. Data:=Item;
  1143. StrIndex:=AddStr(AName);
  1144. end;
  1145. AddToHashTable(FCount);
  1146. Result := FCount;
  1147. inc(FCount);
  1148. end;
  1149. procedure TFPHashList.Clear;
  1150. begin
  1151. if Assigned(FHashList) then
  1152. begin
  1153. FCount:=0;
  1154. SetCapacity(0);
  1155. FHashList := nil;
  1156. end;
  1157. SetHashCapacity(1);
  1158. FHashTable^[0]:=longword(-1); // sethashcapacity does not always call rehash
  1159. if Assigned(FStrs) then
  1160. begin
  1161. FStrCount:=0;
  1162. SetStrCapacity(0);
  1163. FStrs := nil;
  1164. end;
  1165. end;
  1166. procedure TFPHashList.Delete(Index: Integer);
  1167. begin
  1168. If (Index<0) or (Index>=FCount) then
  1169. Error (SListIndexError, Index);
  1170. { Remove from HashList }
  1171. dec(FCount);
  1172. System.Move (FHashList^[Index+1], FHashList^[Index], (FCount - Index) * Sizeof(THashItem));
  1173. { All indexes are updated, we need to build the hashtable again }
  1174. Rehash;
  1175. { Shrink the list if appropriate }
  1176. if (FCapacity > 256) and (FCount < FCapacity shr 2) then
  1177. begin
  1178. FCapacity := FCapacity shr 1;
  1179. ReallocMem(FHashList, Sizeof(THashItem) * FCapacity);
  1180. end;
  1181. end;
  1182. function TFPHashList.Remove(Item: Pointer): Integer;
  1183. begin
  1184. Result := IndexOf(Item);
  1185. If Result <> -1 then
  1186. Self.Delete(Result);
  1187. end;
  1188. class procedure TFPHashList.Error(const Msg: string; Data: PtrInt);
  1189. begin
  1190. Raise EListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame);
  1191. end;
  1192. function TFPHashList.Expand: TFPHashList;
  1193. var
  1194. IncSize : Longint;
  1195. begin
  1196. Result := Self;
  1197. if FCount < FCapacity then
  1198. exit;
  1199. IncSize := sizeof(ptrint)*2;
  1200. if FCapacity > 127 then
  1201. Inc(IncSize, FCapacity shr 2)
  1202. else if FCapacity > sizeof(ptrint)*3 then
  1203. Inc(IncSize, FCapacity shr 1)
  1204. else if FCapacity >= sizeof(ptrint) then
  1205. inc(IncSize,sizeof(ptrint));
  1206. SetCapacity(FCapacity + IncSize);
  1207. end;
  1208. procedure TFPHashList.StrExpand(MinIncSize:Integer);
  1209. var
  1210. IncSize : Longint;
  1211. begin
  1212. if FStrCount+MinIncSize < FStrCapacity then
  1213. exit;
  1214. IncSize := 64;
  1215. if FStrCapacity > 255 then
  1216. Inc(IncSize, FStrCapacity shr 2);
  1217. SetStrCapacity(FStrCapacity + IncSize + MinIncSize);
  1218. end;
  1219. function TFPHashList.IndexOf(Item: Pointer): Integer;
  1220. var
  1221. psrc : PHashItem;
  1222. Index : integer;
  1223. begin
  1224. Result:=-1;
  1225. psrc:=@FHashList^[0];
  1226. For Index:=0 To FCount-1 Do
  1227. begin
  1228. if psrc^.Data=Item then
  1229. begin
  1230. Result:=Index;
  1231. exit;
  1232. end;
  1233. inc(psrc);
  1234. end;
  1235. end;
  1236. function TFPHashList.InternalFind(AHash:LongWord;const AName:shortstring;out PrevIndex:Integer):Integer;
  1237. var
  1238. HashIndex : Integer;
  1239. Len,
  1240. LastChar : Char;
  1241. begin
  1242. HashIndex:=AHash mod LongWord(FHashCapacity);
  1243. Result:=FHashTable^[HashIndex];
  1244. Len:=Char(Length(AName));
  1245. LastChar:=AName[Byte(Len)];
  1246. PrevIndex:=-1;
  1247. while Result<>-1 do
  1248. begin
  1249. with FHashList^[Result] do
  1250. begin
  1251. if assigned(Data) and
  1252. (HashValue=AHash) and
  1253. (Len=FStrs[StrIndex]) and
  1254. (LastChar=FStrs[StrIndex+Byte(Len)]) and
  1255. (AName=PShortString(@FStrs[StrIndex])^) then
  1256. exit;
  1257. PrevIndex:=Result;
  1258. Result:=NextIndex;
  1259. end;
  1260. end;
  1261. end;
  1262. function TFPHashList.Find(const AName:shortstring): Pointer;
  1263. var
  1264. Index,
  1265. PrevIndex : Integer;
  1266. begin
  1267. Result:=nil;
  1268. Index:=InternalFind(FPHash(AName),AName,PrevIndex);
  1269. if Index=-1 then
  1270. exit;
  1271. Result:=FHashList^[Index].Data;
  1272. end;
  1273. function TFPHashList.FindIndexOf(const AName:shortstring): Integer;
  1274. var
  1275. PrevIndex : Integer;
  1276. begin
  1277. Result:=InternalFind(FPHash(AName),AName,PrevIndex);
  1278. end;
  1279. function TFPHashList.FindWithHash(const AName:shortstring;AHash:LongWord): Pointer;
  1280. var
  1281. Index,
  1282. PrevIndex : Integer;
  1283. begin
  1284. Result:=nil;
  1285. Index:=InternalFind(AHash,AName,PrevIndex);
  1286. if Index=-1 then
  1287. exit;
  1288. Result:=FHashList^[Index].Data;
  1289. end;
  1290. function TFPHashList.Rename(const AOldName,ANewName:shortstring): Integer;
  1291. var
  1292. PrevIndex,
  1293. Index : Integer;
  1294. OldHash : LongWord;
  1295. begin
  1296. Result:=-1;
  1297. OldHash:=FPHash(AOldName);
  1298. Index:=InternalFind(OldHash,AOldName,PrevIndex);
  1299. if Index=-1 then
  1300. exit;
  1301. { Remove from current Hash }
  1302. if PrevIndex<>-1 then
  1303. FHashList^[PrevIndex].NextIndex:=FHashList^[Index].NextIndex
  1304. else
  1305. FHashTable^[OldHash mod LongWord(FHashCapacity)]:=FHashList^[Index].NextIndex;
  1306. { Set new name and hash }
  1307. with FHashList^[Index] do
  1308. begin
  1309. HashValue:=FPHash(ANewName);
  1310. StrIndex:=AddStr(ANewName);
  1311. end;
  1312. { Insert back in Hash }
  1313. AddToHashTable(Index);
  1314. { Return Index }
  1315. Result:=Index;
  1316. end;
  1317. procedure TFPHashList.Pack;
  1318. var
  1319. NewCount,
  1320. i : integer;
  1321. pdest,
  1322. psrc : PHashItem;
  1323. begin
  1324. NewCount:=0;
  1325. psrc:=@FHashList^[0];
  1326. pdest:=psrc;
  1327. For I:=0 To FCount-1 Do
  1328. begin
  1329. if assigned(psrc^.Data) then
  1330. begin
  1331. pdest^:=psrc^;
  1332. inc(pdest);
  1333. inc(NewCount);
  1334. end;
  1335. inc(psrc);
  1336. end;
  1337. FCount:=NewCount;
  1338. { We need to ReHash to update the IndexNext }
  1339. ReHash;
  1340. { Release over-capacity }
  1341. SetCapacity(FCount);
  1342. SetStrCapacity(FStrCount);
  1343. end;
  1344. procedure TFPHashList.ShowStatistics;
  1345. var
  1346. HashMean,
  1347. HashStdDev : Double;
  1348. Index,
  1349. i,j : Integer;
  1350. begin
  1351. { Calculate Mean and StdDev }
  1352. HashMean:=0;
  1353. HashStdDev:=0;
  1354. for i:=0 to FHashCapacity-1 do
  1355. begin
  1356. j:=0;
  1357. Index:=FHashTable^[i];
  1358. while (Index<>-1) do
  1359. begin
  1360. inc(j);
  1361. Index:=FHashList^[Index].NextIndex;
  1362. end;
  1363. HashMean:=HashMean+j;
  1364. HashStdDev:=HashStdDev+Sqr(j);
  1365. end;
  1366. HashMean:=HashMean/FHashCapacity;
  1367. HashStdDev:=(HashStdDev-FHashCapacity*Sqr(HashMean));
  1368. If FHashCapacity>1 then
  1369. HashStdDev:=Sqrt(HashStdDev/(FHashCapacity-1))
  1370. else
  1371. HashStdDev:=0;
  1372. { Print info to stdout }
  1373. Writeln('HashSize : ',FHashCapacity);
  1374. Writeln('HashMean : ',HashMean:1:4);
  1375. Writeln('HashStdDev : ',HashStdDev:1:4);
  1376. Writeln('ListSize : ',FCount,'/',FCapacity);
  1377. Writeln('StringSize : ',FStrCount,'/',FStrCapacity);
  1378. end;
  1379. procedure TFPHashList.ForEachCall(proc2call:TListCallback;arg:pointer);
  1380. var
  1381. i : integer;
  1382. p : pointer;
  1383. begin
  1384. For I:=0 To Count-1 Do
  1385. begin
  1386. p:=FHashList^[i].Data;
  1387. if assigned(p) then
  1388. proc2call(p,arg);
  1389. end;
  1390. end;
  1391. procedure TFPHashList.ForEachCall(proc2call:TListStaticCallback;arg:pointer);
  1392. var
  1393. i : integer;
  1394. p : pointer;
  1395. begin
  1396. For I:=0 To Count-1 Do
  1397. begin
  1398. p:=FHashList^[i].Data;
  1399. if assigned(p) then
  1400. proc2call(p,arg);
  1401. end;
  1402. end;
  1403. {*****************************************************************************
  1404. TFPHashObject
  1405. *****************************************************************************}
  1406. procedure TFPHashObject.InternalChangeOwner(HashObjectList:TFPHashObjectList;const s:shortstring);
  1407. var
  1408. Index : integer;
  1409. begin
  1410. FOwner:=HashObjectList;
  1411. Index:=HashObjectList.Add(s,Self);
  1412. FStrIndex:=HashObjectList.List.List^[Index].StrIndex;
  1413. FCachedStr:=PShortString(@FOwner.List.Strs[FStrIndex]);
  1414. end;
  1415. constructor TFPHashObject.CreateNotOwned;
  1416. begin
  1417. FStrIndex:=-1;
  1418. end;
  1419. constructor TFPHashObject.Create(HashObjectList:TFPHashObjectList;const s:shortstring);
  1420. begin
  1421. InternalChangeOwner(HashObjectList,s);
  1422. end;
  1423. procedure TFPHashObject.ChangeOwner(HashObjectList:TFPHashObjectList);
  1424. begin
  1425. InternalChangeOwner(HashObjectList,PShortString(@FOwner.List.Strs[FStrIndex])^);
  1426. end;
  1427. procedure TFPHashObject.ChangeOwnerAndName(HashObjectList:TFPHashObjectList;const s:shortstring);
  1428. begin
  1429. InternalChangeOwner(HashObjectList,s);
  1430. end;
  1431. procedure TFPHashObject.Rename(const ANewName:shortstring);
  1432. var
  1433. Index : integer;
  1434. begin
  1435. Index:=FOwner.Rename(PShortString(@FOwner.List.Strs[FStrIndex])^,ANewName);
  1436. if Index<>-1 then
  1437. begin
  1438. FStrIndex:=FOwner.List.List^[Index].StrIndex;
  1439. FCachedStr:=PShortString(@FOwner.List.Strs[FStrIndex]);
  1440. end;
  1441. end;
  1442. function TFPHashObject.GetName:shortstring;
  1443. begin
  1444. if FOwner<>nil then
  1445. begin
  1446. FCachedStr:=PShortString(@FOwner.List.Strs[FStrIndex]);
  1447. Result:=FCachedStr^;
  1448. end
  1449. else
  1450. Result:='';
  1451. end;
  1452. function TFPHashObject.GetHash:Longword;
  1453. begin
  1454. if FOwner<>nil then
  1455. Result:=FPHash(PShortString(@FOwner.List.Strs[FStrIndex])^)
  1456. else
  1457. Result:=$ffffffff;
  1458. end;
  1459. {*****************************************************************************
  1460. TFPHashObjectList (Copied from rtl/objpas/classes/lists.inc)
  1461. *****************************************************************************}
  1462. constructor TFPHashObjectList.Create(FreeObjects : boolean = True);
  1463. begin
  1464. inherited Create;
  1465. FHashList := TFPHashList.Create;
  1466. FFreeObjects := Freeobjects;
  1467. end;
  1468. destructor TFPHashObjectList.Destroy;
  1469. begin
  1470. if (FHashList <> nil) then
  1471. begin
  1472. Clear;
  1473. FHashList.Destroy;
  1474. end;
  1475. inherited Destroy;
  1476. end;
  1477. procedure TFPHashObjectList.Clear;
  1478. var
  1479. i: integer;
  1480. begin
  1481. if FFreeObjects then
  1482. for i := 0 to FHashList.Count - 1 do
  1483. TObject(FHashList[i]).Free;
  1484. FHashList.Clear;
  1485. end;
  1486. function TFPHashObjectList.GetCount: integer;
  1487. begin
  1488. Result := FHashList.Count;
  1489. end;
  1490. procedure TFPHashObjectList.SetCount(const AValue: integer);
  1491. begin
  1492. if FHashList.Count <> AValue then
  1493. FHashList.Count := AValue;
  1494. end;
  1495. function TFPHashObjectList.GetItem(Index: Integer): TObject;
  1496. begin
  1497. Result := TObject(FHashList[Index]);
  1498. end;
  1499. procedure TFPHashObjectList.SetItem(Index: Integer; AObject: TObject);
  1500. begin
  1501. if OwnsObjects then
  1502. TObject(FHashList[Index]).Free;
  1503. FHashList[index] := AObject;
  1504. end;
  1505. procedure TFPHashObjectList.SetCapacity(NewCapacity: Integer);
  1506. begin
  1507. FHashList.Capacity := NewCapacity;
  1508. end;
  1509. function TFPHashObjectList.GetCapacity: integer;
  1510. begin
  1511. Result := FHashList.Capacity;
  1512. end;
  1513. function TFPHashObjectList.Add(const AName:shortstring;AObject: TObject): Integer;
  1514. begin
  1515. Result := FHashList.Add(AName,AObject);
  1516. end;
  1517. function TFPHashObjectList.NameOfIndex(Index: Integer): shortstring;
  1518. begin
  1519. Result := FHashList.NameOfIndex(Index);
  1520. end;
  1521. function TFPHashObjectList.HashOfIndex(Index: Integer): LongWord;
  1522. begin
  1523. Result := FHashList.HashOfIndex(Index);
  1524. end;
  1525. function TFPHashObjectList.GetNextCollision(Index: Integer): Integer;
  1526. begin
  1527. Result := FHashList.GetNextCollision(Index);
  1528. end;
  1529. procedure TFPHashObjectList.Delete(Index: Integer);
  1530. begin
  1531. if OwnsObjects then
  1532. TObject(FHashList[Index]).Free;
  1533. FHashList.Delete(Index);
  1534. end;
  1535. function TFPHashObjectList.Expand: TFPHashObjectList;
  1536. begin
  1537. FHashList.Expand;
  1538. Result := Self;
  1539. end;
  1540. function TFPHashObjectList.Extract(Item: TObject): TObject;
  1541. begin
  1542. Result := TObject(FHashList.Extract(Item));
  1543. end;
  1544. function TFPHashObjectList.Remove(AObject: TObject): Integer;
  1545. begin
  1546. Result := IndexOf(AObject);
  1547. if (Result <> -1) then
  1548. begin
  1549. if OwnsObjects then
  1550. TObject(FHashList[Result]).Free;
  1551. FHashList.Delete(Result);
  1552. end;
  1553. end;
  1554. function TFPHashObjectList.IndexOf(AObject: TObject): Integer;
  1555. begin
  1556. Result := FHashList.IndexOf(Pointer(AObject));
  1557. end;
  1558. function TFPHashObjectList.Find(const s:shortstring): TObject;
  1559. begin
  1560. result:=TObject(FHashList.Find(s));
  1561. end;
  1562. function TFPHashObjectList.FindIndexOf(const s:shortstring): Integer;
  1563. begin
  1564. result:=FHashList.FindIndexOf(s);
  1565. end;
  1566. function TFPHashObjectList.FindWithHash(const AName:shortstring;AHash:LongWord): Pointer;
  1567. begin
  1568. Result:=TObject(FHashList.FindWithHash(AName,AHash));
  1569. end;
  1570. function TFPHashObjectList.Rename(const AOldName,ANewName:shortstring): Integer;
  1571. begin
  1572. Result:=FHashList.Rename(AOldName,ANewName);
  1573. end;
  1574. function TFPHashObjectList.FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt : Integer): Integer;
  1575. var
  1576. I : Integer;
  1577. begin
  1578. I:=AStartAt;
  1579. Result:=-1;
  1580. If AExact then
  1581. while (I<Count) and (Result=-1) do
  1582. If Items[i].ClassType=AClass then
  1583. Result:=I
  1584. else
  1585. Inc(I)
  1586. else
  1587. while (I<Count) and (Result=-1) do
  1588. If Items[i].InheritsFrom(AClass) then
  1589. Result:=I
  1590. else
  1591. Inc(I);
  1592. end;
  1593. procedure TFPHashObjectList.Pack;
  1594. begin
  1595. FHashList.Pack;
  1596. end;
  1597. procedure TFPHashObjectList.ShowStatistics;
  1598. begin
  1599. FHashList.ShowStatistics;
  1600. end;
  1601. procedure TFPHashObjectList.ForEachCall(proc2call:TObjectListCallback;arg:pointer);
  1602. begin
  1603. FHashList.ForEachCall(TListCallBack(proc2call),arg);
  1604. end;
  1605. procedure TFPHashObjectList.ForEachCall(proc2call:TObjectListStaticCallback;arg:pointer);
  1606. begin
  1607. FHashList.ForEachCall(TListStaticCallBack(proc2call),arg);
  1608. end;
  1609. { ---------------------------------------------------------------------
  1610. Hash support, by Dean Zobec
  1611. ---------------------------------------------------------------------}
  1612. { Default hash function }
  1613. function RSHash(const S: string; const TableSize: Longword): Longword;
  1614. const
  1615. b = 378551;
  1616. var
  1617. a: Longword;
  1618. i: Longword;
  1619. begin
  1620. a := 63689;
  1621. Result := 0;
  1622. if length(s)>0 then
  1623. for i := 1 to Length(S) do
  1624. begin
  1625. Result := Result * a + Ord(S[i]);
  1626. a := a * b;
  1627. end;
  1628. Result := (Result and $7FFFFFFF) mod TableSize;
  1629. end;
  1630. { THTNode }
  1631. constructor THTCustomNode.CreateWith(const AString: string);
  1632. begin
  1633. inherited Create;
  1634. FKey := AString;
  1635. end;
  1636. function THTCustomNode.HasKey(const AKey: string): boolean;
  1637. begin
  1638. if Length(AKey) <> Length(FKey) then
  1639. begin
  1640. Result := false;
  1641. exit;
  1642. end
  1643. else
  1644. Result := CompareMem(PChar(FKey), PChar(AKey), length(AKey));
  1645. end;
  1646. { TFPCustomHashTable }
  1647. constructor TFPCustomHashTable.Create;
  1648. begin
  1649. CreateWith(196613,@RSHash);
  1650. end;
  1651. constructor TFPCustomHashTable.CreateWith(AHashTableSize: Longword;
  1652. aHashFunc: THashFunction);
  1653. begin
  1654. Inherited Create;
  1655. FHashTable := TFPObjectList.Create(True);
  1656. HashTableSize := AHashTableSize;
  1657. FHashFunction := aHashFunc;
  1658. end;
  1659. destructor TFPCustomHashTable.Destroy;
  1660. begin
  1661. FHashTable.Free;
  1662. inherited Destroy;
  1663. end;
  1664. function TFPCustomHashTable.GetDensity: Longword;
  1665. begin
  1666. Result := FHashTableSize - VoidSlots
  1667. end;
  1668. function TFPCustomHashTable.GetNumberOfCollisions: Longword;
  1669. begin
  1670. Result := FCount -(FHashTableSize - VoidSlots)
  1671. end;
  1672. procedure TFPCustomHashTable.SetHashTableSize(const Value: Longword);
  1673. var
  1674. i: Longword;
  1675. newSize: Longword;
  1676. begin
  1677. if Value <> FHashTableSize then
  1678. begin
  1679. i := 0;
  1680. while (PRIMELIST[i] < Value) and (i < 27) do
  1681. inc(i);
  1682. newSize := PRIMELIST[i];
  1683. if Count = 0 then
  1684. begin
  1685. FHashTableSize := newSize;
  1686. InitializeHashTable;
  1687. end
  1688. else
  1689. ChangeTableSize(newSize);
  1690. end;
  1691. end;
  1692. procedure TFPCustomHashTable.InitializeHashTable;
  1693. var
  1694. i: LongWord;
  1695. begin
  1696. if FHashTableSize>0 Then
  1697. for i := 0 to FHashTableSize-1 do
  1698. FHashTable.Add(nil);
  1699. FCount := 0;
  1700. end;
  1701. procedure TFPCustomHashTable.ChangeTableSize(const ANewSize: Longword);
  1702. var
  1703. SavedTable: TFPObjectList;
  1704. SavedTableSize: Longword;
  1705. i, j: Longword;
  1706. temp: THTCustomNode;
  1707. begin
  1708. SavedTable := FHashTable;
  1709. SavedTableSize := FHashTableSize;
  1710. FHashTableSize := ANewSize;
  1711. FHashTable := TFPObjectList.Create(True);
  1712. InitializeHashTable;
  1713. If SavedTableSize>0 Then
  1714. for i := 0 to SavedTableSize-1 do
  1715. begin
  1716. if Assigned(SavedTable[i]) then
  1717. for j := 0 to TFPObjectList(SavedTable[i]).Count -1 do
  1718. begin
  1719. temp := THTCustomNode(TFPObjectList(SavedTable[i])[j]);
  1720. AddNode(temp);
  1721. end;
  1722. end;
  1723. SavedTable.Free;
  1724. end;
  1725. procedure TFPCustomHashTable.SetHashFunction(AHashFunction: THashFunction);
  1726. begin
  1727. if IsEmpty then
  1728. FHashFunction := AHashFunction
  1729. else
  1730. raise Exception.Create(NotEmptyMsg);
  1731. end;
  1732. function TFPCustomHashTable.Find(const aKey: string): THTCustomNode;
  1733. var
  1734. hashCode: Longword;
  1735. chn: TFPObjectList;
  1736. i: Longword;
  1737. begin
  1738. hashCode := FHashFunction(aKey, FHashTableSize);
  1739. chn := Chain(hashCode);
  1740. if Assigned(chn) then
  1741. begin
  1742. if chn.count>0 then
  1743. for i := 0 to chn.Count - 1 do
  1744. if THTCustomNode(chn[i]).HasKey(aKey) then
  1745. begin
  1746. result := THTCustomNode(chn[i]);
  1747. exit;
  1748. end;
  1749. end;
  1750. Result := nil;
  1751. end;
  1752. Function TFPCustomHashTable.FindChainForAdd(Const aKey : String) : TFPObjectList;
  1753. var
  1754. hashCode: Longword;
  1755. i: Longword;
  1756. begin
  1757. hashCode := FHashFunction(aKey, FHashTableSize);
  1758. Result := Chain(hashCode);
  1759. if Assigned(Result) then
  1760. begin
  1761. if Result.count>0 then
  1762. for i := 0 to Result.Count - 1 do
  1763. if THTCustomNode(Result[i]).HasKey(aKey) then
  1764. Raise EDuplicate.CreateFmt(DuplicateMsg, [aKey]);
  1765. end
  1766. else
  1767. begin
  1768. FHashTable[hashcode] := TFPObjectList.Create(true);
  1769. Result := Chain(hashcode);
  1770. end;
  1771. inc(FCount);
  1772. end;
  1773. procedure TFPCustomHashTable.Delete(const aKey: string);
  1774. var
  1775. hashCode: Longword;
  1776. chn: TFPObjectList;
  1777. i: Longword;
  1778. begin
  1779. hashCode := FHashFunction(aKey, FHashTableSize);
  1780. chn := Chain(hashCode);
  1781. if Assigned(chn) then
  1782. begin
  1783. if chn.count>0 then
  1784. for i := 0 to chn.Count - 1 do
  1785. if THTCustomNode(chn[i]).HasKey(aKey) then
  1786. begin
  1787. chn.Delete(i);
  1788. dec(FCount);
  1789. exit;
  1790. end;
  1791. end;
  1792. raise EKeyNotFound.CreateFmt(KeyNotFoundMsg, ['Delete', aKey]);
  1793. end;
  1794. function TFPCustomHashTable.IsEmpty: boolean;
  1795. begin
  1796. Result := (FCount = 0);
  1797. end;
  1798. function TFPCustomHashTable.Chain(const index: Longword): TFPObjectList;
  1799. begin
  1800. Result := TFPObjectList(FHashTable[index]);
  1801. end;
  1802. function TFPCustomHashTable.GetVoidSlots: Longword;
  1803. var
  1804. i: Longword;
  1805. num: Longword;
  1806. begin
  1807. num := 0;
  1808. if FHashTableSize>0 Then
  1809. for i:= 0 to FHashTableSize-1 do
  1810. if Not Assigned(Chain(i)) then
  1811. inc(num);
  1812. result := num;
  1813. end;
  1814. function TFPCustomHashTable.GetLoadFactor: double;
  1815. begin
  1816. Result := Count / FHashTableSize;
  1817. end;
  1818. function TFPCustomHashTable.GetAVGChainLen: double;
  1819. begin
  1820. result := Count / (FHashTableSize - VoidSlots);
  1821. end;
  1822. function TFPCustomHashTable.GetMaxChainLength: Longword;
  1823. var
  1824. i: Longword;
  1825. begin
  1826. Result := 0;
  1827. if FHashTableSize>0 Then
  1828. for i := 0 to FHashTableSize-1 do
  1829. if ChainLength(i) > Result then
  1830. Result := ChainLength(i);
  1831. end;
  1832. function TFPCustomHashTable.FindOrCreateNew(const aKey: string): THTCustomNode;
  1833. var
  1834. hashCode: Longword;
  1835. chn: TFPObjectList;
  1836. i: Longword;
  1837. begin
  1838. hashCode := FHashFunction(aKey, FHashTableSize);
  1839. chn := Chain(hashCode);
  1840. if Assigned(chn) then
  1841. begin
  1842. if chn.count>0 then
  1843. for i := 0 to chn.Count - 1 do
  1844. if THTCustomNode(chn[i]).HasKey(aKey) then
  1845. begin
  1846. Result := THTNode(chn[i]);
  1847. exit;
  1848. end
  1849. end
  1850. else
  1851. begin
  1852. FHashTable[hashcode] := TFPObjectList.Create(true);
  1853. chn := Chain(hashcode);
  1854. end;
  1855. inc(FCount);
  1856. Result := CreateNewNode(aKey);
  1857. chn.Add(Result);
  1858. end;
  1859. function TFPCustomHashTable.ChainLength(const ChainIndex: Longword): Longword;
  1860. begin
  1861. if Assigned(Chain(ChainIndex)) then
  1862. Result := Chain(ChainIndex).Count
  1863. else
  1864. Result := 0;
  1865. end;
  1866. procedure TFPCustomHashTable.Clear;
  1867. var
  1868. i: Longword;
  1869. begin
  1870. if FHashTableSize>0 Then
  1871. for i := 0 to FHashTableSize - 1 do
  1872. begin
  1873. if Assigned(Chain(i)) then
  1874. Chain(i).Clear;
  1875. end;
  1876. FCount := 0;
  1877. end;
  1878. { TFPDataHashTable }
  1879. procedure TFPDataHashTable.Add(const aKey: string; aItem: pointer);
  1880. var
  1881. chn: TFPObjectList;
  1882. NewNode: THtDataNode;
  1883. begin
  1884. chn:=FindChainForAdd(akey);
  1885. NewNode := THtDataNode(CreateNewNode(aKey));
  1886. NewNode.Data := aItem;
  1887. chn.Add(NewNode);
  1888. end;
  1889. function TFPDataHashTable.GetData(const Index: string): Pointer;
  1890. var
  1891. node: THTDataNode;
  1892. begin
  1893. node := THTDataNode(Find(Index));
  1894. if Assigned(node) then
  1895. Result := node.Data
  1896. else
  1897. Result := nil;
  1898. end;
  1899. procedure TFPDataHashTable.SetData(const index: string; const AValue: Pointer);
  1900. begin
  1901. THTDataNode(FindOrCreateNew(index)).Data := AValue;
  1902. end;
  1903. Function TFPDataHashTable.CreateNewNode(const aKey : string) : THTCustomNode;
  1904. begin
  1905. Result:=THTDataNode.CreateWith(aKey);
  1906. end;
  1907. function TFPDataHashTable.ForEachCall(aMethod: TDataIteratorMethod): THTDataNode;
  1908. var
  1909. i, j: Longword;
  1910. continue: boolean;
  1911. begin
  1912. Result := nil;
  1913. continue := true;
  1914. if FHashTableSize>0 then
  1915. for i := 0 to FHashTableSize-1 do
  1916. begin
  1917. if assigned(Chain(i)) then
  1918. begin
  1919. if chain(i).count>0 then
  1920. for j := 0 to Chain(i).Count-1 do
  1921. begin
  1922. aMethod(THTDataNode(Chain(i)[j]).Data, THTDataNode(Chain(i)[j]).Key, continue);
  1923. if not continue then
  1924. begin
  1925. Result := THTDataNode(Chain(i)[j]);
  1926. Exit;
  1927. end;
  1928. end;
  1929. end;
  1930. end;
  1931. end;
  1932. Procedure TFPDataHashTable.AddNode(ANode : THTCustomNode);
  1933. begin
  1934. With THTDataNode(ANode) do
  1935. Add(Key,Data);
  1936. end;
  1937. { TFPStringHashTable }
  1938. Procedure TFPStringHashTable.AddNode(ANode : THTCustomNode);
  1939. begin
  1940. With THTStringNode(ANode) do
  1941. Add(Key,Data);
  1942. end;
  1943. function TFPStringHashTable.GetData(const Index: string): String;
  1944. var
  1945. node: THTStringNode;
  1946. begin
  1947. node := THTStringNode(Find(Index));
  1948. if Assigned(node) then
  1949. Result := node.Data
  1950. else
  1951. Result := '';
  1952. end;
  1953. procedure TFPStringHashTable.SetData(const index, AValue: string);
  1954. begin
  1955. THTStringNode(FindOrCreateNew(index)).Data := AValue;
  1956. end;
  1957. procedure TFPStringHashTable.Add(const aKey, aItem: string);
  1958. var
  1959. chn: TFPObjectList;
  1960. NewNode: THtStringNode;
  1961. begin
  1962. chn:=FindChainForAdd(akey);
  1963. NewNode := THtStringNode(CreateNewNode(aKey));
  1964. NewNode.Data := aItem;
  1965. chn.Add(NewNode);
  1966. end;
  1967. Function TFPStringHashTable.CreateNewNode(const aKey : string) : THTCustomNode;
  1968. begin
  1969. Result:=THTStringNode.CreateWith(aKey);
  1970. end;
  1971. function TFPStringHashTable.ForEachCall(aMethod: TStringIteratorMethod): THTStringNode;
  1972. var
  1973. i, j: Longword;
  1974. continue: boolean;
  1975. begin
  1976. Result := nil;
  1977. continue := true;
  1978. if FHashTableSize>0 then
  1979. for i := 0 to FHashTableSize-1 do
  1980. begin
  1981. if assigned(Chain(i)) then
  1982. begin
  1983. if chain(i).count>0 then
  1984. for j := 0 to Chain(i).Count-1 do
  1985. begin
  1986. aMethod(THTStringNode(Chain(i)[j]).Data, THTStringNode(Chain(i)[j]).Key, continue);
  1987. if not continue then
  1988. begin
  1989. Result := THTStringNode(Chain(i)[j]);
  1990. Exit;
  1991. end;
  1992. end;
  1993. end;
  1994. end;
  1995. end;
  1996. { TFPObjectHashTable }
  1997. Procedure TFPObjectHashTable.AddNode(ANode : THTCustomNode);
  1998. begin
  1999. With THTObjectNode(ANode) do
  2000. Add(Key,Data);
  2001. end;
  2002. function TFPObjectHashTable.GetData(const Index: string): TObject;
  2003. var
  2004. node: THTObjectNode;
  2005. begin
  2006. node := THTObjectNode(Find(Index));
  2007. if Assigned(node) then
  2008. Result := node.Data
  2009. else
  2010. Result := Nil;
  2011. end;
  2012. procedure TFPObjectHashTable.SetData(const index : string; AObject : TObject);
  2013. begin
  2014. THTObjectNode(FindOrCreateNew(index)).Data := AObject;
  2015. end;
  2016. procedure TFPObjectHashTable.Add(const aKey: string; AItem : TObject);
  2017. var
  2018. chn: TFPObjectList;
  2019. NewNode: THTObjectNode;
  2020. begin
  2021. chn:=FindChainForAdd(akey);
  2022. NewNode := THTObjectNode(CreateNewNode(aKey));
  2023. NewNode.Data := aItem;
  2024. chn.Add(NewNode);
  2025. end;
  2026. Function TFPObjectHashTable.CreateNewNode(const aKey : string) : THTCustomNode;
  2027. begin
  2028. If OwnsObjects then
  2029. Result:=THTOwnedObjectNode.CreateWith(aKey)
  2030. else
  2031. Result:=THTObjectNode.CreateWith(aKey);
  2032. end;
  2033. function TFPObjectHashTable.ForEachCall(aMethod: TObjectIteratorMethod): THTObjectNode;
  2034. var
  2035. i, j: Longword;
  2036. continue: boolean;
  2037. begin
  2038. Result := nil;
  2039. continue := true;
  2040. if FHashTableSize>0 then
  2041. for i := 0 to FHashTableSize-1 do
  2042. begin
  2043. if assigned(Chain(i)) then
  2044. begin
  2045. if chain(i).count>0 then
  2046. for j := 0 to Chain(i).Count-1 do
  2047. begin
  2048. aMethod(THTObjectNode(Chain(i)[j]).Data, THTObjectNode(Chain(i)[j]).Key, continue);
  2049. if not continue then
  2050. begin
  2051. Result := THTObjectNode(Chain(i)[j]);
  2052. Exit;
  2053. end;
  2054. end;
  2055. end;
  2056. end;
  2057. end;
  2058. constructor TFPObjectHashTable.Create(AOwnsObjects : Boolean = True);
  2059. begin
  2060. Inherited Create;
  2061. FOwnsObjects:=AOwnsObjects;
  2062. end;
  2063. constructor TFPObjectHashTable.CreateWith(AHashTableSize: Longword; aHashFunc: THashFunction; AOwnsObjects : Boolean = True);
  2064. begin
  2065. Inherited CreateWith(AHashTableSize,AHashFunc);
  2066. FOwnsObjects:=AOwnsObjects;
  2067. end;
  2068. Destructor THTOwnedObjectNode.Destroy;
  2069. begin
  2070. FreeAndNil(FData);
  2071. Inherited;
  2072. end;
  2073. { TCustomBucketList }
  2074. function TCustomBucketList.GetData(AItem: Pointer): Pointer;
  2075. Var
  2076. B,I : Integer;
  2077. begin
  2078. GetBucketItem(AItem,B,I);
  2079. Result:=FBuckets[B].Items[I].Data;
  2080. end;
  2081. function TCustomBucketList.GetBucketCount: Integer;
  2082. begin
  2083. Result:=Length(FBuckets);
  2084. end;
  2085. procedure TCustomBucketList.SetData(AItem: Pointer; const AData: Pointer);
  2086. Var
  2087. B,I : Integer;
  2088. begin
  2089. GetBucketItem(AItem,B,I);
  2090. FBuckets[B].Items[I].Data:=AData;
  2091. end;
  2092. procedure TCustomBucketList.SetBucketCount(const Value: Integer);
  2093. begin
  2094. If (Value<>GetBucketCount) then
  2095. SetLength(FBuckets,Value);
  2096. end;
  2097. procedure TCustomBucketList.GetBucketItem(AItem: Pointer; out ABucket,
  2098. AIndex: Integer);
  2099. begin
  2100. If Not FindItem(AItem,ABucket,AIndex) then
  2101. Error(SErrNoSuchItem,[AItem]);
  2102. end;
  2103. function TCustomBucketList.AddItem(ABucket: Integer; AItem, AData: Pointer
  2104. ): Pointer;
  2105. Var
  2106. B : PBucket;
  2107. L : Integer;
  2108. begin
  2109. B:=@FBuckets[ABucket];
  2110. L:=Length(B^.Items);
  2111. If (B^.Count=L) then
  2112. begin
  2113. If L<8 then
  2114. L:=8
  2115. else
  2116. L:=L+L div 2;
  2117. SetLength(B^.Items,L);
  2118. end;
  2119. With B^ do
  2120. begin
  2121. Items[Count].Item:=AItem;
  2122. Items[Count].Data:=AData;
  2123. Result:=AData;
  2124. Inc(Count);
  2125. end;
  2126. end;
  2127. function TCustomBucketList.DeleteItem(ABucket: Integer; AIndex: Integer): Pointer;
  2128. Var
  2129. B : PBucket;
  2130. L : Integer;
  2131. begin
  2132. B:=@FBuckets[ABucket];
  2133. Result:=B^.Items[Aindex].Data;
  2134. If B^.Count=1 then
  2135. SetLength(B^.Items,0)
  2136. else
  2137. begin
  2138. L:=(B^.Count-AIndex-1);// No point in moving if last one...
  2139. If L>0 then
  2140. Move(B^.Items[AIndex+1],B^.Items[AIndex],L*SizeOf(TBucketItem));
  2141. end;
  2142. Dec(B^.Count);
  2143. end;
  2144. procedure TCustomBucketList.Error(Msg: String; Args: array of const);
  2145. begin
  2146. Raise ElistError.CreateFmt(Msg,Args);
  2147. end;
  2148. function TCustomBucketList.FindItem(AItem: Pointer; out ABucket, AIndex: Integer
  2149. ): Boolean;
  2150. Var
  2151. I : Integer;
  2152. B : TBucket;
  2153. begin
  2154. ABucket:=BucketFor(AItem);
  2155. B:=FBuckets[ABucket];
  2156. I:=B.Count-1;
  2157. While (I>=0) And (B.Items[I].Item<>AItem) do
  2158. Dec(I);
  2159. Result:=I>=0;
  2160. If Result then
  2161. AIndex:=I;
  2162. end;
  2163. destructor TCustomBucketList.Destroy;
  2164. begin
  2165. Clear;
  2166. inherited Destroy;
  2167. end;
  2168. procedure TCustomBucketList.Clear;
  2169. Var
  2170. B : TBucket;
  2171. I,J : Integer;
  2172. begin
  2173. For I:=0 to Length(FBuckets)-1 do
  2174. begin
  2175. B:=FBuckets[I];
  2176. For J:=B.Count-1 downto 0 do
  2177. DeleteItem(I,J);
  2178. end;
  2179. SetLength(FBuckets,0);
  2180. end;
  2181. function TCustomBucketList.Add(AItem, AData: Pointer): Pointer;
  2182. Var
  2183. B,I : Integer;
  2184. begin
  2185. If FindItem(AItem,B,I) then
  2186. Error(SDuplicateItem,[AItem]);
  2187. Result:=AddItem(B,AItem,AData);
  2188. end;
  2189. procedure TCustomBucketList.Assign(AList: TCustomBucketList);
  2190. Var
  2191. I,J : Integer;
  2192. begin
  2193. Clear;
  2194. SetLength(FBuckets,Length(Alist.FBuckets));
  2195. For I:=0 to BucketCount-1 do
  2196. begin
  2197. SetLength(FBuckets[i].Items,Length(AList.Fbuckets[I].Items));
  2198. For J:=0 to AList.Fbuckets[I].Count-1 do
  2199. With AList.Fbuckets[I].Items[J] do
  2200. AddItem(I,Item,Data);
  2201. end;
  2202. end;
  2203. function TCustomBucketList.Exists(AItem: Pointer): Boolean;
  2204. Var
  2205. B,I : Integer;
  2206. begin
  2207. Result:=FindItem(Aitem,B,I);
  2208. end;
  2209. function TCustomBucketList.Find(AItem: Pointer; out AData: Pointer): Boolean;
  2210. Var
  2211. B,I : integer;
  2212. begin
  2213. Result:=FindItem(AItem,B,I);
  2214. If Result then
  2215. AData:=FBuckets[B].Items[I].Data;
  2216. end;
  2217. function TCustomBucketList.ForEach(AProc: TBucketProc; AInfo: Pointer
  2218. ): Boolean;
  2219. Var
  2220. I,J,S : Integer;
  2221. Bu : TBucket;
  2222. begin
  2223. I:=0;
  2224. Result:=True;
  2225. S:=GetBucketCount;
  2226. While Result and (I<S) do
  2227. begin
  2228. J:=0;
  2229. Bu:=FBuckets[I];
  2230. While Result and (J<Bu.Count) do
  2231. begin
  2232. With Bu.Items[J] do
  2233. AProc(AInfo,Item,Data,Result);
  2234. Inc(J);
  2235. end;
  2236. Inc(I);
  2237. end;
  2238. end;
  2239. function TCustomBucketList.ForEach(AProc: TBucketProcObject): Boolean;
  2240. Var
  2241. I,J,S : Integer;
  2242. Bu : TBucket;
  2243. begin
  2244. I:=0;
  2245. Result:=True;
  2246. S:=GetBucketCount;
  2247. While Result and (I<S) do
  2248. begin
  2249. J:=0;
  2250. Bu:=FBuckets[I];
  2251. While Result and (J<Bu.Count) do
  2252. begin
  2253. With Bu.Items[J] do
  2254. AProc(Item,Data,Result);
  2255. Inc(J);
  2256. end;
  2257. Inc(I);
  2258. end;
  2259. end;
  2260. function TCustomBucketList.Remove(AItem: Pointer): Pointer;
  2261. Var
  2262. B,I : integer;
  2263. begin
  2264. If FindItem(AItem,B,I) then
  2265. begin
  2266. Result:=FBuckets[B].Items[I].Data;
  2267. DeleteItem(B,I);
  2268. end
  2269. else
  2270. Result:=Nil;
  2271. end;
  2272. { TBucketList }
  2273. function TBucketList.BucketFor(AItem: Pointer): Integer;
  2274. begin
  2275. // Pointers on average have a granularity of 4
  2276. Result:=(PtrInt(AItem) shr 2) and FBucketMask;
  2277. end;
  2278. constructor TBucketList.Create(ABuckets: TBucketListSizes);
  2279. Var
  2280. L : Integer;
  2281. begin
  2282. Inherited Create;
  2283. L:=1 shl (Ord(Abuckets)+1);
  2284. SetBucketCount(L);
  2285. FBucketMask:=L-1;
  2286. end;
  2287. { TObjectBucketList }
  2288. function TObjectBucketList.GetData(AItem: TObject): TObject;
  2289. begin
  2290. Result:=TObject(Inherited GetData(AItem));
  2291. end;
  2292. procedure TObjectBucketList.SetData(AItem: TObject; const AData: TObject);
  2293. begin
  2294. Inherited SetData(Pointer(AItem),Pointer(AData));
  2295. end;
  2296. function TObjectBucketList.Add(AItem, AData: TObject): TObject;
  2297. begin
  2298. Result:=TObject(Inherited Add(Pointer(AItem),Pointer(AData)));
  2299. end;
  2300. function TObjectBucketList.Remove(AItem: TObject): TObject;
  2301. begin
  2302. Result:=TObject(Inherited Remove(Pointer(AItem)));
  2303. end;
  2304. end.