|
@@ -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
|