4

I have some derived Stream classes for older versions of RADStudio that just reimplement the Read,Write,Seek methods, and the Size and Position properties.

I'm looking to port these to XE3, but I see that there are now (for example) three overloads for Read - the original one, plus two that take TBytes as parameters.

Delphi

function Read(var Buffer; Count: Longint): Longint; overload; virtual;
function Read(Buffer: TBytes; Offset, Count: Longint): Longint; overload; virtual;
function Read(var Buffer: TBytes; Count: Longint): Longint; overload;

C++

virtual int __fastcall Read(void *Buffer, int Count)/* overload */;
virtual int __fastcall Read(System::DynamicArray<System::Byte> Buffer, int Offset, int Count)/* overload */;
int __fastcall Read(System::DynamicArray<System::Byte> &Buffer, int Count)/* overload */;

Do I need to implement all three, or just one? And if just one, which one...?

Normally I'd be able to find this from the VCL source, but I've just got the trial version (no source) at present.

Roddy
  • 66,617
  • 42
  • 165
  • 277
  • 1
    If your old code re-implements the Size and Position properties, you've been doing it wrong all alone. Those properties are already implemented properly with the virtual methods. – Rob Kennedy Dec 18 '12 at 14:59
  • @RobKennedy : Probably ;-) I was redefining the "Size" property (which was probably unnecessary) but using my own GetSize/SetSize methods. Not sure if I need to handle the Position property at all - can't see an example of that anywhere... – Roddy Dec 18 '12 at 15:30
  • 1
    Size and Position are both implemented in terms of the Seek method. There are two versions of Seek, and they are effectively abstract, although you only have to override one of them; whichever one you omit is implemented in terms of the other. – Rob Kennedy Dec 18 '12 at 15:39
  • @RobKennedy - No, you MUST override `SetSize` in `TStream` descendants, at least in Delphi XE (have no XE3). – kludg Dec 18 '12 at 15:46
  • @Serg You only must override it if you want assigning to size to actually do something. Rob means that the default `GetSize` implementation uses `Seek` and that is accurate. He veers away from accuracy when one considers `SetSize`. – David Heffernan Dec 18 '12 at 15:53
  • Yes but you can override `GetSize` for optimization reasons too, say a stream descendant has `FSize` field and no need for multiple `Seek` calls, I did it when implemented my streams. – kludg Dec 18 '12 at 15:58
  • Perhaps you could look into FPC RTL sources. TStream is so base class, that i think its API is identical for the sake of libraries cpompatibility. – Arioch 'The Dec 18 '12 at 16:25

2 Answers2

6

You only need implement the method read and write with these signatures

function Read(var Buffer; Count: Longint): Longint; overload; virtual;
function Write(const Buffer; Count: Longint): Longint

because the overloads versions which uses the TBytes (and System::DynamicArray<System::Byte>) as parameter internally calls to the above versions of Read and Write.

RRUZ
  • 134,889
  • 20
  • 356
  • 483
6

The bare minimum virtual TStream methods that you need to override are:

function Read(var Buffer; Count: Longint): Longint; overload; virtual;
function Write(const Buffer; Count: Longint): Longint; overload; virtual;
function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; overload; virtual;

If you want to support the assigning to the Size property you need to override:

procedure SetSize(NewSize: Longint); overload; virtual;
procedure SetSize(const NewSize: Int64); overload; virtual;

The implementation of the 32 bit SetSize must call the 64 bit SetSize. And the 64 bit SetSize does the work.

If you don't override these methods then assigning to the stream's Size property will silently do nothing.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490