lists.inc 20 KB

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