mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 14:39:36 +01:00 
			
		
		
		
	+ new stream class TCRangeStream that represents a substream of another stream while being also extendable ........ Extend tentryfile so that it can be opened from a stream in addition to a file entfile.pas, tentryfile: + new method openstream() to open a readable tentryfile based on a stream + new method createstream() to open a writeable tentryfile based on a stream * adjust openfile() to use openstream() * adjust createfile() to use createstream() ........ A few extensions for tentryfile needed for package files entfile.pas, tentryfile: + new property position to retrieve/control the position of the underlying stream (works also with tempclose()/tempopen()) + new method substream() to retrieve a stream that goes from the specified offset with the specified length (-1 create a stream that is extendable, aka for writing) + new property stream to get the underlying stream directly; be careful when using this! ........ Extend tppumodule so that it can be opened from a stream as well. fppu.pas, tppumodule: * rename openppu() to openppufile() + new method openppustream() to open a module based on a stream + put the common part of openppufile() and openppustream() into a new method openppu() ........ Fix compilation. fppu.pas, tppumodule: * openppu: add parameter ppufiletime for printing the time of the file (only if filetime is not -1) * openppufile: pass the retrieve time of the PPU to openppu() * openppustream: pass -1 to openppu() ........ git-svn-id: trunk@33109 -
		
			
				
	
	
		
			750 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			750 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
    Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
 | 
						|
 | 
						|
    This module provides stream classes
 | 
						|
 | 
						|
    This program is free software; you can redistribute it and/or modify
 | 
						|
    it under the terms of the GNU General Public License as published by
 | 
						|
    the Free Software Foundation; either version 2 of the License, or
 | 
						|
    (at your option) any later version.
 | 
						|
 | 
						|
    This program is distributed in the hope that it will be useful,
 | 
						|
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
    GNU General Public License for more details.
 | 
						|
 | 
						|
    You should have received a copy of the GNU General Public License
 | 
						|
    along with this program; if not, write to the Free Software
 | 
						|
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
						|
 | 
						|
 ****************************************************************************
 | 
						|
}
 | 
						|
unit cstreams;
 | 
						|
 | 
						|
{$i fpcdefs.inc}
 | 
						|
 | 
						|
interface
 | 
						|
 | 
						|
   uses
 | 
						|
     cutils;
 | 
						|
 | 
						|
 | 
						|
{****************************************************************************
 | 
						|
                                  TCStream
 | 
						|
****************************************************************************}
 | 
						|
 | 
						|
    {
 | 
						|
      TCStream is copied directly from classesh.inc from the FCL so
 | 
						|
      it's compatible with the normal Classes.TStream.
 | 
						|
 | 
						|
      TCFileStream is a merge of THandleStream and TFileStream and updated
 | 
						|
      to have a 'file' type instead of Handle.
 | 
						|
 | 
						|
      TCCustomMemoryStream and TCMemoryStream are direct copies.
 | 
						|
    }
 | 
						|
    const
 | 
						|
       { TCStream seek origins }
 | 
						|
       soFromBeginning = 0;
 | 
						|
       soFromCurrent = 1;
 | 
						|
       soFromEnd = 2;
 | 
						|
 | 
						|
       { TCFileStream create mode }
 | 
						|
       fmCreate        = $FFFF;
 | 
						|
       fmOpenRead      = 0;
 | 
						|
       fmOpenWrite     = 1;
 | 
						|
       fmOpenReadWrite = 2;
 | 
						|
 | 
						|
var
 | 
						|
{ Used for Error reporting instead of exceptions }
 | 
						|
  CStreamError : longint;
 | 
						|
 | 
						|
type
 | 
						|
{ Fake TComponent class, it isn't used any futher }
 | 
						|
  TCComponent = class(TObject)
 | 
						|
  end;
 | 
						|
 | 
						|
{ TCStream abstract class }
 | 
						|
 | 
						|
  TCStream = class(TObject)
 | 
						|
  private
 | 
						|
    function GetPosition: Longint;
 | 
						|
    procedure SetPosition(Pos: Longint);
 | 
						|
    function GetSize: Longint;
 | 
						|
  protected
 | 
						|
    procedure SetSize(NewSize: Longint); virtual;
 | 
						|
  public
 | 
						|
    function Read(var Buffer; Count: Longint): Longint; virtual; abstract;
 | 
						|
    function Write(const Buffer; Count: Longint): Longint; virtual; abstract;
 | 
						|
    function Seek(Offset: Longint; Origin: Word): Longint; virtual; abstract;
 | 
						|
    procedure ReadBuffer(var Buffer; Count: Longint);
 | 
						|
    procedure WriteBuffer(const Buffer; Count: Longint);
 | 
						|
    function CopyFrom(Source: TCStream; Count: Longint): Longint;
 | 
						|
    function ReadComponent(Instance: TCComponent): TCComponent;
 | 
						|
    function ReadComponentRes(Instance: TCComponent): TCComponent;
 | 
						|
    procedure WriteComponent(Instance: TCComponent);
 | 
						|
    procedure WriteComponentRes(const ResName: string; Instance: TCComponent);
 | 
						|
    procedure WriteDescendent(Instance, Ancestor: TCComponent);
 | 
						|
    procedure WriteDescendentRes(const ResName: string; Instance, Ancestor: TCComponent);
 | 
						|
    procedure WriteResourceHeader(const ResName: string; {!!!:out} var FixupInfo: Integer);
 | 
						|
    procedure FixupResourceHeader(FixupInfo: Integer);
 | 
						|
    procedure ReadResHeader;
 | 
						|
    function ReadByte : Byte;
 | 
						|
    function ReadWord : Word;
 | 
						|
    function ReadDWord : Cardinal;
 | 
						|
    function ReadAnsiString : AnsiString;
 | 
						|
    procedure WriteByte(b : Byte);
 | 
						|
    procedure WriteWord(w : Word);
 | 
						|
    procedure WriteDWord(d : Cardinal);
 | 
						|
    Procedure WriteAnsiString (S : AnsiString);
 | 
						|
    property Position: Longint read GetPosition write SetPosition;
 | 
						|
    property Size: Longint read GetSize write SetSize;
 | 
						|
  end;
 | 
						|
 | 
						|
{ TCCustomFileStream class }
 | 
						|
 | 
						|
  TCCustomFileStream = class(TCStream)
 | 
						|
  protected
 | 
						|
    FFileName : String;
 | 
						|
  public
 | 
						|
    constructor Create(const AFileName: string;{shortstring!} Mode: Word); virtual; abstract;
 | 
						|
    function EOF: boolean; virtual; abstract;
 | 
						|
    property FileName : String Read FFilename;
 | 
						|
  end;
 | 
						|
 | 
						|
{ TFileStream class }
 | 
						|
 | 
						|
  TCFileStream = class(TCCustomFileStream)
 | 
						|
  Private
 | 
						|
    FHandle: File;
 | 
						|
  protected
 | 
						|
    procedure SetSize(NewSize: Longint); override;
 | 
						|
  public
 | 
						|
    constructor Create(const AFileName: string; Mode: Word); override;
 | 
						|
    destructor Destroy; override;
 | 
						|
    function Read(var Buffer; Count: Longint): Longint; override;
 | 
						|
    function Write(const Buffer; Count: Longint): Longint; override;
 | 
						|
    function Seek(Offset: Longint; Origin: Word): Longint; override;
 | 
						|
    function EOF: boolean; override;
 | 
						|
  end;
 | 
						|
 | 
						|
  TCFileStreamClass = class of TCCustomFileStream;
 | 
						|
var
 | 
						|
  CFileStreamClass: TCFileStreamClass = TCFileStream;
 | 
						|
 | 
						|
type
 | 
						|
  TCRangeStream = class(TCStream)
 | 
						|
  private
 | 
						|
    FBase: TCStream;
 | 
						|
    FOffset: LongInt;
 | 
						|
    FMaxOffset: LongInt;
 | 
						|
    FSize: LongInt;
 | 
						|
    FPosition: LongInt;
 | 
						|
  public
 | 
						|
    constructor Create(ABase: TCStream; AOffset, ASize: LongInt);
 | 
						|
    function Read(var Buffer; Count: LongInt): LongInt; override;
 | 
						|
    function Write(const Buffer; Count: LongInt): LongInt; override;
 | 
						|
    function Seek(Offset: LongInt; Origin: Word): LongInt; override;
 | 
						|
  end;
 | 
						|
 | 
						|
{ TCustomMemoryStream abstract class }
 | 
						|
 | 
						|
  TCCustomMemoryStream = class(TCStream)
 | 
						|
  private
 | 
						|
    FMemory: Pointer;
 | 
						|
    FSize, FPosition: Longint;
 | 
						|
  protected
 | 
						|
    procedure SetPointer(Ptr: Pointer; ASize: Longint);
 | 
						|
  public
 | 
						|
    function Read(var Buffer; Count: Longint): Longint; override;
 | 
						|
    function Seek(Offset: Longint; Origin: Word): Longint; override;
 | 
						|
    procedure SaveToStream(Stream: TCStream);
 | 
						|
    procedure SaveToFile(const FileName: string);
 | 
						|
    property Memory: Pointer read FMemory;
 | 
						|
  end;
 | 
						|
 | 
						|
{ TCMemoryStream }
 | 
						|
 | 
						|
  TCMemoryStream = class(TCCustomMemoryStream)
 | 
						|
  private
 | 
						|
    FCapacity: Longint;
 | 
						|
    procedure SetCapacity(NewCapacity: Longint);
 | 
						|
  protected
 | 
						|
    function Realloc(var NewCapacity: Longint): Pointer; virtual;
 | 
						|
    property Capacity: Longint read FCapacity write SetCapacity;
 | 
						|
  public
 | 
						|
    destructor Destroy; override;
 | 
						|
    procedure Clear;
 | 
						|
    procedure LoadFromStream(Stream: TCStream);
 | 
						|
    procedure LoadFromFile(const FileName: string);
 | 
						|
    procedure SetSize(NewSize: Longint); override;
 | 
						|
    function Write(const Buffer; Count: Longint): Longint; override;
 | 
						|
  end;
 | 
						|
 | 
						|
 | 
						|
implementation
 | 
						|
 | 
						|
  Type
 | 
						|
    PByte = ^Byte;
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                                   TCStream
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
  function TCStream.GetPosition: Longint;
 | 
						|
 | 
						|
    begin
 | 
						|
       Result:=Seek(0,soFromCurrent);
 | 
						|
    end;
 | 
						|
 | 
						|
  procedure TCStream.SetPosition(Pos: Longint);
 | 
						|
 | 
						|
    begin
 | 
						|
       Seek(pos,soFromBeginning);
 | 
						|
    end;
 | 
						|
 | 
						|
  function TCStream.GetSize: Longint;
 | 
						|
 | 
						|
    var
 | 
						|
       p : longint;
 | 
						|
 | 
						|
    begin
 | 
						|
       p:=GetPosition;
 | 
						|
       GetSize:=Seek(0,soFromEnd);
 | 
						|
       Seek(p,soFromBeginning);
 | 
						|
    end;
 | 
						|
 | 
						|
  procedure TCStream.SetSize(NewSize: Longint);
 | 
						|
 | 
						|
    begin
 | 
						|
    // We do nothing. Pipe streams don't support this
 | 
						|
    // As well as possible read-ony streams !!
 | 
						|
    end;
 | 
						|
 | 
						|
  procedure TCStream.ReadBuffer(var Buffer; Count: Longint);
 | 
						|
 | 
						|
    begin
 | 
						|
       CStreamError:=0;
 | 
						|
       if Read(Buffer,Count)<Count then
 | 
						|
         CStreamError:=102;
 | 
						|
    end;
 | 
						|
 | 
						|
  procedure TCStream.WriteBuffer(const Buffer; Count: Longint);
 | 
						|
 | 
						|
    begin
 | 
						|
       CStreamError:=0;
 | 
						|
       if Write(Buffer,Count)<Count then
 | 
						|
         CStreamError:=103;
 | 
						|
    end;
 | 
						|
 | 
						|
  function TCStream.CopyFrom(Source: TCStream; Count: Longint): Longint;
 | 
						|
 | 
						|
    var
 | 
						|
       i : longint;
 | 
						|
       buffer : array[0..1023] of byte;
 | 
						|
 | 
						|
    begin
 | 
						|
       CStreamError:=0;
 | 
						|
       Result:=0;
 | 
						|
       while Count>0 do
 | 
						|
         begin
 | 
						|
            if (Count>sizeof(buffer)) then
 | 
						|
              i:=sizeof(Buffer)
 | 
						|
            else
 | 
						|
              i:=Count;
 | 
						|
            i:=Source.Read(buffer,i);
 | 
						|
            i:=Write(buffer,i);
 | 
						|
            dec(count,i);
 | 
						|
            inc(Result,i);
 | 
						|
            if i=0 then
 | 
						|
              exit;
 | 
						|
         end;
 | 
						|
    end;
 | 
						|
 | 
						|
  function TCStream.ReadComponent(Instance: TCComponent): TCComponent;
 | 
						|
    begin
 | 
						|
      Result:=nil;
 | 
						|
    end;
 | 
						|
 | 
						|
  function TCStream.ReadComponentRes(Instance: TCComponent): TCComponent;
 | 
						|
    begin
 | 
						|
      Result:=nil;
 | 
						|
    end;
 | 
						|
 | 
						|
  procedure TCStream.WriteComponent(Instance: TCComponent);
 | 
						|
    begin
 | 
						|
    end;
 | 
						|
 | 
						|
  procedure TCStream.WriteComponentRes(const ResName: string; Instance: TCComponent);
 | 
						|
    begin
 | 
						|
    end;
 | 
						|
 | 
						|
  procedure TCStream.WriteDescendent(Instance, Ancestor: TCComponent);
 | 
						|
    begin
 | 
						|
    end;
 | 
						|
 | 
						|
  procedure TCStream.WriteDescendentRes(const ResName: string; Instance, Ancestor: TCComponent);
 | 
						|
    begin
 | 
						|
    end;
 | 
						|
 | 
						|
  procedure TCStream.WriteResourceHeader(const ResName: string; {!!!: out} var FixupInfo: Integer);
 | 
						|
    begin
 | 
						|
    end;
 | 
						|
 | 
						|
  procedure TCStream.FixupResourceHeader(FixupInfo: Integer);
 | 
						|
    begin
 | 
						|
    end;
 | 
						|
 | 
						|
  procedure TCStream.ReadResHeader;
 | 
						|
    begin
 | 
						|
    end;
 | 
						|
 | 
						|
  function TCStream.ReadByte : Byte;
 | 
						|
 | 
						|
    var
 | 
						|
       b : Byte;
 | 
						|
 | 
						|
    begin
 | 
						|
       ReadBuffer(b,1);
 | 
						|
       ReadByte:=b;
 | 
						|
    end;
 | 
						|
 | 
						|
  function TCStream.ReadWord : Word;
 | 
						|
 | 
						|
    var
 | 
						|
       w : Word;
 | 
						|
 | 
						|
    begin
 | 
						|
       ReadBuffer(w,2);
 | 
						|
       ReadWord:=w;
 | 
						|
    end;
 | 
						|
 | 
						|
  function TCStream.ReadDWord : Cardinal;
 | 
						|
 | 
						|
    var
 | 
						|
       d : Cardinal;
 | 
						|
 | 
						|
    begin
 | 
						|
       ReadBuffer(d,4);
 | 
						|
       ReadDWord:=d;
 | 
						|
    end;
 | 
						|
 | 
						|
  Function TCStream.ReadAnsiString : AnsiString;
 | 
						|
  Var
 | 
						|
    TheSize : Longint;
 | 
						|
    P : PByte ;
 | 
						|
  begin
 | 
						|
    ReadBuffer (TheSize,SizeOf(TheSize));
 | 
						|
    SetLength(Result,TheSize);
 | 
						|
    // Illegal typecast if no AnsiStrings defined.
 | 
						|
    if TheSize>0 then
 | 
						|
     begin
 | 
						|
       ReadBuffer (Pointer(Result)^,TheSize);
 | 
						|
       P:=PByte(PtrInt(Result)+TheSize);
 | 
						|
       p^:=0;
 | 
						|
     end;
 | 
						|
   end;
 | 
						|
 | 
						|
  Procedure TCStream.WriteAnsiString (S : AnsiString);
 | 
						|
 | 
						|
  Var L : Longint;
 | 
						|
 | 
						|
  begin
 | 
						|
    L:=Length(S);
 | 
						|
    WriteBuffer (L,SizeOf(L));
 | 
						|
    WriteBuffer (Pointer(S)^,L);
 | 
						|
  end;
 | 
						|
 | 
						|
  procedure TCStream.WriteByte(b : Byte);
 | 
						|
 | 
						|
    begin
 | 
						|
       WriteBuffer(b,1);
 | 
						|
    end;
 | 
						|
 | 
						|
  procedure TCStream.WriteWord(w : Word);
 | 
						|
 | 
						|
    begin
 | 
						|
       WriteBuffer(w,2);
 | 
						|
    end;
 | 
						|
 | 
						|
  procedure TCStream.WriteDWord(d : Cardinal);
 | 
						|
 | 
						|
    begin
 | 
						|
       WriteBuffer(d,4);
 | 
						|
    end;
 | 
						|
 | 
						|
 | 
						|
{****************************************************************************}
 | 
						|
{*                             TCFileStream                                  *}
 | 
						|
{****************************************************************************}
 | 
						|
 | 
						|
constructor TCFileStream.Create(const AFileName: string; Mode: Word);
 | 
						|
var
 | 
						|
  oldfilemode : byte;
 | 
						|
begin
 | 
						|
  FFileName:=AFileName;
 | 
						|
  If Mode=fmcreate then
 | 
						|
    begin
 | 
						|
      system.assign(FHandle,AFileName);
 | 
						|
      {$push} {$I-}
 | 
						|
       system.rewrite(FHandle,1);
 | 
						|
      {$pop}
 | 
						|
      CStreamError:=IOResult;
 | 
						|
    end
 | 
						|
  else
 | 
						|
    begin
 | 
						|
      oldfilemode:=filemode;
 | 
						|
      filemode:=$40 or Mode;
 | 
						|
      system.assign(FHandle,AFileName);
 | 
						|
      {$push} {$I-}
 | 
						|
       system.reset(FHandle,1);
 | 
						|
      {$pop}
 | 
						|
      CStreamError:=IOResult;
 | 
						|
      filemode:=oldfilemode;
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
destructor TCFileStream.Destroy;
 | 
						|
begin
 | 
						|
  {$push} {$I-}
 | 
						|
   System.Close(FHandle);
 | 
						|
  {$pop}
 | 
						|
  CStreamError:=IOResult;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function TCFileStream.Read(var Buffer; Count: Longint): Longint;
 | 
						|
begin
 | 
						|
  CStreamError:=0;
 | 
						|
  BlockRead(FHandle,Buffer,Count,Result);
 | 
						|
  If Result=-1 then Result:=0;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function TCFileStream.Write(const Buffer; Count: Longint): Longint;
 | 
						|
begin
 | 
						|
  CStreamError:=0;
 | 
						|
  BlockWrite (FHandle,(@Buffer)^,Count,Result);
 | 
						|
  If Result=-1 then Result:=0;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
Procedure TCFileStream.SetSize(NewSize: Longint);
 | 
						|
begin
 | 
						|
  {$push} {$I-}
 | 
						|
   System.Seek(FHandle,NewSize);
 | 
						|
   System.Truncate(FHandle);
 | 
						|
  {$pop}
 | 
						|
  CStreamError:=IOResult;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function TCFileStream.Seek(Offset: Longint; Origin: Word): Longint;
 | 
						|
var
 | 
						|
  l : longint;
 | 
						|
begin
 | 
						|
  {$push} {$I-}
 | 
						|
   case Origin of
 | 
						|
     soFromBeginning :
 | 
						|
       begin
 | 
						|
         System.Seek(FHandle,Offset);
 | 
						|
         l:=Offset;
 | 
						|
       end;
 | 
						|
     soFromCurrent :
 | 
						|
       begin
 | 
						|
         l:=System.FilePos(FHandle);
 | 
						|
         inc(l,Offset);
 | 
						|
         System.Seek(FHandle,l);
 | 
						|
       end;
 | 
						|
     soFromEnd :
 | 
						|
       begin
 | 
						|
         l:=System.FileSize(FHandle);
 | 
						|
         dec(l,Offset);
 | 
						|
         if l<0 then
 | 
						|
          l:=0;
 | 
						|
         System.Seek(FHandle,l);
 | 
						|
       end;
 | 
						|
     else
 | 
						|
       begin
 | 
						|
         CStreamError:=103;
 | 
						|
         l:=Offset;
 | 
						|
       end;
 | 
						|
   end;
 | 
						|
  {$pop}
 | 
						|
  CStreamError:=IOResult;
 | 
						|
  Result:=l;
 | 
						|
end;
 | 
						|
 | 
						|
function TCFileStream.EOF: boolean;
 | 
						|
begin
 | 
						|
  EOF:=system.eof(FHandle);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
{****************************************************************************}
 | 
						|
{*                             TCRangeStream                                *}
 | 
						|
{****************************************************************************}
 | 
						|
 | 
						|
 | 
						|
constructor TCRangeStream.Create(ABase: TCStream; AOffset, ASize: LongInt);
 | 
						|
begin
 | 
						|
  if not assigned(ABase) then
 | 
						|
    CStreamError:=155
 | 
						|
  else
 | 
						|
    { we allow to be positioned directly at the end for appending }
 | 
						|
    if (AOffset<0) or (AOffset>ABase.Size) then
 | 
						|
      CStreamError:=156
 | 
						|
    else
 | 
						|
      begin
 | 
						|
        FBase:=ABase;
 | 
						|
        FOffset:=AOffset;
 | 
						|
        if ASize<0 then
 | 
						|
          FSize:=maxLongint-FOffset
 | 
						|
        else
 | 
						|
          FSize:=ASize;
 | 
						|
        FMaxOffset:=FOffset+FSize-1;
 | 
						|
      end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function TCRangeStream.Read(var Buffer; Count: LongInt): LongInt;
 | 
						|
begin
 | 
						|
  Count:=Min(Count,FMaxOffset-FPosition+1);
 | 
						|
  if Count>0 then
 | 
						|
    begin
 | 
						|
      FBase.Seek(FOffset+FPosition,soFromBeginning);
 | 
						|
      result:=FBase.Read(Buffer,Count);
 | 
						|
    end
 | 
						|
  else
 | 
						|
    result:=0;
 | 
						|
  FPosition:=FPosition+result;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function TCRangeStream.Write(const Buffer; Count: LongInt): LongInt;
 | 
						|
begin
 | 
						|
  Count:=Min(Count,FMaxOffset-FPosition+1);
 | 
						|
  if Count>0 then
 | 
						|
    begin
 | 
						|
      FBase.Seek(FOffset+FPosition,soFromBeginning);
 | 
						|
      result:=FBase.Write(Buffer,Count);
 | 
						|
    end
 | 
						|
  else
 | 
						|
    result:=0;
 | 
						|
  FPosition:=FPosition+result;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function TCRangeStream.Seek(Offset: LongInt; Origin: Word): LongInt;
 | 
						|
begin
 | 
						|
  case Origin of
 | 
						|
    soFromBeginning:
 | 
						|
      begin
 | 
						|
        if Offset>FMaxOffset then
 | 
						|
          CStreamError:=156
 | 
						|
        else
 | 
						|
          FPosition:=FBase.Seek(FOffset+Offset,soFromBeginning)-FOffset;
 | 
						|
      end;
 | 
						|
    soFromCurrent:
 | 
						|
      begin
 | 
						|
        if Offset>FMaxOffset then
 | 
						|
          CStreamError:=156
 | 
						|
        else
 | 
						|
          FPosition:=FBase.Seek(FOffset+FPosition+Offset,soFromBeginning)-FOffset;
 | 
						|
      end;
 | 
						|
    soFromEnd:
 | 
						|
      begin
 | 
						|
        if Offset>FSize-1 then
 | 
						|
          CStreamError:=156
 | 
						|
        else
 | 
						|
          FPosition:=FBase.Seek(FMaxOffset-Offset,soFromBeginning)-FOffset;
 | 
						|
      end;
 | 
						|
    else
 | 
						|
      begin
 | 
						|
        CStreamError:=156;
 | 
						|
      end;
 | 
						|
  end;
 | 
						|
  Result:=FPosition;
 | 
						|
end;
 | 
						|
 | 
						|
{****************************************************************************}
 | 
						|
{*                             TCustomMemoryStream                          *}
 | 
						|
{****************************************************************************}
 | 
						|
 | 
						|
procedure TCCustomMemoryStream.SetPointer(Ptr: Pointer; ASize: Longint);
 | 
						|
 | 
						|
begin
 | 
						|
  FMemory:=Ptr;
 | 
						|
  FSize:=ASize;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function TCCustomMemoryStream.Read(var Buffer; Count: Longint): Longint;
 | 
						|
 | 
						|
begin
 | 
						|
  Result:=0;
 | 
						|
  If (FSize>0) and (FPosition<Fsize) then
 | 
						|
    begin
 | 
						|
    Result:=FSize-FPosition;
 | 
						|
    If Result>Count then Result:=Count;
 | 
						|
    Move (Pointer(PtrUInt(FMemory)+PtrUInt(FPosition))^,Buffer,Result);
 | 
						|
    FPosition:=Fposition+Result;
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function TCCustomMemoryStream.Seek(Offset: Longint; Origin: Word): Longint;
 | 
						|
 | 
						|
begin
 | 
						|
  Case Origin of
 | 
						|
    soFromBeginning : FPosition:=Offset;
 | 
						|
    soFromEnd       : FPosition:=FSize+Offset;
 | 
						|
    soFromCurrent   : FpoSition:=FPosition+Offset;
 | 
						|
  end;
 | 
						|
  Result:=FPosition;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure TCCustomMemoryStream.SaveToStream(Stream: TCStream);
 | 
						|
 | 
						|
begin
 | 
						|
  if FSize>0 then Stream.WriteBuffer (FMemory^,FSize);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure TCCustomMemoryStream.SaveToFile(const FileName: string);
 | 
						|
 | 
						|
Var S : TCCustomFileStream;
 | 
						|
 | 
						|
begin
 | 
						|
  Try
 | 
						|
    S:=CFileStreamClass.Create (FileName,fmCreate);
 | 
						|
    SaveToStream(S);
 | 
						|
  finally
 | 
						|
    S.free;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
{****************************************************************************}
 | 
						|
{*                             TCMemoryStream                                *}
 | 
						|
{****************************************************************************}
 | 
						|
 | 
						|
 | 
						|
Const TMSGrow = 4096; { Use 4k blocks. }
 | 
						|
 | 
						|
procedure TCMemoryStream.SetCapacity(NewCapacity: Longint);
 | 
						|
 | 
						|
begin
 | 
						|
  SetPointer (Realloc(NewCapacity),Fsize);
 | 
						|
  FCapacity:=NewCapacity;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function TCMemoryStream.Realloc(var NewCapacity: Longint): Pointer;
 | 
						|
 | 
						|
Var MoveSize : Longint;
 | 
						|
 | 
						|
begin
 | 
						|
  CStreamError:=0;
 | 
						|
  If NewCapacity>0 Then // round off to block size.
 | 
						|
    NewCapacity := (NewCapacity + (TMSGrow-1)) and not (TMSGROW-1);
 | 
						|
  // Only now check !
 | 
						|
  If NewCapacity=FCapacity then
 | 
						|
    Result:=FMemory
 | 
						|
  else
 | 
						|
    If NewCapacity=0 then
 | 
						|
      begin
 | 
						|
        FreeMem (FMemory,Fcapacity);
 | 
						|
        Result:=nil;
 | 
						|
      end
 | 
						|
    else
 | 
						|
      begin
 | 
						|
      GetMem (Result,NewCapacity);
 | 
						|
      If Result=Nil then
 | 
						|
        CStreamError:=204;
 | 
						|
      If FCapacity>0 then
 | 
						|
        begin
 | 
						|
        MoveSize:=FSize;
 | 
						|
        If MoveSize>NewCapacity then MoveSize:=NewCapacity;
 | 
						|
        Move (Fmemory^,Result^,MoveSize);
 | 
						|
        FreeMem (FMemory,FCapacity);
 | 
						|
        end;
 | 
						|
      end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
destructor TCMemoryStream.Destroy;
 | 
						|
 | 
						|
begin
 | 
						|
  Clear;
 | 
						|
  Inherited Destroy;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure TCMemoryStream.Clear;
 | 
						|
 | 
						|
begin
 | 
						|
  FSize:=0;
 | 
						|
  FPosition:=0;
 | 
						|
  SetCapacity (0);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure TCMemoryStream.LoadFromStream(Stream: TCStream);
 | 
						|
 | 
						|
begin
 | 
						|
  Stream.Position:=0;
 | 
						|
  SetSize(Stream.Size);
 | 
						|
  If FSize>0 then Stream.ReadBuffer(FMemory^,FSize);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure TCMemoryStream.LoadFromFile(const FileName: string);
 | 
						|
 | 
						|
Var S : TCCustomFileStream;
 | 
						|
 | 
						|
begin
 | 
						|
  Try
 | 
						|
    S:=CFileStreamClass.Create (FileName,fmOpenRead);
 | 
						|
    LoadFromStream(S);
 | 
						|
  finally
 | 
						|
    S.free;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure TCMemoryStream.SetSize(NewSize: Longint);
 | 
						|
 | 
						|
begin
 | 
						|
  SetCapacity (NewSize);
 | 
						|
  FSize:=NewSize;
 | 
						|
  IF FPosition>FSize then
 | 
						|
    FPosition:=FSize;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function TCMemoryStream.Write(const Buffer; Count: Longint): Longint;
 | 
						|
 | 
						|
Var NewPos : Longint;
 | 
						|
 | 
						|
begin
 | 
						|
  If Count=0 then
 | 
						|
   begin
 | 
						|
     Result:=0;
 | 
						|
     exit;
 | 
						|
   end;
 | 
						|
  NewPos:=FPosition+Count;
 | 
						|
  If NewPos>Fsize then
 | 
						|
    begin
 | 
						|
    IF NewPos>FCapacity then
 | 
						|
      SetCapacity (NewPos);
 | 
						|
    FSize:=Newpos;
 | 
						|
    end;
 | 
						|
  System.Move (Buffer,Pointer(Ptruint(FMemory)+PtrUInt(FPosition))^,Count);
 | 
						|
  FPosition:=NewPos;
 | 
						|
  Result:=Count;
 | 
						|
end;
 | 
						|
 | 
						|
end.
 |