mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-06 20:50:45 +02:00
--- Merging r32797 into '.':
U packages/fcl-base/src/streamex.pp --- Recording mergeinfo for merge of r32797 into '.': U . # revisions: 32797 git-svn-id: branches/fixes_3_0@33350 -
This commit is contained in:
parent
1c6795bd6d
commit
6a42afd135
@ -156,6 +156,28 @@ type
|
||||
function ReadLine: string; override; overload;
|
||||
end;
|
||||
|
||||
{ allows you to represent just a small window of a bigger stream as a substream.
|
||||
also makes sure one is actually at the correct position before clobbering stuff. }
|
||||
|
||||
TWindowedStream = class(TOwnerStream)
|
||||
private
|
||||
fStart : Int64; // in the source.
|
||||
fFrontier : Int64; // in the source.
|
||||
fStartingPositionHere : Int64; // position in this Stream corresponding to Position = fStart in the source.
|
||||
fPositionHere : Int64; // position in this Stream.
|
||||
protected
|
||||
//function GetPosition() : Int64; override; = Seek(0, soCurrent) already.
|
||||
function GetSize() : Int64; override;
|
||||
procedure SetSize(const NewSize: Int64); override; overload;
|
||||
public
|
||||
constructor Create(aStream : TStream; const aSize : Int64; const aPositionHere : Int64 = 0);
|
||||
destructor Destroy(); override;
|
||||
function Read(var aBuffer; aCount : longint) : longint; override;
|
||||
function Write(const aBuffer; aCount : Longint): Longint; override;
|
||||
function Seek(const aOffset: Int64; aOrigin: TSeekorigin): Int64; override;
|
||||
end;
|
||||
|
||||
|
||||
TStreamHelper = class helper for TStream
|
||||
function ReadWordLE :word;
|
||||
function ReadDWordLE:dword;
|
||||
@ -183,6 +205,13 @@ type
|
||||
|
||||
Implementation
|
||||
|
||||
ResourceString
|
||||
SErrCannotWriteOutsideWindow = 'Cannot write outside allocated window.';
|
||||
SErrInvalidSeekWindow = 'Cannot seek outside allocated window.';
|
||||
SErrInvalidSeekOrigin = 'Invalid seek origin.';
|
||||
SErrCannotChangeWindowSize = 'Cannot change the size of a windowed stream';
|
||||
|
||||
|
||||
{ TBidirBinaryObjectReader }
|
||||
|
||||
function TBidirBinaryObjectReader.GetPosition: Longint;
|
||||
@ -607,4 +636,103 @@ begin
|
||||
end;
|
||||
{$endif}
|
||||
|
||||
{ TWindowedStream }
|
||||
|
||||
constructor TWindowedStream.Create(aStream : TStream; const aSize : Int64; const aPositionHere : Int64 = 0);
|
||||
begin
|
||||
inherited Create(aStream);
|
||||
fStart := aStream.Position;
|
||||
fFrontier := fStart + aSize;
|
||||
fStartingPositionHere := aPositionHere;
|
||||
fPositionHere := aPositionHere;
|
||||
end;
|
||||
|
||||
destructor TWindowedStream.Destroy();
|
||||
begin
|
||||
inherited Destroy();
|
||||
end;
|
||||
|
||||
function TWindowedStream.Read(var aBuffer; aCount : longint) : longint;
|
||||
var
|
||||
vSourcePosition : Int64;
|
||||
vNewSourcePosition : Int64;
|
||||
begin
|
||||
vSourcePosition := Source.Position;
|
||||
vNewSourcePosition := fStart + fPositionHere - fStartingPositionHere;
|
||||
if vNewSourcePosition <> vSourcePosition then // someone modified the file position. Bad bad.
|
||||
Source.Seek(vNewSourcePosition, 0);
|
||||
|
||||
if vNewSourcePosition + aCount > fFrontier then // trying to access outside.
|
||||
aCount := fFrontier - vNewSourcePosition;
|
||||
|
||||
Result := Source.Read(aBuffer, aCount);
|
||||
Inc(fPositionHere, Result);
|
||||
end;
|
||||
|
||||
|
||||
function TWindowedStream.Write(const aBuffer; aCount : Longint): Longint;
|
||||
var
|
||||
vSourcePosition : Int64;
|
||||
vNewSourcePosition : Int64;
|
||||
begin
|
||||
vSourcePosition := Source.Position;
|
||||
vNewSourcePosition := fStart + fPositionHere - fStartingPositionHere;
|
||||
if vNewSourcePosition <> vSourcePosition then // someone modified the file position. Bad bad.
|
||||
Source.Seek(vNewSourcePosition, 0);
|
||||
|
||||
if vNewSourcePosition + aCount > fFrontier then // trying to access outside.
|
||||
Raise EWriteError.Create(SErrCannotWriteOutsideWindow);
|
||||
//aCount := fFrontier - vNewSourcePosition;
|
||||
|
||||
Result := Source.Write(aBuffer, aCount);
|
||||
Inc(fPositionHere, Result);
|
||||
end;
|
||||
|
||||
function TWindowedStream.Seek(const aOffset: Int64; aOrigin: TSeekOrigin): Int64;
|
||||
var
|
||||
vNewPositionHere : Int64;
|
||||
vSourcePosition : Int64;
|
||||
begin
|
||||
{
|
||||
here there
|
||||
fStartingPositionHere .... fStart
|
||||
fPositionHere............. x
|
||||
}
|
||||
|
||||
if (aOrigin = soCurrent) and (aOffset = 0) then begin // get position.
|
||||
Result := fPositionHere;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if aOrigin = soBeginning then
|
||||
vNewPositionHere := aOffset
|
||||
else if aOrigin = soCurrent then
|
||||
vNewPositionHere := fPositionHere + aOffset
|
||||
else if aOrigin = soEnd then
|
||||
vNewPositionHere := fStartingPositionHere + fFrontier - fStart + aOffset
|
||||
else
|
||||
raise EReadError.Create(SErrInvalidSeekOrigin);
|
||||
|
||||
vSourcePosition := fStart + vNewPositionHere - fStartingPositionHere;
|
||||
if (vSourcePosition < 0) or (vSourcePosition >= fFrontier) then
|
||||
raise EReadError.Create(SErrInvalidSeekWindow);
|
||||
|
||||
Result := Source.Seek(vSourcePosition, 0);
|
||||
//if Result = -1 ??? can that happen?
|
||||
Result := vNewPositionHere;
|
||||
end;
|
||||
|
||||
function TWindowedStream.GetSize() : Int64;
|
||||
begin
|
||||
Result := fFrontier - fStart;
|
||||
end;
|
||||
|
||||
procedure TWindowedStream.SetSize(const NewSize: Int64); overload;
|
||||
begin
|
||||
if NewSize = Self.GetSize() then
|
||||
Exit;
|
||||
raise EWriteError.Create(SErrCannotChangeWindowSize);
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user