lists.inc 20 KB

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