FPC and DCC Difference in Classes Unit TStream ReadData, WriteData lazarus / 62-General ---------------------------------------------------------------------- Schmitty2005 · 2025-07-27 18:45 Concerning the Unit Classes, and the class of TStream, while writing a unit that I wanted to compile in Delphi DCC and FPC, I have noticed that the WriteData and ReadData from Delphi are not available in FPC TStream.  Delphi's version seemed sleeker and to be more user friendly when programming.   Delphi was , however, lacking ReadByte, ReadWord, ReadDWord, and ReadQWord and the respective write methods.  The FPC methods also make sense, as long as one knows the sizes of the types they are dealing with. https://www.freepascal.org/docs-html/rtl/classes/tstream.html https://docwiki.embarcadero.com/Libraries/Athens/en/System.Classes.TSt ream.WriteData https://docwiki.embarcadero.com/Libraries/Athens/en/System.Classes.TSt ream.ReadData Here is a short Delphi Example. 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 program DelphiMemoryStream; {$APPTYPE CONSOLE}{$R *.res} uses  System.SysUtils, System.Classes; var  m: TMemoryStream;  b: Integer;  c: Uint32;  d: byte;  e: Uint64;begin  m := TMemoryStream.Create;  b := 1023;  c := 65538;  d := 32;  e := High(Uint64);  try    { TODO -oUser -cConsole Main : Insert code here }    m.writeData(b);    m.writeData(c);  except    on e: Exception do      Writeln(e.ClassName, ': ', e.Message);  end;{  No Need to specify size in Delphi! }  Writeln(m.writeData(b));  Writeln(m.writeData(c));  Writeln(m.writeData(d));  Writeln(m.writeData(e));  readln;   {Console Output is byte size of written data:   4   4   1   8   }end. ---------------------------------------------------------------------- LV · 2025-07-27 20:08 The day before yesterday, I was riding the subway and playing the game "find 10 differences". In FPC, we add missing Delphi methods, and in Delphi, we add missing FPC methods. Maybe something like this 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 program Project1;{$APPTYPE CONSOLE}uses  SysUtils, Classes, StreamCompatibilityHelper; // Include the helper unit var  m: TMemoryStream;  b: Integer;  c: UInt32;  d: Byte;  e: UInt64;begin  m := TMemoryStream.Create;  try    b := 1023;    c := 65538;    d := 32;    e := High(UInt64);     // Cross-compiler writing    Writeln(m.WriteData(b));    Writeln(m.WriteData(c));    Writeln(m.WriteData(d));    Writeln(m.WriteData(e));     m.Position := 0;     // Cross-compiler reading    m.ReadData(b);    m.ReadData(c);  m.ReadData(d);    m.ReadData(e);     // Alternative in Delphi using helper methods:    // d := m.ReadByte;    // e := m.ReadQWord;  finally    m.Free;  end;   Readln; end.{   Console Output is byte size of written data:   4   4   1   8} 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 unit StreamCompatibilityHelper; {$IFDEF FPC}  {$MODE DELPHI}{$ENDIF} interface uses  Classes; type  {$IFDEF FPC}  // Helper for FPC (adds missing methods)  TStreamHelper = class helper for TStream  public    // WriteData methods    function WriteData(const Buffer: Integer): Longint; overload;    function WriteData(const Buffer: UInt32): Longint; overload;    function WriteData(const Buffer: Byte): Longint; overload;    function WriteData(const Buffer: UInt64): Longint; overload;     // ReadData methods    function ReadData(var Buffer: Integer): Longint; overload;    function ReadData(var Buffer: UInt32): Longint; overload;    function ReadData(var Buffer: Byte): Longint; overload;    function ReadData(var Buffer: UInt64): Longint; overload;  end;  {$ELSE}  // Helper for Delphi (adds missing methods)  TStreamHelper = class helper for TStream  public    function ReadByte: Byte;    function WriteByte(Value: Byte): Longint;  end;  {$ENDIF} implementation {$IFDEF FPC}// Implementation for FPC // WriteData methodsfunction TStreamHelper.WriteData(const Buffer: Integer): Longint;begin  WriteBuffer(Buffer, SizeOf(Buffer));  Result := SizeOf(Buffer);end; function TStreamHelper.WriteData(const Buffer: UInt32): Longint;begin  WriteBuffer(Buffer, SizeOf(Buffer));  Result := SizeOf(Buffer);end; function TStreamHelper.WriteData(const Buffer: Byte): Longint;begin  WriteBuffer(Buffer, SizeOf(Buffer));  Result := SizeOf(Buffer);end; function TStreamHelper.WriteData(const Buffer: UInt64): Longint;begin  WriteBuffer(Buffer, SizeOf(Buffer));  Result := SizeOf(Buffer);end; // ReadData methodsfunction TStreamHelper.ReadData(var Buffer: Integer): Longint;begin  ReadBuffer(Buffer, SizeOf(Buffer));  Result := SizeOf(Buffer);end; function TStreamHelper.ReadData(var Buffer: UInt32): Longint;begin  ReadBuffer(Buffer, SizeOf(Buffer));  Result := SizeOf(Buffer);end; function TStreamHelper.ReadData(var Buffer: Byte): Longint;begin  ReadBuffer(Buffer, SizeOf(Buffer));  Result := SizeOf(Buffer);end; function TStreamHelper.ReadData(var Buffer: UInt64): Longint;begin  ReadBuffer(Buffer, SizeOf(Buffer));  Result := SizeOf(Buffer);end; {$ELSE}// Implementation for Delphifunction TStreamHelper.ReadByte: Byte;begin  ReadBuffer(Result, SizeOf(Byte));end; function TStreamHelper.WriteByte(Value: Byte): Longint;begin  WriteBuffer(Value, SizeOf(Value));  Result := SizeOf(Value);end;{$ENDIF} end. ---------------------------------------------------------------------- marcov · 2025-07-27 20:13 I've something like that too in my codebases, but it is too large to post. Many strutils routines, a stream helper, general endianess routines and a memorystream derivative with more gentle growth. Most of those date from XE3 times though, since Embarcadero started to do some multiplatform work, some (but probably different ) equivalents might have been added meanwhile. ---------------------------------------------------------------------- jamie · 2025-07-28 00:19 at one point I suggested a compiler feature that I thought would be a great thing but either no one understood it or though it was just garbage but here goes.  Pascal allows for parameters of untyped and thus normally also requires an additional parameter at times to indicate the size of data there.  Etc.    Procedure Test(Var AParam; Size:Integer = SizeOf(Test(AParam));  In this situation you can enter any size of a type and as a default the compiler can fill in Size parameter as it takes in the aParam.  So in the end;   Procedure Test(AByteVar); would set the size input to 0ne   Procedure Test(AWordVar); would do 2 etc. Putting that into context you can build a procedure that will automatically generate the correct Size information, in this case a Memory reader and writer of different types being entered.  And if you want, you can just directly specify it.  Also, I suggested that the Default value in parameters could use a Function, if the calling code does not fill it.   PRocedure Test(Var parama; Size:integer = SomeFunction); Can you see the beauty in that ? ---------------------------------------------------------------------- jamie · 2025-07-28 00:31 Btw 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 Function Test(Var Aparam; Size:Integer = Sizeof(Aparam)):Integer;Begin Result := Size;end;                           This compiles but it only returns 0, the compiler does not examine the incoming Size type. But If I were to put a type there.  Test(Var param:Byte...... it does report the value of 1.  So it kind of half works. jamies ---------------------------------------------------------------------- marcov · 2025-07-28 06:55 Jamie:  Modula2's formal parameter evolved to do exactly this, by allowing everything to pass to an "array of byte" parameter.  The routine could then use low and high() to find out the size. ---------------------------------------------------------------------- Thaddy · 2025-07-28 09:20 Experiment. The pity is it seems you can't use length() in generics, so types that are implicit pointer types, like strings, give the pointer size..which is inconvenient: 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 {$mode delphi}{$if fpc_fullversion < 30301}{$error needs trunk}{$endif}{$modeswitch implicitfunctionspecialization}Function WriteData(const param:T):Integer;Begin  Result := SizeOf(Param);end; function readdata(const param:T):T;begin   Result := param;end;  var  a:set of char;  v:TextRec;  s:string[20];begin   writeln(WriteData('test me')); // pointer. Can't use length() in generics grrrrr.. Shortstring will work.  writeln(WriteData(100)); // byte  writeln(WriteData(1000)); //word  writeln(WriteData(0.999));  // double  writeln(WriteData(a));    // max set size= 32, not the elements  writeln(WriteData(v));    // size of TextRec, which is large.  writeln(WriteData(s));    // size of shortstring = 256, not 20. readln;end.I tried to identify what should be used: length or SizeOf, based on type kind, but that failed because length was not accepted. ---------------------------------------------------------------------- marcov · 2025-07-28 10:15 I tried to workaround that with gettypekind: 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       case GetTypeKind(t) of         tkastring,tkustring: result:=length(param);     else         Result := SizeOf(Param);         end;  but no bananas. ---------------------------------------------------------------------- Thaddy · 2025-07-28 10:17 Yes, that's what I tried.