Unit StreamPart;
Interface
Uses SysUtils, Classes, Math;
Type TStreamPart =
Class(TStream)
Private
_Stream: TStream;
_Offset, _MaxLen: Int64;
Protected
Function GetSize: Int64;
Override;
Procedure SetSize(NewSize: LongInt);
Overload;
Override;
Procedure SetSize(
Const NewSize: Int64);
Overload;
Override;
Public
Constructor Create(Stream: TStream;
Const Offset, MaxLength: Int64);
Function Read(
Var Buffer; Count: LongInt): LongInt;
Override;
Function Write(
Const Buffer; Count: LongInt): LongInt;
Override;
Function Seek(Offset: LongInt; Origin: Word): LongInt;
Overload;
Override;
Function Seek(
Const Offset: Int64; Origin: TSeekOrigin): Int64;
Overload;
Override;
End;
Implementation
Function TStreamPart.GetSize: Int64;
Begin
Result := Min(Max(_Stream.Size - _Offset, 0), _MaxLen);
End;
Procedure TStreamPart.SetSize(NewSize: LongInt);
Begin
SetSize(Int64(NewSize));
End;
Procedure TStreamPart.SetSize(
Const NewSize: Int64);
Begin
If _Stream.Size <= _Offset + _MaxLen
Then
_Stream.Size := _Offset + NewSize
Else Raise Exception.Create('
The StreamPart must lie at the '
+ '
end of the main stream to change its size to be allowed.');
End;
Constructor TStreamPart.Create(Stream: TStream;
Const Offset, MaxLength: Int64);
Begin
_Stream := Stream;
_Offset := Offset;
_MaxLen := MaxLength;
End;
Function TStreamPart.
Read(
Var Buffer; Count: LongInt): LongInt;
Var Pos: Int64;
Begin
Pos := _Stream.Position;
If (Pos < _Offset)
or (Pos >= _Offset + _MaxLen)
Then
Raise Exception.Create('
The .Position is out of range.');
Result := _Stream.
Read(Buffer, Min(Int64(Count), _Stream.Size - Pos));
End;
Function TStreamPart.
Write(
Const Buffer; Count: LongInt): LongInt;
Var Pos: Int64;
Begin
Pos := _Stream.Position;
If (Pos < _Offset)
or (Pos >= _Offset + _MaxLen)
Then
Raise Exception.Create('
The .Position is out of range.');
Result := _Stream.
Write(Buffer, Min(Int64(Count), _Stream.Size - Pos));
End;
Function TStreamPart.Seek(Offset: LongInt; Origin: Word): LongInt;
Begin
Result := Seek(Int64(Offset), TSeekOrigin(Origin));
End;
Function TStreamPart.Seek(
Const Offset: Int64; Origin: TSeekOrigin): Int64;
Begin
Case Origin
of
soEnd: Offset := _Offset + _MaxLen + Offset;
soCurrent: Offset := _Stream.Position + Offset;
Else Offset := _Offset + Offset;
End;
Result := _Stream.Seek(Min(Max(Offset, _Offset), _Offset + _MaxLen), soBeginning);
End;
End.