Browse Source

--- Merging r30623 into '.':
U packages/fcl-base/src/inifiles.pp
--- Recording mergeinfo for merge of r30623 into '.':
U .
--- Merging r31022 into '.':
U packages/fcl-base/src/streamex.pp
U rtl/objpas/rtlconst.inc
--- Recording mergeinfo for merge of r31022 into '.':
G .

# revisions: 30623,31022

git-svn-id: branches/fixes_3_0@31123 -

marco 10 years ago
parent
commit
9f2dca7fc2
3 changed files with 328 additions and 4 deletions
  1. 6 3
      packages/fcl-base/src/inifiles.pp
  2. 321 1
      packages/fcl-base/src/streamex.pp
  3. 1 0
      rtl/objpas/rtlconst.inc

+ 6 - 3
packages/fcl-base/src/inifiles.pp

@@ -194,8 +194,8 @@ type
     procedure MaybeUpdateFile;
     property Dirty : Boolean Read FDirty;
   public
-    constructor Create(const AFileName: string; AEscapeLineFeeds : Boolean = False); override;
-    constructor Create(AStream: TStream; AEscapeLineFeeds : Boolean = False);
+    constructor Create(const AFileName: string; AEscapeLineFeeds : Boolean = False); overload; override;
+    constructor Create(AStream: TStream; AEscapeLineFeeds : Boolean = False); overload;
     destructor Destroy; override;
     function ReadString(const Section, Ident, Default: string): string; override;
     procedure WriteString(const Section, Ident, Value: String); override;
@@ -212,7 +212,7 @@ type
 
   TMemIniFile = class(TIniFile)
   public
-    constructor Create(const AFileName: string; AEscapeLineFeeds : Boolean = False); override;
+    constructor Create(const AFileName: string; AEscapeLineFeeds : Boolean = False); overload; override;
     procedure Clear;
     procedure GetStrings(List: TStrings);
     procedure Rename(const AFileName: string; Reload: Boolean);
@@ -1056,7 +1056,10 @@ begin
       slLines.SaveToFile(FFileName);
       end
     else if FStream <> nil then
+      begin
+      Fstream.Size:=0;
       slLines.SaveToStream(FStream);
+      end;
     FillSectionList(slLines);
     FDirty := false;
   finally

+ 321 - 1
packages/fcl-base/src/streamex.pp

@@ -1,10 +1,35 @@
+{
+    This file is part of the Free Component Library.
+
+    Copyright (c) 2015 by:
+
+      . Michael Van Canneyt [email protected]
+      . Silvio Clecio github.com/silvioprog
+
+    Text reader classes.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    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.
+
+ **********************************************************************}
+
 {$mode objfpc}
 {$h+}
 unit streamex;
 
 Interface
 
-uses Classes;
+uses
+  Classes, SysUtils, RtlConsts;
+
+const
+  MIN_BUFFER_SIZE = 128;
+  BUFFER_SIZE = 4096;
+  FILE_RIGHTS = 438;
 
 type
 
@@ -58,6 +83,78 @@ type
       property Position: LongInt read GetPosition write SetPosition;
    end;
 
+   { TTextReader }
+
+   TTextReader = class(TObject)
+   public
+     constructor Create; virtual;
+     procedure Reset; virtual; abstract;
+     procedure Close; virtual; abstract;
+     function IsEof: Boolean; virtual; abstract;
+     procedure ReadLine(out AString: string); virtual; abstract; overload;
+     function ReadLine: string; virtual; abstract; overload;
+     property Eof: Boolean read IsEof;
+   end;
+
+   { TStreamReader }
+
+   TStreamReader = class(TTextReader)
+   private
+     FBufferRead: Integer;
+     FBufferPosition: Integer;
+     FOwnsStream: Boolean;
+     FStream: TStream;
+     FBuffer: array of Byte;
+     procedure FillBuffer;
+   public
+     constructor Create(AStream: TStream; ABufferSize: Integer;
+       AOwnsStream: Boolean); virtual;
+     constructor Create(AStream: TStream); virtual;
+     destructor Destroy; override;
+     procedure Reset; override;
+     procedure Close; override;
+     function IsEof: Boolean; override;
+     procedure ReadLine(out AString: string); override; overload;
+     function ReadLine: string; override; overload;
+     property BaseStream: TStream read FStream;
+     property OwnsStream: Boolean read FOwnsStream write FOwnsStream;
+   end;
+
+   { TStringReader }
+
+   TStringReader = class(TTextReader)
+   private
+     FReader: TTextReader;
+   public
+     constructor Create(const AString: string; ABufferSize: Integer); virtual;
+     constructor Create(const AString: string); virtual;
+     destructor Destroy; override;
+     procedure Reset; override;
+     procedure Close; override;
+     function IsEof: Boolean; override;
+     procedure ReadLine(out AString: string); override; overload;
+     function ReadLine: string; override; overload;
+   end;
+
+   { TFileReader }
+
+   TFileReader = class(TTextReader)
+   private
+     FReader: TTextReader;
+   public
+     constructor Create(const AFileName: TFileName; AMode: Word;
+       ARights: Cardinal; ABufferSize: Integer); virtual;
+     constructor Create(const AFileName: TFileName; AMode: Word;
+       ABufferSize: Integer); virtual;
+     constructor Create(const AFileName: TFileName; ABufferSize: Integer); virtual;
+     constructor Create(const AFileName: TFileName); virtual;
+     destructor Destroy; override;
+     procedure Reset; override;
+     procedure Close; override;
+     function IsEof: Boolean; override;
+     procedure ReadLine(out AString: string); override; overload;
+     function ReadLine: string; override; overload;
+   end;
 
   TStreamHelper = class helper for TStream
                      function  ReadWordLE :word;
@@ -192,7 +289,230 @@ begin
    GetDriver.WriteValue(Value);
 end;
 
+{ TTextReader }
+
+constructor TTextReader.Create;
+begin
+  inherited Create;
+end;
+
+{ TStreamReader }
+
+constructor TStreamReader.Create(AStream: TStream; ABufferSize: Integer;
+  AOwnsStream: Boolean);
+begin
+  inherited Create;
+  if not Assigned(AStream) then
+    raise EArgumentException.CreateFmt(SParamIsNil, ['AStream']);
+  FStream := AStream;
+  FOwnsStream := AOwnsStream;
+  if ABufferSize >= MIN_BUFFER_SIZE then
+    SetLength(FBuffer, ABufferSize)
+  else
+    SetLength(FBuffer, MIN_BUFFER_SIZE);
+end;
+
+constructor TStreamReader.Create(AStream: TStream);
+begin
+  Create(AStream, BUFFER_SIZE, False);
+end;
+
+destructor TStreamReader.Destroy;
+begin
+  Close;
+  inherited Destroy;
+end;
+
+procedure TStreamReader.FillBuffer;
+begin
+  FBufferRead := FStream.Read(FBuffer[0], Pred(Length(FBuffer)));
+  FBuffer[FBufferRead] := 0;
+  FBufferPosition := 0;
+end;
+
+procedure TStreamReader.Reset;
+begin
+  FBufferRead := 0;
+  FBufferPosition := 0;
+  if Assigned(FStream) then
+    FStream.Seek(0, 0);
+end;
+
+procedure TStreamReader.Close;
+begin
+  if FOwnsStream then
+  begin
+    FStream.Free;
+    FStream := nil;
+  end;
+end;
+
+function TStreamReader.IsEof: Boolean;
+begin
+  if not Assigned(FStream) then
+    Exit(True);
+  Result := FBufferPosition >= FBufferRead;
+  if Result then
+  begin
+    FillBuffer;
+    Result := FBufferRead = 0;
+  end;
+end;
+
+procedure TStreamReader.ReadLine(out AString: string);
+var
+  VPByte: PByte;
+  VPosition, VStrLength, VLength: Integer;
+begin
+  VPosition := FBufferPosition;
+  SetLength(AString, 0);
+  repeat
+    VPByte := @FBuffer[FBufferPosition];
+    while (FBufferPosition < FBufferRead) and not (VPByte^ in [10, 13]) do
+    begin
+      Inc(VPByte);
+      Inc(FBufferPosition);
+    end;
+    if FBufferPosition = FBufferRead then
+    begin
+      VLength := FBufferPosition - VPosition;
+      if VLength > 0 then
+      begin
+        VStrLength := Length(AString);
+        SetLength(AString, VStrLength + VLength);
+        Move(FBuffer[VPosition], AString[Succ(VStrLength)], VLength);
+      end;
+      FillBuffer;
+      VPosition := FBufferPosition;
+    end;
+  until (FBufferPosition = FBufferRead) or (VPByte^ in [10, 13]);
+  VLength := FBufferPosition - VPosition;
+  if VLength > 0 then
+  begin
+    VStrLength := Length(AString);
+    SetLength(AString, VStrLength + VLength);
+    Move(FBuffer[VPosition], AString[Succ(VStrLength)], VLength);
+  end;
+  if (VPByte^ in [10, 13]) and (FBufferPosition < FBufferRead) then
+  begin
+    Inc(FBufferPosition);
+    if VPByte^ = 13 then
+    begin
+      if FBufferPosition = FBufferRead then
+        FillBuffer;
+      if (FBufferPosition < FBufferRead) and (FBuffer[FBufferPosition] = 10) then
+        Inc(FBufferPosition);
+    end;
+  end;
+end;
+
+function TStreamReader.ReadLine: string;
+begin
+  ReadLine(Result);
+end;
+
+{ TStringReader }
+
+constructor TStringReader.Create(const AString: string; ABufferSize: Integer);
+begin
+  inherited Create;
+  FReader := TStreamReader.Create(TStringStream.Create(AString), ABufferSize, True);
+end;
+
+constructor TStringReader.Create(const AString: string);
+begin
+  Create(AString, BUFFER_SIZE);
+end;
+
+destructor TStringReader.Destroy;
+begin
+  FReader.Free;
+  inherited Destroy;
+end;
+
+procedure TStringReader.Reset;
+begin
+  FReader.Reset;
+end;
+
+procedure TStringReader.Close;
+begin
+  FReader.Close;
+end;
+
+function TStringReader.IsEof: Boolean;
+begin
+  Result := FReader.IsEof;
+end;
+
+procedure TStringReader.ReadLine(out AString: string);
+begin
+  FReader.ReadLine(AString);
+end;
+
+function TStringReader.ReadLine: string;
+begin
+  ReadLine(Result);
+end;
+
+{ TFileReader }
+
+constructor TFileReader.Create(const AFileName: TFileName; AMode: Word;
+  ARights: Cardinal; ABufferSize: Integer);
+begin
+  inherited Create;
+  FReader := TStreamReader.Create(TFileStream.Create(AFileName, AMode, ARights),
+    ABufferSize, True);
+end;
+
+constructor TFileReader.Create(const AFileName: TFileName; AMode: Word;
+  ABufferSize: Integer);
+begin
+  Create(AFileName, AMode, FILE_RIGHTS, ABufferSize);
+end;
+
+constructor TFileReader.Create(const AFileName: TFileName; ABufferSize: Integer);
+begin
+  Create(AFileName, fmOpenRead or fmShareDenyWrite, ABufferSize);
+end;
+
+constructor TFileReader.Create(const AFileName: TFileName);
+begin
+  Create(AFileName, BUFFER_SIZE);
+end;
+
+destructor TFileReader.Destroy;
+begin
+  FReader.Free;
+  inherited Destroy;
+end;
+
+procedure TFileReader.Reset;
+begin
+  FReader.Reset;
+end;
+
+procedure TFileReader.Close;
+begin
+  FReader.Close;
+end;
+
+function TFileReader.IsEof: Boolean;
+begin
+  Result := FReader.IsEof;
+end;
+
+procedure TFileReader.ReadLine(out AString: string);
+begin
+  FReader.ReadLine(AString);
+end;
+
+function TFileReader.ReadLine: string;
+begin
+  ReadLine(Result);
+end;
 
+{ TStreamHelper }
 
 function TStreamHelper.readwordLE:word;
 begin

+ 1 - 0
rtl/objpas/rtlconst.inc

@@ -139,6 +139,7 @@ ResourceString
   SImageReadFail                = 'The ImageList data could not be read from stream';
   SImageWriteFail               = 'The ImageList data could not be written to stream';
   SIndexOutOfRange              = 'Grid index out of range';
+  SParamIsNil                   = 'Parameter %s cannot be nil';
   SIniFileWriteError            = 'Unable to write to "%s"';
   SInsertLineError              = 'Line could not be inserted';
   SInvalidActionCreation        = 'Invalid action creation';