I found that TReadBufStream.Seek function did not work properly, especially when seeking backwards.
Indeed, here is its code:
function TReadBufStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
begin
FakeSeekForward(Offset,Origin,FTotalPos);
Result:=FTotalPos; // Pos updated by fake read
end;
First, and important. procedure TStream.FakeSeekForward does not seek backward (as the name suggests).
Second, updated after connet of howardpc:
Third parameter in FakeSeekForward has const modifier, so it should not be changed by the call.
Then what means comment "Position updated by fake read"?
My suggestion is to rewrite Seek function as follows (in my project this worked nicely):
function TReadBufStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
var
NewTotalPos, Delta, NewBufPos: Int64;
begin
case Origin of
soCurrent:
NewTotalPos := FTotalPos + Offset;
soBeginning: begin
if Offset < 0 then
InvalidSeek;
NewTotalPos := Offset;
end;
soEnd: begin
if Offset > 0 then
InvalidSeek;
NewTotalPos := Size + Offset;
end;
end;
if NewTotalPos > Size then
NewTotalPos := Size;
if NewTotalPos < 0 then
NewTotalPos := 0;
Delta := NewTotalPos - FTotalPos;
NewBufPos := Delta + FBufPos;
if (NewBufPos > 0) and (NewBufPos < FBufSize) then
begin
FBufPos := NewBufPos; //if Seek function moves inside the data which are in the Buffer, we only reposition FBufPos
FTotalPos := NewTotalPos;
end
else // otherwise find desired place in the source stream and invalidate buffer
begin
FTotalPos := FSource.Seek(Offset,Origin);
FBufPos := 0;
FBufSize := 0;
end;
Result := FTotalPos;
end;
By the way, what this function must return? I, as mention in comment, return new position relative to beginning. Is it expected?
Best regards to all!