summaryrefslogtreecommitdiff
path: root/compiler/cstreams.pas
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/cstreams.pas')
-rw-r--r--compiler/cstreams.pas613
1 files changed, 613 insertions, 0 deletions
diff --git a/compiler/cstreams.pas b/compiler/cstreams.pas
new file mode 100644
index 0000000000..2595fcb755
--- /dev/null
+++ b/compiler/cstreams.pas
@@ -0,0 +1,613 @@
+{
+ 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;
+
+{ TFileStream class }
+
+ TCFileStream = class(TCStream)
+ Private
+ FFileName : String;
+ FHandle: File;
+ protected
+ procedure SetSize(NewSize: Longint); override;
+ public
+ constructor Create(const AFileName: string; Mode: Word);
+ 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;
+ property FileName : String Read FFilename;
+ 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 wel 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);
+begin
+ FFileName:=AFileName;
+ If Mode=fmcreate then
+ begin
+ system.assign(FHandle,AFileName);
+ {$I-}
+ system.rewrite(FHandle,1);
+ {$I+}
+ CStreamError:=IOResult;
+ end
+ else
+ begin
+ system.assign(FHandle,AFileName);
+ {$I-}
+ system.reset(FHandle,1);
+ {$I+}
+ CStreamError:=IOResult;
+ end;
+end;
+
+
+destructor TCFileStream.Destroy;
+begin
+ {$I-}
+ System.Close(FHandle);
+ {$I+}
+ 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
+ {$I-}
+ System.Seek(FHandle,NewSize);
+ System.Truncate(FHandle);
+ {$I+}
+ CStreamError:=IOResult;
+end;
+
+
+function TCFileStream.Seek(Offset: Longint; Origin: Word): Longint;
+var
+ l : longint;
+begin
+ {$I-}
+ case Origin of
+ soFromBeginning :
+ System.Seek(FHandle,Offset);
+ 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;
+ end;
+ {$I+}
+ CStreamError:=IOResult;
+ Result:=CStreamError;
+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(PtrInt(FMemory)+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 : TCFileStream;
+
+begin
+ Try
+ S:=TCFileStream.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
+ FreeMem (FMemory,Fcapacity)
+ 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 : TCFileStream;
+
+begin
+ Try
+ S:=TCFileStream.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(Ptrint(FMemory)+FPosition)^,Count);
+ FPosition:=NewPos;
+ Result:=Count;
+end;
+
+end.