lists.inc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  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. if NewCount < FList.Count then
  476. while FList.Count > NewCount do
  477. Delete(FList.Count - 1)
  478. else
  479. FList.SetCount(NewCount);
  480. end;
  481. constructor TList.Create;
  482. begin
  483. inherited Create;
  484. FList := TFPList.Create;
  485. end;
  486. destructor TList.Destroy;
  487. begin
  488. If (Flist<>Nil) then
  489. Clear;
  490. FreeAndNil(FList);
  491. inherited Destroy;
  492. end;
  493. function TList.Add(Item: Pointer): Integer;
  494. begin
  495. Result := FList.Add(Item);
  496. if Item <> nil then
  497. Notify(Item, lnAdded);
  498. end;
  499. Procedure TList.AddList(AList : TList);
  500. begin
  501. FList.AddList(AList.FList);
  502. end;
  503. procedure TList.Clear;
  504. begin
  505. If Assigned(Flist) then
  506. While (FList.Count>0) do
  507. Delete(Count-1);
  508. end;
  509. procedure TList.Delete(Index: Integer);
  510. var P : pointer;
  511. begin
  512. P:=FList.Get(Index);
  513. FList.Delete(Index);
  514. if assigned(p) then Notify(p, lnDeleted);
  515. end;
  516. class procedure TList.Error(const Msg: string; Data: PtrInt);
  517. begin
  518. Raise EListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame);
  519. end;
  520. procedure TList.Exchange(Index1, Index2: Integer);
  521. begin
  522. FList.Exchange(Index1, Index2);
  523. end;
  524. function TList.Expand: TList;
  525. begin
  526. FList.Expand;
  527. Result:=Self;
  528. end;
  529. function TList.First: Pointer;
  530. begin
  531. Result := FList.First;
  532. end;
  533. function TList.IndexOf(Item: Pointer): Integer;
  534. begin
  535. Result := FList.IndexOf(Item);
  536. end;
  537. procedure TList.Insert(Index: Integer; Item: Pointer);
  538. begin
  539. FList.Insert(Index, Item);
  540. if Item <> nil then
  541. Notify(Item,lnAdded);
  542. end;
  543. function TList.Last: Pointer;
  544. begin
  545. Result := FList.Last;
  546. end;
  547. procedure TList.Move(CurIndex, NewIndex: Integer);
  548. begin
  549. FList.Move(CurIndex, NewIndex);
  550. end;
  551. function TList.Remove(Item: Pointer): Integer;
  552. begin
  553. Result := IndexOf(Item);
  554. if Result <> -1 then
  555. Self.Delete(Result);
  556. end;
  557. procedure TList.Pack;
  558. begin
  559. FList.Pack;
  560. end;
  561. procedure TList.Sort(Compare: TListSortCompare);
  562. begin
  563. FList.Sort(Compare);
  564. end;
  565. procedure TList.CopyMove (aList : TList);
  566. var r : integer;
  567. begin
  568. Clear;
  569. for r := 0 to aList.count-1 do
  570. Add (aList[r]);
  571. end;
  572. procedure TList.MergeMove (aList : TList);
  573. var r : integer;
  574. begin
  575. For r := 0 to aList.count-1 do
  576. if self.indexof(aList[r]) < 0 then
  577. self.Add (aList[r]);
  578. end;
  579. procedure TList.DoCopy(ListA, ListB : TList);
  580. begin
  581. if assigned (ListB) then
  582. CopyMove (ListB)
  583. else
  584. CopyMove (ListA);
  585. end;
  586. procedure TList.DoDestUnique(ListA, ListB : TList);
  587. procedure MoveElements (src, dest : TList);
  588. var r : integer;
  589. begin
  590. self.clear;
  591. for r := 0 to src.count-1 do
  592. if dest.indexof(src[r]) < 0 then
  593. self.Add (src[r]);
  594. end;
  595. var dest : TList;
  596. begin
  597. if assigned (ListB) then
  598. MoveElements (ListB, ListA)
  599. else
  600. try
  601. dest := TList.Create;
  602. dest.CopyMove (self);
  603. MoveElements (ListA, dest)
  604. finally
  605. dest.Free;
  606. end;
  607. end;
  608. procedure TList.DoAnd(ListA, ListB : TList);
  609. var r : integer;
  610. begin
  611. if assigned (ListB) then
  612. begin
  613. self.clear;
  614. for r := 0 to ListA.count-1 do
  615. if ListB.indexOf (ListA[r]) >= 0 then
  616. self.Add (ListA[r]);
  617. end
  618. else
  619. begin
  620. for r := self.Count-1 downto 0 do
  621. if ListA.indexof (Self[r]) < 0 then
  622. self.delete (r);
  623. end;
  624. end;
  625. procedure TList.DoSrcUnique(ListA, ListB : TList);
  626. var r : integer;
  627. begin
  628. if assigned (ListB) then
  629. begin
  630. self.Clear;
  631. for r := 0 to ListA.Count-1 do
  632. if ListB.indexof (ListA[r]) < 0 then
  633. self.Add (ListA[r]);
  634. end
  635. else
  636. begin
  637. for r := self.count-1 downto 0 do
  638. if ListA.indexof (self[r]) >= 0 then
  639. self.delete (r);
  640. end;
  641. end;
  642. procedure TList.DoOr(ListA, ListB : TList);
  643. begin
  644. if assigned (ListB) then
  645. begin
  646. CopyMove (ListA);
  647. MergeMove (ListB);
  648. end
  649. else
  650. MergeMove (ListA);
  651. end;
  652. procedure TList.DoXOr(ListA, ListB : TList);
  653. var r : integer;
  654. l : TList;
  655. begin
  656. if assigned (ListB) then
  657. begin
  658. self.Clear;
  659. for r := 0 to ListA.count-1 do
  660. if ListB.indexof (ListA[r]) < 0 then
  661. self.Add (ListA[r]);
  662. for r := 0 to ListB.count-1 do
  663. if ListA.indexof (ListB[r]) < 0 then
  664. self.Add (ListB[r]);
  665. end
  666. else
  667. try
  668. l := TList.Create;
  669. l.CopyMove (Self);
  670. for r := self.count-1 downto 0 do
  671. if listA.indexof (self[r]) >= 0 then
  672. self.delete (r);
  673. for r := 0 to ListA.count-1 do
  674. if l.indexof (ListA[r]) < 0 then
  675. self.add (ListA[r]);
  676. finally
  677. l.Free;
  678. end;
  679. end;
  680. procedure TList.Assign (ListA: TList; AOperator: TListAssignOp=laCopy; ListB: TList=nil);
  681. begin
  682. case AOperator of
  683. laCopy : DoCopy (ListA, ListB); // replace dest with src
  684. laSrcUnique : DoSrcUnique (ListA, ListB); // replace dest with src that are not in dest
  685. laAnd : DoAnd (ListA, ListB); // remove from dest that are not in src
  686. laDestUnique : DoDestUnique (ListA, ListB); // remove from dest that are in src
  687. laOr : DoOr (ListA, ListB); // add to dest from src and not in dest
  688. laXOr : DoXOr (ListA, ListB); // add to dest from src and not in dest, remove from dest that are in src
  689. end;
  690. end;
  691. function TList.GetList: PPointerList;
  692. begin
  693. Result := PPointerList(FList.List);
  694. end;
  695. {****************************************************************************}
  696. {* TThreadList *}
  697. {****************************************************************************}
  698. constructor TThreadList.Create;
  699. begin
  700. inherited Create;
  701. FDuplicates:=dupIgnore;
  702. InitCriticalSection(FLock);
  703. FList:=TList.Create;
  704. end;
  705. destructor TThreadList.Destroy;
  706. begin
  707. LockList;
  708. try
  709. FList.Free;
  710. inherited Destroy;
  711. finally
  712. UnlockList;
  713. DoneCriticalSection(FLock);
  714. end;
  715. end;
  716. procedure TThreadList.Add(Item: Pointer);
  717. begin
  718. LockList;
  719. try
  720. if (Duplicates=dupAccept) or
  721. // make sure it's not already in the list
  722. (FList.IndexOf(Item)=-1) then
  723. FList.Add(Item)
  724. else if (Duplicates=dupError) then
  725. FList.Error(SDuplicateItem,PtrUInt(Item));
  726. finally
  727. UnlockList;
  728. end;
  729. end;
  730. procedure TThreadList.Clear;
  731. begin
  732. Locklist;
  733. try
  734. FList.Clear;
  735. finally
  736. UnLockList;
  737. end;
  738. end;
  739. function TThreadList.LockList: TList;
  740. begin
  741. Result:=FList;
  742. System.EnterCriticalSection(FLock);
  743. end;
  744. procedure TThreadList.Remove(Item: Pointer);
  745. begin
  746. LockList;
  747. try
  748. FList.Remove(Item);
  749. finally
  750. UnlockList;
  751. end;
  752. end;
  753. procedure TThreadList.UnlockList;
  754. begin
  755. System.LeaveCriticalSection(FLock);
  756. end;