lists.inc 18 KB

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