(*
 * 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( 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( AStream: IStream);
  end;

implementation

{ TThriftStreamAdapterCOM }

procedure TThriftStreamAdapterCOM.Close;
begin
  FStream := nil;
end;

constructor TThriftStreamAdapterCOM.Create(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(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.
