diff options
author | michael <michael@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2021-01-24 17:40:32 +0000 |
---|---|---|
committer | michael <michael@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2021-01-24 17:40:32 +0000 |
commit | 8424f270648b6d1418fc6581ac7c386bb3c53025 (patch) | |
tree | 9eaafe4045da9fb90ff484505e4099dedab6442f /packages/fcl-stl | |
parent | bad0d7e5b6ec306b2034e164fd2bf4e39abe8b08 (diff) | |
download | fpc-8424f270648b6d1418fc6581ac7c386bb3c53025.tar.gz |
* Patch from Bart Broersma to fix issue ID 38306
git-svn-id: https://svn.freepascal.org/svn/fpc/trunk@48405 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'packages/fcl-stl')
-rw-r--r-- | packages/fcl-stl/src/gdeque.pp | 54 |
1 files changed, 44 insertions, 10 deletions
diff --git a/packages/fcl-stl/src/gdeque.pp b/packages/fcl-stl/src/gdeque.pp index a2ad0db57b..2fa9d2d443 100644 --- a/packages/fcl-stl/src/gdeque.pp +++ b/packages/fcl-stl/src/gdeque.pp @@ -31,6 +31,10 @@ type function GetValue(position:SizeUInt):T;inline; function GetMutable(position:SizeUInt):PT;inline; procedure IncreaseCapacity(); + protected + procedure MoveSimpleData(StartIndex: SizeUInt; Offset: SizeInt; NrElems: SizeUInt); + procedure MoveManagedData(StartIndex: SizeUInt; Offset: SizeInt; NrElems: SizeUInt); + procedure MoveData(StartIndex: SizeUInt; Offset: SizeInt; NrElems: SizeUInt); public function Size():SizeUInt;inline; constructor Create(); @@ -127,6 +131,8 @@ end; procedure TDeque.SetValue(position:SizeUInt; value:T);inline; begin Assert(position < size, 'Deque access out of range'); + if IsManagedType(T) then + Finalize(FData[(FStart+position)mod FCapacity]); FData[(FStart+position)mod FCapacity]:=value; end; @@ -142,6 +148,40 @@ begin GetMutable:=@FData[(FStart+position) mod FCapacity]; end; + + +procedure TDeque.MoveSimpleData(StartIndex: SizeUInt; Offset: SizeInt; NrElems: SizeUInt); +begin + Move(FData[StartIndex], FData[StartIndex+Offset], NrElems*SizeOf(T)); + if Offset>0 then + FillChar(FData[StartIndex], NrElems*SizeOf(T), 0) + else + FillChar(FData[StartIndex+NrElems+Offset], -Offset*SizeOf(T), 0); +end; + +procedure TDeque.MoveManagedData(StartIndex: SizeUInt; Offset: SizeInt; NrElems: SizeUInt); +var + i: SizeUInt; +begin + //since we always move blocks where Abs(Offset)>=NrElems, there is no need for + //2 seperate loops (1 for ngeative and 1 for positive Offsett) + for i := 0 to NrElems-1 do + begin + Finalize(FData[StartIndex+i+Offset]); + FData[StartIndex+i+Offset] := FData[StartIndex+i]; + Finalize(FData[StartIndex+i]); + FillChar(FData[StartIndex+i], SizeOf(T), 0); + end; +end; + +procedure TDeque.MoveData(StartIndex: SizeUInt; Offset: SizeInt; NrElems: SizeUInt); +begin + if IsManagedType(T) then + MoveManagedData(StartIndex, Offset, NrElems) + else + MoveSimpleData(StartIndex, Offset, NrElems); +end; + procedure TDeque.IncreaseCapacity; function Min(const A,B: SizeUInt): SizeUInt; inline; //no need to drag in the entire Math unit ;-) begin @@ -177,11 +217,7 @@ begin begin if (FCapacity-OldEnd>=FStart) then //we have room to move all items in one go begin - if IsManagedType(T) then - for i:=0 to FStart-1 do - FData[OldEnd+i]:=FData[i] - else - Move(FData[0], FData[OldEnd], FStart*SizeOf(T)); + MoveData(0, OldEnd ,FStart) end else begin //we have to move things around in chunks: we have more data in front of FStart than we have newly created unused elements @@ -189,11 +225,9 @@ begin EmptyElems:=FCapacity-1-CurLast; while (FStart>0) do begin - Elems:=Min(EmptyElems, FStart); - for i:=0 to Elems-1 do - FData[CurLast+1+i]:=FData[i]; - for i := 0 to FCapacity-Elems-1 do - FData[i]:=FData[Elems+i]; + Elems := Min(EmptyElems, FStart); + MoveData(0, CurLast+1, Elems); + MoveData(Elems, -Elems, FCapacity-Elems); Dec(FStart, Elems); end; end; |