mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-31 16:31:36 +01:00 
			
		
		
		
	 1945bf64b4
			
		
	
	
		1945bf64b4
		
	
	
	
	
		
			
			+ 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.
 |