lists.inc 20 KB

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