1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042 |
- {
- This file is part of the Free Pascal Run Time Library (rtl)
- Copyright (c) 1999-2005 by the Free Pascal development team
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- {$if defined(VER2_0) or not defined(FPC_TESTGENERICS)}
- {****************************************************************************}
- {* TFPListEnumerator *}
- {****************************************************************************}
- constructor TFPListEnumerator.Create(AList: TFPList);
- begin
- inherited Create;
- FList := AList;
- FPosition := -1;
- end;
- function TFPListEnumerator.GetCurrent: Pointer;
- begin
- Result := FList[FPosition];
- end;
- function TFPListEnumerator.MoveNext: Boolean;
- begin
- Inc(FPosition);
- Result := FPosition < FList.Count;
- end;
- {****************************************************************************}
- {* TFPList *}
- {****************************************************************************}
- Const
- // Ratio of Pointer and Word Size.
- WordRatio = SizeOf(Pointer) Div SizeOf(Word);
- procedure TFPList.RaiseIndexError(Index : Integer);
- begin
- // We should be able to remove this, but unfortunately it is marked protected.
- Error(SListIndexError, Index);
- end;
- Procedure TFPList.CheckIndex(AIndex : Integer);
- begin
- If (AIndex < 0) or (AIndex >= FCount) then
- Error(SListIndexError, AIndex); // Don't use RaiseIndexError, exception address will be better if we use error.
- end;
- function TFPList.Get(Index: Integer): Pointer;
- begin
- CheckIndex(Index);
- Result:=FList^[Index];
- end;
- procedure TFPList.Put(Index: Integer; Item: Pointer);
- begin
- CheckIndex(Index);
- Flist^[Index] := Item;
- end;
- function TFPList.Extract(Item: Pointer): Pointer;
- var
- i : Integer;
- begin
- i := IndexOf(item);
- if i >= 0 then
- begin
- Result := item;
- Delete(i);
- end
- else
- result := nil;
- end;
- procedure TFPList.SetCapacity(NewCapacity: Integer);
- begin
- If (NewCapacity < FCount) or (NewCapacity > MaxListSize) then
- Error (SListCapacityError, NewCapacity);
- if NewCapacity = FCapacity then
- exit;
- ReallocMem(FList, SizeOf(Pointer)*NewCapacity);
- FCapacity := NewCapacity;
- end;
- procedure TFPList.SetCount(NewCount: Integer);
- begin
- if (NewCount < 0) or (NewCount > MaxListSize)then
- Error(SListCountError, NewCount);
- If NewCount > FCount then
- begin
- If NewCount > FCapacity then
- SetCapacity(NewCount);
- If FCount < NewCount then
- FillWord(Flist^[FCount], (NewCount-FCount) * WordRatio, 0);
- end;
- FCount := Newcount;
- end;
- destructor TFPList.Destroy;
- begin
- Self.Clear;
- inherited Destroy;
- end;
- Procedure TFPList.AddList(AList : TFPList);
- Var
- I : Integer;
- begin
- If (Capacity<Count+AList.Count) then
- Capacity:=Count+AList.Count;
- For I:=0 to AList.Count-1 do
- Add(AList[i]);
- end;
- function TFPList.Add(Item: Pointer): Integer;
- begin
- if FCount = FCapacity then
- Self.Expand;
- FList^[FCount] := Item;
- Result := FCount;
- FCount := FCount + 1;
- end;
- procedure TFPList.Clear;
- begin
- if Assigned(FList) then
- begin
- SetCount(0);
- SetCapacity(0);
- FList := nil;
- end;
- end;
- procedure TFPList.Delete(Index: Integer);
- begin
- CheckIndex(Index);
- FCount := FCount-1;
- System.Move (FList^[Index+1], FList^[Index], (FCount - Index) * SizeOf(Pointer));
- // Shrink the list if appropriate:
- // If capacity>256 and the list is less than a quarter filled, shrink to 1/2 the size.
- // Shr is used because it is faster than div.
- if (FCapacity > 256) and (FCount < FCapacity shr 2) then
- begin
- FCapacity := FCapacity shr 1;
- ReallocMem(FList, SizeOf(Pointer) * FCapacity);
- end;
- end;
- class procedure TFPList.Error(const Msg: string; Data: PtrInt);
- begin
- Raise EListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame), get_caller_frame(get_frame);
- end;
- procedure TFPList.Exchange(Index1, Index2: Integer);
- var
- Temp : Pointer;
- begin
- CheckIndex(Index1);
- CheckIndex(Index2);
- Temp := FList^[Index1];
- FList^[Index1] := FList^[Index2];
- FList^[Index2] := Temp;
- end;
- function TFPList.Expand: TFPList;
- var
- IncSize : Longint;
- begin
- if FCount < FCapacity then exit(self);
- {
- For really big lists, (128Mb elements), increase with fixed amount: 16Mb elements (=1/8th of 128Mb).
- For big lists (8mb elements), increase with 1/8th of the size
- For moderate lists (128 or more, increase with 1/4th the size
- For smaller sizes, increase with 16 or 4
- }
- if FCapacity > 128*1024*1024 then IncSize := 16*1024*1024
- else if FCapacity > 8*1024*1024 then IncSize := FCapacity shr 3
- else if FCapacity > 128 then IncSize := FCapacity shr 2
- else if FCapacity > 8 then IncSize := 16
- else IncSize := 4;
- SetCapacity(FCapacity + IncSize);
- Result := Self;
- end;
- function TFPList.First: Pointer;
- begin
- If FCount = 0 then
- Result := Nil
- else
- Result := Items[0];
- end;
- function TFPList.GetEnumerator: TFPListEnumerator;
- begin
- Result := TFPListEnumerator.Create(Self);
- end;
- function TFPList.IndexOf(Item: Pointer): Integer;
- Var
- C : Integer;
- begin
- Result:=0;
- C:=Count;
- while (Result<C) and (Flist^[Result]<>Item) do
- Inc(Result);
- If Result>=C then
- Result:=-1;
- end;
- function TFPList.IndexOfItem(Item: Pointer; Direction: TDirection): Integer;
- begin
- if Direction=fromBeginning then
- Result:=IndexOf(Item)
- else
- begin
- Result:=Count-1;
- while (Result >=0) and (Flist^[Result]<>Item) do
- Result:=Result - 1;
- end;
- end;
- procedure TFPList.Insert(Index: Integer; Item: Pointer);
- begin
- if (Index < 0) or (Index > FCount )then
- Error(SlistIndexError, Index);
- iF FCount = FCapacity then Self.Expand;
- if Index<FCount then
- System.Move(Flist^[Index], Flist^[Index+1], (FCount - Index) * SizeOf(Pointer));
- FList^[Index] := Item;
- FCount := FCount + 1;
- end;
- function TFPList.Last: Pointer;
- begin
- { Wouldn't it be better to return nil if the count is zero ?}
- If FCount = 0 then
- Result := nil
- else
- Result := Items[FCount - 1];
- end;
- procedure TFPList.Move(CurIndex, NewIndex: Integer);
- var
- Temp : Pointer;
- begin
- CheckIndex(CurIndex);
- CheckIndex(NewIndex);
- Temp := FList^[CurIndex];
- if NewIndex > CurIndex then
- System.Move(FList^[CurIndex+1], FList^[CurIndex], (NewIndex - CurIndex) * SizeOf(Pointer))
- else
- System.Move(FList^[NewIndex], FList^[NewIndex+1], (CurIndex - NewIndex) * SizeOf(Pointer));
- FList^[NewIndex] := Temp;
- end;
- function TFPList.Remove(Item: Pointer): Integer;
- begin
- Result := IndexOf(Item);
- If Result <> -1 then
- Self.Delete(Result);
- end;
- procedure TFPList.Pack;
- var
- NewCount,
- i : integer;
- pdest,
- psrc : PPointer;
- begin
- NewCount:=0;
- psrc:=@FList^[0];
- pdest:=psrc;
- For I:=0 To FCount-1 Do
- begin
- if assigned(psrc^) then
- begin
- pdest^:=psrc^;
- inc(pdest);
- inc(NewCount);
- end;
- inc(psrc);
- end;
- FCount:=NewCount;
- end;
- // Needed by Sort method.
- Procedure QuickSort(FList: PPointerList; L, R : Longint;
- Compare: TListSortCompare);
- var
- I, J : Longint;
- P, Q : Pointer;
- begin
- repeat
- I := L;
- J := R;
- P := FList^[ (L + R) div 2 ];
- repeat
- while Compare(P, FList^[i]) > 0 do
- I := I + 1;
- while Compare(P, FList^[J]) < 0 do
- J := J - 1;
- If I <= J then
- begin
- Q := FList^[I];
- Flist^[I] := FList^[J];
- FList^[J] := Q;
- I := I + 1;
- J := J - 1;
- end;
- until I > J;
- // sort the smaller range recursively
- // sort the bigger range via the loop
- // Reasons: memory usage is O(log(n)) instead of O(n) and loop is faster than recursion
- if J - L < R - I then
- begin
- if L < J then
- QuickSort(FList, L, J, Compare);
- L := I;
- end
- else
- begin
- if I < R then
- QuickSort(FList, I, R, Compare);
- R := J;
- end;
- until L >= R;
- end;
- procedure TFPList.Sort(Compare: TListSortCompare);
- begin
- if Not Assigned(FList) or (FCount < 2) then exit;
- QuickSort(Flist, 0, FCount-1, Compare);
- end;
- procedure TFPList.ForEachCall(proc2call:TListCallback;arg:pointer);
- var
- i : integer;
- p : pointer;
- begin
- For I:=0 To Count-1 Do
- begin
- p:=FList^[i];
- if assigned(p) then
- proc2call(p,arg);
- end;
- end;
- procedure TFPList.ForEachCall(proc2call:TListStaticCallback;arg:pointer);
- var
- i : integer;
- p : pointer;
- begin
- For I:=0 To Count-1 Do
- begin
- p:=FList^[i];
- if assigned(p) then
- proc2call(p,arg);
- end;
- end;
- procedure TFPList.CopyMove (aList : TFPList);
- var r : integer;
- begin
- Clear;
- for r := 0 to aList.count-1 do
- Add (aList[r]);
- end;
- procedure TFPList.MergeMove (aList : TFPList);
- var r : integer;
- begin
- For r := 0 to aList.count-1 do
- if self.indexof(aList[r]) < 0 then
- self.Add (aList[r]);
- end;
- procedure TFPList.DoCopy(ListA, ListB : TFPList);
- begin
- if assigned (ListB) then
- CopyMove (ListB)
- else
- CopyMove (ListA);
- end;
- procedure TFPList.DoDestUnique(ListA, ListB : TFPList);
- procedure MoveElements (src, dest : TFPList);
- var r : integer;
- begin
- self.clear;
- for r := 0 to src.count-1 do
- if dest.indexof(src[r]) < 0 then
- self.Add (src[r]);
- end;
- var dest : TFPList;
- begin
- if assigned (ListB) then
- MoveElements (ListB, ListA)
- else
- try
- dest := TFPList.Create;
- dest.CopyMove (self);
- MoveElements (ListA, dest)
- finally
- dest.Free;
- end;
- end;
- procedure TFPList.DoAnd(ListA, ListB : TFPList);
- var r : integer;
- begin
- if assigned (ListB) then
- begin
- self.clear;
- for r := 0 to ListA.count-1 do
- if ListB.indexOf (ListA[r]) >= 0 then
- self.Add (ListA[r]);
- end
- else
- begin
- for r := self.Count-1 downto 0 do
- if ListA.indexof (Self[r]) < 0 then
- self.delete (r);
- end;
- end;
- procedure TFPList.DoSrcUnique(ListA, ListB : TFPList);
- var r : integer;
- begin
- if assigned (ListB) then
- begin
- self.Clear;
- for r := 0 to ListA.Count-1 do
- if ListB.indexof (ListA[r]) < 0 then
- self.Add (ListA[r]);
- end
- else
- begin
- for r := self.count-1 downto 0 do
- if ListA.indexof (self[r]) >= 0 then
- self.delete (r);
- end;
- end;
- procedure TFPList.DoOr(ListA, ListB : TFPList);
- begin
- if assigned (ListB) then
- begin
- CopyMove (ListA);
- MergeMove (ListB);
- end
- else
- MergeMove (ListA);
- end;
- procedure TFPList.DoXOr(ListA, ListB : TFPList);
- var r : integer;
- l : TFPList;
- begin
- if assigned (ListB) then
- begin
- self.Clear;
- for r := 0 to ListA.count-1 do
- if ListB.indexof (ListA[r]) < 0 then
- self.Add (ListA[r]);
- for r := 0 to ListB.count-1 do
- if ListA.indexof (ListB[r]) < 0 then
- self.Add (ListB[r]);
- end
- else
- try
- l := TFPList.Create;
- l.CopyMove (Self);
- for r := self.count-1 downto 0 do
- if listA.indexof (self[r]) >= 0 then
- self.delete (r);
- for r := 0 to ListA.count-1 do
- if l.indexof (ListA[r]) < 0 then
- self.add (ListA[r]);
- finally
- l.Free;
- end;
- end;
- procedure TFPList.Assign (ListA: TFPList; AOperator: TListAssignOp=laCopy; ListB: TFPList=nil);
- begin
- case AOperator of
- laCopy : DoCopy (ListA, ListB); // replace dest with src
- laSrcUnique : DoSrcUnique (ListA, ListB); // replace dest with src that are not in dest
- laAnd : DoAnd (ListA, ListB); // remove from dest that are not in src
- laDestUnique : DoDestUnique (ListA, ListB); // remove from dest that are in src
- laOr : DoOr (ListA, ListB); // add to dest from src and not in dest
- laXOr : DoXOr (ListA, ListB); // add to dest from src and not in dest, remove from dest that are in src
- end;
- end;
- {$else}
- { generics based implementation of TFPList follows }
- procedure TFPList.Assign(Source: TFPList);
- begin
- inherited Assign(Source);
- end;
- type
- TFPPtrListSortCompare = function(const Item1, Item2: Pointer): Integer;
- procedure TFPList.Sort(Compare: TListSortCompare);
- begin
- inherited Sort(TFPPtrListSortCompare(Compare));
- end;
- procedure TFPList.ForEachCall(Proc2call: TListCallback; Arg: Pointer);
- var
- I: integer;
- begin
- for I:=0 to Count-1 do
- proc2call(InternalItems[I],arg);
- end;
- procedure TFPList.ForEachCall(Proc2call: TListStaticCallback; Arg: Pointer);
- var
- I: integer;
- begin
- for I:=0 to Count-1 do
- Proc2call(InternalItems[I], Arg);
- end;
- {$endif}
- {****************************************************************************}
- {* TListEnumerator *}
- {****************************************************************************}
- constructor TListEnumerator.Create(AList: TList);
- begin
- inherited Create;
- FList := AList;
- FPosition := -1;
- end;
- function TListEnumerator.GetCurrent: Pointer;
- begin
- Result := FList[FPosition];
- end;
- function TListEnumerator.MoveNext: Boolean;
- begin
- Inc(FPosition);
- Result := FPosition < FList.Count;
- end;
- {****************************************************************************}
- {* TList *}
- {****************************************************************************}
- { TList = class(TObject)
- private
- FList: TFPList;
- }
- function TList.Get(Index: Integer): Pointer;
- begin
- Result := FList.Get(Index);
- end;
- procedure TList.Grow;
- begin
- // Only for compatibility with Delphi. Not needed.
- end;
- procedure TList.Put(Index: Integer; Item: Pointer);
- var p : pointer;
- begin
- p := get(Index);
- FList.Put(Index, Item);
- if assigned (p) then
- Notify (p, lnDeleted);
- if assigned (Item) then
- Notify (Item, lnAdded);
- end;
- function TList.Extract(item: Pointer): Pointer;
- var c : integer;
- begin
- c := FList.Count;
- Result := FList.Extract(item);
- if c <> FList.Count then
- Notify (Result, lnExtracted);
- end;
- procedure TList.Notify(Ptr: Pointer; Action: TListNotification);
- begin
- if Assigned(FObservers) then
- Case ACtion of
- lnAdded : FPONotifyObservers(Self,ooAddItem,Ptr);
- lnExtracted : FPONotifyObservers(Self,ooDeleteItem,Ptr);
- lnDeleted : FPONotifyObservers(Self,ooDeleteItem,Ptr);
- end;
- end;
- function TList.GetCapacity: integer;
- begin
- Result := FList.Capacity;
- end;
- procedure TList.SetCapacity(NewCapacity: Integer);
- begin
- FList.SetCapacity(NewCapacity);
- end;
- function TList.GetCount: Integer;
- begin
- Result := FList.Count;
- end;
- procedure TList.SetCount(NewCount: Integer);
- begin
- if NewCount < FList.Count then
- while FList.Count > NewCount do
- Delete(FList.Count - 1)
- else
- FList.SetCount(NewCount);
- end;
- constructor TList.Create;
- begin
- inherited Create;
- FList := TFPList.Create;
- end;
- destructor TList.Destroy;
- begin
- if Assigned(Flist) then
- Clear;
- If Assigned(FObservers) then
- begin
- FPONotifyObservers(Self,ooFree,Nil);
- FreeAndNil(FObservers);
- end;
- FreeAndNil(FList);
- inherited Destroy;
- end;
- procedure TList.FPOAttachObserver(AObserver: TObject);
- Var
- I : IFPObserver;
- begin
- If Not AObserver.GetInterface(SGUIDObserver,I) then
- Raise EObserver.CreateFmt(SErrNotObserver,[AObserver.ClassName]);
- If not Assigned(FObservers) then
- FObservers:=TFPList.Create;
- FObservers.Add(I);
- end;
- procedure TList.FPODetachObserver(AObserver: TObject);
- Var
- I : IFPObserver;
- begin
- If Not AObserver.GetInterface(SGUIDObserver,I) then
- Raise EObserver.CreateFmt(SErrNotObserver,[AObserver.ClassName]);
- If Assigned(FObservers) then
- begin
- FObservers.Remove(I);
- If (FObservers.Count=0) then
- FreeAndNil(FObservers);
- end;
- end;
- procedure TList.FPONotifyObservers(ASender: TObject;
- AOperation: TFPObservedOperation; Data : Pointer);
- Var
- I : Integer;
- Obs : IFPObserver;
- begin
- If Assigned(FObservers) then
- For I:=FObservers.Count-1 downto 0 do
- begin
- Obs:=IFPObserver(FObservers[i]);
- Obs.FPOObservedChanged(ASender,AOperation,Data);
- end;
- end;
- function TList.Add(Item: Pointer): Integer;
- begin
- Result := FList.Add(Item);
- if Item <> nil then
- Notify(Item, lnAdded);
- end;
- Procedure TList.AddList(AList : TList);
- var
- I: Integer;
- begin
- { this only does FList.AddList(AList.FList), avoiding notifications }
- FList.AddList(AList.FList);
- { make lnAdded notifications }
- for I := 0 to AList.Count - 1 do
- if AList[I] <> nil then
- Notify(AList[I], lnAdded);
- end;
- procedure TList.Clear;
- begin
- While (FList.Count>0) do
- Delete(Count-1);
- end;
- procedure TList.Delete(Index: Integer);
- var P : pointer;
- begin
- P:=FList.Get(Index);
- FList.Delete(Index);
- if assigned(p) then
- Notify(p, lnDeleted);
- end;
- class procedure TList.Error(const Msg: string; Data: PtrInt);
- begin
- Raise EListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame), get_caller_frame(get_frame);
- end;
- procedure TList.Exchange(Index1, Index2: Integer);
- begin
- FList.Exchange(Index1, Index2);
- FPONotifyObservers(Self,ooChange,Nil);
- end;
- function TList.Expand: TList;
- begin
- FList.Expand;
- Result:=Self;
- end;
- function TList.First: Pointer;
- begin
- Result := FList.First;
- end;
- function TList.GetEnumerator: TListEnumerator;
- begin
- Result := TListEnumerator.Create(Self);
- end;
- function TList.IndexOf(Item: Pointer): Integer;
- begin
- Result := FList.IndexOf(Item);
- end;
- procedure TList.Insert(Index: Integer; Item: Pointer);
- begin
- FList.Insert(Index, Item);
- if Item <> nil then
- Notify(Item,lnAdded);
- end;
- function TList.Last: Pointer;
- begin
- Result := FList.Last;
- end;
- procedure TList.Move(CurIndex, NewIndex: Integer);
- begin
- FList.Move(CurIndex, NewIndex);
- end;
- function TList.Remove(Item: Pointer): Integer;
- begin
- Result := IndexOf(Item);
- if Result <> -1 then
- Self.Delete(Result);
- end;
- procedure TList.Pack;
- begin
- FList.Pack;
- end;
- procedure TList.Sort(Compare: TListSortCompare);
- begin
- FList.Sort(Compare);
- end;
- procedure TList.CopyMove (aList : TList);
- var r : integer;
- begin
- Clear;
- for r := 0 to aList.count-1 do
- Add (aList[r]);
- end;
- procedure TList.MergeMove (aList : TList);
- var r : integer;
- begin
- For r := 0 to aList.count-1 do
- if self.indexof(aList[r]) < 0 then
- self.Add (aList[r]);
- end;
- procedure TList.DoCopy(ListA, ListB : TList);
- begin
- if assigned (ListB) then
- CopyMove (ListB)
- else
- CopyMove (ListA);
- end;
- procedure TList.DoDestUnique(ListA, ListB : TList);
- procedure MoveElements (src, dest : TList);
- var r : integer;
- begin
- self.clear;
- for r := 0 to src.count-1 do
- if dest.indexof(src[r]) < 0 then
- self.Add (src[r]);
- end;
- var dest : TList;
- begin
- if assigned (ListB) then
- MoveElements (ListB, ListA)
- else
- try
- dest := TList.Create;
- dest.CopyMove (self);
- MoveElements (ListA, dest)
- finally
- dest.Free;
- end;
- end;
- procedure TList.DoAnd(ListA, ListB : TList);
- var r : integer;
- begin
- if assigned (ListB) then
- begin
- self.clear;
- for r := 0 to ListA.count-1 do
- if ListB.indexOf (ListA[r]) >= 0 then
- self.Add (ListA[r]);
- end
- else
- begin
- for r := self.Count-1 downto 0 do
- if ListA.indexof (Self[r]) < 0 then
- self.delete (r);
- end;
- end;
- procedure TList.DoSrcUnique(ListA, ListB : TList);
- var r : integer;
- begin
- if assigned (ListB) then
- begin
- self.Clear;
- for r := 0 to ListA.Count-1 do
- if ListB.indexof (ListA[r]) < 0 then
- self.Add (ListA[r]);
- end
- else
- begin
- for r := self.count-1 downto 0 do
- if ListA.indexof (self[r]) >= 0 then
- self.delete (r);
- end;
- end;
- procedure TList.DoOr(ListA, ListB : TList);
- begin
- if assigned (ListB) then
- begin
- CopyMove (ListA);
- MergeMove (ListB);
- end
- else
- MergeMove (ListA);
- end;
- procedure TList.DoXOr(ListA, ListB : TList);
- var r : integer;
- l : TList;
- begin
- if assigned (ListB) then
- begin
- self.Clear;
- for r := 0 to ListA.count-1 do
- if ListB.indexof (ListA[r]) < 0 then
- self.Add (ListA[r]);
- for r := 0 to ListB.count-1 do
- if ListA.indexof (ListB[r]) < 0 then
- self.Add (ListB[r]);
- end
- else
- try
- l := TList.Create;
- l.CopyMove (Self);
- for r := self.count-1 downto 0 do
- if listA.indexof (self[r]) >= 0 then
- self.delete (r);
- for r := 0 to ListA.count-1 do
- if l.indexof (ListA[r]) < 0 then
- self.add (ListA[r]);
- finally
- l.Free;
- end;
- end;
- procedure TList.Assign (ListA: TList; AOperator: TListAssignOp=laCopy; ListB: TList=nil);
- begin
- case AOperator of
- laCopy : DoCopy (ListA, ListB); // replace dest with src
- laSrcUnique : DoSrcUnique (ListA, ListB); // replace dest with src that are not in dest
- laAnd : DoAnd (ListA, ListB); // remove from dest that are not in src
- laDestUnique : DoDestUnique (ListA, ListB); // remove from dest that are in src
- laOr : DoOr (ListA, ListB); // add to dest from src and not in dest
- laXOr : DoXOr (ListA, ListB); // add to dest from src and not in dest, remove from dest that are in src
- end;
- end;
- function TList.GetList: PPointerList;
- begin
- Result := PPointerList(FList.List);
- end;
- {****************************************************************************}
- {* TThreadList *}
- {****************************************************************************}
- constructor TThreadList.Create;
- begin
- inherited Create;
- FDuplicates:=dupIgnore;
- {$ifdef FPC_HAS_FEATURE_THREADING}
- InitCriticalSection(FLock);
- {$endif}
- FList:=TList.Create;
- end;
- destructor TThreadList.Destroy;
- begin
- LockList;
- try
- FList.Free;
- inherited Destroy;
- finally
- UnlockList;
- {$ifdef FPC_HAS_FEATURE_THREADING}
- DoneCriticalSection(FLock);
- {$endif}
- end;
- end;
- procedure TThreadList.Add(Item: Pointer);
- begin
- LockList;
- try
- if (Duplicates=dupAccept) or
- // make sure it's not already in the list
- (FList.IndexOf(Item)=-1) then
- FList.Add(Item)
- else if (Duplicates=dupError) then
- FList.Error(SDuplicateItem,PtrUInt(Item));
- finally
- UnlockList;
- end;
- end;
- procedure TThreadList.Clear;
- begin
- Locklist;
- try
- FList.Clear;
- finally
- UnLockList;
- end;
- end;
- function TThreadList.LockList: TList;
- begin
- Result:=FList;
- {$ifdef FPC_HAS_FEATURE_THREADING}
- System.EnterCriticalSection(FLock);
- {$endif}
- end;
- procedure TThreadList.Remove(Item: Pointer);
- begin
- LockList;
- try
- FList.Remove(Item);
- finally
- UnlockList;
- end;
- end;
- procedure TThreadList.UnlockList;
- begin
- {$ifdef FPC_HAS_FEATURE_THREADING}
- System.LeaveCriticalSection(FLock);
- {$endif}
- end;
|