THRIFT-5007 Implement MAX_MESSAGE_SIZE and remaining read bytes control
Client: Delphi
Patch: Jens Geyer
This closes #1932
diff --git a/lib/delphi/src/Thrift.Stream.pas b/lib/delphi/src/Thrift.Stream.pas
index 7cb9219..0f4e723 100644
--- a/lib/delphi/src/Thrift.Stream.pas
+++ b/lib/delphi/src/Thrift.Stream.pas
@@ -37,11 +37,12 @@
type
IThriftStream = interface
- ['{2A77D916-7446-46C1-8545-0AEC0008DBCA}']
+ ['{DBE61E28-2A77-42DB-A5A3-3CCB8A2D09FA}']
procedure Write( const buffer: TBytes; offset: Integer; count: Integer); overload;
procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); overload;
function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; overload;
function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; overload;
+ procedure CheckReadBytesAvailable( const value : Integer);
procedure Open;
procedure Close;
procedure Flush;
@@ -49,14 +50,24 @@
function ToArray: TBytes;
end;
- TThriftStreamImpl = class( TInterfacedObject, IThriftStream)
+
+ IThriftStream2 = interface( IThriftStream)
+ ['{1F55D9FE-F617-4B80-B8CA-4A300D8E33F6}']
+ function Size : Int64;
+ function Position : Int64;
+ end;
+
+
+ TThriftStreamImpl = class abstract( TInterfacedObject, IThriftStream)
strict private
procedure CheckSizeAndOffset( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer); overload;
strict protected
+ // IThriftStream
procedure Write( const buffer: TBytes; offset: Integer; count: Integer); overload; inline;
procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); overload; virtual;
function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; overload; inline;
function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; overload; virtual;
+ procedure CheckReadBytesAvailable( const value : Integer); virtual; abstract;
procedure Open; virtual; abstract;
procedure Close; virtual; abstract;
procedure Flush; virtual; abstract;
@@ -64,40 +75,54 @@
function ToArray: TBytes; virtual; abstract;
end;
- TThriftStreamAdapterDelphi = class( TThriftStreamImpl )
+ TThriftStreamAdapterDelphi = class( TThriftStreamImpl, IThriftStream2)
strict private
FStream : TStream;
FOwnsStream : Boolean;
strict protected
+ // IThriftStream
procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override;
function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override;
+ procedure CheckReadBytesAvailable( const value : Integer); override;
procedure Open; override;
procedure Close; override;
procedure Flush; override;
function IsOpen: Boolean; override;
function ToArray: TBytes; override;
+
+ // IThriftStream2
+ function Size : Int64;
+ function Position : Int64;
public
- constructor Create( const AStream: TStream; AOwnsStream : Boolean);
+ constructor Create( const aStream: TStream; aOwnsStream : Boolean);
destructor Destroy; override;
end;
- TThriftStreamAdapterCOM = class( TThriftStreamImpl)
+ TThriftStreamAdapterCOM = class( TThriftStreamImpl, IThriftStream2)
strict private
FStream : IStream;
strict protected
+ // IThriftStream
procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override;
function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override;
+ procedure CheckReadBytesAvailable( const value : Integer); override;
procedure Open; override;
procedure Close; override;
procedure Flush; override;
function IsOpen: Boolean; override;
function ToArray: TBytes; override;
+
+ // IThriftStream2
+ function Size : Int64;
+ function Position : Int64;
public
- constructor Create( const AStream: IStream);
+ constructor Create( const aStream: IStream);
end;
implementation
+uses Thrift.Transport;
+
{ TThriftStreamAdapterCOM }
procedure TThriftStreamAdapterCOM.Close;
@@ -105,10 +130,10 @@
FStream := nil;
end;
-constructor TThriftStreamAdapterCOM.Create( const AStream: IStream);
+constructor TThriftStreamAdapterCOM.Create( const aStream: IStream);
begin
inherited Create;
- FStream := AStream;
+ FStream := aStream;
end;
procedure TThriftStreamAdapterCOM.Flush;
@@ -120,6 +145,24 @@
end;
end;
+function TThriftStreamAdapterCOM.Size : Int64;
+var statstg: TStatStg;
+begin
+ FillChar( statstg, SizeOf( statstg), 0);
+ if IsOpen
+ and Succeeded( FStream.Stat( statstg, STATFLAG_NONAME ))
+ then result := statstg.cbSize
+ else result := 0;
+end;
+
+function TThriftStreamAdapterCOM.Position : Int64;
+var newpos : {$IF CompilerVersion >= 29.0} UInt64 {$ELSE} Int64 {$IFEND};
+begin
+ if SUCCEEDED( FStream.Seek( 0, STREAM_SEEK_CUR, newpos))
+ then result := Int64(newpos)
+ else raise TTransportExceptionEndOfFile.Create('Seek() error');
+end;
+
function TThriftStreamAdapterCOM.IsOpen: Boolean;
begin
Result := FStream <> nil;
@@ -148,21 +191,21 @@
end;
end;
+procedure TThriftStreamAdapterCOM.CheckReadBytesAvailable( const value : Integer);
+var nRemaining : Int64;
+begin
+ nRemaining := Self.Size - Self.Position;
+ if nRemaining < value
+ then raise TTransportExceptionEndOfFile.Create('Not enough input data');
+end;
+
function TThriftStreamAdapterCOM.ToArray: TBytes;
var
- statstg: TStatStg;
- len : Integer;
+ len : Int64;
NewPos : {$IF CompilerVersion >= 29.0} UInt64 {$ELSE} Int64 {$IFEND};
cbRead : Integer;
begin
- FillChar( statstg, SizeOf( statstg), 0);
- len := 0;
- if IsOpen then begin
- if Succeeded( FStream.Stat( statstg, STATFLAG_NONAME )) then begin
- len := statstg.cbSize;
- end;
- end;
-
+ len := Self.Size;
SetLength( Result, len );
if len > 0 then begin
@@ -226,6 +269,21 @@
{ TThriftStreamAdapterDelphi }
+constructor TThriftStreamAdapterDelphi.Create( const aStream: TStream; aOwnsStream: Boolean);
+begin
+ inherited Create;
+ FStream := aStream;
+ FOwnsStream := aOwnsStream;
+end;
+
+destructor TThriftStreamAdapterDelphi.Destroy;
+begin
+ if FOwnsStream
+ then Close;
+
+ inherited;
+end;
+
procedure TThriftStreamAdapterDelphi.Close;
begin
FStream.Free;
@@ -233,26 +291,21 @@
FOwnsStream := False;
end;
-constructor TThriftStreamAdapterDelphi.Create( const AStream: TStream; AOwnsStream: Boolean);
-begin
- inherited Create;
- FStream := AStream;
- FOwnsStream := AOwnsStream;
-end;
-
-destructor TThriftStreamAdapterDelphi.Destroy;
-begin
- if FOwnsStream
- then Close;
-
- inherited;
-end;
-
procedure TThriftStreamAdapterDelphi.Flush;
begin
// nothing to do
end;
+function TThriftStreamAdapterDelphi.Size : Int64;
+begin
+ result := FStream.Size;
+end;
+
+function TThriftStreamAdapterDelphi.Position : Int64;
+begin
+ result := FStream.Position;
+end;
+
function TThriftStreamAdapterDelphi.IsOpen: Boolean;
begin
Result := FStream <> nil;
@@ -279,16 +332,21 @@
else Result := 0;
end;
+procedure TThriftStreamAdapterDelphi.CheckReadBytesAvailable( const value : Integer);
+var nRemaining : Int64;
+begin
+ nRemaining := FStream.Size - FStream.Position;
+ if nRemaining < value then raise TTransportExceptionEndOfFile.Create('Not enough input data');
+end;
+
function TThriftStreamAdapterDelphi.ToArray: TBytes;
var
OrgPos : Integer;
len : Integer;
begin
- len := 0;
- if FStream <> nil then
- begin
- len := FStream.Size;
- end;
+ if FStream <> nil
+ then len := FStream.Size
+ else len := 0;
SetLength( Result, len );