home *** CD-ROM | disk | FTP | other *** search
- {$INCLUDE ..\cDefines.inc}
- unit cReaders;
-
- { }
- { Readers v3.06 }
- { }
- { This unit is copyright ⌐ 1999-2002 by David Butler (david@e.co.za) }
- { }
- { This unit is part of Delphi Fundamentals. }
- { Its original file name is cReaders.pas }
- { The latest version is available from the Fundamentals home page }
- { http://fundementals.sourceforge.net/ }
- { }
- { I invite you to use this unit, free of charge. }
- { I invite you to distibute this unit, but it must be for free. }
- { I also invite you to contribute to its development, }
- { but do not distribute a modified copy of this file. }
- { }
- { A forum is available on SourceForge for general discussion }
- { http://sourceforge.net/forum/forum.php?forum_id=2117 }
- { }
- { }
- { Revision history: }
- { [ cStreams ] }
- { 01/03/1999 0.01 Initial version of TextParser }
- { 26/06/1999 1.02 Moved AStream from cDataStruct unit to cStreams. }
- { [ cReaders ] }
- { 03/05/2002 3.03 Created cReaders unit from cStreams. }
- { AReader, TMemoryReader, TStringReader, TFileReader. }
- { 13/05/2002 3.04 Added TBufferedReader, TSplitBufferReader and }
- { TTextReader. }
- { 13/07/2002 3.05 Moved TTextReader functionality to AReaderEx. }
- { 23/08/2002 3.06 Added SelfTest procedure. }
- { }
-
- interface
-
- uses
- // Delphi
- SysUtils,
-
- // Fundamentals
- cUtils;
-
-
-
- { }
- { AReader }
- { Abstract base class for a Reader. }
- { }
- { Inherited classes must implement the abstract methods from AReader. }
- { Read returns the actual number of bytes copied to the buffer. }
- { }
- type
- AReader = class
- protected
- Function GetPosition : Int64; virtual; abstract;
- Procedure SetPosition (const Position : Int64); virtual; abstract;
- Function GetSize : Int64; virtual; abstract;
-
- public
- Function Read (var Buffer; const Size : Integer) : Integer; virtual; abstract;
-
- Property Position : Int64 read GetPosition write SetPosition;
- Property Size : Int64 read GetSize;
- Function EOF : Boolean; virtual; abstract;
- end;
- EReader = class (Exception);
-
-
-
- { }
- { AReaderEx }
- { Base class for Reader implementations. AReaderEx extends AReader with }
- { commonly used functions. }
- { }
- { All methods in AReaderEx is implemented using calls to the abstract }
- { methods in AReader. Reader implementations can override the virtual }
- { methods in AReaderEx with more efficient versions. }
- { }
- { Match functions return True when a match is found. Match leaves the }
- { reader's position unchanged except if a match is made and SkipOnMatch }
- { is True. }
- { }
- { Locate returns the offset (relative to the current position) of the }
- { first match in the stream. Locate preserves the reader's position. }
- { Locate returns -1 if a match was not made. }
- { }
- type
- AReaderEx = class (AReader)
- protected
- Procedure SkipLineTerminator;
-
- public
- Procedure RaiseReadError (const Msg : String = '');
-
- Procedure ReadBuffer (var Buffer; const Size : Integer);
- Function ReadStr (const Size : Integer) : String; virtual;
- Function GetAsString : String; virtual;
-
- Function ReadByte : Byte; virtual;
- Function ReadWord : Word;
- Function ReadLongWord : LongWord;
- Function ReadLongInt : LongInt;
- Function ReadInt64 : Int64;
-
- Function Peek (var Buffer; const Size : Integer) : Integer; virtual;
- Procedure PeekBuffer (var Buffer; const Size : Integer);
- Function PeekStr (const Size : Integer) : String; virtual;
-
- Function PeekByte : Byte; virtual;
- Function PeekWord : Word;
- Function PeekLongWord : LongWord;
- Function PeekLongInt : LongInt;
- Function PeekInt64 : Int64;
-
- Function Match (const Buffer; const Size : Integer;
- const CaseSensitive : Boolean = True) : Integer; virtual;
- Function MatchBuffer (const Buffer; const Size : Integer;
- const CaseSensitive : Boolean = True) : Boolean;
- Function MatchStr (const S : String; const CaseSensitive : Boolean = True) : Boolean; virtual;
-
- Function MatchChar (const Ch : Char; const MatchNonMatch : Boolean = False;
- const SkipOnMatch : Boolean = False) : Boolean; overload;
- Function MatchChar (const C : CharSet; var Ch : Char;
- const MatchNonMatch : Boolean = False; const SkipOnMatch : Boolean = False) : Boolean; overload;
-
- Procedure Skip (const Count : Integer = 1); virtual;
- Procedure SkipByte;
-
- Function SkipAll (const Ch : Char; const MatchNonMatch : Boolean = False;
- const MaxCount : Integer = -1) : Integer; overload;
- Function SkipAll (const C : CharSet; const MatchNonMatch : Boolean = False;
- const MaxCount : Integer = -1) : Integer; overload;
-
- Function Locate (const Ch : Char; const LocateNonMatch : Boolean = False;
- const MaxOffset : Integer = -1) : Integer; overload; virtual;
- Function Locate (const C : CharSet; const LocateNonMatch : Boolean = False;
- const MaxOffset : Integer = -1) : Integer; overload; virtual;
- Function LocateBuffer (const Buffer; const Size : Integer;
- const MaxOffset : Integer = -1; const CaseSensitive : Boolean = True) : Integer; virtual;
- Function LocateStr (const S : String; const MaxOffset : Integer = -1;
- const CaseSensitive : Boolean = True) : Integer; virtual;
-
- Function ExtractAll (const C : CharSet; const ExtractNonMatch : Boolean = False;
- const MaxCount : Integer = -1) : String;
-
- Function ExtractLine (const MaxLineLength : Integer = -1;
- const EOFIsEOL : Boolean = True) : String;
- Function SkipLine (const MaxLineLength : Integer = -1) : Boolean;
- end;
-
-
-
- { }
- { TMemoryReader }
- { Reader implementation for a memory block. }
- { }
- type
- TMemoryReader = class (AReaderEx)
- protected
- FData : Pointer;
- FSize : Integer;
- FPos : Integer;
-
- Function GetPosition : Int64; override;
- Procedure SetPosition (const Position : Int64); override;
- Function GetSize : Int64; override;
-
- public
- Constructor Create (const Data : Pointer; const Size : Integer);
-
- Property Data : Pointer read FData;
- Property Size : Integer read FSize;
-
- Function Read (var Buffer; const Size : Integer) : Integer; override;
- Function EOF : Boolean; override;
-
- Function ReadByte : Byte; override;
- Function PeekByte : Byte; override;
- Function Match (const Buffer; const Size : Integer;
- const CaseSensitive : Boolean = True) : Integer; override;
- end;
- EMemoryReader = class (EReader);
-
-
-
- { }
- { TStringReader }
- { Memory reader implementation for a reference counted string (long string). }
- { }
- type
- TStringReader = class (TMemoryReader)
- protected
- FDataString : String;
-
- public
- Constructor Create (const Data : String);
-
- Property DataString : String read FDataString;
-
- Function GetAsString : String; override;
- end;
-
-
-
- { }
- { TFileReader }
- { Reader implementation for a file. }
- { }
- type
- TFileReader = class (AReaderEx)
- protected
- FHandle : Integer;
- FHandleOwner : Boolean;
-
- Function GetPosition : Int64; override;
- Procedure SetPosition (const Position : Int64); override;
- Function GetSize : Int64; override;
-
- public
- Constructor Create (const FileName : String); overload;
- Constructor Create (const FileHandle : Integer; const HandleOwner : Boolean = False); overload;
- Destructor Destroy; override;
-
- Property Handle : Integer read FHandle;
- Property HandleOwner : Boolean read FHandleOwner;
-
- Function Read (var Buffer; const Size : Integer) : Integer; override;
- Function EOF : Boolean; override;
- end;
- EFileReader = class (EReader);
-
- Function ReadFileToStr (const FileName : String) : String;
-
-
-
- { }
- { AReaderProxy }
- { Base class for Reader Proxies. }
- { }
- type
- AReaderProxy = class (AReaderEx)
- protected
- FReader : AReaderEx;
- FReaderOwner : Boolean;
-
- Function GetPosition : Int64; override;
- Procedure SetPosition (const Position : Int64); override;
- Function GetSize : Int64; override;
-
- public
- Constructor Create (const Reader : AReaderEx; const ReaderOwner : Boolean = True);
- Destructor Destroy; override;
-
- Function Read (var Buffer; const Size : Integer) : Integer; override;
- Function EOF : Boolean; override;
-
- Property Reader : AReaderEx read FReader;
- Property ReaderOwner : Boolean read FReaderOwner write FReaderOwner;
- end;
-
-
-
- { }
- { TReaderProxy }
- { Reader Proxy implementation. }
- { }
- { Proxies a block of data from Reader from the Reader's current position. }
- { Size specifies the size of the data to be proxied, or if Size = -1, }
- { all data up to EOF is proxied. }
- { }
- type
- TReaderProxy = class (AReaderProxy)
- protected
- FOffset : Int64;
- FSize : Int64;
-
- Function GetPosition : Int64; override;
- Procedure SetPosition (const Position : Int64); override;
- Function GetSize : Int64; override;
-
- public
- Constructor Create (const Reader : AReaderEx; const ReaderOwner : Boolean = True;
- const Size : Int64 = -1);
-
- Function Read (var Buffer; const Size : Integer) : Integer; override;
- Function EOF : Boolean; override;
- end;
-
-
-
- { }
- { TBufferedReader }
- { ReaderProxy implementation for buffered reading. }
- { }
- type
- TBufferedReader = class (AReaderProxy)
- protected
- FBufferSize : Integer;
- FPos : Int64;
- FBuffer : Pointer;
- FBufUsed : Integer;
- FBufPos : Integer;
-
- Function GetPosition : Int64; override;
- Procedure SetPosition (const Position : Int64); override;
- Function GetSize : Int64; override;
-
- Function FillBuf : Boolean;
- Procedure BufferByte;
- Function PosBuf (const C : CharSet; const LocateNonMatch : Boolean;
- const MaxOffset : Integer) : Integer;
-
- public
- Constructor Create (const Reader : AReaderEx; const BufferSize : Integer = 128;
- const ReaderOwner : Boolean = True);
- Destructor Destroy; override;
-
- Function Read (var Buffer; const Size : Integer) : Integer; override;
- Function EOF : Boolean; override;
-
- Function ReadByte : Byte; override;
- Function PeekByte : Byte; override;
- Procedure Skip (const Count : Integer = 1); override;
-
- Function Locate (const C : CharSet; const LocateNonMatch : Boolean = False;
- const MaxOffset : Integer = -1) : Integer; override;
-
- Property BufferSize : Integer read FBufferSize;
- Procedure InvalidateBuffer;
- end;
-
-
-
- { }
- { TSplitBufferedReader }
- { ReaderProxy implementation for split buffered reading. }
- { }
- { One buffer is used for read-ahead buffering, the other for seek-back }
- { buffering. }
- { }
- type
- TSplitBufferedReader = class (AReaderProxy)
- protected
- FBufferSize : Integer;
-
- FPos : Int64;
- FBuffer : Array [0..1] of Pointer;
- FBufUsed : Array [0..1] of Integer;
- FBufNr : Integer;
- FBufPos : Integer;
-
- Function GetPosition : Int64; override;
- Procedure SetPosition (const Position : Int64); override;
- Function GetSize : Int64; override;
-
- Function BufferStart : Integer;
- Function BufferRemaining : Integer;
- Function MoveBuf (var Dest : PByte; var Remaining : Integer) : Boolean;
- Function FillBuf (var Dest : PByte; var Remaining : Integer) : Boolean;
-
- public
- Constructor Create (const Reader : AReaderEx; const BufferSize : Integer = 128;
- const ReaderOwner : Boolean = True);
- Destructor Destroy; override;
-
- Property BufferSize : Integer read FBufferSize;
-
- Function Read (var Buffer; const Size : Integer) : Integer; override;
- Function EOF : Boolean; override;
-
- Procedure InvalidateBuffer;
- end;
-
-
-
- { }
- { TBufferedFileReader }
- { TBufferedReader instance using a TFileReader. }
- { }
- type
- TBufferedFileReader = class (TBufferedReader)
- public
- Constructor Create (const FileName : String; const BufferSize : Integer = 512); overload;
- Constructor Create (const FileHandle : Integer; const HandleOwner : Boolean = False;
- const BufferSize : Integer = 512); overload;
- end;
-
-
-
- { }
- { TSplitBufferedFileReader }
- { TSplitBufferedReader instance using a TFileReader. }
- { }
- type
- TSplitBufferedFileReader = class (TSplitBufferedReader)
- public
- Constructor Create (const FileName : String; const BufferSize : Integer = 512);
- end;
-
-
-
- { }
- { Self-testing code }
- { }
- Procedure SelfTest;
-
-
-
- implementation
-
-
-
- { }
- { AReaderEx }
- { }
- const
- DefaultBufSize = 2048;
-
- Procedure AReaderEx.RaiseReadError (const Msg : String);
- var S : String;
- Begin
- if Msg = '' then
- S := 'Read error' else
- S := Msg;
- raise EReader.Create (S);
- End;
-
- Procedure AReaderEx.ReadBuffer (var Buffer; const Size : Integer);
- Begin
- if Size <= 0 then
- exit;
- if Read (Buffer, Size) <> Size then
- RaiseReadError;
- End;
-
- Function AReaderEx.ReadStr (const Size : Integer) : String;
- var L : Integer;
- Begin
- if Size <= 0 then
- begin
- Result := '';
- exit;
- end;
- SetLength (Result, Size);
- L := Read (Pointer (Result)^, Size);
- if L <= 0 then
- begin
- Result := '';
- exit;
- end;
- if L < Size then
- SetLength (Result, L);
- End;
-
- Function AReaderEx.GetAsString : String;
- var S : Int64;
- B : String;
- I : Integer;
- Begin
- SetPosition (0);
- S := GetSize;
- if S < 0 then
- begin
- Result := '';
- While not EOF do
- begin
- SetLength (B, DefaultBufSize);
- I := Read (Pointer (B)^, DefaultBufSize);
- if I > 0 then
- begin
- if I < DefaultBufSize then
- SetLength (B, I);
- Result := Result + B;
- end else
- if not EOF then
- RaiseReadError;
- end;
- end else
- Result := ReadStr (S);
- End;
-
- Function AReaderEx.ReadByte : Byte;
- Begin
- ReadBuffer (Result, Sizeof (Byte));
- End;
-
- Function AReaderEx.ReadWord : Word;
- Begin
- ReadBuffer (Result, Sizeof (Word));
- End;
-
- Function AReaderEx.ReadLongWord : LongWord;
- Begin
- ReadBuffer (Result, Sizeof (LongInt));
- End;
-
- Function AReaderEx.ReadLongInt : LongInt;
- Begin
- ReadBuffer (Result, Sizeof (LongInt));
- End;
-
- Function AReaderEx.ReadInt64 : Int64;
- Begin
- ReadBuffer (Result, Sizeof (Int64));
- End;
-
- Function AReaderEx.Peek (var Buffer; const Size : Integer) : Integer;
- var P : Int64;
- Begin
- P := GetPosition;
- Result := Read (Buffer, Size);
- if Result > 0 then
- SetPosition (P);
- End;
-
- Procedure AReaderEx.PeekBuffer (var Buffer; const Size : Integer);
- Begin
- if Size <= 0 then
- exit;
- if Peek (Buffer, Size) <> Size then
- RaiseReadError;
- End;
-
- Function AReaderEx.PeekStr (const Size : Integer) : String;
- var L : Integer;
- Begin
- if Size <= 0 then
- begin
- Result := '';
- exit;
- end;
- SetLength (Result, Size);
- L := Peek (Pointer (Result)^, Size);
- if L <= 0 then
- begin
- Result := '';
- exit;
- end;
- if L < Size then
- SetLength (Result, L);
- End;
-
- Function AReaderEx.PeekByte : Byte;
- Begin
- PeekBuffer (Result, Sizeof (Byte));
- End;
-
- Function AReaderEx.PeekWord : Word;
- Begin
- PeekBuffer (Result, Sizeof (Word));
- End;
-
- Function AReaderEx.PeekLongWord : LongWord;
- Begin
- PeekBuffer (Result, Sizeof (LongWord));
- End;
-
- Function AReaderEx.PeekLongInt : LongInt;
- Begin
- PeekBuffer (Result, Sizeof (LongInt));
- End;
-
- Function AReaderEx.PeekInt64 : Int64;
- Begin
- PeekBuffer (Result, Sizeof (Int64));
- End;
-
- Function AReaderEx.Match (const Buffer; const Size : Integer; const CaseSensitive : Boolean) : Integer;
- var B : Pointer;
- R : Boolean;
- Begin
- if Size <= 0 then
- begin
- Result := -1;
- exit;
- end;
- GetMem (B, Size);
- try
- Result := Peek (B^, Size);
- if Result <= 0 then
- exit;
- if CaseSensitive then
- R := CompareMem (Buffer, B^, Result) else
- R := CompareMemNoCase (Buffer, B^, Result);
- if not R then
- Result := -1;
- finally
- FreeMem (B);
- end;
- End;
-
- Function AReaderEx.MatchBuffer (const Buffer; const Size : Integer; const CaseSensitive : Boolean) : Boolean;
- var I : Integer;
- Begin
- I := Match (Buffer, Size, CaseSensitive);
- if I = -1 then
- begin
- Result := False;
- exit;
- end;
- if I < Size then
- RaiseReadError;
- Result := True;
- End;
-
- Function AReaderEx.MatchStr (const S : String; const CaseSensitive : Boolean) : Boolean;
- Begin
- Result := MatchBuffer (Pointer (S)^, Length (S), CaseSensitive);
- End;
-
- Function AReaderEx.MatchChar (const Ch : Char; const MatchNonMatch : Boolean; const SkipOnMatch : Boolean) : Boolean;
- Begin
- if EOF then
- begin
- Result := False;
- exit;
- end;
- Result := (Char (PeekByte) = Ch) xor MatchNonMatch;
- if Result and SkipOnMatch then
- Skip (Sizeof (Byte));
- End;
-
- Function AReaderEx.MatchChar (const C : CharSet; var Ch : Char; const MatchNonMatch : Boolean; const SkipOnMatch : Boolean) : Boolean;
- Begin
- if EOF then
- begin
- Result := False;
- exit;
- end;
- Ch := Char (PeekByte);
- Result := (Ch in C) xor MatchNonMatch;
- if Result and SkipOnMatch then
- Skip (Sizeof (Byte));
- End;
-
- Procedure AReaderEx.Skip (const Count : Integer);
- Begin
- if Count < 0 then
- raise EReader.Create ('Skip error');
- if Count = 0 then
- exit;
- SetPosition (GetPosition + Count);
- End;
-
- Procedure AReaderEx.SkipByte;
- Begin
- Skip (Sizeof (Byte));
- End;
-
- Function AReaderEx.SkipAll (const Ch : Char; const MatchNonMatch : Boolean; const MaxCount : Integer) : Integer;
- Begin
- Result := 0;
- While (MaxCount < 0) or (Result < MaxCount) do
- if not MatchChar (Ch, MatchNonMatch, True) then
- exit else
- Inc (Result);
- End;
-
- Function AReaderEx.SkipAll (const C : CharSet; const MatchNonMatch : Boolean; const MaxCount : Integer) : Integer;
- var Ch : Char;
- Begin
- Result := 0;
- While (MaxCount < 0) or (Result < MaxCount) do
- if not MatchChar (C, Ch, MatchNonMatch, True) then
- exit else
- Inc (Result);
- End;
-
- Function AReaderEx.Locate (const Ch : Char; const LocateNonMatch : Boolean; const MaxOffset : Integer) : Integer;
- var P : Int64;
- I : Integer;
- Begin
- P := GetPosition;
- I := 0;
- While not EOF and ((MaxOffset < 0) or (I <= MaxOffset)) do
- if (Char (ReadByte) = Ch) xor LocateNonMatch then
- begin
- SetPosition (P);
- Result := I;
- exit;
- end else
- Inc (I);
- SetPosition (P);
- Result := -1;
- End;
-
- Function AReaderEx.Locate (const C : CharSet; const LocateNonMatch : Boolean; const MaxOffset : Integer) : Integer;
- var P : Int64;
- I : Integer;
- Begin
- P := GetPosition;
- I := 0;
- While not EOF and ((MaxOffset < 0) or (I <= MaxOffset)) do
- if (Char (ReadByte) in C) xor LocateNonMatch then
- begin
- SetPosition (P);
- Result := I;
- exit;
- end else
- Inc (I);
- SetPosition (P);
- Result := -1;
- End;
-
- Function AReaderEx.LocateBuffer (const Buffer; const Size : Integer; const MaxOffset : Integer; const CaseSensitive : Boolean) : Integer;
- var P : Int64;
- I : Integer;
- B : Pointer;
- R : Boolean;
- Begin
- GetMem (B, Size);
- try
- P := GetPosition;
- I := 0;
- While not EOF and ((MaxOffset < 0) or (I <= MaxOffset)) do
- begin
- Result := Peek (B^, Size);
- if Result <= 0 then
- exit;
- if CaseSensitive then
- R := CompareMem (Buffer, B^, Result) else
- R := CompareMemNoCase (Buffer, B^, Result);
- if R then
- begin
- SetPosition (P);
- Result := I;
- exit;
- end else
- begin
- Inc (I);
- SetPosition (P + I);
- end;
- end;
- SetPosition (P);
- Result := -1;
- finally
- FreeMem (B);
- end;
- End;
-
- Function AReaderEx.LocateStr (const S : String; const MaxOffset : Integer; const CaseSensitive : Boolean) : Integer;
- Begin
- Result := LocateBuffer (Pointer (S)^, Length (S), MaxOffset, CaseSensitive);
- End;
-
- Function AReaderEx.ExtractAll (const C : CharSet; const ExtractNonMatch : Boolean; const MaxCount : Integer) : String;
- var I : Integer;
- Begin
- I := Locate (C, not ExtractNonMatch, MaxCount);
- if I = -1 then
- if MaxCount = -1 then
- begin
- Result := '';
- While not EOF do
- Result := Result + ReadStr (1024);
- end else
- Result := ReadStr (MaxCount)
- else
- Result := ReadStr (I);
- End;
-
- Procedure AReaderEx.SkipLineTerminator;
- var C, D : Char;
- Begin
- if EOF then
- exit;
- C := Char (ReadByte);
- if C = #26 then // EOF
- exit;
- if EOF then
- exit;
- D := Char (PeekByte);
- if ((C = #13) and (D = #10)) or // CRLF
- ((C = #10) and (D = #13)) then // LFCR
- SkipByte;
- End;
-
- const
- NewLineCharacters = [#10, #13, #26]; // LF, CR, EOF
-
- Function AReaderEx.ExtractLine (const MaxLineLength : Integer; const EOFIsEOL : Boolean) : String;
- Begin
- Result := ExtractAll (NewLineCharacters, True, MaxLineLength);
- if EOF then
- if EOFIsEOL then
- exit else
- RaiseReadError;
- SkipLineTerminator;
- End;
-
- Function AReaderEx.SkipLine (const MaxLineLength : Integer) : Boolean;
- var I : Integer;
- Begin
- I := Locate (NewLineCharacters, False, MaxLineLength);
- Result := I >= 0;
- if not Result then
- exit;
- Skip (I);
- SkipLineTerminator;
- End;
-
-
-
- { }
- { TMemoryReader }
- { }
- Constructor TMemoryReader.Create (const Data : Pointer; const Size : Integer);
- Begin
- FData := Data;
- FSize := Size;
- FPos := 0;
- inherited Create;
- End;
-
- Function TMemoryReader.GetPosition : Int64;
- Begin
- Result := FPos;
- End;
-
- Procedure TMemoryReader.SetPosition (const Position : Int64);
- Begin
- if (Position < 0) or (Position > FSize) then
- raise EMemoryReader.Create ('Seek error');
- FPos := Integer (Position);
- End;
-
- Function TMemoryReader.GetSize : Int64;
- Begin
- Result := FSize;
- End;
-
- Function TMemoryReader.Read (var Buffer; const Size : Integer) : Integer;
- var L : Integer;
- P : PByte;
- Begin
- if (Size <= 0) or (FPos >= FSize) then
- begin
- Result := 0;
- exit;
- end;
- L := FSize - FPos;
- if Size < L then
- L := Size;
- P := FData;
- Inc (P, FPos);
- MoveMem (P^, Buffer, L);
- Result := L;
- Inc (FPos, L);
- End;
-
- Function TMemoryReader.ReadByte : Byte;
- var I : Integer;
- P : PByte;
- Begin
- I := FPos;
- if I >= FSize then
- RaiseReadError;
- P := FData;
- Inc (P, I);
- Result := P^;
- Inc (FPos);
- End;
-
- Function TMemoryReader.PeekByte : Byte;
- var I : Integer;
- P : PByte;
- Begin
- I := FPos;
- if I >= FSize then
- RaiseReadError;
- P := FData;
- Inc (P, I);
- Result := P^;
- End;
-
- Function TMemoryReader.Match (const Buffer; const Size : Integer; const CaseSensitive : Boolean) : Integer;
- var I : Integer;
- P : PByte;
- R : Boolean;
- Begin
- I := FSize - FPos;
- if I > Size then
- I := Size;
- if I <= 0 then
- begin
- Result := -1;
- exit;
- end;
- P := FData;
- Inc (P, FPos);
- if CaseSensitive then
- R := CompareMem (Buffer, P^, I) else
- R := CompareMemNoCase (Buffer, P^, I);
- if R then
- Result := I else
- Result := -1;
- End;
-
- Function TMemoryReader.EOF : Boolean;
- Begin
- Result := FPos >= FSize;
- End;
-
-
-
- { }
- { TStringReader }
- { }
- Constructor TStringReader.Create (const Data : String);
- Begin
- inherited Create (Pointer (Data), Length (Data));
- FDataString := Data;
- End;
-
- Function TStringReader.GetAsString : String;
- Begin
- Result := FDataString;
- End;
-
-
-
- { }
- { TFileReader }
- { }
- Constructor TFileReader.Create (const FileName : String);
- Begin
- inherited Create;
- FHandle := FileOpen (FileName, fmOpenRead or fmShareDenyNone);
- if FHandle = -1 then
- raise EFileReader.Create ('File open error');
- FHandleOwner := True;
- End;
-
- Constructor TFileReader.Create (const FileHandle : Integer; const HandleOwner : Boolean);
- Begin
- inherited Create;
- FHandle := FileHandle;
- FHandleOwner := HandleOwner;
- End;
-
- Destructor TFileReader.Destroy;
- Begin
- if FHandleOwner and (FHandle <> -1) and (FHandle <> 0) then
- FileClose (FHandle);
- inherited Destroy;
- End;
-
- Function TFileReader.GetPosition : Int64;
- Begin
- Result := FileSeek (FHandle, Int64 (0), 1);
- if Result = -1 then
- raise EFileReader.Create ('File error');
- End;
-
- Procedure TFileReader.SetPosition (const Position : Int64);
- Begin
- if FileSeek (FHandle, Position, 0) = -1 then
- raise EFileReader.Create ('File seek error');
- End;
-
- Function TFileReader.GetSize : Int64;
- var I : Int64;
- Begin
- I := GetPosition;
- Result := FileSeek (FHandle, Int64 (0), 2);
- SetPosition (I);
- if Result = -1 then
- raise EFileReader.Create ('File error');
- End;
-
- Function TFileReader.Read (var Buffer; const Size : Integer) : Integer;
- var I : Integer;
- Begin
- if Size <= 0 then
- begin
- Result := 0;
- exit;
- end;
- I := FileRead (FHandle, Buffer, Size);
- if I <= 0 then
- begin
- Result := 0;
- exit;
- end;
- Result := I;
- End;
-
- Function TFileReader.EOF : Boolean;
- Begin
- Result := GetPosition >= GetSize;
- End;
-
-
-
- { ReadFileToStr }
- Function ReadFileToStr (const FileName : String) : String;
- var F : TFileReader;
- Begin
- F := TFileReader.Create (FileName);
- try
- Result := F.GetAsString;
- finally
- F.Free;
- end;
- End;
-
-
-
- { }
- { AReaderProxy }
- { }
- Constructor AReaderProxy.Create (const Reader : AReaderEx; const ReaderOwner : Boolean);
- Begin
- inherited Create;
- FReader := Reader;
- FReaderOwner := ReaderOwner;
- End;
-
- Destructor AReaderProxy.Destroy;
- Begin
- if FReaderOwner then
- FreeAndNil (FReader);
- inherited Destroy;
- End;
-
- Function AReaderProxy.Read (var Buffer; const Size : Integer) : Integer;
- Begin
- Result := FReader.Read (Buffer, Size);
- End;
-
- Function AReaderProxy.EOF : Boolean;
- Begin
- Result := FReader.EOF;
- End;
-
- Function AReaderProxy.GetPosition : Int64;
- Begin
- Result := FReader.GetPosition;
- End;
-
- Procedure AReaderProxy.SetPosition (const Position : Int64);
- Begin
- FReader.SetPosition (Position);
- End;
-
- Function AReaderProxy.GetSize : Int64;
- Begin
- Result := FReader.GetSize;
- End;
-
-
-
- { }
- { TReaderProxy }
- { }
- Constructor TReaderProxy.Create (const Reader : AReaderEx; const ReaderOwner : Boolean; const Size : Int64);
- Begin
- inherited Create (Reader, ReaderOwner);
- FOffset := Reader.GetPosition;
- FSize := Size;
- End;
-
- Function TReaderProxy.GetPosition : Int64;
- Begin
- Result := FReader.GetPosition - FOffset;
- End;
-
- Procedure TReaderProxy.SetPosition (const Position : Int64);
- Begin
- if Position < 0 then
- raise EReader.Create ('Seek error');
- if (FSize >= 0) and (Position > FOffset + FSize) then
- raise EReader.Create ('Seek error');
- FReader.SetPosition (FOffset + Position);
- End;
-
- Function TReaderProxy.GetSize : Int64;
- Begin
- Result := FReader.GetSize - FOffset;
- if (FSize >= 0) and (FSize < Result) then
- Result := FSize;
- End;
-
- Function TReaderProxy.EOF : Boolean;
- Begin
- Result := FReader.EOF;
- if Result or (FSize < 0) then
- exit;
- Result := FReader.Position >= FOffset + FSize;
- End;
-
- Function TReaderProxy.Read (var Buffer; const Size : Integer) : Integer;
- var L : Integer;
- M : Int64;
- Begin
- L := Size;
- if FSize >= 0 then
- begin
- M := FSize - (FReader.Position - FOffset);
- if M < L then
- L := Integer (M);
- end;
- if L <= 0 then
- begin
- Result := 0;
- exit;
- end;
- Result := FReader.Read (Buffer, L);
- End;
-
-
-
- { }
- { TBufferedReader }
- { }
- Constructor TBufferedReader.Create (const Reader : AReaderEx; const BufferSize : Integer; const ReaderOwner : Boolean);
- Begin
- inherited Create (Reader, ReaderOwner);
- FBufferSize := BufferSize;
- GetMem (FBuffer, BufferSize);
- FPos := Reader.GetPosition;
- End;
-
- Destructor TBufferedReader.Destroy;
- Begin
- if Assigned (FBuffer) then
- FreeMem (FBuffer);
- inherited Destroy;
- End;
-
- Function TBufferedReader.GetPosition : Int64;
- Begin
- Result := FPos;
- End;
-
- Function TBufferedReader.GetSize : Int64;
- Begin
- Result := FReader.GetSize;
- End;
-
- Procedure TBufferedReader.SetPosition (const Position : Int64);
- var B, C : Int64;
- Begin
- B := Position - FPos;
- if B = 0 then
- exit;
- C := B + FBufPos;
- if (C >= 0) and (C <= FBufUsed) then
- begin
- Inc (FBufPos, Integer (B));
- FPos := Position;
- exit;
- end;
- FReader.SetPosition (Position);
- FPos := Position;
- FBufPos := 0;
- FBufUsed := 0;
- End;
-
- Procedure TBufferedReader.Skip (const Count : Integer);
- var I : Integer;
- P : Int64;
- Begin
- if Count < 0 then
- raise EReader.Create ('Seek error');
- if Count = 0 then
- exit;
- I := FBufUsed - FBufPos;
- if I >= Count then
- begin
- Inc (FBufPos, Count);
- Inc (FPos, Count);
- exit;
- end;
- P := GetPosition + Count;
- FReader.SetPosition (P);
- FPos := P;
- FBufPos := 0;
- FBufUsed := 0;
- End;
-
- // Internal function FillBuf
- // Returns True if buffer was only partially filled
- Function TBufferedReader.FillBuf : Boolean;
- var P : PByte;
- L, N : Integer;
- Begin
- L := FBufferSize - FBufUsed;
- if L <= 0 then
- begin
- Result := False;
- exit;
- end;
- P := FBuffer;
- Inc (P, FBufPos);
- N := FReader.Read (P^, L);
- Inc (FBufUsed, N);
- Result := N < L;
- End;
-
- Function TBufferedReader.Read (var Buffer; const Size : Integer) : Integer;
- var L, M : Integer;
- P, Q : PByte;
- R : Boolean;
- Begin
- if Size <= 0 then
- begin
- Result := 0;
- exit;
- end;
- Q := @Buffer;
- M := Size;
- R := False;
- Repeat
- L := FBufUsed - FBufPos;
- if L > M then
- L := M;
- if L > 0 then
- begin
- P := FBuffer;
- Inc (P, FBufPos);
- MoveMem (P^, Q^, L);
- Inc (FBufPos, L);
- Inc (FPos, L);
- Dec (M, L);
- if M = 0 then
- begin
- Result := Size;
- exit;
- end;
- Inc (Q, L);
- end;
- FBufPos := 0;
- FBufUsed := 0;
- if R then
- begin
- Result := Size - M;
- exit;
- end;
- R := FillBuf;
- Until False;
- End;
-
- Function TBufferedReader.EOF : Boolean;
- Begin
- if FBufUsed > FBufPos then
- Result := False else
- Result := FReader.EOF;
- End;
-
- Procedure TBufferedReader.InvalidateBuffer;
- Begin
- FReader.SetPosition (FPos);
- FBufPos := 0;
- FBufUsed := 0;
- End;
-
- // Internal function BufferByte
- // Fills buffer with at least one character, otherwise raises an exception
- Procedure TBufferedReader.BufferByte;
- var I : Integer;
- Begin
- I := FBufUsed;
- if FBufPos < I then
- exit;
- if I >= FBufferSize then
- begin
- FBufPos := 0;
- FBufUsed := 0;
- end;
- FillBuf;
- if FBufPos >= FBufUsed then
- RaiseReadError;
- End;
-
- Function TBufferedReader.ReadByte : Byte;
- var P : PByte;
- Begin
- BufferByte;
- P := FBuffer;
- Inc (P, FBufPos);
- Result := P^;
- Inc (FBufPos);
- Inc (FPos);
- End;
-
- Function TBufferedReader.PeekByte : Byte;
- var P : PByte;
- Begin
- BufferByte;
- P := FBuffer;
- Inc (P, FBufPos);
- Result := P^;
- End;
-
- Function TBufferedReader.PosBuf (const C : CharSet; const LocateNonMatch : Boolean; const MaxOffset : Integer) : Integer;
- var P : PChar;
- L : Integer;
- Begin
- P := FBuffer;
- L := FBufPos;
- Inc (P, L);
- Result := 0;
- While (L < FBufUsed) and ((MaxOffset < 0) or (Result <= MaxOffset)) do
- if (P^ in C) xor LocateNonMatch then
- exit else
- begin
- Inc (P);
- Inc (L);
- Inc (Result);
- end;
- Result := -1;
- End;
-
- Function TBufferedReader.Locate (const C : CharSet; const LocateNonMatch : Boolean; const MaxOffset : Integer) : Integer;
- var I, J, M, K : Integer;
- P : Int64;
- R : Boolean;
- Begin
- P := GetPosition;
- M := MaxOffset;
- J := 0;
- R := False;
- Repeat
- K := FBufUsed - FBufPos;
- if K > 0 then
- begin
- I := PosBuf (C, LocateNonMatch, M);
- if I >= 0 then
- begin
- SetPosition (P);
- Result := J + I;
- exit;
- end;
- end;
- if R then
- begin
- SetPosition (P);
- Result := -1;
- exit;
- end;
- Inc (J, K);
- Inc (FPos, K);
- FBufPos := 0;
- FBufUsed := 0;
- if M >= 0 then
- begin
- Dec (M, K);
- if M < 0 then
- begin
- SetPosition (P);
- Result := -1;
- exit;
- end;
- end;
- R := FillBuf;
- Until False;
- End;
-
-
-
- { }
- { TSplitBufferedReader }
- { }
- Constructor TSplitBufferedReader.Create (const Reader : AReaderEx; const BufferSize : Integer; const ReaderOwner : Boolean);
- var I : Integer;
- Begin
- inherited Create (Reader, ReaderOwner);
- FBufferSize := BufferSize;
- For I := 0 to 1 do
- GetMem (FBuffer [I], BufferSize);
- FPos := Reader.GetPosition;
- End;
-
- Destructor TSplitBufferedReader.Destroy;
- var I : Integer;
- Begin
- For I := 0 to 1 do
- if Assigned (FBuffer [I]) then
- FreeMem (FBuffer [I]);
- inherited Destroy;
- End;
-
- Function TSplitBufferedReader.GetSize : Int64;
- Begin
- Result := FReader.GetSize;
- End;
-
- Function TSplitBufferedReader.GetPosition : Int64;
- Begin
- Result := FPos;
- End;
-
- // Internal function BufferStart used by SetPosition
- // Returns the relative offset of the first buffered byte
- Function TSplitBufferedReader.BufferStart : Integer;
- Begin
- Result := -FBufPos;
- if FBufNr = 1 then
- Dec (Result, FBufUsed [0]);
- End;
-
- // Internal function BufferRemaining used by SetPosition
- // Returns the length of the remaining buffered data
- Function TSplitBufferedReader.BufferRemaining : Integer;
- Begin
- Result := FBufUsed [FBufNr] - FBufPos;
- if FBufNr = 0 then
- Inc (Result, FBufUsed [1]);
- End;
-
- Procedure TSplitBufferedReader.SetPosition (const Position : Int64);
- var D : Int64;
- Begin
- D := Position - FPos;
- if D = 0 then
- exit;
- if (D >= BufferStart) and (D <= BufferRemaining) then
- begin
- Inc (FBufPos, D);
- if (FBufNr = 1) and (FBufPos < 0) then // Set position from Buf1 to Buf0
- begin
- Inc (FBufPos, FBufUsed [0]);
- FBufNr := 0;
- end else
- if (FBufNr = 0) and (FBufPos > FBufUsed [0]) then // Set position from Buf0 to Buf1
- begin
- Dec (FBufPos, FBufUsed [0]);
- FBufNr := 1;
- end;
- FPos := Position;
- exit;
- end;
- FReader.SetPosition (Position);
- FPos := Position;
- FBufNr := 0;
- FBufPos := 0;
- FBufUsed [0] := 0;
- FBufUsed [1] := 0;
- End;
-
- Procedure TSplitBufferedReader.InvalidateBuffer;
- Begin
- FReader.SetPosition (FPos);
- FBufNr := 0;
- FBufPos := 0;
- FBufUsed [0] := 0;
- FBufUsed [1] := 0;
- End;
-
- // Internal function MoveBuf used by Read
- // Moves remaining data from Buffer [BufNr]^[BufPos] to Dest
- // Returns True if complete (Remaining=0)
- Function TSplitBufferedReader.MoveBuf (var Dest : PByte; var Remaining : Integer) : Boolean;
- var P : PByte;
- L, R, N, O : Integer;
- Begin
- N := FBufNr;
- O := FBufPos;
- L := FBufUsed [N] - O;
- if L <= 0 then
- begin
- Result := False;
- exit;
- end;
- P := FBuffer [N];
- Inc (P, O);
- R := Remaining;
- if R < L then
- L := R;
- MoveMem (P^, Dest^, L);
- Inc (Dest, L);
- Inc (FBufPos, L);
- Dec (R, L);
- if R <= 0 then
- Result := True else
- Result := False;
- Remaining := R;
- End;
-
- // Internal function FillBuf used by Read
- // Fill Buffer [BufNr]^[BufPos] with up to BufferSize bytes and moves
- // the read data to Dest
- // Returns True if complete (incomplete Read or Remaining=0)
- Function TSplitBufferedReader.FillBuf (var Dest : PByte; var Remaining : Integer) : Boolean;
- var P : PByte;
- I, L, N : Integer;
- Begin
- N := FBufNr;
- I := FBufUsed [N];
- L := FBufferSize - I;
- if L <= 0 then
- begin
- Result := False;
- exit;
- end;
- P := FBuffer [N];
- Inc (P, I);
- I := FReader.Read (P^, L);
- if I > 0 then
- begin
- Inc (FBufUsed [N], I);
- if MoveBuf (Dest, Remaining) then
- begin
- Result := True;
- exit;
- end;
- end;
- Result := I < L;
- End;
-
- Function TSplitBufferedReader.Read (var Buffer; const Size : Integer) : Integer;
- var Dest : PByte;
- Remaining : Integer;
- Begin
- if Size <= 0 then
- begin
- Result := 0;
- exit;
- end;
- Dest := @Buffer;
- Remaining := Size;
- Repeat
- if MoveBuf (Dest, Remaining) then
- begin
- Result := Size;
- Inc (FPos, Size);
- exit;
- end;
- if FillBuf (Dest, Remaining) then
- begin
- Result := Size - Remaining;
- Inc (FPos, Result);
- exit;
- end;
- if FBufNr = 0 then
- FBufNr := 1 else
- begin
- Swap (FBuffer [0], FBuffer [1]);
- FBufUsed [0] := FBufUsed [1];
- FBufUsed [1] := 0;
- end;
- FBufPos := 0;
- Until False;
- End;
-
- Function TSplitBufferedReader.EOF : Boolean;
- Begin
- if FBufUsed [FBufNr] > FBufPos then
- Result := False else
- if FBufNr = 1 then
- Result := FReader.EOF else
- if FBufUsed [1] > 0 then
- Result := False else
- Result := FReader.EOF;
- End;
-
-
-
- { }
- { TBufferedFileReader }
- { }
- Constructor TBufferedFileReader.Create (const FileName : String; const BufferSize : Integer);
- Begin
- inherited Create (TFileReader.Create (FileName), BufferSize, True);
- End;
-
- Constructor TBufferedFileReader.Create (const FileHandle : Integer; const HandleOwner : Boolean; const BufferSize : Integer);
- Begin
- inherited Create (TFileReader.Create (FileHandle, HandleOwner), BufferSize, True);
- End;
-
-
-
- { }
- { TSplitBufferedFileReader }
- { }
- Constructor TSplitBufferedFileReader.Create (const FileName : String; const BufferSize : Integer);
- Begin
- inherited Create (TFileReader.Create (FileName), BufferSize, True);
- End;
-
-
-
- { }
- { Self-testing code }
- { }
- Procedure TestReader (const Reader : AReaderEx; const FreeReader : Boolean);
- Begin
- try
- Reader.Position := 0;
- Assert (not Reader.EOF, 'Reader.EOF');
- Assert (Reader.Size = 26, 'Reader.Size');
- Assert (Reader.PeekStr (0) = '', 'Reader.PeekStr');
- Assert (Reader.PeekStr (-1) = '', 'Reader.PeekStr');
- Assert (Reader.PeekStr (2) = '01', 'Reader.PeekStr');
- Assert (Char (Reader.PeekByte) = '0', 'Reader.PeekByte');
- Assert (Char (Reader.ReadByte) = '0', 'Reader.ReadByte');
- Assert (Char (Reader.PeekByte) = '1', 'Reader.PeekByte');
- Assert (Char (Reader.ReadByte) = '1', 'Reader.ReadByte');
- Assert (Reader.ReadStr (0) = '', 'Reader.ReadStr');
- Assert (Reader.ReadStr (-1) = '', 'Reader.ReadStr');
- Assert (Reader.ReadStr (1) = '2', 'Reader.ReadStr');
- Assert (Reader.MatchChar ('3'), 'Reader.MatchChar');
- Assert (Reader.MatchStr ('3', True), 'Reader.MatchStr');
- Assert (Reader.MatchStr ('345', True), 'Reader.MatchStr');
- Assert (not Reader.MatchStr ('35', True), 'Reader.MatchStr');
- Assert (not Reader.MatchStr ('4', True), 'Reader.MatchStr');
- Assert (not Reader.MatchStr ('', True), 'Reader.MatchStr');
- Assert (Reader.ReadStr (2) = '34', 'Reader.ReadStr');
- Assert (Reader.PeekStr (3) = '567', 'Reader.PeekStr');
- Assert (Reader.Locate ('5', False, 0) = 0, 'Reader.Locate');
- Assert (Reader.Locate ('8', False, -1) = 3, 'Reader.Locate');
- Assert (Reader.Locate ('8', False, 3) = 3, 'Reader.Locate');
- Assert (Reader.Locate ('8', False, 2) = -1, 'Reader.Locate');
- Assert (Reader.Locate ('8', False, 4) = 3, 'Reader.Locate');
- Assert (Reader.Locate ('0', False, -1) = -1, 'Reader.Locate');
- Assert (Reader.Locate (['8'], False, -1) = 3, 'Reader.Locate');
- Assert (Reader.Locate (['8'], False, 3) = 3, 'Reader.Locate');
- Assert (Reader.Locate (['8'], False, 2) = -1, 'Reader.Locate');
- Assert (Reader.Locate (['0'], False, -1) = -1, 'Reader.Locate');
- Assert (Reader.LocateStr ('8', -1, True) = 3, 'Reader.LocateStr');
- Assert (Reader.LocateStr ('8', 3, True) = 3, 'Reader.LocateStr');
- Assert (Reader.LocateStr ('8', 2, True) = -1, 'Reader.LocateStr');
- Assert (Reader.LocateStr ('89', -1, True) = 3, 'Reader.LocateStr');
- Assert (Reader.LocateStr ('0', -1, True) = -1, 'Reader.LocateStr');
- Assert (not Reader.EOF, 'Reader.EOF');
- Assert (Reader.Position = 5, 'Reader.Position');
- Reader.Position := 7;
- Reader.SkipByte;
- Assert (Reader.Position = 8, 'Reader.Position');
- Reader.Skip (2);
- Assert (Reader.Position = 10, 'Reader.Position');
- Assert (not Reader.EOF, 'Reader.EOF');
- Assert (Reader.MatchStr ('abcd', False), 'Reader.MatchStr');
- Assert (not Reader.MatchStr ('abcd', True), 'Reader.MatchStr');
- Assert (Reader.LocateStr ('d', -1, True) = 3, 'Reader.LocateStr');
- Assert (Reader.LocateStr ('d', 3, False) = 3, 'Reader.LocateStr');
- Assert (Reader.LocateStr ('D', -1, True) = -1, 'Reader.LocateStr');
- Assert (Reader.LocateStr ('D', -1, False) = 3, 'Reader.LocateStr');
- Assert (Reader.SkipAll ('X', False, -1) = 0, 'Reader.SkipAll');
- Assert (Reader.SkipAll ('A', False, -1) = 1, 'Reader.SkipAll');
- Assert (Reader.SkipAll (['b', 'C'], False, -1) = 2, 'Reader.SkipAll');
- Assert (Reader.SkipAll (['d'], False, 0) = 0, 'Reader.SkipAll');
- Assert (Reader.ExtractAll (['d', 'E'], False, 1) = 'd', 'Reader.ExtractAll');
- Assert (Reader.ExtractAll (['*'], True, 1) = 'E', 'Reader.ExtractAll');
- Assert (Reader.ReadStr (2) = '*.', 'Reader.ReadStr');
- Assert (Reader.ExtractAll (['X'], False, 1) = 'X', 'Reader.ExtractAll');
- Assert (Reader.ExtractAll (['X'], False, -1) = 'XX', 'Reader.ExtractAll');
- Assert (Reader.ExtractAll (['X', '*'], True, 1) = 'Y', 'Reader.ExtractAll');
- Assert (Reader.ExtractAll (['X', '*'], True, -1) = 'YYY','Reader.ExtractAll');
- Assert (Reader.ExtractAll (['X'], False, -1) = '', 'Reader.ExtractAll');
- Assert (Reader.ExtractAll (['X'], True, -1) = '*.', 'Reader.ExtractAll');
- Assert (Reader.EOF, 'Reader.EOF');
- Assert (Reader.Position = 26, 'Reader.Position');
- Reader.Position := Reader.Position - 2;
- Assert (Reader.PeekStr (3) = '*.', 'Reader.PeekStr');
- Assert (Reader.ReadStr (3) = '*.', 'Reader.ReadStr');
- finally
- if FreeReader then
- Reader.Free;
- end;
- End;
-
- Procedure TestLineReader (const Reader : AReaderEx; const FreeReader : Boolean);
- Begin
- try
- Reader.Position := 0;
- Assert (not Reader.EOF, 'Reader.EOF');
- Assert (Reader.ExtractLine = '1', 'Reader.ExtractLine');
- Assert (Reader.ExtractLine = '23', 'Reader.ExtractLine');
- Assert (Reader.ExtractLine = '', 'Reader.ExtractLine');
- Assert (Reader.ExtractLine = '4', 'Reader.ExtractLine');
- Assert (Reader.ExtractLine = '5', 'Reader.ExtractLine');
- Assert (Reader.ExtractLine = '6', 'Reader.ExtractLine');
- Assert (Reader.EOF, 'Reader.EOF');
- finally
- if FreeReader then
- Reader.Free;
- end;
- End;
-
- Procedure SelfTest;
- var S : TStringReader;
- I : Integer;
- Begin
- S := TStringReader.Create ('0123456789AbCdE*.XXXYYYY*.');
- try
- TestReader (TReaderProxy.Create (S, False, -1), True);
- TestReader (S, False);
- TestReader (TBufferedReader.Create (S, 128, False), True);
- For I := 1 to 16 do
- TestReader (TBufferedReader.Create (S, I, False), True);
- TestReader (TSplitBufferedReader.Create (S, 128, False), True);
- For I := 1 to 16 do
- TestReader (TSplitBufferedReader.Create (S, I, False), True);
- finally
- S.Free;
- end;
-
- S := TStringReader.Create ('1'#13#10'23'#13#13'4'#10'5'#10#13'6');
- try
- TestLineReader (TReaderProxy.Create (S, False, -1), True);
- For I := 1 to 32 do
- TestLineReader (TBufferedReader.Create (S, I, False), True);
- For I := 1 to 32 do
- TestLineReader (TSplitBufferedReader.Create (S, I, False), True);
- TestLineReader (S, False);
- finally
- S.Free;
- end;
- End;
-
-
-
- end.
-
-