(* * 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 inherited Create; 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 inherited Create; 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.