lists.inc 23 KB

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