contnrs.pas 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857
  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. {$mode objfpc}
  11. unit contnrs;
  12. interface
  13. uses
  14. SysUtils, Classes;
  15. Type
  16. TObjectListCallback = Reference to Procedure(data:TObject;arg:JSValue);
  17. TFPObjectList = class(TObject)
  18. private
  19. FFreeObjects : Boolean;
  20. FList: TFPList;
  21. Function GetCount: integer;
  22. Procedure SetCount(const AValue: integer);
  23. protected
  24. Function GetItem(Index: Integer): TObject;
  25. Procedure SetItem(Index: Integer; AObject: TObject);
  26. Procedure SetCapacity(NewCapacity: Integer);
  27. Function GetCapacity: integer;
  28. public
  29. constructor Create; reintroduce;
  30. constructor Create(FreeObjects : Boolean);
  31. destructor Destroy; override;
  32. Procedure Clear;
  33. Function Add(AObject: TObject): Integer;
  34. Procedure Delete(Index: Integer);
  35. Procedure Exchange(Index1, Index2: Integer);
  36. Function Expand: TFPObjectList;
  37. Function Extract(Item: TObject): TObject;
  38. Function Remove(AObject: TObject): Integer;
  39. Function IndexOf(AObject: TObject): Integer;
  40. Function FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt: Integer): Integer;
  41. Procedure Insert(Index: Integer; AObject: TObject);
  42. Function First: TObject;
  43. Function Last: TObject;
  44. Procedure Move(CurIndex, NewIndex: Integer);
  45. Procedure Assign(Obj:TFPObjectList);
  46. Procedure Pack;
  47. Procedure Sort(Compare: TListSortCompare);
  48. Procedure ForEachCall(proc2call:TObjectListCallback;arg:JSValue);
  49. property Capacity: Integer read GetCapacity write SetCapacity;
  50. property Count: Integer read GetCount write SetCount;
  51. property OwnsObjects: Boolean read FFreeObjects write FFreeObjects;
  52. property Items[Index: Integer]: TObject read GetItem write SetItem; default;
  53. property List: TFPList read FList;
  54. end;
  55. { TObjectList }
  56. TObjectList = class(TList)
  57. private
  58. FFreeObjects : Boolean;
  59. Protected
  60. Procedure Notify(Ptr: JSValue; Action: TListNotification); override;
  61. Function GetItem(Index: Integer): TObject;
  62. Procedure SetItem(Index: Integer; AObject: TObject);
  63. public
  64. constructor Create; reintroduce;
  65. constructor Create(FreeObjects : boolean);
  66. Function Add(AObject: TObject): Integer; reintroduce;
  67. Function Extract(Item: TObject): TObject; reintroduce;
  68. Function Remove(AObject: TObject): Integer; reintroduce;
  69. Function IndexOf(AObject: TObject): Integer; reintroduce;
  70. Function FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt: Integer): Integer;
  71. Procedure Insert(Index: Integer; AObject: TObject); reintroduce;
  72. Function First: TObject; reintroduce;
  73. Function Last: TObject; reintroduce;
  74. property OwnsObjects: Boolean read FFreeObjects write FFreeObjects;
  75. property Items[Index: Integer]: TObject read GetItem write SetItem; default;
  76. end;
  77. TComponentList = class(TObjectList)
  78. Private
  79. FNotifier : TComponent;
  80. Protected
  81. Procedure Notify(Ptr: JSValue; Action: TListNotification); override;
  82. Function GetItems(Index: Integer): TComponent;
  83. Procedure SetItems(Index: Integer; AComponent: TComponent);
  84. Procedure HandleFreeNotify(Sender: TObject; AComponent: TComponent);
  85. public
  86. destructor Destroy; override;
  87. Function Add(AComponent: TComponent): Integer; reintroduce;
  88. Function Extract(Item: TComponent): TComponent; reintroduce;
  89. Function Remove(AComponent: TComponent): Integer; reintroduce;
  90. Function IndexOf(AComponent: TComponent): Integer; reintroduce;
  91. Function First: TComponent; reintroduce;
  92. Function Last: TComponent; reintroduce;
  93. Procedure Insert(Index: Integer; AComponent: TComponent); reintroduce;
  94. property Items[Index: Integer]: TComponent read GetItems write SetItems; default;
  95. end;
  96. TClassList = class(TList)
  97. protected
  98. Function GetItems(Index: Integer): TClass;
  99. Procedure SetItems(Index: Integer; AClass: TClass);
  100. public
  101. Function Add(AClass: TClass): Integer; reintroduce;
  102. Function Extract(Item: TClass): TClass; reintroduce;
  103. Function Remove(AClass: TClass): Integer; reintroduce;
  104. Function IndexOf(AClass: TClass): Integer; reintroduce;
  105. Function First: TClass; reintroduce;
  106. Function Last: TClass; reintroduce;
  107. Procedure Insert(Index: Integer; AClass: TClass); reintroduce;
  108. property Items[Index: Integer]: TClass read GetItems write SetItems; default;
  109. end;
  110. TOrderedList = class(TObject)
  111. private
  112. FList: TList;
  113. protected
  114. Procedure PushItem(AItem: JSValue); virtual; abstract;
  115. Function PopItem: JSValue; virtual;
  116. Function PeekItem: JSValue; virtual;
  117. property List: TList read FList;
  118. public
  119. constructor Create; reintroduce;
  120. destructor Destroy; override;
  121. Function Count: Integer;
  122. Function AtLeast(ACount: Integer): Boolean;
  123. Function Push(AItem: JSValue): JSValue;
  124. Function Pop: JSValue;
  125. Function Peek: JSValue;
  126. end;
  127. { TStack class }
  128. TStack = class(TOrderedList)
  129. protected
  130. Procedure PushItem(AItem: JSValue); override;
  131. end;
  132. { TObjectStack class }
  133. TObjectStack = class(TStack)
  134. public
  135. Function Push(AObject: TObject): TObject; reintroduce;
  136. Function Pop: TObject; reintroduce;
  137. Function Peek: TObject; reintroduce;
  138. end;
  139. { TQueue class }
  140. TQueue = class(TOrderedList)
  141. protected
  142. Procedure PushItem(AItem: JSValue); override;
  143. end;
  144. { TObjectQueue class }
  145. TObjectQueue = class(TQueue)
  146. public
  147. Function Push(AObject: TObject): TObject; reintroduce;
  148. Function Pop: TObject; reintroduce;
  149. Function Peek: TObject; reintroduce;
  150. end;
  151. { ---------------------------------------------------------------------
  152. Hash support, implemented by Dean Zobec
  153. ---------------------------------------------------------------------}
  154. { Must return a Longword value in the range 0..TableSize,
  155. usually via a mod operator; }
  156. THashFunction = Function(const S: string; const TableSize: Longword): Longword;
  157. { THTNode }
  158. THTCustomNode = class(TObject)
  159. private
  160. FKey: string;
  161. public
  162. constructor CreateWith(const AString: String);
  163. Function HasKey(const AKey: string): boolean;
  164. property Key: string read FKey;
  165. end;
  166. THTCustomNodeClass = Class of THTCustomNode;
  167. { TFPCustomHashTable }
  168. TFPCustomHashTable = class(TObject)
  169. private
  170. FHashTable: TFPObjectList;
  171. FHashFunction: THashFunction;
  172. FCount: Longword;
  173. Function GetDensity: Longword;
  174. Function GetNumberOfCollisions: Longword;
  175. Procedure SetHashTableSize(const Value: Longword);
  176. Procedure InitializeHashTable;
  177. Function GetVoidSlots: Longword;
  178. Function GetLoadFactor: double;
  179. Function GetAVGChainLen: double;
  180. Function GetMaxChainLength: Longword;
  181. protected
  182. FHashTableSize: Longword;
  183. Function Chain(const index: Longword):TFPObjectList;
  184. Function CreateNewNode(const aKey : string) : THTCustomNode; virtual; abstract;
  185. Procedure AddNode(ANode : THTCustomNode); virtual; abstract;
  186. Function ChainLength(const ChainIndex: Longword): Longword; virtual;
  187. Function FindOrCreateNew(const aKey: string): THTCustomNode; virtual;
  188. Procedure SetHashFunction(AHashFunction: THashFunction); virtual;
  189. Function FindChainForAdd(Const aKey : String) : TFPObjectList;
  190. public
  191. constructor Create; reintroduce;
  192. constructor CreateWith(AHashTableSize: Longword; aHashFunc: THashFunction);
  193. destructor Destroy; override;
  194. Procedure ChangeTableSize(const ANewSize: Longword); virtual;
  195. Procedure Clear; virtual;
  196. Procedure Delete(const aKey: string); virtual;
  197. Function Find(const aKey: string): THTCustomNode;
  198. Function IsEmpty: boolean;
  199. property HashFunction: THashFunction read FHashFunction write SetHashFunction;
  200. property Count: Longword read FCount;
  201. property HashTableSize: Longword read FHashTableSize write SetHashTableSize;
  202. property HashTable: TFPObjectList read FHashTable;
  203. property VoidSlots: Longword read GetVoidSlots;
  204. property LoadFactor: double read GetLoadFactor;
  205. property AVGChainLen: double read GetAVGChainLen;
  206. property MaxChainLength: Longword read GetMaxChainLength;
  207. property NumberOfCollisions: Longword read GetNumberOfCollisions;
  208. property Density: Longword read GetDensity;
  209. end;
  210. { TFPDataHashTable : Hash table with simple data JSValues }
  211. THTDataNode = Class(THTCustomNode)
  212. Private
  213. FData: JSValue;
  214. public
  215. property Data: JSValue read FData write FData;
  216. end;
  217. // For compatibility
  218. THTNode = THTDataNode;
  219. TDataIteratorMethod = Procedure(Item: JSValue; const Key: string; var Continue: Boolean) of object;
  220. TDataIteratorCallBack = Procedure(Item: JSValue; const Key: string; var Continue: Boolean);
  221. // For compatibility
  222. TIteratorMethod = TDataIteratorMethod;
  223. TFPDataHashTable = Class(TFPCustomHashTable)
  224. Private
  225. FIteratorCallBack: TDataIteratorCallBack;
  226. Procedure CallbackIterator(Item: JSValue; const Key: string; var Continue: Boolean);
  227. Protected
  228. Function CreateNewNode(const aKey : String) : THTCustomNode; override;
  229. Procedure AddNode(ANode : THTCustomNode); override;
  230. Procedure SetData(const index: string; const AValue: JSValue); virtual;
  231. Function GetData(const index: string):JSValue; virtual;
  232. Function ForEachCall(aMethod: TDataIteratorMethod): THTDataNode; virtual;
  233. Public
  234. Function Iterate(aMethod: TDataIteratorMethod): JSValue; virtual;
  235. Function Iterate(aMethod: TDataIteratorCallBack): JSValue; virtual;
  236. Procedure Add(const aKey: string; AItem: JSValue); virtual;
  237. property Items[const index: string]: JSValue read GetData write SetData; default;
  238. end;
  239. { TFPStringHashTable : Hash table with simple strings as data }
  240. THTStringNode = Class(THTCustomNode)
  241. Private
  242. FData : String;
  243. public
  244. property Data: String read FData write FData;
  245. end;
  246. TStringIteratorMethod = Procedure(Item: String; const Key: string; var Continue: Boolean) of object;
  247. TStringIteratorCallback = Procedure(Item: String; const Key: string; var Continue: Boolean);
  248. TFPStringHashTable = Class(TFPCustomHashTable)
  249. Private
  250. FIteratorCallBack: TStringIteratorCallback;
  251. Procedure CallbackIterator(Item: String; const Key: string; var Continue: Boolean);
  252. Protected
  253. Function CreateNewNode(const aKey : String) : THTCustomNode; override;
  254. Procedure AddNode(ANode : THTCustomNode); override;
  255. Procedure SetData(const Index, AValue: string); virtual;
  256. Function GetData(const index: string): String; virtual;
  257. Function ForEachCall(aMethod: TStringIteratorMethod): THTStringNode; virtual;
  258. Public
  259. Function Iterate(aMethod: TStringIteratorMethod): String; virtual;
  260. Function Iterate(aMethod: TStringIteratorCallback): String; virtual;
  261. Procedure Add(const aKey,aItem: string); virtual;
  262. property Items[const index: string]: String read GetData write SetData; default;
  263. end;
  264. { TFPStringHashTable : Hash table with simple strings as data }
  265. THTObjectNode = Class(THTCustomNode)
  266. Private
  267. FData : TObject;
  268. public
  269. property Data: TObject read FData write FData;
  270. end;
  271. THTOwnedObjectNode = Class(THTObjectNode)
  272. public
  273. destructor Destroy; override;
  274. end;
  275. TObjectIteratorMethod = Procedure(Item: TObject; const Key: string; var Continue: Boolean) of object;
  276. TObjectIteratorCallback = Procedure(Item: TObject; const Key: string; var Continue: Boolean);
  277. TFPObjectHashTable = Class(TFPCustomHashTable)
  278. Private
  279. FOwnsObjects : Boolean;
  280. FIteratorCallBack: TObjectIteratorCallback;
  281. procedure CallbackIterator(Item: TObject; const Key: string; var Continue: Boolean);
  282. Protected
  283. Function CreateNewNode(const aKey : String) : THTCustomNode; override;
  284. Procedure AddNode(ANode : THTCustomNode); override;
  285. Procedure SetData(const Index: string; AObject : TObject); virtual;
  286. Function GetData(const index: string): TObject; virtual;
  287. Function ForEachCall(aMethod: TObjectIteratorMethod): THTObjectNode; virtual;
  288. Public
  289. constructor Create(AOwnsObjects : Boolean = True); reintroduce;
  290. constructor CreateWith(AHashTableSize: Longword; aHashFunc: THashFunction; AOwnsObjects : Boolean = True); reintroduce;
  291. Function Iterate(aMethod: TObjectIteratorMethod): TObject; virtual;
  292. Function Iterate(aMethod: TObjectIteratorCallback): TObject; virtual;
  293. Procedure Add(const aKey: string; AItem : TObject); virtual;
  294. property Items[const index: string]: TObject read GetData write SetData; default;
  295. Property OwnsObjects : Boolean Read FOwnsObjects;
  296. end;
  297. EDuplicate = class(Exception);
  298. EKeyNotFound = class(Exception);
  299. Function RSHash(const S: string; const TableSize: Longword): Longword;
  300. { ---------------------------------------------------------------------
  301. Bucket lists as in Delphi
  302. ---------------------------------------------------------------------}
  303. Type
  304. TBucketItem = record
  305. Item, Data: JSValue;
  306. end;
  307. TBucketItemArray = array of TBucketItem;
  308. TBucket = record
  309. Count : Integer;
  310. Items : TBucketItemArray;
  311. end;
  312. TBucketArray = array of TBucket;
  313. TBucketProc = Reference to Procedure(AInfo, AItem, AData: JSValue; out AContinue: Boolean);
  314. { ---------------------------------------------------------------------
  315. TCustomBucketList
  316. ---------------------------------------------------------------------}
  317. { TCustomBucketList }
  318. TCustomBucketList = class(TObject)
  319. private
  320. FBuckets: TBucketArray;
  321. Function GetBucketCount: Integer;
  322. Function GetData(AItem: JSValue): JSValue;
  323. Procedure SetData(AItem: JSValue; const AData: JSValue);
  324. Procedure SetBucketCount(const Value: Integer);
  325. protected
  326. Procedure GetBucketItem(AItem: JSValue; out ABucket, AIndex: Integer);
  327. Function AddItem(ABucket: Integer; AItem, AData: JSValue): JSValue; virtual;
  328. Function BucketFor(AItem: JSValue): Integer; virtual; abstract;
  329. Function DeleteItem(ABucket: Integer; AIndex: Integer): JSValue; virtual;
  330. Procedure Error(Msg : String; Args : Array of Const);
  331. Function FindItem(AItem: JSValue; out ABucket, AIndex: Integer): Boolean; virtual;
  332. property Buckets: TBucketArray read FBuckets;
  333. property BucketCount: Integer read GetBucketCount write SetBucketCount;
  334. public
  335. destructor Destroy; override;
  336. Procedure Clear;
  337. Function Add(AItem, AData: JSValue): JSValue;
  338. Procedure Assign(AList: TCustomBucketList);
  339. Function Exists(AItem: JSValue): Boolean;
  340. Function Find(AItem: JSValue; out AData: JSValue): Boolean;
  341. Function ForEach(AProc: TBucketProc; AInfo: JSValue): Boolean;
  342. Function ForEach(AProc: TBucketProc): Boolean;
  343. Function Remove(AItem: JSValue): JSValue;
  344. property Data[AItem: JSValue]: JSValue read GetData write SetData; default;
  345. end;
  346. { ---------------------------------------------------------------------
  347. TBucketList
  348. ---------------------------------------------------------------------}
  349. TBucketListSizes = (bl2, bl4, bl8, bl16, bl32, bl64, bl128, bl256);
  350. { TBucketList }
  351. TBucketList = class(TCustomBucketList)
  352. private
  353. FBucketMask: Byte;
  354. protected
  355. Function BucketFor(AItem: JSValue): Integer; override;
  356. public
  357. constructor Create(ABuckets: TBucketListSizes = bl16); reintroduce;
  358. end;
  359. { ---------------------------------------------------------------------
  360. TObjectBucketList
  361. ---------------------------------------------------------------------}
  362. { TObjectBucketList }
  363. TObjectBucketList = class(TBucketList)
  364. protected
  365. Function GetData(AItem: TObject): TObject; reintroduce;
  366. Procedure SetData(AItem: TObject; const AData: TObject); reintroduce;
  367. public
  368. Function Add(AItem, AData: TObject): TObject; reintroduce;
  369. Function Remove(AItem: TObject): TObject; reintroduce;
  370. property Data[AItem: TObject]: TObject read GetData write SetData; default;
  371. end;
  372. implementation
  373. uses
  374. js;
  375. ResourceString
  376. DuplicateMsg = 'An item with key %0:s already exists';
  377. //KeyNotFoundMsg = 'Method: %0:s key [''%1:s''] not found in container';
  378. NotEmptyMsg = 'Hash table not empty.';
  379. SErrNoSuchItem = 'No item in list for %p';
  380. SDuplicateItem = 'Item already exists in list: %p';
  381. const
  382. NPRIMES = 28;
  383. PRIMELIST: array[0 .. NPRIMES-1] of Longword =
  384. ( 53, 97, 193, 389, 769,
  385. 1543, 3079, 6151, 12289, 24593,
  386. 49157, 98317, 196613, 393241, 786433,
  387. 1572869, 3145739, 6291469, 12582917, 25165843,
  388. 50331653, 100663319, 201326611, 402653189, 805306457,
  389. 1610612741, 3221225473, 4294967291 );
  390. constructor TFPObjectList.Create(FreeObjects : boolean);
  391. begin
  392. Create;
  393. FFreeObjects:=Freeobjects;
  394. end;
  395. destructor TFPObjectList.Destroy;
  396. begin
  397. if (FList <> nil) then
  398. begin
  399. Clear;
  400. FList.Destroy;
  401. end;
  402. inherited Destroy;
  403. end;
  404. Procedure TFPObjectList.Clear;
  405. var
  406. i: integer;
  407. O : TObject;
  408. begin
  409. if FFreeObjects then
  410. for i:=FList.Count-1 downto 0 do
  411. begin
  412. O:=TObject(FList[i]);
  413. FList[i]:=Nil;
  414. O.Free;
  415. end;
  416. FList.Clear;
  417. end;
  418. constructor TFPObjectList.Create;
  419. begin
  420. inherited Create;
  421. FList:=TFPList.Create;
  422. FFreeObjects:=True;
  423. end;
  424. Function TFPObjectList.GetCount: integer;
  425. begin
  426. Result:=FList.Count;
  427. end;
  428. Procedure TFPObjectList.SetCount(const AValue: integer);
  429. begin
  430. if FList.Count <> AValue then
  431. FList.Count:=AValue;
  432. end;
  433. Function TFPObjectList.GetItem(Index: Integer): TObject;
  434. begin
  435. Result:=TObject(FList[Index]);
  436. end;
  437. Procedure TFPObjectList.SetItem(Index: Integer; AObject: TObject);
  438. Var
  439. O : TObject;
  440. begin
  441. if OwnsObjects then
  442. begin
  443. O:=TObject(FList[Index]);
  444. FList[Index]:=AObject;
  445. O.Free;
  446. end
  447. else
  448. FList[index]:=AObject;
  449. end;
  450. Procedure TFPObjectList.SetCapacity(NewCapacity: Integer);
  451. begin
  452. FList.Capacity:=NewCapacity;
  453. end;
  454. Function TFPObjectList.GetCapacity: integer;
  455. begin
  456. Result:=FList.Capacity;
  457. end;
  458. Function TFPObjectList.Add(AObject: TObject): Integer;
  459. begin
  460. Result:=FList.Add(AObject);
  461. end;
  462. Procedure TFPObjectList.Delete(Index: Integer);
  463. Var
  464. O : TObject;
  465. begin
  466. if OwnsObjects then
  467. begin
  468. O:=TObject(FList[Index]);
  469. FList[Index]:=Nil;
  470. O.Free;
  471. end;
  472. FList.Delete(Index);
  473. end;
  474. Procedure TFPObjectList.Exchange(Index1, Index2: Integer);
  475. begin
  476. FList.Exchange(Index1, Index2);
  477. end;
  478. Function TFPObjectList.Expand: TFPObjectList;
  479. begin
  480. FList.Expand;
  481. Result:=Self;
  482. end;
  483. Function TFPObjectList.Extract(Item: TObject): TObject;
  484. begin
  485. Result:=TObject(FList.Extract(Item));
  486. end;
  487. Function TFPObjectList.Remove(AObject: TObject): Integer;
  488. Var
  489. O : TObject;
  490. begin
  491. Result:=IndexOf(AObject);
  492. if (Result <> -1) then
  493. begin
  494. if OwnsObjects then
  495. begin
  496. O:=TObject(FList[Result]);
  497. FList[Result]:=Nil;
  498. O.Free;
  499. end;
  500. FList.Delete(Result);
  501. end;
  502. end;
  503. Function TFPObjectList.IndexOf(AObject: TObject): Integer;
  504. begin
  505. Result:=FList.IndexOf(JSValue(AObject));
  506. end;
  507. Function TFPObjectList.FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt : Integer): Integer;
  508. var
  509. I : Integer;
  510. begin
  511. I:=AStartAt;
  512. Result:=-1;
  513. if AExact then
  514. while (I<Count) and (Result=-1) do
  515. if Items[i].ClassType=AClass then
  516. Result:=I
  517. else
  518. Inc(I)
  519. else
  520. while (I<Count) and (Result=-1) do
  521. if Items[i].InheritsFrom(AClass) then
  522. Result:=I
  523. else
  524. Inc(I);
  525. end;
  526. Procedure TFPObjectList.Insert(Index: Integer; AObject: TObject);
  527. begin
  528. FList.Insert(Index, JSValue(AObject));
  529. end;
  530. Procedure TFPObjectList.Move(CurIndex, NewIndex: Integer);
  531. begin
  532. FList.Move(CurIndex, NewIndex);
  533. end;
  534. Procedure TFPObjectList.Assign(Obj: TFPObjectList);
  535. var
  536. i: Integer;
  537. begin
  538. Clear;
  539. for i:=0 to Obj.Count - 1 do
  540. Add(Obj[i]);
  541. end;
  542. Procedure TFPObjectList.Pack;
  543. begin
  544. FList.Pack;
  545. end;
  546. Procedure TFPObjectList.Sort(Compare: TListSortCompare);
  547. begin
  548. FList.Sort(Compare);
  549. end;
  550. Function TFPObjectList.First: TObject;
  551. begin
  552. Result:=TObject(FList.First);
  553. end;
  554. Function TFPObjectList.Last: TObject;
  555. begin
  556. Result:=TObject(FList.Last);
  557. end;
  558. Procedure TFPObjectList.ForEachCall(proc2call:TObjectListCallback;arg:JSValue);
  559. begin
  560. FList.ForEachCall(TListCallBack(proc2call),arg);
  561. end;
  562. { TObjectList }
  563. constructor TObjectList.Create(FreeObjects: boolean);
  564. begin
  565. inherited Create;
  566. FFreeObjects:=FreeObjects;
  567. end;
  568. constructor TObjectList.Create;
  569. begin
  570. inherited Create;
  571. FFreeObjects:=True;
  572. end;
  573. Procedure TObjectList.Notify(Ptr: JSValue; Action: TListNotification);
  574. Var
  575. O : TObject;
  576. begin
  577. if FFreeObjects then
  578. if (Action=lnDeleted) then
  579. begin
  580. O:=TObject(Ptr);
  581. O.Free;
  582. end;
  583. inherited Notify(Ptr,Action);
  584. end;
  585. Function TObjectList.GetItem(Index: Integer): TObject;
  586. begin
  587. Result:=TObject(inherited Get(Index));
  588. end;
  589. Procedure TObjectList.SetItem(Index: Integer; AObject: TObject);
  590. begin
  591. // Put will take care of deleting old one in Notify.
  592. Put(Index,JSValue(AObject));
  593. end;
  594. Function TObjectList.Add(AObject: TObject): Integer;
  595. begin
  596. Result:=inherited Add(JSValue(AObject));
  597. end;
  598. Function TObjectList.Extract(Item: TObject): TObject;
  599. begin
  600. Result:=TObject(inherited Extract(JSValue(Item)));
  601. end;
  602. Function TObjectList.Remove(AObject: TObject): Integer;
  603. begin
  604. Result:=inherited Remove(JSValue(AObject));
  605. end;
  606. Function TObjectList.IndexOf(AObject: TObject): Integer;
  607. begin
  608. Result:=inherited IndexOf(JSValue(AObject));
  609. end;
  610. Function TObjectList.FindInstanceOf(AClass: TClass; AExact: Boolean;
  611. AStartAt: Integer): Integer;
  612. var
  613. I : Integer;
  614. begin
  615. I:=AStartAt;
  616. Result:=-1;
  617. if AExact then
  618. while (I<Count) and (Result=-1) do
  619. if Items[i].ClassType=AClass then
  620. Result:=I
  621. else
  622. Inc(I)
  623. else
  624. while (I<Count) and (Result=-1) do
  625. if Items[i].InheritsFrom(AClass) then
  626. Result:=I
  627. else
  628. Inc(I);
  629. end;
  630. Procedure TObjectList.Insert(Index: Integer; AObject: TObject);
  631. begin
  632. Inherited Insert(Index,JSValue(AObject));
  633. end;
  634. Function TObjectList.First: TObject;
  635. begin
  636. Result:=TObject(inherited First);
  637. end;
  638. Function TObjectList.Last: TObject;
  639. begin
  640. Result:=TObject(inherited Last);
  641. end;
  642. { TListComponent }
  643. type
  644. TlistComponent = class(TComponent)
  645. private
  646. Flist : TComponentList;
  647. public
  648. Procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  649. end;
  650. Procedure TlistComponent.Notification(AComponent: TComponent;
  651. Operation: TOperation);
  652. begin
  653. if (Operation=opRemove) then
  654. Flist.HandleFreeNotify(Self,AComponent);
  655. inherited;
  656. end;
  657. { TComponentList }
  658. Function TComponentList.Add(AComponent: TComponent): Integer;
  659. begin
  660. Result:=inherited Add(AComponent);
  661. end;
  662. destructor TComponentList.Destroy;
  663. begin
  664. inherited;
  665. FreeAndNil(FNotifier);
  666. end;
  667. Function TComponentList.Extract(Item: TComponent): TComponent;
  668. begin
  669. Result:=TComponent(inherited Extract(Item));
  670. end;
  671. Function TComponentList.First: TComponent;
  672. begin
  673. Result:=TComponent(inherited First);
  674. end;
  675. Function TComponentList.GetItems(Index: Integer): TComponent;
  676. begin
  677. Result:=TComponent(inherited Items[Index]);
  678. end;
  679. Procedure TComponentList.HandleFreeNotify(Sender: TObject;
  680. AComponent: TComponent);
  681. begin
  682. Extract(AComponent);
  683. if Sender=nil then ;
  684. end;
  685. Function TComponentList.IndexOf(AComponent: TComponent): Integer;
  686. begin
  687. Result:=inherited IndexOf(AComponent);
  688. end;
  689. Procedure TComponentList.Insert(Index: Integer; AComponent: TComponent);
  690. begin
  691. inherited Insert(Index,AComponent)
  692. end;
  693. Function TComponentList.Last: TComponent;
  694. begin
  695. Result:=TComponent(inherited Last);
  696. end;
  697. Procedure TComponentList.Notify(Ptr: JSValue; Action: TListNotification);
  698. begin
  699. if FNotifier=nil then
  700. begin
  701. FNotifier:=TlistComponent.Create(nil);
  702. TlistComponent(FNotifier).FList:=Self;
  703. end;
  704. if Assigned(Ptr) then
  705. with TComponent(Ptr) do
  706. case Action of
  707. lnAdded : FreeNotification(FNotifier);
  708. lnExtracted, lnDeleted: RemoveFreeNotification(FNotifier);
  709. end;
  710. inherited Notify(Ptr, Action);
  711. end;
  712. Function TComponentList.Remove(AComponent: TComponent): Integer;
  713. begin
  714. Result:=inherited Remove(AComponent);
  715. end;
  716. Procedure TComponentList.SetItems(Index: Integer; AComponent: TComponent);
  717. begin
  718. Put(Index,AComponent);
  719. end;
  720. { TClassList }
  721. Function TClassList.Add(AClass: TClass): Integer;
  722. begin
  723. Result:=inherited Add(JSValue(AClass));
  724. end;
  725. Function TClassList.Extract(Item: TClass): TClass;
  726. begin
  727. Result:=TClass(inherited Extract(JSValue(Item)));
  728. end;
  729. Function TClassList.First: TClass;
  730. begin
  731. Result:=TClass(inherited First);
  732. end;
  733. Function TClassList.GetItems(Index: Integer): TClass;
  734. begin
  735. Result:=TClass(inherited Items[Index]);
  736. end;
  737. Function TClassList.IndexOf(AClass: TClass): Integer;
  738. begin
  739. Result:=inherited IndexOf(JSValue(AClass));
  740. end;
  741. Procedure TClassList.Insert(Index: Integer; AClass: TClass);
  742. begin
  743. inherited Insert(Index,JSValue(AClass));
  744. end;
  745. Function TClassList.Last: TClass;
  746. begin
  747. Result:=TClass(inherited Last);
  748. end;
  749. Function TClassList.Remove(AClass: TClass): Integer;
  750. begin
  751. Result:=inherited Remove(JSValue(AClass));
  752. end;
  753. Procedure TClassList.SetItems(Index: Integer; AClass: TClass);
  754. begin
  755. Put(Index,JSValue(AClass));
  756. end;
  757. { TOrderedList }
  758. Function TOrderedList.AtLeast(ACount: Integer): Boolean;
  759. begin
  760. Result:=(FList.Count>=Acount)
  761. end;
  762. Function TOrderedList.Count: Integer;
  763. begin
  764. Result:=FList.Count;
  765. end;
  766. constructor TOrderedList.Create;
  767. begin
  768. FList:=Tlist.Create;
  769. end;
  770. destructor TOrderedList.Destroy;
  771. begin
  772. FList.Free;
  773. end;
  774. Function TOrderedList.Peek: JSValue;
  775. begin
  776. if AtLeast(1) then
  777. Result:=PeekItem
  778. else
  779. Result:=nil;
  780. end;
  781. Function TOrderedList.PeekItem: JSValue;
  782. begin
  783. with Flist do
  784. Result:=Items[Count-1]
  785. end;
  786. Function TOrderedList.Pop: JSValue;
  787. begin
  788. If Atleast(1) then
  789. Result:=PopItem
  790. else
  791. Result:=nil;
  792. end;
  793. Function TOrderedList.PopItem: JSValue;
  794. begin
  795. with FList do
  796. if Count>0 then
  797. begin
  798. Result:=Items[Count-1];
  799. Delete(Count-1);
  800. end
  801. else
  802. Result:=nil;
  803. end;
  804. Function TOrderedList.Push(AItem: JSValue): JSValue;
  805. begin
  806. PushItem(AItem);
  807. Result:=AItem;
  808. end;
  809. { TStack }
  810. Procedure TStack.PushItem(AItem: JSValue);
  811. begin
  812. FList.Add(AItem);
  813. end;
  814. { TObjectStack }
  815. Function TObjectStack.Peek: TObject;
  816. begin
  817. Result:=TObject(inherited Peek);
  818. end;
  819. Function TObjectStack.Pop: TObject;
  820. begin
  821. Result:=TObject(Inherited Pop);
  822. end;
  823. Function TObjectStack.Push(AObject: TObject): TObject;
  824. begin
  825. Result:=TObject(inherited Push(JSValue(AObject)));
  826. end;
  827. { TQueue }
  828. Procedure TQueue.PushItem(AItem: JSValue);
  829. begin
  830. with FList Do
  831. Insert(0,AItem);
  832. end;
  833. { TObjectQueue }
  834. Function TObjectQueue.Peek: TObject;
  835. begin
  836. Result:=TObject(inherited Peek);
  837. end;
  838. Function TObjectQueue.Pop: TObject;
  839. begin
  840. Result:=TObject(inherited Pop);
  841. end;
  842. Function TObjectQueue.Push(AObject: TObject): TObject;
  843. begin
  844. Result:=TObject(inherited Push(JSValue(AObject)));
  845. end;
  846. {*****************************************************************************
  847. TFPHashList
  848. *****************************************************************************}
  849. (*
  850. Function FPHash(const s:shortstring):LongWord;
  851. var
  852. p,pmax : PChar;
  853. begin
  854. {$push}
  855. {$Q-}
  856. Result:=0;
  857. p:=@s[1];
  858. pmax:=@s[length(s)+1];
  859. while (p<pmax) do
  860. begin
  861. Result:=LongWord(LongInt(Result shl 5) - LongInt(Result)) xor LongWord(P^);
  862. Inc(p);
  863. end;
  864. {$pop}
  865. end;
  866. Function FPHash(P: PChar; Len: Integer): LongWord;
  867. var
  868. pmax : PChar;
  869. begin
  870. {$push}
  871. {$Q-}
  872. Result:=0;
  873. pmax:=p+len;
  874. while (p<pmax) do
  875. begin
  876. Result:=LongWord(LongInt(Result shl 5) - LongInt(Result)) xor LongWord(P^);
  877. Inc(p);
  878. end;
  879. {$pop}
  880. end;
  881. *)
  882. { ---------------------------------------------------------------------
  883. Hash support, by Dean Zobec
  884. ---------------------------------------------------------------------}
  885. { Default hash Function }
  886. Function RSHash(const S: string; const TableSize: Longword): Longword;
  887. const
  888. b = 378551;
  889. var
  890. a: Longword;
  891. i: Longword;
  892. begin
  893. a:=63689;
  894. Result:=0;
  895. if length(s)>0 then
  896. for i:=1 to Length(S) do
  897. begin
  898. Result:=Result * a + Ord(S[i]);
  899. a:=a * b;
  900. end;
  901. Result:=(Result and $7FFFFFFF) mod TableSize;
  902. end;
  903. { THTNode }
  904. constructor THTCustomNode.CreateWith(const AString: string);
  905. begin
  906. inherited Create;
  907. FKey:=AString;
  908. end;
  909. Function THTCustomNode.HasKey(const AKey: string): boolean;
  910. begin
  911. Result:=(AKey=FKey);
  912. end;
  913. { TFPCustomHashTable }
  914. constructor TFPCustomHashTable.Create;
  915. begin
  916. CreateWith(196613,@RSHash);
  917. end;
  918. constructor TFPCustomHashTable.CreateWith(AHashTableSize: Longword;
  919. aHashFunc: THashFunction);
  920. begin
  921. inherited Create;
  922. FHashTable:=TFPObjectList.Create(True);
  923. HashTableSize:=AHashTableSize;
  924. FHashFunction:=aHashFunc;
  925. end;
  926. destructor TFPCustomHashTable.Destroy;
  927. begin
  928. FHashTable.Free;
  929. inherited Destroy;
  930. end;
  931. Function TFPCustomHashTable.GetDensity: Longword;
  932. begin
  933. Result:=FHashTableSize - VoidSlots
  934. end;
  935. Function TFPCustomHashTable.GetNumberOfCollisions: Longword;
  936. begin
  937. Result:=FCount -(FHashTableSize - VoidSlots)
  938. end;
  939. Procedure TFPCustomHashTable.SetHashTableSize(const Value: Longword);
  940. var
  941. i: Longword;
  942. newSize: Longword;
  943. begin
  944. if Value <> FHashTableSize then
  945. begin
  946. i:=0;
  947. while (PRIMELIST[i] < Value) and (i < 27) do
  948. Inc(i);
  949. newSize:=PRIMELIST[i];
  950. if Count = 0 then
  951. begin
  952. FHashTableSize:=newSize;
  953. InitializeHashTable;
  954. end
  955. else
  956. ChangeTableSize(newSize);
  957. end;
  958. end;
  959. Procedure TFPCustomHashTable.InitializeHashTable;
  960. var
  961. i: LongWord;
  962. begin
  963. if FHashTableSize>0 Then
  964. for i:=0 to FHashTableSize-1 do
  965. FHashTable.Add(nil);
  966. FCount:=0;
  967. end;
  968. Procedure TFPCustomHashTable.ChangeTableSize(const ANewSize: Longword);
  969. var
  970. SavedTable, List: TFPObjectList;
  971. SavedTableSize: Longword;
  972. i, j: Longword;
  973. temp: THTCustomNode;
  974. begin
  975. SavedTable:=FHashTable;
  976. SavedTableSize:=FHashTableSize;
  977. FHashTableSize:=ANewSize;
  978. FHashTable:=TFPObjectList.Create(True);
  979. InitializeHashTable;
  980. if SavedTableSize>0 Then
  981. for i:=0 to SavedTableSize-1 do
  982. begin
  983. List:=TFPObjectList(SavedTable[i]);
  984. if Assigned(List) then
  985. for j:=0 to List.Count -1 do
  986. begin
  987. temp:=THTCustomNode(List[j]);
  988. AddNode(temp);
  989. end;
  990. end;
  991. SavedTable.Free;
  992. end;
  993. Procedure TFPCustomHashTable.SetHashFunction(AHashFunction: THashFunction);
  994. begin
  995. if IsEmpty then
  996. FHashFunction:=AHashFunction
  997. else
  998. raise Exception.Create(NotEmptyMsg);
  999. end;
  1000. Function TFPCustomHashTable.Find(const aKey: string): THTCustomNode;
  1001. var
  1002. hashCode: Longword;
  1003. chn: TFPObjectList;
  1004. i: Longword;
  1005. begin
  1006. hashCode:=FHashFunction(aKey, FHashTableSize);
  1007. chn:=Chain(hashCode);
  1008. if Assigned(chn) then
  1009. if chn.count>0 then
  1010. for i:=0 to chn.Count - 1 do
  1011. if THTCustomNode(chn[i]).Key=aKey then
  1012. Exit(THTCustomNode(chn[i]));
  1013. Result:=nil;
  1014. end;
  1015. Function TFPCustomHashTable.FindChainForAdd(Const aKey : String) : TFPObjectList;
  1016. var
  1017. hashCode: Longword;
  1018. i: Longword;
  1019. begin
  1020. hashCode:=FHashFunction(aKey, FHashTableSize);
  1021. Result:=Chain(hashCode);
  1022. if Assigned(Result) then
  1023. begin
  1024. if Result.count>0 then
  1025. for i:=0 to Result.Count - 1 do
  1026. if (THTCustomNode(Result[i]).Key=aKey) then
  1027. raise EDuplicate.CreateFmt(DuplicateMsg, [aKey]);
  1028. end
  1029. else
  1030. begin
  1031. FHashTable[hashcode]:=TFPObjectList.Create(True);
  1032. Result:=Chain(hashCode);
  1033. end;
  1034. Inc(FCount);
  1035. end;
  1036. Procedure TFPCustomHashTable.Delete(const aKey: string);
  1037. var
  1038. hashCode: Longword;
  1039. chn: TFPObjectList;
  1040. i: Longword;
  1041. begin
  1042. hashCode:=FHashFunction(aKey, FHashTableSize);
  1043. chn:=Chain(hashCode);
  1044. if Assigned(chn) then
  1045. if chn.count>0 then
  1046. for i:=0 to chn.Count - 1 do
  1047. if THTCustomNode(chn[i]).Key=aKey then
  1048. begin
  1049. chn.Delete(i);
  1050. dec(FCount);
  1051. Exit;
  1052. end;
  1053. end;
  1054. Function TFPCustomHashTable.IsEmpty: boolean;
  1055. begin
  1056. Result:=(FCount = 0);
  1057. end;
  1058. Function TFPCustomHashTable.Chain(const index: Longword): TFPObjectList;
  1059. begin
  1060. Result:=TFPObjectList(FHashTable[index]);
  1061. end;
  1062. Function TFPCustomHashTable.GetVoidSlots: Longword;
  1063. var
  1064. i: Longword;
  1065. num: Longword;
  1066. begin
  1067. num:=0;
  1068. if FHashTableSize>0 then
  1069. for i:= 0 to FHashTableSize-1 do
  1070. if not Assigned(Chain(i)) then
  1071. Inc(num);
  1072. Result:=num;
  1073. end;
  1074. Function TFPCustomHashTable.GetLoadFactor: double;
  1075. begin
  1076. Result:=Count / FHashTableSize;
  1077. end;
  1078. Function TFPCustomHashTable.GetAVGChainLen: double;
  1079. begin
  1080. Result:=Count / (FHashTableSize - VoidSlots);
  1081. end;
  1082. Function TFPCustomHashTable.GetMaxChainLength: Longword;
  1083. var
  1084. i: Longword;
  1085. begin
  1086. Result:=0;
  1087. if FHashTableSize>0 Then
  1088. for i:=0 to FHashTableSize-1 do
  1089. if ChainLength(i) > Result then
  1090. Result:=ChainLength(i);
  1091. end;
  1092. Function TFPCustomHashTable.FindOrCreateNew(const aKey: string): THTCustomNode;
  1093. var
  1094. hashCode: Longword;
  1095. chn: TFPObjectList;
  1096. i: Longword;
  1097. begin
  1098. hashCode:=FHashFunction(aKey, FHashTableSize);
  1099. chn:=Chain(hashCode);
  1100. if Assigned(chn) then
  1101. begin
  1102. if chn.count>0 then
  1103. for i:=0 to chn.Count - 1 do
  1104. if (THTCustomNode(chn[i]).Key=aKey) then
  1105. Exit(THTNode(chn[i]));
  1106. end
  1107. else
  1108. begin
  1109. FHashTable[hashcode]:=TFPObjectList.Create(true);
  1110. chn:=Chain(hashcode);
  1111. end;
  1112. Inc(FCount);
  1113. Result:=CreateNewNode(aKey);
  1114. chn.Add(Result);
  1115. end;
  1116. Function TFPCustomHashTable.ChainLength(const ChainIndex: Longword): Longword;
  1117. begin
  1118. if Assigned(Chain(ChainIndex)) then
  1119. Result:=Chain(ChainIndex).Count
  1120. else
  1121. Result:=0;
  1122. end;
  1123. Procedure TFPCustomHashTable.Clear;
  1124. var
  1125. i: Longword;
  1126. begin
  1127. if FHashTableSize>0 then
  1128. for i:=0 to FHashTableSize - 1 do
  1129. if Assigned(Chain(i)) then
  1130. Chain(i).Clear;
  1131. FCount:=0;
  1132. end;
  1133. { TFPDataHashTable }
  1134. Procedure TFPDataHashTable.Add(const aKey: string; aItem: JSValue);
  1135. var
  1136. chn: TFPObjectList;
  1137. NewNode: THtDataNode;
  1138. begin
  1139. chn:=FindChainForAdd(akey);
  1140. NewNode:=THtDataNode(CreateNewNode(aKey));
  1141. NewNode.Data:=aItem;
  1142. chn.Add(NewNode);
  1143. end;
  1144. Function TFPDataHashTable.GetData(const Index: string): JSValue;
  1145. var
  1146. node: THTDataNode;
  1147. begin
  1148. node:=THTDataNode(Find(Index));
  1149. if Assigned(node) then
  1150. Result:=node.Data
  1151. else
  1152. Result:=nil;
  1153. end;
  1154. Procedure TFPDataHashTable.SetData(const index: string; const AValue: JSValue);
  1155. begin
  1156. THTDataNode(FindOrCreateNew(index)).Data:=AValue;
  1157. end;
  1158. Function TFPDataHashTable.CreateNewNode(const aKey : string) : THTCustomNode;
  1159. begin
  1160. Result:=THTDataNode.CreateWith(aKey);
  1161. end;
  1162. Function TFPDataHashTable.Iterate(aMethod: TDataIteratorMethod): JSValue;
  1163. var
  1164. N : THTDataNode;
  1165. begin
  1166. N:=ForEachCall(AMethod);
  1167. if Assigned(N) then
  1168. Result:=N.Data
  1169. else
  1170. Result:=nil;
  1171. end;
  1172. Procedure TFPDataHashTable.CallbackIterator(Item: JSValue; const Key: string; var Continue: Boolean);
  1173. begin
  1174. FIteratorCallBack(Item, Key, Continue);
  1175. end;
  1176. Function TFPDataHashTable.Iterate(aMethod: TDataIteratorCallBack): JSValue;
  1177. begin
  1178. FIteratorCallBack := aMethod;
  1179. Result := Iterate(@CallbackIterator);
  1180. end;
  1181. Function TFPDataHashTable.ForEachCall(aMethod: TDataIteratorMethod): THTDataNode;
  1182. var
  1183. i, j: Longword;
  1184. continue: Boolean;
  1185. begin
  1186. Result:=nil;
  1187. continue:=true;
  1188. if FHashTableSize>0 then
  1189. for i:=0 to FHashTableSize-1 do
  1190. if Assigned(Chain(i)) then
  1191. if chain(i).count>0 then
  1192. for j:=0 to Chain(i).Count-1 do
  1193. begin
  1194. aMethod(THTDataNode(Chain(i)[j]).Data, THTDataNode(Chain(i)[j]).Key, continue);
  1195. if not continue then
  1196. begin
  1197. Result:=THTDataNode(Chain(i)[j]);
  1198. Exit;
  1199. end;
  1200. end;
  1201. end;
  1202. Procedure TFPDataHashTable.AddNode(ANode : THTCustomNode);
  1203. begin
  1204. with THTDataNode(ANode) do
  1205. Add(Key,Data);
  1206. end;
  1207. { TFPStringHashTable }
  1208. Procedure TFPStringHashTable.AddNode(ANode : THTCustomNode);
  1209. begin
  1210. with THTStringNode(ANode) do
  1211. Add(Key,Data);
  1212. end;
  1213. Function TFPStringHashTable.GetData(const Index: string): String;
  1214. var
  1215. node: THTStringNode;
  1216. begin
  1217. node:=THTStringNode(Find(Index));
  1218. if Assigned(node) then
  1219. Result:=node.Data
  1220. else
  1221. Result:='';
  1222. end;
  1223. Procedure TFPStringHashTable.SetData(const index, AValue: string);
  1224. begin
  1225. THTStringNode(FindOrCreateNew(index)).Data:=AValue;
  1226. end;
  1227. Procedure TFPStringHashTable.Add(const aKey, aItem: string);
  1228. var
  1229. chn: TFPObjectList;
  1230. NewNode: THtStringNode;
  1231. begin
  1232. chn:=FindChainForAdd(akey);
  1233. NewNode:=THtStringNode(CreateNewNode(aKey));
  1234. NewNode.Data:=aItem;
  1235. chn.Add(NewNode);
  1236. end;
  1237. Function TFPStringHashTable.CreateNewNode(const aKey : string) : THTCustomNode;
  1238. begin
  1239. Result:=THTStringNode.CreateWith(aKey);
  1240. end;
  1241. Function TFPStringHashTable.Iterate(aMethod: TStringIteratorMethod): String;
  1242. var
  1243. N : THTStringNode;
  1244. begin
  1245. N:=ForEachCall(AMethod);
  1246. if Assigned(N) then
  1247. Result:=N.Data
  1248. else
  1249. Result:='';
  1250. end;
  1251. Procedure TFPStringHashTable.CallbackIterator(Item: String; const Key: string; var Continue: Boolean);
  1252. begin
  1253. FIteratorCallBack(Item, Key, Continue);
  1254. end;
  1255. Function TFPStringHashTable.Iterate(aMethod: TStringIteratorCallback): String;
  1256. begin
  1257. FIteratorCallBack := aMethod;
  1258. Result := Iterate(@CallbackIterator);
  1259. end;
  1260. Function TFPStringHashTable.ForEachCall(aMethod: TStringIteratorMethod): THTStringNode;
  1261. var
  1262. i, j: Longword;
  1263. continue: boolean;
  1264. begin
  1265. Result:=nil;
  1266. continue:=True;
  1267. if FHashTableSize>0 then
  1268. for i:=0 to FHashTableSize-1 do
  1269. if Assigned(Chain(i)) then
  1270. if chain(i).Count>0 then
  1271. for j:=0 to Chain(i).Count-1 do
  1272. begin
  1273. aMethod(THTStringNode(Chain(i)[j]).Data, THTStringNode(Chain(i)[j]).Key, continue);
  1274. if not continue then
  1275. begin
  1276. Result:=THTStringNode(Chain(i)[j]);
  1277. Exit;
  1278. end;
  1279. end;
  1280. end;
  1281. { TFPObjectHashTable }
  1282. Procedure TFPObjectHashTable.AddNode(ANode : THTCustomNode);
  1283. begin
  1284. With THTObjectNode(ANode) do
  1285. Add(Key,Data);
  1286. end;
  1287. Function TFPObjectHashTable.GetData(const Index: string): TObject;
  1288. var
  1289. node: THTObjectNode;
  1290. begin
  1291. node:=THTObjectNode(Find(Index));
  1292. if Assigned(node) then
  1293. Result:=node.Data
  1294. else
  1295. Result:=nil;
  1296. end;
  1297. Procedure TFPObjectHashTable.SetData(const index : string; AObject : TObject);
  1298. begin
  1299. THTObjectNode(FindOrCreateNew(index)).Data:=AObject;
  1300. end;
  1301. Procedure TFPObjectHashTable.Add(const aKey: string; AItem : TObject);
  1302. var
  1303. chn: TFPObjectList;
  1304. NewNode: THTObjectNode;
  1305. begin
  1306. chn:=FindChainForAdd(akey);
  1307. NewNode:=THTObjectNode(CreateNewNode(aKey));
  1308. NewNode.Data:=aItem;
  1309. chn.Add(NewNode);
  1310. end;
  1311. Function TFPObjectHashTable.CreateNewNode(const aKey : string) : THTCustomNode;
  1312. begin
  1313. if OwnsObjects then
  1314. Result:=THTOwnedObjectNode.CreateWith(aKey)
  1315. else
  1316. Result:=THTObjectNode.CreateWith(aKey);
  1317. end;
  1318. Function TFPObjectHashTable.Iterate(aMethod: TObjectIteratorMethod): TObject;
  1319. var
  1320. N : THTObjectNode;
  1321. begin
  1322. N:=ForEachCall(AMethod);
  1323. if Assigned(N) then
  1324. Result:=N.Data
  1325. else
  1326. Result:=nil;
  1327. end;
  1328. Procedure TFPObjectHashTable.CallbackIterator(Item: TObject; const Key: string; var Continue: Boolean);
  1329. begin
  1330. FIteratorCallBack(Item, Key, Continue);
  1331. end;
  1332. Function TFPObjectHashTable.Iterate(aMethod: TObjectIteratorCallback): TObject;
  1333. begin
  1334. FIteratorCallBack := aMethod;
  1335. Result := Iterate(@CallbackIterator);
  1336. end;
  1337. Function TFPObjectHashTable.ForEachCall(aMethod: TObjectIteratorMethod): THTObjectNode;
  1338. var
  1339. i, j: Longword;
  1340. continue: boolean;
  1341. begin
  1342. Result:=nil;
  1343. continue:=true;
  1344. if FHashTableSize>0 then
  1345. for i:=0 to FHashTableSize-1 do
  1346. if Assigned(Chain(i)) then
  1347. if Chain(i).Count>0 then
  1348. for j:=0 to Chain(i).Count-1 do
  1349. begin
  1350. aMethod(THTObjectNode(Chain(i)[j]).Data, THTObjectNode(Chain(i)[j]).Key, continue);
  1351. if not continue then
  1352. begin
  1353. Result:=THTObjectNode(Chain(i)[j]);
  1354. Exit;
  1355. end;
  1356. end;
  1357. end;
  1358. constructor TFPObjectHashTable.Create(AOwnsObjects : Boolean = True);
  1359. begin
  1360. inherited Create;
  1361. FOwnsObjects:=AOwnsObjects;
  1362. end;
  1363. constructor TFPObjectHashTable.CreateWith(AHashTableSize: Longword; aHashFunc: THashFunction; AOwnsObjects : Boolean = True);
  1364. begin
  1365. inherited CreateWith(AHashTableSize,AHashFunc);
  1366. FOwnsObjects:=AOwnsObjects;
  1367. end;
  1368. destructor THTOwnedObjectNode.Destroy;
  1369. begin
  1370. FreeAndNil(FData);
  1371. inherited;
  1372. end;
  1373. { TCustomBucketList }
  1374. Function TCustomBucketList.GetData(AItem: JSValue): JSValue;
  1375. var
  1376. B,I : Integer;
  1377. begin
  1378. GetBucketItem(AItem,B,I);
  1379. Result:=FBuckets[B].Items[I].Data;
  1380. end;
  1381. Function TCustomBucketList.GetBucketCount: Integer;
  1382. begin
  1383. Result:=Length(FBuckets);
  1384. end;
  1385. Procedure TCustomBucketList.SetData(AItem: JSValue; const AData: JSValue);
  1386. var
  1387. B,I : Integer;
  1388. begin
  1389. GetBucketItem(AItem,B,I);
  1390. FBuckets[B].Items[I].Data:=AData;
  1391. end;
  1392. Procedure TCustomBucketList.SetBucketCount(const Value: Integer);
  1393. begin
  1394. if (Value<>GetBucketCount) then
  1395. SetLength(FBuckets,Value);
  1396. end;
  1397. Procedure TCustomBucketList.GetBucketItem(AItem: JSValue; out ABucket,
  1398. AIndex: Integer);
  1399. begin
  1400. if not FindItem(AItem,ABucket,AIndex) then
  1401. Error(SErrNoSuchItem,[AItem]);
  1402. end;
  1403. Function TCustomBucketList.AddItem(ABucket: Integer; AItem, AData: JSValue
  1404. ): JSValue;
  1405. var
  1406. L : Integer;
  1407. begin
  1408. L:=Length(FBuckets[ABucket].Items);
  1409. if (FBuckets[ABucket].Count=L) then
  1410. begin
  1411. if L<8 then
  1412. L:=8
  1413. else
  1414. L:=L+L div 2;
  1415. SetLength(FBuckets[ABucket].Items,L);
  1416. end;
  1417. with FBuckets[ABucket] do
  1418. begin
  1419. Items[Count].Item:=AItem;
  1420. Items[Count].Data:=AData;
  1421. Result:=AData;
  1422. Inc(Count);
  1423. end;
  1424. end;
  1425. Function TCustomBucketList.DeleteItem(ABucket: Integer; AIndex: Integer): JSValue;
  1426. var
  1427. I,L : Integer;
  1428. begin
  1429. Result:=FBuckets[ABucket].Items[AIndex].Data;
  1430. if FBuckets[ABucket].Count=1 then
  1431. SetLength(FBuckets[ABucket].Items,0)
  1432. else
  1433. begin
  1434. L:=(FBuckets[ABucket].Count-AIndex-1);// No point in moving if last one...
  1435. For I:=0 to L-1 do
  1436. FBuckets[ABucket].Items[AIndex+I]:=FBuckets[ABucket].Items[AIndex+I+1];
  1437. end;
  1438. Dec(FBuckets[ABucket].Count);
  1439. end;
  1440. Procedure TCustomBucketList.Error(Msg: String; Args: array of Const);
  1441. begin
  1442. raise ElistError.CreateFmt(Msg,Args);
  1443. end;
  1444. Function TCustomBucketList.FindItem(AItem: JSValue; out ABucket, AIndex: Integer
  1445. ): Boolean;
  1446. var
  1447. I : Integer;
  1448. B : TBucket;
  1449. begin
  1450. ABucket:=BucketFor(AItem);
  1451. B:=FBuckets[ABucket];
  1452. I:=B.Count-1;
  1453. while (I>=0) and (B.Items[I].Item<>AItem) do
  1454. Dec(I);
  1455. Result:=I>=0;
  1456. if Result then
  1457. AIndex:=I;
  1458. end;
  1459. destructor TCustomBucketList.Destroy;
  1460. begin
  1461. Clear;
  1462. inherited Destroy;
  1463. end;
  1464. Procedure TCustomBucketList.Clear;
  1465. var
  1466. B : TBucket;
  1467. I,J : Integer;
  1468. begin
  1469. for I:=0 to Length(FBuckets)-1 do
  1470. begin
  1471. B:=FBuckets[I];
  1472. for J:=B.Count-1 downto 0 do
  1473. DeleteItem(I,J);
  1474. end;
  1475. SetLength(FBuckets,0);
  1476. end;
  1477. Function TCustomBucketList.Add(AItem, AData: JSValue): JSValue;
  1478. var
  1479. B,I : Integer;
  1480. begin
  1481. if FindItem(AItem,B,I) then
  1482. Error(SDuplicateItem,[AItem]);
  1483. Result:=AddItem(B,AItem,AData);
  1484. end;
  1485. Procedure TCustomBucketList.Assign(AList: TCustomBucketList);
  1486. var
  1487. I,J : Integer;
  1488. begin
  1489. Clear;
  1490. SetLength(FBuckets,Length(Alist.FBuckets));
  1491. for I:=0 to BucketCount-1 do
  1492. begin
  1493. SetLength(FBuckets[i].Items,Length(AList.Fbuckets[I].Items));
  1494. for J:=0 to AList.Fbuckets[I].Count-1 do
  1495. with AList.Fbuckets[I].Items[J] do
  1496. AddItem(I,Item,Data);
  1497. end;
  1498. end;
  1499. Function TCustomBucketList.Exists(AItem: JSValue): Boolean;
  1500. var
  1501. B,I : Integer;
  1502. begin
  1503. Result:=FindItem(AItem,B,I);
  1504. end;
  1505. Function TCustomBucketList.Find(AItem: JSValue; out AData: JSValue): Boolean;
  1506. var
  1507. B,I : integer;
  1508. begin
  1509. Result:=FindItem(AItem,B,I);
  1510. if Result then
  1511. AData:=FBuckets[B].Items[I].Data;
  1512. end;
  1513. Function TCustomBucketList.ForEach(AProc: TBucketProc): Boolean;
  1514. begin
  1515. Result:=Foreach(aProc,Null);
  1516. end;
  1517. Function TCustomBucketList.ForEach(AProc: TBucketProc; AInfo: JSValue): Boolean;
  1518. var
  1519. I,J,S : Integer;
  1520. Bu : TBucket;
  1521. begin
  1522. I:=0;
  1523. Result:=True;
  1524. S:=GetBucketCount;
  1525. while Result and (I<S) do
  1526. begin
  1527. J:=0;
  1528. Bu:=FBuckets[I];
  1529. while Result and (J<Bu.Count) do
  1530. begin
  1531. with Bu.Items[J] do
  1532. AProc(AInfo,Item,Data,Result);
  1533. Inc(J);
  1534. end;
  1535. Inc(I);
  1536. end;
  1537. end;
  1538. Function TCustomBucketList.Remove(AItem: JSValue): JSValue;
  1539. var
  1540. B,I : integer;
  1541. begin
  1542. if FindItem(AItem,B,I) then
  1543. begin
  1544. Result:=FBuckets[B].Items[I].Data;
  1545. DeleteItem(B,I);
  1546. end
  1547. else
  1548. Result:=nil;
  1549. end;
  1550. { TBucketList }
  1551. Function TBucketList.BucketFor(AItem: JSValue): Integer;
  1552. begin
  1553. // JSValues on average have a granularity of 4
  1554. Result:=(longword(AItem) shr 2) and FBucketMask;
  1555. end;
  1556. constructor TBucketList.Create(ABuckets: TBucketListSizes);
  1557. var
  1558. L : Integer;
  1559. begin
  1560. inherited Create;
  1561. L:=1 shl (Ord(Abuckets)+1);
  1562. SetBucketCount(L);
  1563. FBucketMask:=L-1;
  1564. end;
  1565. { TObjectBucketList }
  1566. Function TObjectBucketList.GetData(AItem: TObject): TObject;
  1567. begin
  1568. Result:=TObject(inherited GetData(AItem));
  1569. end;
  1570. Procedure TObjectBucketList.SetData(AItem: TObject; const AData: TObject);
  1571. begin
  1572. inherited SetData(JSValue(AItem),JSValue(AData));
  1573. end;
  1574. Function TObjectBucketList.Add(AItem, AData: TObject): TObject;
  1575. begin
  1576. Result:=TObject(inherited Add(JSValue(AItem),JSValue(AData)));
  1577. end;
  1578. Function TObjectBucketList.Remove(AItem: TObject): TObject;
  1579. begin
  1580. Result:=TObject(inherited Remove(JSValue(AItem)));
  1581. end;
  1582. end.