lists.inc 22 KB

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