generics.collections.pas 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021
  1. unit Generics.Collections;
  2. {$Mode Delphi}
  3. {$COperators On}
  4. interface
  5. uses
  6. Classes, SysUtils, rtlconsts, Types,
  7. {$IFDEF Pas2js}JS,{$ENDIF}
  8. Generics.Strings, Generics.Defaults;
  9. type
  10. TCollectionNotification = (cnAdded, cnRemoved, cnExtracted);
  11. TCollectionNotifyEvent<T> = procedure(ASender: TObject; const AItem: T;
  12. AAction: TCollectionNotification) of object;
  13. { TBinarySearchResult }
  14. TBinarySearchResult = record
  15. FoundIndex, CandidateIndex: SizeInt;
  16. CompareResult: SizeInt;
  17. end;
  18. { TCustomArrayHelper }
  19. TCustomArrayHelper<T> = class abstract
  20. protected
  21. class procedure QuickSort(var AValues: array of T; ALeft, ARight: SizeInt;
  22. const AComparer: IComparer<T>); virtual; abstract;
  23. public
  24. //class procedure Sort(var AValues: array of T); overload;
  25. class procedure Sort(var AValues: array of T;
  26. const AComparer: IComparer<T>); overload;
  27. class procedure Sort(var AValues: array of T;
  28. const AComparer: IComparer<T>; AIndex, ACount: SizeInt); overload;
  29. class function BinarySearch(const AValues: array of T; const AItem: T;
  30. out ASearchResult: TBinarySearchResult; const AComparer: IComparer<T>;
  31. AIndex, ACount: SizeInt): Boolean; virtual; abstract; overload;
  32. class function BinarySearch(const AValues: array of T; const AItem: T;
  33. out AFoundIndex: SizeInt; const AComparer: IComparer<T>;
  34. AIndex, ACount: SizeInt): Boolean; virtual; abstract; overload;
  35. class function BinarySearch(const AValues: array of T; const AItem: T;
  36. out AFoundIndex: SizeInt; const AComparer: IComparer<T>): Boolean; overload;
  37. class function BinarySearch(const AValues: array of T; const AItem: T;
  38. out ASearchResult: TBinarySearchResult; const AComparer: IComparer<T>): Boolean; overload;
  39. // No support for automatically creating a comparer.
  40. // class function BinarySearch(const AValues: array of T; const AItem: T;
  41. // out AFoundIndex: SizeInt): Boolean; overload;
  42. // class function BinarySearch(const AValues: array of T; const AItem: T;
  43. // out ASearchResult: TBinarySearchResult): Boolean; overload;
  44. end;
  45. { TArrayHelper }
  46. TArrayHelper<T> = class(TCustomArrayHelper<T>)
  47. protected
  48. class procedure QuickSort(var AValues: array of T; ALeft, ARight: SizeInt;
  49. const AComparer: IComparer<T>); override;
  50. public
  51. class function BinarySearch(const AValues: array of T; const AItem: T;
  52. out ASearchResult: TBinarySearchResult; const AComparer: IComparer<T>;
  53. AIndex, ACount: SizeInt): Boolean; override; overload;
  54. class function BinarySearch(const AValues: array of T; const AItem: T;
  55. out AFoundIndex: SizeInt; const AComparer: IComparer<T>;
  56. AIndex, ACount: SizeInt): Boolean; override; overload;
  57. end;
  58. { TEnumerator }
  59. TEnumerator<T> = class abstract
  60. protected
  61. function DoGetCurrent: T; virtual; abstract;
  62. function DoMoveNext: boolean; virtual; abstract;
  63. public
  64. property Current: T read DoGetCurrent;
  65. function MoveNext: boolean;
  66. end;
  67. { TEnumerable }
  68. TEnumerable<T> = class abstract
  69. protected
  70. type
  71. TMyEnumerator = TEnumerator<T>;
  72. function DoGetEnumerator: TMyEnumerator; virtual; abstract;
  73. public
  74. type
  75. TMyArray = TArray<T>;
  76. function GetEnumerator: TMyEnumerator; inline;
  77. function ToArray: TMyArray; virtual;
  78. end;
  79. { TCustomList }
  80. TCustomList<T> = class abstract(TEnumerable<T>)
  81. private
  82. FOnNotify: TCollectionNotifyEvent<T>;
  83. function GetCapacity: SizeInt; inline;
  84. protected
  85. type TMyArrayHelper = TArrayHelper<T>;
  86. protected
  87. FLength: SizeInt;
  88. FItems: array of T;
  89. function PrepareAddingItem: SizeInt; virtual;
  90. function PrepareAddingRange(ACount: SizeInt): SizeInt; virtual;
  91. procedure Notify(const AValue: T; ACollectionNotification: TCollectionNotification); virtual;
  92. function DoRemove(AIndex: SizeInt; ACollectionNotification: TCollectionNotification): T; virtual;
  93. procedure SetCapacity(AValue: SizeInt); virtual; abstract;
  94. function GetCount: SizeInt; virtual;
  95. public
  96. property Count: SizeInt read GetCount;
  97. property Capacity: SizeInt read GetCapacity write SetCapacity;
  98. property OnNotify: TCollectionNotifyEvent<T> read FOnNotify write FOnNotify;
  99. procedure TrimExcess; virtual; abstract;
  100. end;
  101. { TCustomListEnumerator }
  102. TCustomListEnumerator<T> = class abstract(TEnumerator<T>)
  103. private
  104. FList: TCustomList<T>;
  105. FIndex: SizeInt;
  106. protected
  107. function DoMoveNext: boolean; override;
  108. function DoGetCurrent: T; override;
  109. function GetCurrent: T; virtual;
  110. public
  111. constructor Create(AList: TCustomList<T>);
  112. end;
  113. { TCustomInvertedListEnumerator }
  114. TCustomInvertedListEnumerator<T> = class abstract(TEnumerator<T>)
  115. private
  116. FList: TCustomList<T>;
  117. FIndex: SizeInt;
  118. protected
  119. function DoMoveNext: boolean; override;
  120. function DoGetCurrent: T; override;
  121. function GetCurrent: T; virtual;
  122. public
  123. constructor Create(AList: TCustomList<T>);
  124. end;
  125. { TList }
  126. {$SCOPEDENUMS ON}
  127. TDirection = (FromBeginning,fromEnd);
  128. {$SCOPEDENUMS OFF}
  129. TList<T> = class(TCustomList<T>)
  130. private
  131. FComparer: IComparer<T>;
  132. protected
  133. procedure SetCapacity(AValue: SizeInt); override;
  134. procedure SetCount(AValue: SizeInt);
  135. procedure InitializeList; virtual;
  136. procedure InternalInsert(AIndex: SizeInt; const AValue: T);
  137. function DoGetEnumerator: TEnumerator<T>; override;
  138. private
  139. function GetItem(AIndex: SizeInt): T;
  140. procedure SetItem(AIndex: SizeInt; const AValue: T);
  141. public
  142. type
  143. TEnumerator = class(TCustomListEnumerator<T>);
  144. TMyType = TList<T>;
  145. function GetEnumerator: TEnumerator; reintroduce;
  146. public
  147. constructor Create; overload;
  148. constructor Create(const AComparer: IComparer<T>); overload;
  149. constructor Create(ACollection: TEnumerable<T>); overload;
  150. destructor Destroy; override;
  151. function Add(const AValue: T): SizeInt; virtual;
  152. procedure AddRange(const AValues: array of T); virtual; overload;
  153. procedure AddRange(const AEnumerable: IEnumerable<T>); overload;
  154. procedure AddRange(AEnumerable: TEnumerable<T>); overload;
  155. procedure Insert(AIndex: SizeInt; const AValue: T); virtual;
  156. procedure InsertRange(AIndex: SizeInt; const AValues: array of T); virtual; overload;
  157. procedure InsertRange(AIndex: SizeInt; const AEnumerable: IEnumerable<T>); overload;
  158. procedure InsertRange(AIndex: SizeInt; const AEnumerable: TEnumerable<T>); overload;
  159. function Remove(const AValue: T): SizeInt;
  160. function RemoveItem(const AValue: T; Direction : TDirection): SizeInt;
  161. procedure Delete(AIndex: SizeInt); inline;
  162. procedure DeleteRange(AIndex, ACount: SizeInt);
  163. function ExtractIndex(const AIndex: SizeInt): T; overload;
  164. function Extract(const AValue: T): T; overload;
  165. procedure Exchange(AIndex1, AIndex2: SizeInt); virtual;
  166. procedure Move(AIndex, ANewIndex: SizeInt); virtual;
  167. function First: T; inline;
  168. function Last: T; inline;
  169. procedure Clear;
  170. function Contains(const AValue: T): Boolean; inline;
  171. function IndexOf(const AValue: T): SizeInt; virtual;
  172. function LastIndexOf(const AValue: T): SizeInt; virtual;
  173. procedure Reverse;
  174. procedure TrimExcess; override;
  175. procedure Sort; overload;
  176. procedure Sort(const AComparer: IComparer<T>); overload;
  177. function BinarySearch(const AItem: T; out AIndex: SizeInt): Boolean; overload;
  178. function BinarySearch(const AItem: T; out AIndex: SizeInt; const AComparer: IComparer<T>): Boolean; overload;
  179. property Count: SizeInt read FLength write SetCount;
  180. property Items[Index: SizeInt]: T read GetItem write SetItem; default;
  181. end;
  182. TObjectList<T: class> = class(TList<T>)
  183. private
  184. FObjectsOwner: Boolean;
  185. protected
  186. procedure Notify(const aValue: T; Action: TCollectionNotification); override;
  187. public
  188. constructor Create(aOwnsObjects: Boolean = True); overload;
  189. constructor Create(const AComparer: IComparer<T>; aOwnsObjects: Boolean = True); overload;
  190. constructor Create(const aCollection: TEnumerable<T>; aOwnsObjects: Boolean = True); overload;
  191. property OwnsObjects: Boolean read FObjectsOwner write FObjectsOwner;
  192. end;
  193. { TThreadList }
  194. // This is provided for delphi/FPC compatibility
  195. // No locking is done, since Javascript is single-threaded. We do keep a lock count for debugging purposes.
  196. TThreadList<T> = class
  197. private
  198. FList: TList<T>;
  199. FLock: Integer;
  200. FDuplicates: TDuplicates;
  201. public
  202. constructor Create;
  203. destructor Destroy; override;
  204. procedure Add(const Item: T);
  205. procedure Clear;
  206. function LockList: TList<T>;
  207. procedure Remove(const Item: T); inline;
  208. procedure RemoveItem(const Item: T; Direction: TDirection);
  209. procedure UnlockList; inline;
  210. property Duplicates: TDuplicates read FDuplicates write FDuplicates;
  211. end;
  212. { TQueue }
  213. TQueue<T> = class(TCustomList<T>)
  214. private
  215. FMaxGapLength: Integer;
  216. FLow: SizeInt;
  217. protected
  218. function DoGetEnumerator: TEnumerator<T>; override;
  219. public
  220. type
  221. TMyType = TQueue<T>;
  222. { TEnumerator }
  223. TEnumerator = class(TCustomListEnumerator<T>)
  224. public
  225. constructor Create(AQueue: TMyType);
  226. end;
  227. function GetEnumerator: TEnumerator; reintroduce;
  228. protected
  229. Procedure Rebase; virtual;
  230. procedure SetCapacity(AValue: SizeInt); override;
  231. function DoRemove(AIndex: SizeInt; ACollectionNotification: TCollectionNotification): T; override;
  232. function GetCount: SizeInt; override;
  233. public
  234. Constructor Create; overload;
  235. constructor Create(ACollection: TEnumerable<T>); overload;
  236. destructor Destroy; override;
  237. procedure Enqueue(const AValue: T);
  238. function Dequeue: T;
  239. function Extract: T;
  240. function Peek: T;
  241. procedure Clear;
  242. procedure TrimExcess; override;
  243. // Maximum gap (=amount of empty slots in array before first element)
  244. // before doing a rebase of the list. Defaults to 10.
  245. Property MaxGapLength : Integer Read FMaxGapLength Write FMaxGapLength;
  246. end;
  247. { TObjectQueue }
  248. TObjectQueue<T: class> = class(TQueue<T>)
  249. private
  250. FOwnsObjects: Boolean;
  251. protected
  252. procedure Notify(const Value: T; Action: TCollectionNotification); override;
  253. public
  254. constructor Create(AOwnsObjects: Boolean = True); overload;
  255. constructor Create(const Collection: TEnumerable<T>; AOwnsObjects: Boolean = True); overload;
  256. procedure Dequeue; reintroduce; // Can't use the result, it might have been freed;
  257. property OwnsObjects: Boolean read FOwnsObjects write FOwnsObjects;
  258. end;
  259. { TStack }
  260. TStack<T> = class(TCustomList<T>)
  261. private
  262. protected
  263. function DoRemove(AIndex: SizeInt; ACollectionNotification: TCollectionNotification): T; override;
  264. procedure SetCapacity(AValue: SizeInt); override;
  265. function DoGetEnumerator: TEnumerator<T>; override;
  266. public
  267. type
  268. TMyType = TStack<T>;
  269. { TEnumerator }
  270. TEnumerator = class(TCustomListEnumerator<T>)
  271. public
  272. constructor Create(AStack: TMyType);
  273. end;
  274. function GetEnumerator: TEnumerator; reintroduce;
  275. Public
  276. destructor Destroy; override;
  277. procedure Clear;
  278. procedure Push(const aValue: T);
  279. function Pop: T;
  280. function Peek: T;
  281. function Extract: T;
  282. procedure TrimExcess; override;
  283. property Count: SizeInt read GetCount;
  284. end;
  285. { TObjectStack }
  286. TObjectStack<T: class> = class(TStack<T>)
  287. private
  288. FOwnsObjects: Boolean;
  289. protected
  290. procedure Notify(const aValue: T; Action: TCollectionNotification); override;
  291. public
  292. constructor Create(AOwnsObjects: Boolean = True); overload;
  293. constructor Create(const Collection: TEnumerable<T>; AOwnsObjects: Boolean = True); overload;
  294. procedure Pop; reintroduce; // Can't use the result, it might have been freed;
  295. property OwnsObjects: Boolean read FOwnsObjects write FOwnsObjects;
  296. end;
  297. { TPair }
  298. TPair<TKey,TValue> = record
  299. Key: TKey;
  300. Value: TValue;
  301. constructor Create(const AKey: TKey; const AValue: TValue);
  302. end;
  303. // Hash table using linear probing
  304. { TDictionary }
  305. EDictionary = Class(Exception);
  306. TDictionary<TKey,TValue> = class(TEnumerable<TPair<TKey,TValue>>)
  307. private
  308. FMap: TJSMap;
  309. function GetItem(const Key: TKey): TValue;
  310. procedure SetItem(const Key: TKey; const Value: TValue);
  311. procedure DoAdd(const Key: TKey; const Value: TValue);
  312. function DoRemove(const Key: TKey; Notification: TCollectionNotification): TValue;
  313. Function GetCount : Integer;
  314. protected
  315. Function CanClearMap : Boolean; virtual;
  316. function DoGetEnumerator: TEnumerator<TPair<TKey,TValue>>; override;
  317. procedure PairNotify(const Key: TKey; Value : TValue; Action: TCollectionNotification); virtual;
  318. procedure KeyNotify(const Key: TKey; Action: TCollectionNotification); virtual;
  319. procedure ValueNotify(const Value: TValue; Action: TCollectionNotification); virtual;
  320. public
  321. Type
  322. TMyType = TDictionary<TKey,TValue>;
  323. TMyPair = TPair<TKey,TValue>;
  324. constructor Create(ACapacity: Integer=0); overload;
  325. constructor Create(const Collection: TEnumerable<TMyPair>); overload;
  326. destructor Destroy; override;
  327. procedure Add(const Key: TKey; const Value: TValue);
  328. procedure Remove(const Key: TKey);
  329. function ExtractPair(const Key: TKey): TMyPair;
  330. procedure Clear;
  331. function TryGetValue(const Key: TKey; out Value: TValue): Boolean;
  332. procedure AddOrSetValue(const Key: TKey; const Value: TValue);
  333. function ContainsKey(const Key: TKey): Boolean;
  334. function ContainsValue(const Value: TValue): Boolean;
  335. function ToArray: TArray<TMyPair>; override;
  336. property Items[const Key: TKey]: TValue read GetItem write SetItem; default;
  337. property Count: Integer read GetCount;
  338. type
  339. { TPairEnumerator }
  340. TPairEnumerator = class(TEnumerator<TMyPair>)
  341. private
  342. FIter: TJSIterator;
  343. FVal : TJSIteratorValue;
  344. function GetCurrent: TMyPair;
  345. protected
  346. function DoGetCurrent: TMyPair; override;
  347. function DoMoveNext: Boolean; override;
  348. public
  349. constructor Create(const ADictionary: TMyType);
  350. function MoveNext: Boolean; reintroduce;
  351. property Current: TMyPair read GetCurrent;
  352. end;
  353. { TKeyEnumerator }
  354. TKeyEnumerator = class(TEnumerator<TKey>)
  355. private
  356. FIter: TJSIterator;
  357. FVal : TJSIteratorValue;
  358. function GetCurrent: TKey;
  359. protected
  360. function DoGetCurrent: TKey; override;
  361. function DoMoveNext: Boolean; override;
  362. public
  363. constructor Create(const AIter: TJSIterator); overload;
  364. constructor Create(const ADictionary: TMyType); overload;
  365. function MoveNext: Boolean; reintroduce;
  366. property Current: TKey read GetCurrent;
  367. end;
  368. { TValueEnumerator }
  369. TValueEnumerator = class(TEnumerator<TValue>)
  370. private
  371. FIter: TJSIterator;
  372. FVal : TJSIteratorValue;
  373. function GetCurrent: TValue;
  374. protected
  375. function DoGetCurrent: TValue; override;
  376. function DoMoveNext: Boolean; override;
  377. public
  378. constructor Create(const AIter: TJSIterator); overload;
  379. constructor Create(const ADictionary: TMyType); overload;
  380. function MoveNext: Boolean; reintroduce;
  381. property Current: TValue read GetCurrent;
  382. end;
  383. { TValueCollection }
  384. TValueCollection = class(TEnumerable<TValue>)
  385. private
  386. FMap: TJSMap;
  387. function GetCount: Integer;
  388. protected
  389. function DoGetEnumerator: TEnumerator<TValue>; override;
  390. public
  391. constructor Create(const ADictionary: TMyType);
  392. function GetEnumerator: TValueEnumerator; reintroduce;
  393. function ToArray: TArray<TValue>; override;
  394. property Count: Integer read GetCount;
  395. end;
  396. { TKeyCollection }
  397. TKeyCollection = class(TEnumerable<TKey>)
  398. private
  399. FMap: TJSMap;
  400. function GetCount: Integer;
  401. protected
  402. function DoGetEnumerator: TEnumerator<TKey>; override;
  403. public
  404. constructor Create(const ADictionary: TMyType);
  405. function GetEnumerator: TKeyEnumerator; reintroduce;
  406. function ToArray: TArray<TKey>; override;
  407. property Count: Integer read GetCount;
  408. end;
  409. private
  410. FOnKeyNotify: TCollectionNotifyEvent<TKey>;
  411. FOnValueNotify: TCollectionNotifyEvent<TValue>;
  412. FKeyCollection: TKeyCollection;
  413. FValueCollection: TValueCollection;
  414. function GetKeys: TKeyCollection;
  415. function GetValues: TValueCollection;
  416. public
  417. function GetEnumerator: TPairEnumerator; reintroduce;
  418. property Keys: TKeyCollection read GetKeys;
  419. property Values: TValueCollection read GetValues;
  420. property OnKeyNotify: TCollectionNotifyEvent<TKey> read FOnKeyNotify write FOnKeyNotify;
  421. property OnValueNotify: TCollectionNotifyEvent<TValue> read FOnValueNotify write FOnValueNotify;
  422. end;
  423. TDictionaryOwnership = (doOwnsKeys, doOwnsValues);
  424. TDictionaryOwnerships = set of TDictionaryOwnership;
  425. { TObjectDictionary }
  426. TObjectDictionary<TKey,TValue> = class(TDictionary<TKey,TValue>)
  427. private
  428. FOwnerships: TDictionaryOwnerships;
  429. protected
  430. Function CanClearMap : Boolean; override;
  431. procedure KeyNotify(const Key: TKey; Action: TCollectionNotification); override;
  432. procedure ValueNotify(const Value: TValue; Action: TCollectionNotification); override;
  433. public
  434. constructor Create(aOwnerships: TDictionaryOwnerships; ACapacity: Integer); overload;
  435. constructor Create(aOwnerships: TDictionaryOwnerships); overload;
  436. Property OwnerShips : TDictionaryOwnerships Read FOwnerships Write FOwnerShips;
  437. end;
  438. implementation
  439. { TCustomArrayHelper }
  440. class procedure TCustomArrayHelper<T>.Sort(var AValues: array of T;
  441. const AComparer: IComparer<T>);
  442. begin
  443. QuickSort(AValues, 0, Length(AValues), AComparer);
  444. end;
  445. class procedure TCustomArrayHelper<T>.Sort(var AValues: array of T;
  446. const AComparer: IComparer<T>; AIndex, ACount: SizeInt);
  447. begin
  448. if ACount <= 1 then
  449. Exit;
  450. QuickSort(AValues, AIndex, Pred(AIndex + ACount), AComparer);
  451. end;
  452. class function TCustomArrayHelper<T>.BinarySearch(const AValues: array of T;
  453. const AItem: T; out AFoundIndex: SizeInt; const AComparer: IComparer<T>
  454. ): Boolean;
  455. begin
  456. Result := BinarySearch(AValues, AItem, AFoundIndex, AComparer,
  457. 0, Length(AValues));
  458. end;
  459. class function TCustomArrayHelper<T>.BinarySearch(const AValues: array of T;
  460. const AItem: T; out ASearchResult: TBinarySearchResult;
  461. const AComparer: IComparer<T>): Boolean;
  462. begin
  463. Result := BinarySearch(AValues, AItem, ASearchResult, AComparer,
  464. 0, Length(AValues));
  465. end;
  466. { TArrayHelper }
  467. class procedure TArrayHelper<T>.QuickSort(var AValues: array of T; ALeft,
  468. ARight: SizeInt; const AComparer: IComparer<T>);
  469. var
  470. I, J: SizeInt;
  471. P, Q: T;
  472. begin
  473. if ((ARight - ALeft) <= 0) or (Length(AValues) = 0) then
  474. Exit;
  475. repeat
  476. I := ALeft;
  477. J := ARight;
  478. P := AValues[ALeft + (ARight - ALeft) shr 1];
  479. repeat
  480. while AComparer.Compare(AValues[I], P) < 0 do
  481. Inc(I);
  482. while AComparer.Compare(AValues[J], P) > 0 do
  483. Dec(J);
  484. if I <= J then
  485. begin
  486. if I <> J then
  487. begin
  488. Q := AValues[I];
  489. AValues[I] := AValues[J];
  490. AValues[J] := Q;
  491. end;
  492. Inc(I);
  493. Dec(J);
  494. end;
  495. until I > J;
  496. // sort the smaller range recursively
  497. // sort the bigger range via the loop
  498. // Reasons: memory usage is O(log(n)) instead of O(n) and loop is faster than recursion
  499. if J - ALeft < ARight - I then
  500. begin
  501. if ALeft < J then
  502. QuickSort(AValues, ALeft, J, AComparer);
  503. ALeft := I;
  504. end
  505. else
  506. begin
  507. if I < ARight then
  508. QuickSort(AValues, I, ARight, AComparer);
  509. ARight := J;
  510. end;
  511. until ALeft >= ARight;
  512. end;
  513. class function TArrayHelper<T>.BinarySearch(const AValues: array of T;
  514. const AItem: T; out ASearchResult: TBinarySearchResult;
  515. const AComparer: IComparer<T>; AIndex, ACount: SizeInt): Boolean;
  516. var
  517. imin, imax, imid, ilo: Int32;
  518. begin
  519. // Writeln('Enter ',Length(aValues),' Idx ',aIndex,' acount: ',aCount);
  520. // continually narrow search until just one element remains
  521. imin := AIndex;
  522. imax := Pred(AIndex + ACount);
  523. // Writeln('Start Imax, imin : ',Imax, ' - ', imin);
  524. ilo:=imid * imid;
  525. imid:=ilo*imid;
  526. while (imin < imax) do
  527. begin
  528. imid := (imax+imin) div 2;
  529. // writeln('imid',imid);
  530. ASearchResult.CompareResult := AComparer.Compare(AValues[imid], AItem);
  531. // reduce the search
  532. if (ASearchResult.CompareResult < 0) then
  533. imin := imid + 1
  534. else
  535. begin
  536. if ASearchResult.CompareResult = 0 then
  537. begin
  538. ASearchResult.FoundIndex := imid;
  539. ASearchResult.CandidateIndex := imid;
  540. Exit(True);
  541. end;
  542. imax := imid;
  543. end;
  544. end;
  545. // At exit of while:
  546. // if A[] is empty, then imax < imin
  547. // otherwise imax == imin
  548. // deferred test for equality
  549. // Writeln('End Imax, imin : ',Imax, ' - ', imin);
  550. Result:=(imax = imin);
  551. if Result then
  552. begin
  553. ASearchResult.CompareResult := AComparer.Compare(AValues[imin], AItem);
  554. ASearchResult.CandidateIndex := imin;
  555. Result:=(ASearchResult.CompareResult = 0);
  556. if Result then
  557. ASearchResult.FoundIndex := imin
  558. else
  559. ASearchResult.FoundIndex := -1;
  560. end
  561. else
  562. begin
  563. ASearchResult.CompareResult := 0;
  564. ASearchResult.FoundIndex := -1;
  565. ASearchResult.CandidateIndex := -1;
  566. end;
  567. end;
  568. class function TArrayHelper<T>.BinarySearch(const AValues: array of T;
  569. const AItem: T; out AFoundIndex: SizeInt; const AComparer: IComparer<T>;
  570. AIndex, ACount: SizeInt): Boolean;
  571. var
  572. imin, imax, imid: Int32;
  573. LCompare: SizeInt;
  574. begin
  575. // continually narrow search until just one element remains
  576. imin := AIndex;
  577. imax := Pred(AIndex + ACount);
  578. // http://en.wikipedia.org/wiki/Binary_search_algorithm
  579. while (imin < imax) do
  580. begin
  581. imid := (imin + imax) div 2;
  582. // code must guarantee the interval is reduced at each iteration
  583. // assert(imid < imax);
  584. // note: 0 <= imin < imax implies imid will always be less than imax
  585. LCompare := AComparer.Compare(AValues[imid], AItem);
  586. // reduce the search
  587. if (LCompare < 0) then
  588. imin := imid + 1
  589. else
  590. begin
  591. if LCompare = 0 then
  592. begin
  593. AFoundIndex := imid;
  594. Exit(True);
  595. end;
  596. imax := imid;
  597. end;
  598. end;
  599. // At exit of while:
  600. // if A[] is empty, then imax < imin
  601. // otherwise imax == imin
  602. // deferred test for equality
  603. LCompare := AComparer.Compare(AValues[imin], AItem);
  604. Result:=(imax = imin) and (LCompare = 0);
  605. if Result then
  606. AFoundIndex := imin
  607. else
  608. AFoundIndex := -1;
  609. end;
  610. { TEnumerator }
  611. function TEnumerator<T>.MoveNext: boolean;
  612. begin
  613. Result:=DoMoveNext;
  614. end;
  615. { TEnumerable }
  616. function TEnumerable<T>.GetEnumerator: TMyEnumerator;
  617. begin
  618. Result:=DoGetEnumerator;
  619. end;
  620. function TEnumerable<T>.ToArray: TMyArray;
  621. var
  622. LEnumerator: TMyEnumerator;
  623. begin
  624. Result:=[];
  625. LEnumerator := GetEnumerator;
  626. try
  627. while LEnumerator.MoveNext do
  628. TJSArray(Result).push(LEnumerator.Current);
  629. finally
  630. LEnumerator.Free;
  631. end;
  632. end;
  633. { TCustomList }
  634. function TCustomList<T>.GetCapacity: SizeInt;
  635. begin
  636. Result:=length(FItems);
  637. end;
  638. function TCustomList<T>.PrepareAddingItem: SizeInt;
  639. begin
  640. if FLength=length(FItems) then
  641. TJSArray(FItems).push(Default(T));
  642. Result := FLength;
  643. Inc(FLength);
  644. end;
  645. function TCustomList<T>.PrepareAddingRange(ACount: SizeInt): SizeInt;
  646. var
  647. l: SizeInt;
  648. begin
  649. if ACount < 0 then
  650. raise EArgumentOutOfRangeException.Create(SArgumentOutOfRange);
  651. if ACount = 0 then
  652. Exit(FLength - 1);
  653. for l:=length(FItems)+1 to FLength+ACount do
  654. TJSArray(FItems).push(Default(T));
  655. Result := FLength;
  656. Inc(FLength, ACount);
  657. end;
  658. procedure TCustomList<T>.Notify(const AValue: T;
  659. ACollectionNotification: TCollectionNotification);
  660. begin
  661. if Assigned(FOnNotify) then
  662. FOnNotify(Self, AValue, ACollectionNotification);
  663. end;
  664. function TCustomList<T>.DoRemove(AIndex: SizeInt;
  665. ACollectionNotification: TCollectionNotification): T;
  666. begin
  667. if (AIndex < 0) or (AIndex >= FLength) then
  668. raise EArgumentOutOfRangeException.Create(SArgumentOutOfRange);
  669. Result := FItems[AIndex];
  670. Dec(FLength);
  671. FItems[AIndex] := Default(T); // needed for refcounted types
  672. TJSArray(FItems).splice(AIndex,1);
  673. Notify(Result, ACollectionNotification);
  674. end;
  675. function TCustomList<T>.GetCount: SizeInt;
  676. begin
  677. Result := FLength;
  678. end;
  679. { TCustomListEnumerator }
  680. function TCustomListEnumerator<T>.DoMoveNext: boolean;
  681. begin
  682. Inc(FIndex);
  683. Result := (FList.FLength > 0) and (FIndex < FList.FLength)
  684. end;
  685. function TCustomListEnumerator<T>.DoGetCurrent: T;
  686. begin
  687. Result := GetCurrent;
  688. end;
  689. function TCustomListEnumerator<T>.GetCurrent: T;
  690. begin
  691. Result := FList.FItems[FIndex];
  692. end;
  693. constructor TCustomListEnumerator<T>.Create(AList: TCustomList<T>);
  694. begin
  695. inherited Create;
  696. FIndex := -1;
  697. FList := AList;
  698. end;
  699. { TList }
  700. procedure TList<T>.SetCapacity(AValue: SizeInt);
  701. begin
  702. if AValue < Count then
  703. Count := AValue;
  704. SetLength(FItems, AValue);
  705. end;
  706. procedure TList<T>.SetCount(AValue: SizeInt);
  707. begin
  708. if AValue < 0 then
  709. raise EArgumentOutOfRangeException.Create(SArgumentOutOfRange);
  710. if AValue > Capacity then
  711. Capacity := AValue
  712. else if AValue < Count then
  713. DeleteRange(AValue, Count - AValue);
  714. FLength := AValue;
  715. end;
  716. procedure TList<T>.InitializeList;
  717. begin
  718. end;
  719. procedure TList<T>.InternalInsert(AIndex: SizeInt; const AValue: T);
  720. begin
  721. if (AIndex < 0) or (AIndex > Count) then
  722. raise EArgumentOutOfRangeException.Create(SArgumentOutOfRange);
  723. TJSArray(FItems).splice(AIndex,0,AValue);
  724. inc(FLength);
  725. FItems[AIndex] := AValue;
  726. Notify(AValue, cnAdded);
  727. end;
  728. function TList<T>.DoGetEnumerator: TEnumerator<T>;
  729. begin
  730. Result := GetEnumerator;
  731. end;
  732. function TList<T>.GetItem(AIndex: SizeInt): T;
  733. begin
  734. if (AIndex < 0) or (AIndex >= Count) then
  735. raise EArgumentOutOfRangeException.Create(SArgumentOutOfRange);
  736. Result := FItems[AIndex];
  737. end;
  738. procedure TList<T>.SetItem(AIndex: SizeInt; const AValue: T);
  739. begin
  740. if (AIndex < 0) or (AIndex >= Count) then
  741. raise EArgumentOutOfRangeException.Create(SArgumentOutOfRange);
  742. Notify(FItems[AIndex], cnRemoved);
  743. FItems[AIndex] := AValue;
  744. Notify(AValue, cnAdded);
  745. end;
  746. function TList<T>.GetEnumerator: TEnumerator;
  747. begin
  748. Result := TEnumerator.Create(Self);
  749. end;
  750. constructor TList<T>.Create;
  751. begin
  752. InitializeList;
  753. FComparer := TComparer<T>.Default;
  754. end;
  755. constructor TList<T>.Create(const AComparer: IComparer<T>);
  756. begin
  757. InitializeList;
  758. FComparer := AComparer;
  759. end;
  760. constructor TList<T>.Create(ACollection: TEnumerable<T>);
  761. var
  762. LItem: T;
  763. begin
  764. Create;
  765. for LItem in ACollection do
  766. Add(LItem);
  767. end;
  768. destructor TList<T>.Destroy;
  769. begin
  770. SetCapacity(0);
  771. end;
  772. function TList<T>.Add(const AValue: T): SizeInt;
  773. begin
  774. Result := PrepareAddingItem;
  775. FItems[Result] := AValue;
  776. Notify(AValue, cnAdded);
  777. end;
  778. procedure TList<T>.AddRange(const AValues: array of T);
  779. begin
  780. InsertRange(Count, AValues);
  781. end;
  782. procedure TList<T>.AddRange(const AEnumerable: IEnumerable<T>);
  783. var
  784. LValue: T;
  785. begin
  786. for LValue in AEnumerable do
  787. Add(LValue);
  788. end;
  789. procedure TList<T>.AddRange(AEnumerable: TEnumerable<T>);
  790. var
  791. LValue: T;
  792. begin
  793. for LValue in AEnumerable do
  794. Add(LValue);
  795. end;
  796. procedure TList<T>.Insert(AIndex: SizeInt; const AValue: T);
  797. begin
  798. if (AIndex < 0) or (AIndex > Count) then
  799. raise EArgumentOutOfRangeException.Create(SArgumentOutOfRange);
  800. InternalInsert(AIndex, AValue);
  801. end;
  802. procedure TList<T>.InsertRange(AIndex: SizeInt; const AValues: array of T);
  803. var
  804. LLength, i: sizeint;
  805. LValue: T;
  806. begin
  807. if (AIndex < 0) or (AIndex > Count) then
  808. raise EArgumentOutOfRangeException.Create(SArgumentOutOfRange);
  809. LLength := Length(AValues);
  810. if LLength = 0 then
  811. Exit;
  812. if AIndex <> PrepareAddingRange(LLength) then
  813. begin
  814. for i := AIndex to Count - LLength -1 do
  815. FItems[i+LLength] := FItems[i];
  816. for i := 0 to LLength -1 do
  817. FItems[AIndex+i] := Default(T);
  818. end;
  819. for i := 0 to Pred(LLength) do
  820. begin
  821. LValue:=AValues[i];
  822. FItems[i+AIndex] := LValue;
  823. Notify(LValue, cnAdded);
  824. end;
  825. end;
  826. procedure TList<T>.InsertRange(AIndex: SizeInt; const AEnumerable: IEnumerable<T>);
  827. var
  828. LValue: T;
  829. i: SizeInt;
  830. begin
  831. if (AIndex < 0) or (AIndex > Count) then
  832. raise EArgumentOutOfRangeException.Create(SArgumentOutOfRange);
  833. i := 0;
  834. for LValue in AEnumerable do
  835. begin
  836. InternalInsert(AIndex + i, LValue);
  837. Inc(i);
  838. end;
  839. end;
  840. procedure TList<T>.InsertRange(AIndex: SizeInt; const AEnumerable: TEnumerable<T>);
  841. var
  842. LValue: T;
  843. i: SizeInt;
  844. begin
  845. if (AIndex < 0) or (AIndex > Count) then
  846. raise EArgumentOutOfRangeException.Create(SArgumentOutOfRange);
  847. i := 0;
  848. for LValue in AEnumerable do
  849. begin
  850. InternalInsert(Aindex + i, LValue);
  851. Inc(i);
  852. end;
  853. end;
  854. function TList<T>.RemoveItem(const AValue: T; Direction : TDirection): SizeInt;
  855. begin
  856. if Direction=TDirection.FromEnd then
  857. Result := LastIndexOf(AValue)
  858. else
  859. Result := IndexOf(AValue);
  860. if Result >= 0 then
  861. DoRemove(Result, cnRemoved);
  862. end;
  863. function TList<T>.Remove(const AValue: T): SizeInt;
  864. begin
  865. Result := IndexOf(AValue);
  866. if Result >= 0 then
  867. DoRemove(Result, cnRemoved);
  868. end;
  869. procedure TList<T>.Delete(AIndex: SizeInt);
  870. begin
  871. DoRemove(AIndex, cnRemoved);
  872. end;
  873. procedure TList<T>.DeleteRange(AIndex, ACount: SizeInt);
  874. var
  875. LDeleted: TMyArray;
  876. i: SizeInt;
  877. begin
  878. if ACount = 0 then
  879. Exit;
  880. if (ACount < 0) or (AIndex < 0) or (AIndex + ACount > Count) then
  881. raise EArgumentOutOfRangeException.Create(SArgumentOutOfRange);
  882. LDeleted:=TMyArray(TJSArray(FItems).splice(AIndex,Count));
  883. Dec(FLength, ACount);
  884. for i := 0 to High(LDeleted) do
  885. Notify(LDeleted[i], cnRemoved);
  886. end;
  887. function TList<T>.ExtractIndex(const AIndex: SizeInt): T;
  888. begin
  889. Result := DoRemove(AIndex, cnExtracted);
  890. end;
  891. function TList<T>.Extract(const AValue: T): T;
  892. var
  893. LIndex: SizeInt;
  894. begin
  895. LIndex := IndexOf(AValue);
  896. if LIndex < 0 then
  897. Result:=Default(T)
  898. else
  899. Result := DoRemove(LIndex, cnExtracted);
  900. end;
  901. procedure TList<T>.Exchange(AIndex1, AIndex2: SizeInt);
  902. var
  903. LTemp: T;
  904. begin
  905. LTemp := FItems[AIndex1];
  906. FItems[AIndex1] := FItems[AIndex2];
  907. FItems[AIndex2] := LTemp;
  908. end;
  909. procedure TList<T>.Move(AIndex, ANewIndex: SizeInt);
  910. var
  911. Arr: TJSArray;
  912. LTemp: JSValue;
  913. i: SizeInt;
  914. begin
  915. if ANewIndex = AIndex then
  916. Exit;
  917. if (ANewIndex < 0) or (ANewIndex >= Count) then
  918. raise EArgumentOutOfRangeException.Create(SArgumentOutOfRange);
  919. Arr := TJSArray(FItems);
  920. LTemp := Arr[AIndex];
  921. if AIndex < ANewIndex then
  922. for i := AIndex to ANewIndex-1 do
  923. Arr[i] := Arr[i+1]
  924. else
  925. for i := ANewIndex downto AIndex+1 do
  926. Arr[i] := Arr[i-1];
  927. Arr[ANewIndex] := LTemp;
  928. end;
  929. function TList<T>.First: T;
  930. begin
  931. Result := Items[0];
  932. end;
  933. function TList<T>.Last: T;
  934. begin
  935. Result := Items[Pred(Count)];
  936. end;
  937. procedure TList<T>.Clear;
  938. begin
  939. SetCount(0);
  940. SetCapacity(0);
  941. end;
  942. function TList<T>.Contains(const AValue: T): Boolean;
  943. begin
  944. Result := IndexOf(AValue) >= 0;
  945. end;
  946. function TList<T>.IndexOf(const AValue: T): SizeInt;
  947. var
  948. i: SizeInt;
  949. begin
  950. for i := 0 to Count - 1 do
  951. if FComparer.Compare(AValue, FItems[i]) = 0 then
  952. Exit(i);
  953. Result:=-1;
  954. end;
  955. function TList<T>.LastIndexOf(const AValue: T): SizeInt;
  956. var
  957. i: SizeInt;
  958. begin
  959. for i := Count - 1 downto 0 do
  960. if FComparer.Compare(AValue, FItems[i]) = 0 then
  961. Exit(i);
  962. Result:=-1;
  963. end;
  964. procedure TList<T>.Reverse;
  965. var
  966. a, b: SizeInt;
  967. LTemp: T;
  968. begin
  969. a := 0;
  970. b := Count - 1;
  971. while a < b do
  972. begin
  973. LTemp := FItems[a];
  974. FItems[a] := FItems[b];
  975. FItems[b] := LTemp;
  976. Inc(a);
  977. Dec(b);
  978. end;
  979. end;
  980. procedure TList<T>.TrimExcess;
  981. begin
  982. SetCapacity(Count);
  983. end;
  984. procedure TList<T>.Sort;
  985. begin
  986. TMyArrayHelper.Sort(FItems, FComparer, 0, Count);
  987. end;
  988. procedure TList<T>.Sort(const AComparer: IComparer<T>);
  989. begin
  990. TMyArrayHelper.Sort(FItems, AComparer, 0, Count);
  991. end;
  992. function TList<T>.BinarySearch(const AItem: T; out AIndex: SizeInt): Boolean;
  993. begin
  994. Result := TMyArrayHelper.BinarySearch(FItems, AItem, AIndex, FComparer, 0, Count);
  995. end;
  996. function TList<T>.BinarySearch(const AItem: T; out AIndex: SizeInt;
  997. const AComparer: IComparer<T>): Boolean;
  998. begin
  999. Result := TMyArrayHelper.BinarySearch(FItems, AItem, AIndex, AComparer, 0, Count);
  1000. end;
  1001. { TPair }
  1002. constructor TPair<TKey,TValue>.Create(const AKey: TKey; const AValue: TValue);
  1003. begin
  1004. Key:=aKey;
  1005. Value:=aValue;
  1006. end;
  1007. { TDictionary }
  1008. ResourceString
  1009. SErrDictKeyNotFound = 'Key value not found';
  1010. SErrDictDuplicateKey = 'Duplicate key value';
  1011. function TDictionary<TKey, TValue>.GetItem(const Key: TKey): TValue;
  1012. Var
  1013. V : JSValue;
  1014. begin
  1015. V:=FMap.Get(Key);
  1016. if isUndefined(v) then
  1017. Raise EDictionary.Create(SErrDictKeyNotFound);
  1018. Result:=TValue(V);
  1019. end;
  1020. procedure TDictionary<TKey, TValue>.SetItem(const Key: TKey; const Value: TValue);
  1021. Var
  1022. V : JSValue;
  1023. begin
  1024. V:=FMap.Get(Key);
  1025. if Not isUndefined(v) then
  1026. ValueNotify(TValue(V),cnRemoved);
  1027. FMap.&Set(Key,Value);
  1028. ValueNotify(Value, cnAdded);
  1029. end;
  1030. procedure TDictionary<TKey, TValue>.DoAdd(const Key: TKey; const Value: TValue);
  1031. begin
  1032. FMap.&Set(Key,Value);
  1033. KeyNotify(Key,cnAdded);
  1034. ValueNotify(Value,cnAdded);
  1035. end;
  1036. function TDictionary<TKey, TValue>.DoRemove(const Key: TKey; Notification: TCollectionNotification): TValue;
  1037. Var
  1038. V : JSValue;
  1039. begin
  1040. V:=FMap.Get(Key);
  1041. if Not isUndefined(v) then
  1042. begin
  1043. FMap.Delete(Key);
  1044. Result:=TValue(v);
  1045. KeyNotify(Key,Notification);
  1046. ValueNotify(Result,Notification);
  1047. end;
  1048. end;
  1049. function TDictionary<TKey, TValue>.GetCount: Integer;
  1050. begin
  1051. Result:=FMap.Size;
  1052. end;
  1053. function TDictionary<TKey, TValue>.DoGetEnumerator: TEnumerator<TMyPair>;
  1054. begin
  1055. Result:=TPairEnumerator.Create(Self);
  1056. end;
  1057. procedure TDictionary<TKey, TValue>.PairNotify(const Key: TKey; Value : TValue; Action: TCollectionNotification);
  1058. begin
  1059. KeyNotify(Key,action);
  1060. ValueNotify(Value,action);
  1061. end;
  1062. procedure TDictionary<TKey, TValue>.KeyNotify(const Key: TKey; Action: TCollectionNotification);
  1063. begin
  1064. if Assigned(FOnKeyNotify) then
  1065. FOnKeyNotify(Self,Key,Action);
  1066. end;
  1067. procedure TDictionary<TKey, TValue>.ValueNotify(const Value: TValue; Action: TCollectionNotification);
  1068. begin
  1069. if Assigned(FOnValueNotify) then
  1070. FOnValueNotify(Self,Value,Action);
  1071. end;
  1072. constructor TDictionary<TKey, TValue>.Create(ACapacity: Integer = 0);
  1073. begin
  1074. FMap:=TJSMap.New;
  1075. end;
  1076. constructor TDictionary<TKey, TValue>.Create(const Collection: TEnumerable<TMyPair>);
  1077. Var
  1078. aPair : TMyPair;
  1079. begin
  1080. Create(0);
  1081. For aPair in Collection do
  1082. Add(aPair.Key,aPair.Value);
  1083. end;
  1084. destructor TDictionary<TKey, TValue>.Destroy;
  1085. begin
  1086. FreeAndNil(FKeyCollection);
  1087. FreeAndNil(FValueCollection);
  1088. Clear;
  1089. FMap:=Nil;
  1090. inherited Destroy;
  1091. end;
  1092. procedure TDictionary<TKey, TValue>.Add(const Key: TKey; const Value: TValue);
  1093. begin
  1094. if FMap.Has(Key) then
  1095. Raise EDictionary.Create(SErrDictDuplicateKey);
  1096. DoAdd(Key,Value);
  1097. end;
  1098. procedure TDictionary<TKey, TValue>.Remove(const Key: TKey);
  1099. begin
  1100. doRemove(Key,cnRemoved);
  1101. end;
  1102. function TDictionary<TKey, TValue>.ExtractPair(const Key: TKey): TMyPair;
  1103. begin
  1104. if FMap.Has(Key) then
  1105. begin
  1106. Result.Create(Key,TValue(FMap.get(key)));
  1107. FMap.Delete(Key);
  1108. end
  1109. else
  1110. Result.Create(Key,Default(TValue));
  1111. end;
  1112. Function TDictionary<TKey, TValue>.CanClearMap : Boolean;
  1113. begin
  1114. Result:=(FOnKeyNotify=Nil) and (FOnValueNotify=Nil);
  1115. end;
  1116. procedure TDictionary<TKey, TValue>.Clear;
  1117. Var
  1118. Iter : TJSIterator;
  1119. IVal : TJSIteratorValue;
  1120. A : TJSValueDynArray;
  1121. K : TKey;
  1122. V : TValue;
  1123. begin
  1124. if CanClearMap then
  1125. Fmap.Clear
  1126. else
  1127. begin
  1128. Iter:=FMap.Entries;
  1129. Repeat
  1130. IVal:=Iter.next;
  1131. if not ival.Done then
  1132. begin
  1133. A:=TJSValueDynArray(IVal.Value);
  1134. K:=TKey(A[0]);
  1135. V:=TValue(A[1]);
  1136. FMap.delete(k);
  1137. PairNotify(K,V,cnRemoved);
  1138. end;
  1139. Until Ival.Done;
  1140. end;
  1141. end;
  1142. function TDictionary<TKey, TValue>.TryGetValue(const Key: TKey; out Value: TValue): Boolean;
  1143. begin
  1144. Result:=FMap.Has(Key);
  1145. If Result then
  1146. Value:=TValue(FMap.get(Key));
  1147. end;
  1148. procedure TDictionary<TKey, TValue>.AddOrSetValue(const Key: TKey; const Value: TValue);
  1149. begin
  1150. if Not FMap.Has(Key) then
  1151. DoAdd(Key,Value)
  1152. else
  1153. SetItem(Key,Value);
  1154. end;
  1155. function TDictionary<TKey, TValue>.ContainsKey(const Key: TKey): Boolean;
  1156. begin
  1157. Result:=FMap.Has(Key);
  1158. end;
  1159. function TDictionary<TKey, TValue>.ContainsValue(const Value: TValue): Boolean;
  1160. Var
  1161. It : TJSIterator;
  1162. Res : TJSIteratorValue;
  1163. begin
  1164. Result:=False;
  1165. It:=FMap.Values;
  1166. Repeat
  1167. Res:=It.next;
  1168. if not Res.done then
  1169. Result:=(Value=TValue(Res.value));
  1170. Until (Result or Res.done);
  1171. end;
  1172. function TDictionary<TKey, TValue>.ToArray: TArray<TMyPair>;
  1173. begin
  1174. Result:=inherited ToArray;
  1175. end;
  1176. function TDictionary<TKey, TValue>.GetKeys: TKeyCollection;
  1177. begin
  1178. if FKeyCollection=Nil then
  1179. FKeyCollection:=TKeyCollection.Create(Self);
  1180. Result:=FKeyCollection;
  1181. end;
  1182. function TDictionary<TKey, TValue>.GetValues: TValueCollection;
  1183. begin
  1184. if FValueCollection=Nil then
  1185. FValueCollection:=TValueCollection.Create(Self);
  1186. Result:=FValueCollection;
  1187. end;
  1188. function TDictionary<TKey, TValue>.GetEnumerator: TPairEnumerator;
  1189. begin
  1190. Result:=TPairEnumerator.Create(Self);
  1191. end;
  1192. { TDictionary.TPairEnumerator }
  1193. function TDictionary<TKey, TValue>.TPairEnumerator.GetCurrent: TMyPair;
  1194. begin
  1195. Result:=DoGetCurrent;
  1196. end;
  1197. function TDictionary<TKey, TValue>.TPairEnumerator.DoGetCurrent: TMyPair;
  1198. Var
  1199. A : TJSValueDynArray;
  1200. begin
  1201. A:=TJSValueDynArray(FVal.Value);
  1202. Result.Create(TKey(A[0]),TValue(A[1]));
  1203. end;
  1204. function TDictionary<TKey, TValue>.TPairEnumerator.DoMoveNext: Boolean;
  1205. begin
  1206. FVal:=FIter.Next;
  1207. Result:=Not FVal.Done;
  1208. end;
  1209. constructor TDictionary<TKey, TValue>.TPairEnumerator.Create(const ADictionary: TMyType);
  1210. begin
  1211. FIter:=ADictionary.FMap.Entries;
  1212. end;
  1213. function TDictionary<TKey, TValue>.TPairEnumerator.MoveNext: Boolean;
  1214. begin
  1215. Result:=DoMoveNext;
  1216. end;
  1217. { TDictionary.TKeyEnumerator }
  1218. function TDictionary<TKey, TValue>.TKeyEnumerator.GetCurrent: TKey;
  1219. begin
  1220. Result:=DoGetCurrent;
  1221. end;
  1222. function TDictionary<TKey, TValue>.TKeyEnumerator.DoGetCurrent: TKey;
  1223. begin
  1224. Result:=TKey(FVal.Value);
  1225. end;
  1226. function TDictionary<TKey, TValue>.TKeyEnumerator.DoMoveNext: Boolean;
  1227. begin
  1228. FVal:=FIter.Next;
  1229. Result:=Not FVal.Done;
  1230. end;
  1231. constructor TDictionary<TKey, TValue>.TKeyEnumerator.Create(const ADictionary: TMyType);
  1232. begin
  1233. Create(ADictionary.FMap.Keys);
  1234. end;
  1235. constructor TDictionary<TKey, TValue>.TKeyEnumerator.Create(const AIter : TJSIterator);
  1236. begin
  1237. FIter:=aIter;
  1238. end;
  1239. function TDictionary<TKey, TValue>.TKeyEnumerator.MoveNext: Boolean;
  1240. begin
  1241. Result:=DoMoveNext;
  1242. end;
  1243. { TDictionary.TValueEnumerator }
  1244. function TDictionary<TKey, TValue>.TValueEnumerator.GetCurrent: TValue;
  1245. begin
  1246. Result:=DoGetCurrent;
  1247. end;
  1248. function TDictionary<TKey, TValue>.TValueEnumerator.DoGetCurrent: TValue;
  1249. begin
  1250. Result:=TValue(FVal.Value);
  1251. end;
  1252. function TDictionary<TKey, TValue>.TValueEnumerator.DoMoveNext: Boolean;
  1253. begin
  1254. FVal:=FIter.Next;
  1255. Result:=Not FVal.Done;
  1256. end;
  1257. constructor TDictionary<TKey, TValue>.TValueEnumerator.Create(const ADictionary: TMyType);
  1258. begin
  1259. Create(aDictionary.FMap.Values);
  1260. end;
  1261. constructor TDictionary<TKey, TValue>.TValueEnumerator.Create(const AIter: TJSIterator);
  1262. begin
  1263. FIter:=AIter;
  1264. end;
  1265. function TDictionary<TKey, TValue>.TValueEnumerator.MoveNext: Boolean;
  1266. begin
  1267. Result:=DoMoveNext;
  1268. end;
  1269. { TDictionary.TValueCollection }
  1270. function TDictionary<TKey, TValue>.TValueCollection.GetCount: Integer;
  1271. begin
  1272. Result:=FMap.Size;
  1273. end;
  1274. function TDictionary<TKey, TValue>.TValueCollection.DoGetEnumerator: TEnumerator<TValue>;
  1275. begin
  1276. Result:=TValueEnumerator.Create(FMap.Values);
  1277. end;
  1278. constructor TDictionary<TKey, TValue>.TValueCollection.Create(const ADictionary: TMyType);
  1279. begin
  1280. FMap:=ADictionary.FMap;
  1281. end;
  1282. function TDictionary<TKey, TValue>.TValueCollection.GetEnumerator: TValueEnumerator;
  1283. begin
  1284. Result:=TValueEnumerator(DoGetEnumerator);
  1285. end;
  1286. function TDictionary<TKey, TValue>.TValueCollection.ToArray: TArray<TValue>;
  1287. Var
  1288. I : Integer;
  1289. P : TValue;
  1290. begin
  1291. SetLength(Result,FMap.Size);
  1292. For P in Self do
  1293. begin
  1294. Result[i]:=P;
  1295. Inc(I);
  1296. End;
  1297. end;
  1298. { TDictionary.TKeyCollection }
  1299. function TDictionary<TKey, TValue>.TKeyCollection.GetCount: Integer;
  1300. begin
  1301. Result:=FMap.Size;
  1302. end;
  1303. function TDictionary<TKey, TValue>.TKeyCollection.DoGetEnumerator: TEnumerator<TKey>;
  1304. begin
  1305. Result:=GetEnumerator;
  1306. end;
  1307. constructor TDictionary<TKey, TValue>.TKeyCollection.Create(const ADictionary: TMyType);
  1308. begin
  1309. FMap:=aDictionary.FMap;
  1310. end;
  1311. function TDictionary<TKey, TValue>.TKeyCollection.GetEnumerator: TKeyEnumerator;
  1312. begin
  1313. Result:=TKeyEnumerator.Create(FMap.Keys);
  1314. end;
  1315. function TDictionary<TKey, TValue>.TKeyCollection.ToArray: TArray<TKey>;
  1316. begin
  1317. Result:=inherited ToArray;
  1318. end;
  1319. { TObjectList<T> }
  1320. procedure TObjectList<T>.Notify(const aValue: T; Action: TCollectionNotification);
  1321. Var
  1322. A : TObject absolute aValue; // needed to fool compiler
  1323. begin
  1324. inherited Notify(aValue, Action);
  1325. if FObjectsOwner and (action = cnRemoved) then
  1326. a.Free;
  1327. end;
  1328. constructor TObjectList<T>.Create(AOwnsObjects: Boolean);
  1329. begin
  1330. inherited Create;
  1331. FObjectsOwner := AOwnsObjects;
  1332. end;
  1333. constructor TObjectList<T>.Create(const AComparer: IComparer<T>; AOwnsObjects: Boolean);
  1334. begin
  1335. inherited Create(AComparer);
  1336. FObjectsOwner := AOwnsObjects;
  1337. end;
  1338. constructor TObjectList<T>.Create(const ACollection: TEnumerable<T>; aOwnsObjects: Boolean);
  1339. begin
  1340. inherited Create(ACollection);
  1341. FObjectsOwner := AOwnsObjects;
  1342. end;
  1343. { TThreadList }
  1344. constructor TThreadList<T>.Create;
  1345. begin
  1346. inherited Create;
  1347. FLock:=0;
  1348. FList := TList<T>.Create;
  1349. FDuplicates := dupIgnore;
  1350. end;
  1351. destructor TThreadList<T>.Destroy;
  1352. begin
  1353. // No need to unlock.
  1354. FList.Free;
  1355. inherited Destroy;
  1356. end;
  1357. procedure TThreadList<T>.Add(const Item: T);
  1358. begin
  1359. LockList;
  1360. try
  1361. if (Duplicates = dupAccept) or (FList.IndexOf(Item) = -1) then
  1362. FList.Add(Item)
  1363. else if Duplicates = dupError then
  1364. raise EListError.Create(SDuplicateItem);
  1365. finally
  1366. UnlockList;
  1367. end;
  1368. end;
  1369. procedure TThreadList<T>.Clear;
  1370. begin
  1371. LockList;
  1372. try
  1373. FList.Clear;
  1374. finally
  1375. UnlockList;
  1376. end;
  1377. end;
  1378. function TThreadList<T>.LockList: TList<T>;
  1379. begin
  1380. Inc(FLock);
  1381. if (FLock>1) then
  1382. Writeln('Locking already locked list, lockcount : ',FLock);
  1383. Result:=FList;
  1384. end;
  1385. procedure TThreadList<T>.Remove(const Item: T);
  1386. begin
  1387. RemoveItem(T,TDirection.FromBeginning);
  1388. end;
  1389. procedure TThreadList<T>.RemoveItem(const Item: T; Direction: TDirection);
  1390. begin
  1391. LockList;
  1392. try
  1393. FList.RemoveItem(T,Direction);
  1394. finally
  1395. UnlockList;
  1396. end;
  1397. end;
  1398. procedure TThreadList<T>.UnlockList;
  1399. begin
  1400. Dec(FLock);
  1401. if (FLock<0) then
  1402. Writeln('Unlocking already unlocked list, lockcount : ',FLock);
  1403. end;
  1404. { TObjectDictionary }
  1405. function TObjectDictionary<TKey, TValue>.CanClearMap: Boolean;
  1406. begin
  1407. Result:=(Inherited CanClearMap) and (FOwnerships=[]);
  1408. end;
  1409. procedure TObjectDictionary<TKey, TValue>.KeyNotify(const Key: TKey; Action: TCollectionNotification);
  1410. Var
  1411. A : TObject absolute key; // Avoid typecast, refused by compiler
  1412. begin
  1413. inherited KeyNotify(Key, Action);
  1414. if (doOwnsKeys in FOwnerships) and (Action = cnRemoved) then
  1415. A.Free;
  1416. end;
  1417. procedure TObjectDictionary<TKey, TValue>.ValueNotify(const Value: TValue; Action: TCollectionNotification);
  1418. Var
  1419. A : TObject absolute Value; // Avoid typecast, refused by compiler
  1420. begin
  1421. inherited ValueNotify(Value, Action);
  1422. if (doOwnsValues in FOwnerships) and (Action = cnRemoved) then
  1423. A.Free;
  1424. end;
  1425. constructor TObjectDictionary<TKey, TValue>.Create(aOwnerships: TDictionaryOwnerships; ACapacity: Integer);
  1426. begin
  1427. Create(aOwnerShips);
  1428. end;
  1429. constructor TObjectDictionary<TKey, TValue>.Create(aOwnerships: TDictionaryOwnerships);
  1430. begin
  1431. Inherited Create;
  1432. FOwnerShips:=aOwnerships;
  1433. end;
  1434. { TQueue }
  1435. function TQueue<T>.DoGetEnumerator: TEnumerator<T>;
  1436. begin
  1437. Result:=GetEnumerator;
  1438. end;
  1439. function TQueue<T>.GetEnumerator: TEnumerator;
  1440. begin
  1441. Result := TEnumerator.Create(Self);
  1442. end;
  1443. procedure TQueue<T>.SetCapacity(AValue: SizeInt);
  1444. begin
  1445. if AValue < Count then
  1446. raise EArgumentOutOfRangeException.Create(SArgumentOutOfRange);
  1447. if FLow>0 then
  1448. Rebase;
  1449. SetLength(FItems,aValue);
  1450. end;
  1451. function TQueue<T>.DoRemove(AIndex: SizeInt; ACollectionNotification: TCollectionNotification): T;
  1452. begin
  1453. if (FLow>=FLength) then
  1454. raise EArgumentOutOfRangeException.Create(SArgumentOutOfRange);
  1455. Result := FItems[AIndex];
  1456. FItems[AIndex] := Default(T);
  1457. Inc(FLow);
  1458. if FLow >= FLength then
  1459. begin
  1460. FLow:=0;
  1461. FLength:=0;
  1462. end;
  1463. Notify(Result, ACollectionNotification);
  1464. end;
  1465. function TQueue<T>.GetCount: SizeInt;
  1466. begin
  1467. Result:=FLength-FLow;
  1468. end;
  1469. constructor TQueue<T>.Create;
  1470. begin
  1471. FMaxGapLength:=10;
  1472. end;
  1473. constructor TQueue<T>.Create(ACollection: TEnumerable<T>);
  1474. var
  1475. Itm: T;
  1476. begin
  1477. Create;
  1478. for Itm in ACollection do
  1479. Enqueue(Itm);
  1480. end;
  1481. destructor TQueue<T>.Destroy;
  1482. begin
  1483. Clear;
  1484. inherited Destroy;
  1485. end;
  1486. procedure TQueue<T>.Enqueue(const AValue: T);
  1487. begin
  1488. if Capacity<=FLength then
  1489. SetCapacity(FLength+10);
  1490. FItems[FLength]:=aValue;
  1491. Inc(FLength);
  1492. Notify(aValue,cnAdded);
  1493. end;
  1494. function TQueue<T>.Dequeue: T;
  1495. begin
  1496. Result := DoRemove(FLow, cnRemoved);
  1497. if FLow>FMaxGapLength then
  1498. Rebase;
  1499. end;
  1500. function TQueue<T>.Extract: T;
  1501. begin
  1502. Result := DoRemove(FLow, cnExtracted);
  1503. if FLow>FMaxGapLength then
  1504. Rebase;
  1505. end;
  1506. function TQueue<T>.Peek: T;
  1507. begin
  1508. if (Count=0) then
  1509. raise EArgumentOutOfRangeException.Create(SArgumentOutOfRange);
  1510. Result:=FItems[FLow];
  1511. end;
  1512. procedure TQueue<T>.Clear;
  1513. begin
  1514. while Count <> 0 do
  1515. Dequeue;
  1516. end;
  1517. procedure TQueue<T>.Rebase;
  1518. Var
  1519. I,Spare : integer;
  1520. begin
  1521. Spare:=Capacity-Count;
  1522. if FLow>0 then
  1523. begin
  1524. For I:=Flow to FLength do
  1525. FItems[I-FLow]:=FItems[I];
  1526. SetLength(FItems,FLength+Spare);
  1527. FLength:=FLength-Flow+1;
  1528. Flow:=0;
  1529. end;
  1530. end;
  1531. procedure TQueue<T>.TrimExcess;
  1532. begin
  1533. Rebase;
  1534. SetCapacity(Count);
  1535. end;
  1536. { TQueue.TEnumerator }
  1537. constructor TQueue<T>.TEnumerator.Create(AQueue: TMyType);
  1538. begin
  1539. aQueue.Rebase;
  1540. Inherited Create(aQueue);
  1541. end;
  1542. { TObjectQueue }
  1543. procedure TObjectQueue<T>.Notify(const Value: T; Action: TCollectionNotification);
  1544. Var
  1545. A : TObject absolute Value;
  1546. begin
  1547. inherited Notify(Value, Action);
  1548. if OwnsObjects and (Action = cnRemoved) then
  1549. A.Free;
  1550. end;
  1551. constructor TObjectQueue<T>.Create(AOwnsObjects: Boolean);
  1552. begin
  1553. Inherited create;
  1554. FOwnsObjects:=aOwnsObjects;
  1555. end;
  1556. constructor TObjectQueue<T>.Create(const Collection: TEnumerable<T>; AOwnsObjects: Boolean);
  1557. Var
  1558. A : T;
  1559. begin
  1560. Create(aOwnsObjects);
  1561. For A in Collection do
  1562. EnQueue(A);
  1563. end;
  1564. procedure TObjectQueue<T>.Dequeue;
  1565. begin
  1566. Inherited DeQueue;
  1567. end;
  1568. { TStack }
  1569. function TStack<T>.DoRemove(aIndex : SizeInt; ACollectionNotification: TCollectionNotification): T;
  1570. begin
  1571. if (FLength=0) or (aIndex<>FLength-1) then
  1572. raise EArgumentOutOfRangeException.Create(SArgumentOutOfRange);
  1573. Result:=FItems[AIndex];
  1574. FItems[AIndex] := Default(T);
  1575. Dec(FLength);
  1576. Notify(Result, ACollectionNotification);
  1577. end;
  1578. procedure TStack<T>.SetCapacity(aValue: SizeInt);
  1579. begin
  1580. if AValue < Count then
  1581. raise EArgumentOutOfRangeException.Create(SArgumentOutOfRange);
  1582. SetLength(FItems,aValue);
  1583. end;
  1584. function TStack<T>.DoGetEnumerator: TEnumerator<T>;
  1585. begin
  1586. Result:=GetEnumerator;
  1587. end;
  1588. function TStack<T>.GetEnumerator: TEnumerator;
  1589. begin
  1590. Result:=TEnumerator.Create(Self);
  1591. end;
  1592. destructor TStack<T>.Destroy;
  1593. begin
  1594. Clear;
  1595. inherited Destroy;
  1596. end;
  1597. procedure TStack<T>.Clear;
  1598. begin
  1599. While Count>0 do Pop;
  1600. end;
  1601. procedure TStack<T>.Push(const aValue: T);
  1602. begin
  1603. if Capacity<=FLength then
  1604. SetCapacity(FLength+10);
  1605. FItems[FLength]:=aValue;
  1606. Inc(FLength);
  1607. Notify(aValue,cnAdded);
  1608. end;
  1609. function TStack<T>.Pop: T;
  1610. begin
  1611. Result:=DoRemove(FLength-1,cnRemoved);
  1612. end;
  1613. function TStack<T>.Peek: T;
  1614. begin
  1615. if Count<1 then
  1616. raise EArgumentOutOfRangeException.Create(SArgumentOutOfRange);
  1617. Result:=FItems[FLength-1];
  1618. end;
  1619. function TStack<T>.Extract: T;
  1620. begin
  1621. Result:=DoRemove(FLength-1,cnExtracted);
  1622. end;
  1623. procedure TStack<T>.TrimExcess;
  1624. begin
  1625. SetCapacity(FLength);
  1626. end;
  1627. { TCustomInvertedListEnumerator }
  1628. function TCustomInvertedListEnumerator<T>.DoMoveNext: boolean;
  1629. begin
  1630. Result:=FIndex>0;
  1631. If Result then
  1632. Dec(FIndex);
  1633. end;
  1634. function TCustomInvertedListEnumerator<T>.DoGetCurrent: T;
  1635. begin
  1636. Result:=FList.FItems[FIndex];
  1637. end;
  1638. function TCustomInvertedListEnumerator<T>.GetCurrent: T;
  1639. begin
  1640. Result:=DoGetCurrent;
  1641. end;
  1642. constructor TCustomInvertedListEnumerator<T>.Create(AList: TCustomList<T>);
  1643. begin
  1644. inherited Create;
  1645. FList:=AList;
  1646. FIndex:=AList.FLength;
  1647. end;
  1648. { TStack.TEnumerator }
  1649. constructor TStack<T>.TEnumerator.Create(AStack: TMyType);
  1650. begin
  1651. Inherited Create(aStack);
  1652. end;
  1653. { TObjectStack }
  1654. procedure TObjectStack<T>.Notify(const aValue: T; Action: TCollectionNotification);
  1655. Var
  1656. A : T absolute aValue;
  1657. begin
  1658. inherited Notify(aValue, Action);
  1659. if (Action=cnRemoved) and FOwnsObjects then
  1660. a.Free;
  1661. end;
  1662. constructor TObjectStack<T>.Create(AOwnsObjects: Boolean);
  1663. begin
  1664. Inherited Create;
  1665. FOwnsObjects:=aOwnsObjects;
  1666. end;
  1667. constructor TObjectStack<T>.Create(const Collection: TEnumerable<T>; AOwnsObjects: Boolean);
  1668. Var
  1669. A : T;
  1670. begin
  1671. Create(aOwnsObjects);
  1672. For A in Collection do
  1673. Push(A);
  1674. end;
  1675. procedure TObjectStack<T>.Pop;
  1676. begin
  1677. Inherited Pop;
  1678. end;
  1679. end.