lists.inc 23 KB

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