lists.inc 22 KB

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