TReader.Position lazarus / 62-General ---------------------------------------------------------------------- Tesla2k · 2021-08-26 09:46 Hello, I am trying to port this code from Delphi 7. I check if I am at the end of the data with Reader.Position. Unfortunately this property does not exists in FPC. Is there an other way to check if I a at the end of the stream? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   Stream:=TMemoryStream.Create;  Reader:=TReader.Create(Stream,1024);  //Load Data to Stream  Stream.Position:=0;  repeat        Reader.ReadInteger();              Reader.ReadVariant;  until Reader.Position=Stream.Size; ---------------------------------------------------------------------- Remy Lebeau · 2021-08-26 22:27 Quote from: jamie on August 26, 2021, 11:23:23 pmCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Until Reader.EndOFList; Checking if the stream contains an end marker is not the same thing as checking if the stream is at the end of its available data. ---------------------------------------------------------------------- Remy Lebeau · 2021-08-26 23:02 Quote from: jamie on August 27, 2021, 12:35:08 amSo why isn't the "Stream.Position >= Stream.Size" being used in that case ? Because TReader has an internal buffer.  If you just look at Stream.Position by itself, you won't take into account any data that hasn't been read from the buffer yet. Quote from: Tesla2k on August 26, 2021, 11:46:41 amIs there an other way to check if I am at the end of the stream? In both Delphi and FreePascal, TReader has an internal buffer.  TReader.Position in Delphi subtracts the amount of unread data in the buffer from the TStream's current Position, which is the total amount of data that has been buffered. But in FreePascal, TReader does not provide a direct way for users to determine the amount of unread data in that buffer.  However, I can think of a couple of indirect ways you can approach this. TReader uses an internal TBinaryObjectReader to handle its buffer, and has a public Driver property to access that object.  And fortunately, TBinaryObjectReader's data members are declared as protected, not private.  So you can use an accessor class, or a class helper, to reach them at runtime, eg: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type  TBinaryObjectReaderAccess = class(TBinaryObjectReader)  end;   { or:  TBinaryObjectReaderHelper = class helper for TBinaryObjectReader    function GetPosition: Longint;    property Position: Longint read GetPosition;  end;  }   TReaderHelper = class helper for TReader    function GetPosition: Longint;    property Position: Longint read GetPosition;  end; {function TBinaryObjectReaderHelper.GetPosition: Longint;begin  with TBinaryObjectReader(Self) do    Result := FStream.Position - (FBufEnd - FBufPos);end;} function TReaderHelper.GetPosition: Longint;begin  with TBinaryObjectReaderAccess(Driver as TBinaryObjectReader) do    Result := FStream.Position - (FBufEnd - FBufPos);  // or: Result := (Driver as TBinaryObjectReader).Position;end; ... Stream := TMemoryStream.Create;Reader := TReader.Create(Stream, 1024);//Load Data to StreamStream.Position := 0;repeat  Reader.ReadInteger;  Reader.ReadVariant;until Reader.Position = Stream.Size; // should work now... You could then take this a step further by deriving your own class from TBinaryObjectReader, and then deriving a class from TReader to override its virtual CreateDriver() method, eg: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type  TMyBinaryObjectReader = class(TBinaryObjectReader)    function GetPosition: Longint;    property Position: Longint read GetPosition;  end;   TMyReader = class(TReader)    function CreateDriver(Stream: TStream; BufSize: Integer): TAbstractObjectReader; override;    function GetPosition: Longint;    property Position: Longint read GetPosition;  end; function TMyBinaryObjectReader.GetPosition: Longint;begin  Result := FStream.Position - (FBufEnd - FBufPos);end; function TMyReader.CreateDriver(Stream: TStream; BufSize: Integer): TAbstractObjectReader;begin  Result := TMyBinaryObjectReader.Create(Stream, BufSize);end; function TMyReader.GetPosition: Longint;begin  Result := TMyBinaryObjectReader(Driver).Position;end; ... Stream := TMemoryStream.Create;Reader := TMyReader.Create(Stream, 1024); // be sure to declare Reader as TMyReader, not TReader!//Load Data to StreamStream.Position := 0;repeat  Reader.ReadInteger;  Reader.ReadVariant;until Reader.Position = Stream.Size; // should work now... ---------------------------------------------------------------------- Tesla2k · 2021-08-28 08:49 Thank You very much! I will use the version with the TReaderHelper class. ---------------------------------------------------------------------- marcov · 2021-08-28 10:34 Please file a bug for the missing property. ---------------------------------------------------------------------- Remy Lebeau · 2021-08-31 00:16 Quote from: marcov on August 28, 2021, 12:34:07 pmPlease file a bug for the missing property. A ticket already exists, created 11 years ago, closed and locked 3 weeks ago, so can't add comments to it: #16765: Position property is missing from TReader (and TWriter)