Recent

Author Topic: TMemoryStream, manual memory management  (Read 383 times)

LemonParty

  • Hero Member
  • *****
  • Posts: 537
TMemoryStream, manual memory management
« on: May 19, 2026, 09:40:05 pm »
How to create and use TMemoryStream where you manually specify the buffer and it's size?
I mean this thing from Delphi https://docwiki.embarcadero.com/Libraries/Sydney/en/System.Classes.TCustomMemoryStream.SetPointer
Lazarus v. 4.99. FPC v. 3.3.1. Windows 11

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12905
  • FPC developer.
Re: TMemoryStream, manual memory management
« Reply #1 on: May 19, 2026, 09:57:59 pm »
I use this, derived from Indy's memorystream:

Code: Pascal  [Select][+][-]
  1. Type
  2.  
  3. // in a different (Indy)  Unit:
  4.   TIdMemoryBufferStream = class(TCustomMemoryStream)
  5.   public
  6.     constructor Create(APtr: Pointer; ASize: TIdNativeInt);
  7.     function Write(const Buffer; Count: Longint): Longint; override;
  8.   end;
  9.  
  10.     TIdCandelaMemoryBufferStream = class(TIdMemoryBufferStream)
  11.                                      procedure dosetpointer(aptr:pointer;asize:TIdNativeInt);
  12.                                      procedure write(io:TIdIOHandler;aptr:pointer;asize:TIdNativeInt);
  13.     end;
  14.  
  15. ....
  16.  
  17. constructor TIdMemoryBufferStream.Create(APtr: Pointer; ASize: TIdNativeInt);
  18. begin
  19.   inherited Create;
  20.   SetPointer(APtr, ASize);
  21. end;
  22.  
  23. function TIdMemoryBufferStream.Write(const Buffer; Count: Longint): Longint;
  24. var
  25.   LNumToCopy: Longint;
  26. begin
  27.   Result := 0;
  28.   if (Position >= 0) and (Size > 0) and (Count > 0) then
  29.   begin
  30.     LNumToCopy := IndyMin(Size - Position, Count);
  31.     if LNumToCopy > 0 then
  32.     begin
  33.       System.Move(Buffer, Pointer(PtrUInt(Memory) + Position)^, LNumToCopy);
  34.       TIdStreamHelper.Seek(Self, LNumToCopy, soCurrent);
  35.       Result := LNumToCopy;
  36.     end;
  37.   end;
  38. end;
  39.  
  40. { TIdCandelaMemoryBufferStream }
  41.  
  42. procedure TIdCandelaMemoryBufferStream.dosetpointer(aptr: pointer;
  43.   asize: TIdNativeInt);
  44. begin
  45.   SetPointer(aptr,asize);
  46.   position:=0;
  47. end;
  48.  
  49. procedure TIdCandelaMemoryBufferStream.write(io:TIdIOHandler;aptr:pointer;asize:TIdNativeInt);
  50. begin
  51.   SetPointer(aptr,asize);
  52.   position:=0;
  53.   if asize>0 then
  54.     io.Write(self,asize);
  55. end;
  56.  
  57.  

It's from Indy, but more the utility routines, and used by but not connected to the rest of Indy.

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1596
    • Lebeau Software
Re: TMemoryStream, manual memory management
« Reply #2 on: May 20, 2026, 01:33:46 am »
How to create and use TMemoryStream where you manually specify the buffer and it's size?

TMemoryStream does not support that option. It manages its own buffer and size. To do what you ask, you need to use TCustomMemoryStream instead.

I mean this thing from Delphi https://docwiki.embarcadero.com/Libraries/en/System.Classes.TCustomMemoryStream.SetPointer

FPC has TCustomMemoryStream, too: https://www.freepascal.org/docs-html/rtl/classes/tcustommemorystream.html

In both Delphi and FPC, SetPointer() is a protected member, so you need to derive a new class from TCustomMemoryStream in order to access SetPointer(), eg:

Code: Pascal  [Select][+][-]
  1. type
  2.   TMyMemoryBufferStream = class(TCustomMemoryStream)
  3.   public
  4.     constructor Create(Ptr: Pointer; ASize: PtrInt);
  5.   end;
  6.  
  7. constructor TMyMemoryBufferStream.Create(Ptr: Pointer; ASize: PtrInt);
  8. begin
  9.   inherited Create;
  10.   SetPointer(APtr, ASize);
  11. end;
« Last Edit: May 20, 2026, 01:35:26 am by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

LemonParty

  • Hero Member
  • *****
  • Posts: 537
Re: TMemoryStream, manual memory management
« Reply #3 on: May 20, 2026, 10:30:13 am »
marcov, what is TIdStreamHelper? Can you give a code?
Lazarus v. 4.99. FPC v. 3.3.1. Windows 11

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12905
  • FPC developer.
Re: TMemoryStream, manual memory management
« Reply #4 on: May 20, 2026, 12:16:31 pm »
marcov, what is TIdStreamHelper? Can you give a code?

Remy knows that better than me, but I think it is a simple wrapper for seek to abstract between standard VCL and other targets.  Just replace it with seek on the stream.

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1596
    • Lebeau Software
Re: TMemoryStream, manual memory management
« Reply #5 on: May 22, 2026, 03:00:32 am »
marcov, what is TIdStreamHelper?

It is a utility class used internally by the Indy library to hide interface differences in TStream between Delphi/FPC and Delphi.NET.
« Last Edit: May 22, 2026, 03:02:10 am by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

 

TinyPortal © 2005-2018