(* | |
* Licensed to the Apache Software Foundation (ASF) under one | |
* or more contributor license agreements. See the NOTICE file | |
* distributed with this work for additional information | |
* regarding copyright ownership. The ASF licenses this file | |
* to you under the Apache License, Version 2.0 (the | |
* "License"); you may not use this file except in compliance | |
* with the License. You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, | |
* software distributed under the License is distributed on an | |
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
* KIND, either express or implied. See the License for the | |
* specific language governing permissions and limitations | |
* under the License. | |
*) | |
unit Thrift.Stream; | |
interface | |
uses | |
Classes, | |
SysUtils, | |
SysConst, | |
RTLConsts, | |
Thrift.Utils, | |
ActiveX; | |
type | |
IThriftStream = interface | |
['{732621B3-F697-4D76-A1B0-B4DD5A8E4018}'] | |
procedure Write( const buffer: TBytes; offset: Integer; count: Integer); | |
function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; | |
procedure Open; | |
procedure Close; | |
procedure Flush; | |
function IsOpen: Boolean; | |
function ToArray: TBytes; | |
end; | |
TThriftStreamImpl = class( TInterfacedObject, IThriftStream) | |
private | |
procedure CheckSizeAndOffset( const buffer: TBytes; offset: Integer; count: Integer); | |
protected | |
procedure Write( const buffer: TBytes; offset: Integer; count: Integer); virtual; | |
function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; virtual; | |
procedure Open; virtual; abstract; | |
procedure Close; virtual; abstract; | |
procedure Flush; virtual; abstract; | |
function IsOpen: Boolean; virtual; abstract; | |
function ToArray: TBytes; virtual; abstract; | |
end; | |
TThriftStreamAdapterDelphi = class( TThriftStreamImpl ) | |
private | |
FStream : TStream; | |
FOwnsStream : Boolean; | |
protected | |
procedure Write( const buffer: TBytes; offset: Integer; count: Integer); override; | |
function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; override; | |
procedure Open; override; | |
procedure Close; override; | |
procedure Flush; override; | |
function IsOpen: Boolean; override; | |
function ToArray: TBytes; override; | |
public | |
constructor Create( const AStream: TStream; AOwnsStream : Boolean); | |
destructor Destroy; override; | |
end; | |
TThriftStreamAdapterCOM = class( TThriftStreamImpl) | |
private | |
FStream : IStream; | |
protected | |
procedure Write( const buffer: TBytes; offset: Integer; count: Integer); override; | |
function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; override; | |
procedure Open; override; | |
procedure Close; override; | |
procedure Flush; override; | |
function IsOpen: Boolean; override; | |
function ToArray: TBytes; override; | |
public | |
constructor Create( const AStream: IStream); | |
end; | |
implementation | |
{ TThriftStreamAdapterCOM } | |
procedure TThriftStreamAdapterCOM.Close; | |
begin | |
FStream := nil; | |
end; | |
constructor TThriftStreamAdapterCOM.Create( const AStream: IStream); | |
begin | |
FStream := AStream; | |
end; | |
procedure TThriftStreamAdapterCOM.Flush; | |
begin | |
if IsOpen then | |
begin | |
if FStream <> nil then | |
begin | |
FStream.Commit( STGC_DEFAULT ); | |
end; | |
end; | |
end; | |
function TThriftStreamAdapterCOM.IsOpen: Boolean; | |
begin | |
Result := FStream <> nil; | |
end; | |
procedure TThriftStreamAdapterCOM.Open; | |
begin | |
end; | |
function TThriftStreamAdapterCOM.Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; | |
begin | |
inherited; | |
Result := 0; | |
if FStream <> nil then | |
begin | |
if count > 0 then | |
begin | |
FStream.Read( @buffer[offset], count, @Result); | |
end; | |
end; | |
end; | |
function TThriftStreamAdapterCOM.ToArray: TBytes; | |
var | |
statstg: TStatStg; | |
len : Integer; | |
NewPos : Int64; | |
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; | |
SetLength( Result, len ); | |
if len > 0 then | |
begin | |
if Succeeded( FStream.Seek( 0, STREAM_SEEK_SET, NewPos) ) then | |
begin | |
FStream.Read( @Result[0], len, @cbRead); | |
end; | |
end; | |
end; | |
procedure TThriftStreamAdapterCOM.Write( const buffer: TBytes; offset: Integer; count: Integer); | |
var | |
nWritten : Integer; | |
begin | |
inherited; | |
if IsOpen then | |
begin | |
if count > 0 then | |
begin | |
FStream.Write( @buffer[0], count, @nWritten); | |
end; | |
end; | |
end; | |
{ TThriftStreamImpl } | |
procedure TThriftStreamImpl.CheckSizeAndOffset(const buffer: TBytes; offset, | |
count: Integer); | |
var | |
len : Integer; | |
begin | |
if count > 0 then | |
begin | |
len := Length( buffer ); | |
if (offset < 0) or ( offset >= len) then | |
begin | |
raise ERangeError.Create( SBitsIndexError ); | |
end; | |
if count > len then | |
begin | |
raise ERangeError.Create( SBitsIndexError ); | |
end; | |
end; | |
end; | |
function TThriftStreamImpl.Read(var buffer: TBytes; offset, | |
count: Integer): Integer; | |
begin | |
Result := 0; | |
CheckSizeAndOffset( buffer, offset, count ); | |
end; | |
procedure TThriftStreamImpl.Write(const buffer: TBytes; offset, count: Integer); | |
begin | |
CheckSizeAndOffset( buffer, offset, count ); | |
end; | |
{ TThriftStreamAdapterDelphi } | |
procedure TThriftStreamAdapterDelphi.Close; | |
begin | |
FStream.Free; | |
FStream := nil; | |
FOwnsStream := False; | |
end; | |
constructor TThriftStreamAdapterDelphi.Create( const AStream: TStream; AOwnsStream: Boolean); | |
begin | |
FStream := AStream; | |
FOwnsStream := AOwnsStream; | |
end; | |
destructor TThriftStreamAdapterDelphi.Destroy; | |
begin | |
if FOwnsStream then | |
begin | |
FStream.Free; | |
end; | |
inherited; | |
end; | |
procedure TThriftStreamAdapterDelphi.Flush; | |
begin | |
end; | |
function TThriftStreamAdapterDelphi.IsOpen: Boolean; | |
begin | |
Result := FStream <> nil; | |
end; | |
procedure TThriftStreamAdapterDelphi.Open; | |
begin | |
end; | |
function TThriftStreamAdapterDelphi.Read(var buffer: TBytes; offset, | |
count: Integer): Integer; | |
begin | |
inherited; | |
Result := 0; | |
if count > 0 then | |
begin | |
Result := FStream.Read( Pointer(@buffer[offset])^, count) | |
end; | |
end; | |
function TThriftStreamAdapterDelphi.ToArray: TBytes; | |
var | |
OrgPos : Integer; | |
len : Integer; | |
begin | |
len := 0; | |
if FStream <> nil then | |
begin | |
len := FStream.Size; | |
end; | |
SetLength( Result, len ); | |
if len > 0 then | |
begin | |
OrgPos := FStream.Position; | |
try | |
FStream.Position := 0; | |
FStream.ReadBuffer( Pointer(@Result[0])^, len ); | |
finally | |
FStream.Position := OrgPos; | |
end; | |
end | |
end; | |
procedure TThriftStreamAdapterDelphi.Write(const buffer: TBytes; offset, | |
count: Integer); | |
begin | |
inherited; | |
if count > 0 then | |
begin | |
FStream.Write( Pointer(@buffer[offset])^, count) | |
end; | |
end; | |
end. |