lists.inc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026
  1. {
  2. This file is part of the Free Pascal Run Time Library (rtl)
  3. Copyright (c) 1999-2005 by the Free Pascal development team
  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. {$if not defined(FPC_TESTGENERICS)}
  11. {****************************************************************************}
  12. {* TFPListEnumerator *}
  13. {****************************************************************************}
  14. constructor TFPListEnumerator.Create(AList: TFPList);
  15. begin
  16. inherited Create;
  17. FList := AList;
  18. FPosition := -1;
  19. end;
  20. function TFPListEnumerator.GetCurrent: Pointer;
  21. begin
  22. Result := FList[FPosition];
  23. end;
  24. function TFPListEnumerator.MoveNext: Boolean;
  25. begin
  26. Inc(FPosition);
  27. Result := FPosition < FList.Count;
  28. end;
  29. {****************************************************************************}
  30. {* TFPList *}
  31. {****************************************************************************}
  32. Const
  33. // Ratio of Pointer and Word Size.
  34. WordRatio = SizeOf(Pointer) Div SizeOf(Word);
  35. procedure TFPList.RaiseIndexError(Index : Integer);
  36. begin
  37. // We should be able to remove this, but unfortunately it is marked protected.
  38. Error(SListIndexError, Index);
  39. end;
  40. Procedure TFPList.CheckIndex(AIndex : Integer);
  41. begin
  42. If (AIndex < 0) or (AIndex >= FCount) then
  43. Error(SListIndexError, AIndex); // Don't use RaiseIndexError, exception address will be better if we use error.
  44. end;
  45. function TFPList.Get(Index: Integer): Pointer;
  46. begin
  47. CheckIndex(Index);
  48. Result:=FList^[Index];
  49. end;
  50. procedure TFPList.Put(Index: Integer; Item: Pointer);
  51. begin
  52. CheckIndex(Index);
  53. Flist^[Index] := Item;
  54. end;
  55. function TFPList.Extract(Item: Pointer): Pointer;
  56. var
  57. i : Integer;
  58. begin
  59. i := IndexOf(item);
  60. if i >= 0 then
  61. begin
  62. Result := item;
  63. Delete(i);
  64. end
  65. else
  66. result := nil;
  67. end;
  68. procedure TFPList.SetCapacity(NewCapacity: Integer);
  69. begin
  70. If (NewCapacity < FCount) or (NewCapacity > MaxListSize) then
  71. Error (SListCapacityError, NewCapacity);
  72. if NewCapacity = FCapacity then
  73. exit;
  74. ReallocMem(FList, SizeOf(Pointer)*NewCapacity);
  75. FCapacity := NewCapacity;
  76. end;
  77. procedure TFPList.SetCount(NewCount: Integer);
  78. begin
  79. if (NewCount < 0) or (NewCount > MaxListSize)then
  80. Error(SListCountError, NewCount);
  81. If NewCount > FCount then
  82. begin
  83. If NewCount > FCapacity then
  84. SetCapacity(NewCount);
  85. If FCount < NewCount then
  86. FillWord(Flist^[FCount], (NewCount-FCount) * WordRatio, 0);
  87. end;
  88. FCount := Newcount;
  89. end;
  90. destructor TFPList.Destroy;
  91. begin
  92. Self.Clear;
  93. inherited Destroy;
  94. end;
  95. Procedure TFPList.AddList(AList : TFPList);
  96. Var
  97. I : Integer;
  98. begin
  99. If (Capacity<Count+AList.Count) then
  100. Capacity:=Count+AList.Count;
  101. For I:=0 to AList.Count-1 do
  102. Add(AList[i]);
  103. end;
  104. function TFPList.Add(Item: Pointer): Integer;
  105. begin
  106. if FCount = FCapacity then
  107. Self.Expand;
  108. FList^[FCount] := Item;
  109. Result := FCount;
  110. FCount := FCount + 1;
  111. end;
  112. procedure TFPList.Clear;
  113. begin
  114. if Assigned(FList) then
  115. begin
  116. SetCount(0);
  117. SetCapacity(0);
  118. // FList := nil; // Already set by SetCapacity
  119. end;
  120. end;
  121. procedure TFPList.Delete(Index: Integer);
  122. begin
  123. CheckIndex(Index);
  124. FCount := FCount-1;
  125. System.Move (FList^[Index+1], FList^[Index], (FCount - Index) * SizeOf(Pointer));
  126. // Shrink the list if appropriate:
  127. // If capacity>256 and the list is less than a quarter filled, shrink to 1/2 the size.
  128. // Shr is used because it is faster than div.
  129. if (FCapacity > 256) and (FCount < FCapacity shr 2) then
  130. begin
  131. FCapacity := FCapacity shr 1;
  132. ReallocMem(FList, SizeOf(Pointer) * FCapacity);
  133. end;
  134. end;
  135. class procedure TFPList.Error(const Msg: string; Data: PtrInt);
  136. begin
  137. Raise EListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame), get_caller_frame(get_frame);
  138. end;
  139. procedure TFPList.Exchange(Index1, Index2: Integer);
  140. var
  141. Temp : Pointer;
  142. begin
  143. CheckIndex(Index1);
  144. CheckIndex(Index2);
  145. Temp := FList^[Index1];
  146. FList^[Index1] := FList^[Index2];
  147. FList^[Index2] := Temp;
  148. end;
  149. function TFPList.Expand: TFPList;
  150. var
  151. IncSize : Longint;
  152. begin
  153. if FCount < FCapacity then exit(self);
  154. {
  155. For really big lists, (128Mb elements), increase with fixed amount: 16Mb elements (=1/8th of 128Mb).
  156. For big lists (8mb elements), increase with 1/8th of the size
  157. For moderate lists (128 or more, increase with 1/4th the size
  158. For smaller sizes, increase with 16 or 4
  159. }
  160. if FCapacity > 128*1024*1024 then IncSize := 16*1024*1024
  161. else if FCapacity > 8*1024*1024 then IncSize := FCapacity shr 3
  162. else if FCapacity > 128 then IncSize := FCapacity shr 2
  163. else if FCapacity > 8 then IncSize := 16
  164. else IncSize := 4;
  165. SetCapacity(FCapacity + IncSize);
  166. Result := Self;
  167. end;
  168. function TFPList.First: Pointer;
  169. begin
  170. If FCount = 0 then
  171. Result := Nil
  172. else
  173. Result := Items[0];
  174. end;
  175. function TFPList.GetEnumerator: TFPListEnumerator;
  176. begin
  177. Result := TFPListEnumerator.Create(Self);
  178. end;
  179. function TFPList.IndexOf(Item: Pointer): Integer;
  180. begin
  181. Result :=
  182. {$if sizeof(pointer) = sizeof(dword)}
  183. IndexDWord
  184. {$elseif sizeof(pointer) = sizeof(qword)}
  185. IndexQWord
  186. {$else}
  187. {$error unknown pointer size}
  188. {$endif}
  189. (FList^, FCount, PtrUint(Item));
  190. end;
  191. function TFPList.IndexOfItem(Item: Pointer; Direction: TDirection): Integer;
  192. begin
  193. if Direction=fromBeginning then
  194. Result:=IndexOf(Item)
  195. else
  196. begin
  197. Result:=Count-1;
  198. while (Result >=0) and (Flist^[Result]<>Item) do
  199. Result:=Result - 1;
  200. end;
  201. end;
  202. procedure TFPList.Insert(Index: Integer; Item: Pointer);
  203. begin
  204. if (Index < 0) or (Index > FCount )then
  205. Error(SlistIndexError, Index);
  206. iF FCount = FCapacity then Self.Expand;
  207. if Index<FCount then
  208. System.Move(Flist^[Index], Flist^[Index+1], (FCount - Index) * SizeOf(Pointer));
  209. FList^[Index] := Item;
  210. FCount := FCount + 1;
  211. end;
  212. function TFPList.Last: Pointer;
  213. begin
  214. { Wouldn't it be better to return nil if the count is zero ?}
  215. If FCount = 0 then
  216. Result := nil
  217. else
  218. Result := Items[FCount - 1];
  219. end;
  220. procedure TFPList.Move(CurIndex, NewIndex: Integer);
  221. var
  222. Temp : Pointer;
  223. begin
  224. CheckIndex(CurIndex);
  225. CheckIndex(NewIndex);
  226. if (CurIndex=NewIndex) then
  227. exit;
  228. Temp := FList^[CurIndex];
  229. if NewIndex > CurIndex then
  230. System.Move(FList^[CurIndex+1], FList^[CurIndex], (NewIndex - CurIndex) * SizeOf(Pointer))
  231. else
  232. System.Move(FList^[NewIndex], FList^[NewIndex+1], (CurIndex - NewIndex) * SizeOf(Pointer));
  233. FList^[NewIndex] := Temp;
  234. end;
  235. function TFPList.Remove(Item: Pointer): Integer;
  236. begin
  237. Result := IndexOf(Item);
  238. If Result <> -1 then
  239. Self.Delete(Result);
  240. end;
  241. procedure TFPList.Pack;
  242. var
  243. NewCount,
  244. i : integer;
  245. pdest,
  246. psrc : PPointer;
  247. begin
  248. NewCount:=0;
  249. psrc:=@FList^[0];
  250. pdest:=psrc;
  251. For I:=0 To FCount-1 Do
  252. begin
  253. if assigned(psrc^) then
  254. begin
  255. pdest^:=psrc^;
  256. inc(pdest);
  257. inc(NewCount);
  258. end;
  259. inc(psrc);
  260. end;
  261. FCount:=NewCount;
  262. end;
  263. procedure TFPList.Sort(Compare: TListSortCompare);
  264. begin
  265. Sort(Compare, SortBase.DefaultSortingAlgorithm);
  266. end;
  267. procedure TFPList.Sort(Compare: TListSortCompare; SortingAlgorithm: PSortingAlgorithm);
  268. begin
  269. SortingAlgorithm^.PtrListSorter_NoContextComparer(PPointer(FList), FCount, Compare);
  270. end;
  271. procedure TFPList.Sort(Compare: TListSortComparer_Context; Context: Pointer);
  272. begin
  273. Sort(Compare, Context, SortBase.DefaultSortingAlgorithm);
  274. end;
  275. procedure TFPList.Sort(Compare: TListSortComparer_Context; Context: Pointer; SortingAlgorithm: PSortingAlgorithm);
  276. begin
  277. SortingAlgorithm^.PtrListSorter_ContextComparer(PPointer(FList), FCount, Compare, Context);
  278. end;
  279. procedure TFPList.ForEachCall(proc2call:TListCallback;arg:pointer);
  280. var
  281. i : integer;
  282. p : pointer;
  283. begin
  284. For I:=0 To Count-1 Do
  285. begin
  286. p:=FList^[i];
  287. if assigned(p) then
  288. proc2call(p,arg);
  289. end;
  290. end;
  291. procedure TFPList.ForEachCall(proc2call:TListStaticCallback;arg:pointer);
  292. var
  293. i : integer;
  294. p : pointer;
  295. begin
  296. For I:=0 To Count-1 Do
  297. begin
  298. p:=FList^[i];
  299. if assigned(p) then
  300. proc2call(p,arg);
  301. end;
  302. end;
  303. procedure TFPList.CopyMove (aList : TFPList);
  304. var r : integer;
  305. begin
  306. Clear;
  307. for r := 0 to aList.count-1 do
  308. Add (aList[r]);
  309. end;
  310. procedure TFPList.MergeMove (aList : TFPList);
  311. var r : integer;
  312. begin
  313. For r := 0 to aList.count-1 do
  314. if self.indexof(aList[r]) < 0 then
  315. self.Add (aList[r]);
  316. end;
  317. procedure TFPList.DoCopy(ListA, ListB : TFPList);
  318. begin
  319. if assigned (ListB) then
  320. CopyMove (ListB)
  321. else
  322. CopyMove (ListA);
  323. end;
  324. procedure TFPList.DoDestUnique(ListA, ListB : TFPList);
  325. procedure MoveElements (src, dest : TFPList);
  326. var r : integer;
  327. begin
  328. self.clear;
  329. for r := 0 to src.count-1 do
  330. if dest.indexof(src[r]) < 0 then
  331. self.Add (src[r]);
  332. end;
  333. var dest : TFPList;
  334. begin
  335. if assigned (ListB) then
  336. MoveElements (ListB, ListA)
  337. else
  338. try
  339. dest := TFPList.Create;
  340. dest.CopyMove (self);
  341. MoveElements (ListA, dest)
  342. finally
  343. dest.Free;
  344. end;
  345. end;
  346. procedure TFPList.DoAnd(ListA, ListB : TFPList);
  347. var r : integer;
  348. begin
  349. if assigned (ListB) then
  350. begin
  351. self.clear;
  352. for r := 0 to ListA.count-1 do
  353. if ListB.indexOf (ListA[r]) >= 0 then
  354. self.Add (ListA[r]);
  355. end
  356. else
  357. begin
  358. for r := self.Count-1 downto 0 do
  359. if ListA.indexof (Self[r]) < 0 then
  360. self.delete (r);
  361. end;
  362. end;
  363. procedure TFPList.DoSrcUnique(ListA, ListB : TFPList);
  364. var r : integer;
  365. begin
  366. if assigned (ListB) then
  367. begin
  368. self.Clear;
  369. for r := 0 to ListA.Count-1 do
  370. if ListB.indexof (ListA[r]) < 0 then
  371. self.Add (ListA[r]);
  372. end
  373. else
  374. begin
  375. for r := self.count-1 downto 0 do
  376. if ListA.indexof (self[r]) >= 0 then
  377. self.delete (r);
  378. end;
  379. end;
  380. procedure TFPList.DoOr(ListA, ListB : TFPList);
  381. begin
  382. if assigned (ListB) then
  383. begin
  384. CopyMove (ListA);
  385. MergeMove (ListB);
  386. end
  387. else
  388. MergeMove (ListA);
  389. end;
  390. procedure TFPList.DoXOr(ListA, ListB : TFPList);
  391. var r : integer;
  392. l : TFPList;
  393. begin
  394. if assigned (ListB) then
  395. begin
  396. self.Clear;
  397. for r := 0 to ListA.count-1 do
  398. if ListB.indexof (ListA[r]) < 0 then
  399. self.Add (ListA[r]);
  400. for r := 0 to ListB.count-1 do
  401. if ListA.indexof (ListB[r]) < 0 then
  402. self.Add (ListB[r]);
  403. end
  404. else
  405. try
  406. l := TFPList.Create;
  407. l.CopyMove (Self);
  408. for r := self.count-1 downto 0 do
  409. if listA.indexof (self[r]) >= 0 then
  410. self.delete (r);
  411. for r := 0 to ListA.count-1 do
  412. if l.indexof (ListA[r]) < 0 then
  413. self.add (ListA[r]);
  414. finally
  415. l.Free;
  416. end;
  417. end;
  418. procedure TFPList.Assign (ListA: TFPList; AOperator: TListAssignOp=laCopy; ListB: TFPList=nil);
  419. begin
  420. case AOperator of
  421. laCopy : DoCopy (ListA, ListB); // replace dest with src
  422. laSrcUnique : DoSrcUnique (ListA, ListB); // replace dest with src that are not in dest
  423. laAnd : DoAnd (ListA, ListB); // remove from dest that are not in src
  424. laDestUnique : DoDestUnique (ListA, ListB); // remove from dest that are in src
  425. laOr : DoOr (ListA, ListB); // add to dest from src and not in dest
  426. laXOr : DoXOr (ListA, ListB); // add to dest from src and not in dest, remove from dest that are in src
  427. end;
  428. end;
  429. {$else}
  430. { generics based implementation of TFPList follows }
  431. procedure TFPList.Assign(Source: TFPList);
  432. begin
  433. inherited Assign(Source);
  434. end;
  435. type
  436. TFPPtrListSortCompare = function(const Item1, Item2: Pointer): Integer;
  437. procedure TFPList.Sort(Compare: TListSortCompare);
  438. begin
  439. inherited Sort(TFPPtrListSortCompare(Compare));
  440. end;
  441. procedure TFPList.Sort(Compare: TListSortCompare; SortingAlgorithm: PSortingAlgorithm);
  442. begin
  443. inherited Sort(TFPPtrListSortCompare(Compare), SortingAlgorithm);
  444. end;
  445. procedure TFPList.ForEachCall(Proc2call: TListCallback; Arg: Pointer);
  446. var
  447. I: integer;
  448. begin
  449. for I:=0 to Count-1 do
  450. proc2call(InternalItems[I],arg);
  451. end;
  452. procedure TFPList.ForEachCall(Proc2call: TListStaticCallback; Arg: Pointer);
  453. var
  454. I: integer;
  455. begin
  456. for I:=0 to Count-1 do
  457. Proc2call(InternalItems[I], Arg);
  458. end;
  459. {$endif}
  460. {****************************************************************************}
  461. {* TListEnumerator *}
  462. {****************************************************************************}
  463. constructor TListEnumerator.Create(AList: TList);
  464. begin
  465. inherited Create(AList.FList);
  466. end;
  467. {****************************************************************************}
  468. {* TList *}
  469. {****************************************************************************}
  470. { TList = class(TObject)
  471. private
  472. FList: TFPList;
  473. }
  474. function TList.Get(Index: Integer): Pointer;
  475. begin
  476. Result := FList.Get(Index);
  477. end;
  478. procedure TList.Grow;
  479. begin
  480. // Only for compatibility with Delphi. Not needed.
  481. end;
  482. procedure TList.Put(Index: Integer; Item: Pointer);
  483. var p : pointer;
  484. begin
  485. p := get(Index);
  486. FList.Put(Index, Item);
  487. if assigned (p) then
  488. Notify (p, lnDeleted);
  489. if assigned (Item) then
  490. Notify (Item, lnAdded);
  491. end;
  492. function TList.Extract(item: Pointer): Pointer;
  493. var c : integer;
  494. begin
  495. c := FList.Count;
  496. Result := FList.Extract(item);
  497. if c <> FList.Count then
  498. Notify (Result, lnExtracted);
  499. end;
  500. procedure TList.Notify(Ptr: Pointer; Action: TListNotification);
  501. begin
  502. if Assigned(FObservers) then
  503. Case ACtion of
  504. lnAdded : FPONotifyObservers(Self,ooAddItem,Ptr);
  505. lnExtracted : FPONotifyObservers(Self,ooDeleteItem,Ptr);
  506. lnDeleted : FPONotifyObservers(Self,ooDeleteItem,Ptr);
  507. end;
  508. end;
  509. function TList.GetCapacity: integer;
  510. begin
  511. Result := FList.Capacity;
  512. end;
  513. procedure TList.SetCapacity(NewCapacity: Integer);
  514. begin
  515. FList.SetCapacity(NewCapacity);
  516. end;
  517. function TList.GetCount: Integer;
  518. begin
  519. Result := FList.Count;
  520. end;
  521. procedure TList.SetCount(NewCount: Integer);
  522. begin
  523. if NewCount < FList.Count then
  524. while FList.Count > NewCount do
  525. Delete(FList.Count - 1)
  526. else
  527. FList.SetCount(NewCount);
  528. end;
  529. constructor TList.Create;
  530. begin
  531. inherited Create;
  532. FList := TFPList.Create;
  533. end;
  534. destructor TList.Destroy;
  535. begin
  536. if Assigned(Flist) then
  537. Clear;
  538. If Assigned(FObservers) then
  539. begin
  540. FPONotifyObservers(Self,ooFree,Nil);
  541. FreeAndNil(FObservers);
  542. end;
  543. FreeAndNil(FList);
  544. inherited Destroy;
  545. end;
  546. procedure TList.FPOAttachObserver(AObserver: TObject);
  547. Var
  548. I : IFPObserver;
  549. begin
  550. If Not AObserver.GetInterface(SGUIDObserver,I) then
  551. Raise EObserver.CreateFmt(SErrNotObserver,[AObserver.ClassName]);
  552. If not Assigned(FObservers) then
  553. FObservers:=TFPList.Create;
  554. FObservers.Add(I);
  555. end;
  556. procedure TList.FPODetachObserver(AObserver: TObject);
  557. Var
  558. I : IFPObserver;
  559. begin
  560. If Not AObserver.GetInterface(SGUIDObserver,I) then
  561. Raise EObserver.CreateFmt(SErrNotObserver,[AObserver.ClassName]);
  562. If Assigned(FObservers) then
  563. begin
  564. FObservers.Remove(I);
  565. If (FObservers.Count=0) then
  566. FreeAndNil(FObservers);
  567. end;
  568. end;
  569. procedure TList.FPONotifyObservers(ASender: TObject;
  570. AOperation: TFPObservedOperation; Data : Pointer);
  571. Var
  572. I : Integer;
  573. Obs : IFPObserver;
  574. begin
  575. If Assigned(FObservers) then
  576. For I:=FObservers.Count-1 downto 0 do
  577. begin
  578. Obs:=IFPObserver(FObservers[i]);
  579. Obs.FPOObservedChanged(ASender,AOperation,Data);
  580. end;
  581. end;
  582. function TList.Add(Item: Pointer): Integer;
  583. begin
  584. Result := FList.Add(Item);
  585. if Item <> nil then
  586. Notify(Item, lnAdded);
  587. end;
  588. Procedure TList.AddList(AList : TList);
  589. var
  590. I: Integer;
  591. begin
  592. { this only does FList.AddList(AList.FList), avoiding notifications }
  593. FList.AddList(AList.FList);
  594. { make lnAdded notifications }
  595. for I := 0 to AList.Count - 1 do
  596. if AList[I] <> nil then
  597. Notify(AList[I], lnAdded);
  598. end;
  599. procedure TList.Clear;
  600. begin
  601. While (FList.Count>0) do
  602. Delete(Count-1);
  603. end;
  604. procedure TList.Delete(Index: Integer);
  605. var P : pointer;
  606. begin
  607. P:=FList.Get(Index);
  608. FList.Delete(Index);
  609. if assigned(p) then
  610. Notify(p, lnDeleted);
  611. end;
  612. class procedure TList.Error(const Msg: string; Data: PtrInt);
  613. begin
  614. Raise EListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame), get_caller_frame(get_frame);
  615. end;
  616. procedure TList.Exchange(Index1, Index2: Integer);
  617. begin
  618. FList.Exchange(Index1, Index2);
  619. FPONotifyObservers(Self,ooChange,Nil);
  620. end;
  621. function TList.Expand: TList;
  622. begin
  623. FList.Expand;
  624. Result:=Self;
  625. end;
  626. function TList.First: Pointer;
  627. begin
  628. Result := FList.First;
  629. end;
  630. function TList.GetEnumerator: TListEnumerator;
  631. begin
  632. Result := TListEnumerator.Create(Self);
  633. end;
  634. function TList.IndexOf(Item: Pointer): Integer;
  635. begin
  636. Result := FList.IndexOf(Item);
  637. end;
  638. procedure TList.Insert(Index: Integer; Item: Pointer);
  639. begin
  640. FList.Insert(Index, Item);
  641. if Item <> nil then
  642. Notify(Item,lnAdded);
  643. end;
  644. function TList.Last: Pointer;
  645. begin
  646. Result := FList.Last;
  647. end;
  648. procedure TList.Move(CurIndex, NewIndex: Integer);
  649. begin
  650. FList.Move(CurIndex, NewIndex);
  651. end;
  652. function TList.Remove(Item: Pointer): Integer;
  653. begin
  654. Result := IndexOf(Item);
  655. if Result <> -1 then
  656. Self.Delete(Result);
  657. end;
  658. procedure TList.Pack;
  659. begin
  660. FList.Pack;
  661. end;
  662. procedure TList.Sort(Compare: TListSortCompare);
  663. begin
  664. FList.Sort(Compare);
  665. end;
  666. procedure TList.Sort(Compare: TListSortCompare; SortingAlgorithm: PSortingAlgorithm);
  667. begin
  668. FList.Sort(Compare, SortingAlgorithm);
  669. end;
  670. procedure TList.Sort(Compare: TListSortComparer_Context; Context: Pointer);
  671. begin
  672. FList.Sort(Compare, Context);
  673. end;
  674. procedure TList.Sort(Compare: TListSortComparer_Context; Context: Pointer; SortingAlgorithm: PSortingAlgorithm);
  675. begin
  676. FList.Sort(Compare, Context, SortingAlgorithm);
  677. end;
  678. procedure TList.CopyMove (aList : TList);
  679. var r : integer;
  680. begin
  681. Clear;
  682. for r := 0 to aList.count-1 do
  683. Add (aList[r]);
  684. end;
  685. procedure TList.MergeMove (aList : TList);
  686. var r : integer;
  687. begin
  688. For r := 0 to aList.count-1 do
  689. if self.indexof(aList[r]) < 0 then
  690. self.Add (aList[r]);
  691. end;
  692. procedure TList.DoCopy(ListA, ListB : TList);
  693. begin
  694. if assigned (ListB) then
  695. CopyMove (ListB)
  696. else
  697. CopyMove (ListA);
  698. end;
  699. procedure TList.DoDestUnique(ListA, ListB : TList);
  700. procedure MoveElements (src, dest : TList);
  701. var r : integer;
  702. begin
  703. self.clear;
  704. for r := 0 to src.count-1 do
  705. if dest.indexof(src[r]) < 0 then
  706. self.Add (src[r]);
  707. end;
  708. var dest : TList;
  709. begin
  710. if assigned (ListB) then
  711. MoveElements (ListB, ListA)
  712. else
  713. try
  714. dest := TList.Create;
  715. dest.CopyMove (self);
  716. MoveElements (ListA, dest)
  717. finally
  718. dest.Free;
  719. end;
  720. end;
  721. procedure TList.DoAnd(ListA, ListB : TList);
  722. var r : integer;
  723. begin
  724. if assigned (ListB) then
  725. begin
  726. self.clear;
  727. for r := 0 to ListA.count-1 do
  728. if ListB.indexOf (ListA[r]) >= 0 then
  729. self.Add (ListA[r]);
  730. end
  731. else
  732. begin
  733. for r := self.Count-1 downto 0 do
  734. if ListA.indexof (Self[r]) < 0 then
  735. self.delete (r);
  736. end;
  737. end;
  738. procedure TList.DoSrcUnique(ListA, ListB : TList);
  739. var r : integer;
  740. begin
  741. if assigned (ListB) then
  742. begin
  743. self.Clear;
  744. for r := 0 to ListA.Count-1 do
  745. if ListB.indexof (ListA[r]) < 0 then
  746. self.Add (ListA[r]);
  747. end
  748. else
  749. begin
  750. for r := self.count-1 downto 0 do
  751. if ListA.indexof (self[r]) >= 0 then
  752. self.delete (r);
  753. end;
  754. end;
  755. procedure TList.DoOr(ListA, ListB : TList);
  756. begin
  757. if assigned (ListB) then
  758. begin
  759. CopyMove (ListA);
  760. MergeMove (ListB);
  761. end
  762. else
  763. MergeMove (ListA);
  764. end;
  765. procedure TList.DoXOr(ListA, ListB : TList);
  766. var r : integer;
  767. l : TList;
  768. begin
  769. if assigned (ListB) then
  770. begin
  771. self.Clear;
  772. for r := 0 to ListA.count-1 do
  773. if ListB.indexof (ListA[r]) < 0 then
  774. self.Add (ListA[r]);
  775. for r := 0 to ListB.count-1 do
  776. if ListA.indexof (ListB[r]) < 0 then
  777. self.Add (ListB[r]);
  778. end
  779. else
  780. try
  781. l := TList.Create;
  782. l.CopyMove (Self);
  783. for r := self.count-1 downto 0 do
  784. if listA.indexof (self[r]) >= 0 then
  785. self.delete (r);
  786. for r := 0 to ListA.count-1 do
  787. if l.indexof (ListA[r]) < 0 then
  788. self.add (ListA[r]);
  789. finally
  790. l.Free;
  791. end;
  792. end;
  793. procedure TList.Assign (ListA: TList; AOperator: TListAssignOp=laCopy; ListB: TList=nil);
  794. begin
  795. case AOperator of
  796. laCopy : DoCopy (ListA, ListB); // replace dest with src
  797. laSrcUnique : DoSrcUnique (ListA, ListB); // replace dest with src that are not in dest
  798. laAnd : DoAnd (ListA, ListB); // remove from dest that are not in src
  799. laDestUnique : DoDestUnique (ListA, ListB); // remove from dest that are in src
  800. laOr : DoOr (ListA, ListB); // add to dest from src and not in dest
  801. laXOr : DoXOr (ListA, ListB); // add to dest from src and not in dest, remove from dest that are in src
  802. end;
  803. end;
  804. function TList.GetList: PPointerList;
  805. begin
  806. Result := PPointerList(FList.List);
  807. end;
  808. {****************************************************************************}
  809. {* TThreadList *}
  810. {****************************************************************************}
  811. constructor TThreadList.Create;
  812. begin
  813. inherited Create;
  814. FDuplicates:=dupIgnore;
  815. {$ifdef FPC_HAS_FEATURE_THREADING}
  816. InitCriticalSection(FLock);
  817. {$endif}
  818. FList:=TList.Create;
  819. end;
  820. destructor TThreadList.Destroy;
  821. begin
  822. LockList;
  823. try
  824. FList.Free;
  825. inherited Destroy;
  826. finally
  827. UnlockList;
  828. {$ifdef FPC_HAS_FEATURE_THREADING}
  829. DoneCriticalSection(FLock);
  830. {$endif}
  831. end;
  832. end;
  833. procedure TThreadList.Add(Item: Pointer);
  834. begin
  835. LockList;
  836. try
  837. if (Duplicates=dupAccept) or
  838. // make sure it's not already in the list
  839. (FList.IndexOf(Item)=-1) then
  840. FList.Add(Item)
  841. else if (Duplicates=dupError) then
  842. FList.Error(SDuplicateItem,PtrUInt(Item));
  843. finally
  844. UnlockList;
  845. end;
  846. end;
  847. procedure TThreadList.Clear;
  848. begin
  849. Locklist;
  850. try
  851. FList.Clear;
  852. finally
  853. UnLockList;
  854. end;
  855. end;
  856. function TThreadList.LockList: TList;
  857. begin
  858. Result:=FList;
  859. {$ifdef FPC_HAS_FEATURE_THREADING}
  860. System.EnterCriticalSection(FLock);
  861. {$endif}
  862. end;
  863. procedure TThreadList.Remove(Item: Pointer);
  864. begin
  865. LockList;
  866. try
  867. FList.Remove(Item);
  868. finally
  869. UnlockList;
  870. end;
  871. end;
  872. procedure TThreadList.UnlockList;
  873. begin
  874. {$ifdef FPC_HAS_FEATURE_THREADING}
  875. System.LeaveCriticalSection(FLock);
  876. {$endif}
  877. end;