home *** CD-ROM | disk | FTP | other *** search
- {$INCLUDE ..\cDefines.inc}
- unit cUnicodeReader;
-
- { }
- { Unicode Reader class v3.02 }
- { }
- { This unit is copyright ⌐ 2002 by David Butler (david@e.co.za) }
- { }
- { This unit is part of Delphi Fundamentals. }
- { Its original file name is cUnicodeReader.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 }
- { }
- { }
- { Description: }
- { Unicode reader class. }
- { }
- { Revision history: }
- { 19/04/2002 0.01 Initial version }
- { 28/10/2002 3.02 Refactored for Fundamentals 3. }
- { }
-
- interface
-
- uses
- // Fundamentals
- cUtils,
- cReaders,
- cUnicodeChar,
- cUnicodeCodecs,
- cUnicode;
-
-
-
- { }
- { AUnicodeReader }
- { }
- type
- AUnicodeReader = class
- protected
- FReader : AReader;
- FReaderOwner : Boolean;
- FCodec : AUnicodeCodec;
- FBuffer : WideString;
- FBufPos : Integer;
- FRawBuf : Pointer;
- FRawSize : Integer;
-
- procedure ReadError;
- function BufferChars(const Count: Integer): Boolean;
-
- public
- constructor Create(const Reader: AReader; const ReaderOwner: Boolean = True);
- destructor Destroy; override;
-
- property Codec: AUnicodeCodec read FCodec write FCodec;
-
- procedure Skip(const Count: Integer);
- function SkipAll(const CharMatchFunc: WideCharMatchFunction): Integer;
-
- function MatchChar(const CharMatchFunc: WideCharMatchFunction;
- const Skip: Boolean): Boolean; overload;
- function MatchChar(const Ch: WideChar; const Skip: Boolean): Boolean; overload;
- function MatchChar(const Ch: Char; const Skip: Boolean): Boolean; overload;
- function MatchAnsiStr(const S: String; const CaseSensitive: Boolean;
- const Skip: Boolean): Boolean;
- function MatchAnsiStrDelimited(const S: String; const CaseSensitive: Boolean;
- const Delimiter: WideCharMatchFunction;
- const Skip: Boolean): Boolean;
-
- function PeekChar: WideChar;
-
- function ReadChar: WideChar;
- function ReadChars(const CharMatchFunc: WideCharMatchFunction): WideString;
- function ReadToAnsiStr(const S: String; const CaseSensitive: Boolean): WideString;
- function ReadToChar(const C: CharSet): WideString;
- end;
- EUnicodeReader = class(EUnicode);
- EUnicodeReaderReadError = class(EUnicodeReader);
-
-
-
- { }
- { TUnicodeMemoryReader }
- { }
- type
- TUnicodeMemoryReader = class(AUnicodeReader)
- public
- constructor Create(const Data: Pointer; const Size: Integer);
- end;
-
-
-
- { }
- { TUnicodeFileReader }
- { }
- type
- TUnicodeFileReader = class(AUnicodeReader)
- public
- constructor Create(const FileName: String);
- end;
-
-
-
- implementation
-
- uses
- // Delphi
- SysUtils;
-
-
-
- { }
- { AUnicodeReader }
- { }
- const
- ReaderBlockSize = 1024;
-
- constructor AUnicodeReader.Create(const Reader: AReader; const ReaderOwner: Boolean);
- begin
- inherited Create;
- FReader := Reader;
- FReaderOwner := ReaderOwner;
- GetMem(FRawBuf, ReaderBlockSize);
- end;
-
- destructor AUnicodeReader.Destroy;
- begin
- if Assigned(FRawBuf) then
- FreeMem(FRawBuf);
- if FReaderOwner then
- FreeAndNil(FReader) else
- FReader := nil;
- inherited Destroy;
- end;
-
- procedure AUnicodeReader.ReadError;
- begin
- raise EUnicodeReaderReadError.Create('Read error');
- end;
-
- function AUnicodeReader.BufferChars(const Count: Integer): Boolean;
- const PackLevel = 1024;
- var L, I, J : Integer;
- P : PByte;
- S : WideString;
- T : String;
- begin
- L := Length(FBuffer) - FBufPos;
- if L >= Count then
- begin
- Result := True;
- exit;
- end;
- if FBufPos > PackLevel then
- begin
- if L > 0 then
- Move(FBuffer[FBufPos + 1], FBuffer[1], Sizeof(WideChar) * L);
- FBufPos := 0;
- SetLength(FBuffer, L);
- end;
- Repeat
- P := FRawBuf;
- Inc(P, FRawSize);
- J := FReader.Read(P, ReaderBlockSize - FRawSize);
- if J = 0 then
- begin
- Result := False;
- exit;
- end;
- Inc(FRawSize, J);
- if Assigned(FCodec) then
- S := FCodec.DecodeStr(FRawBuf, FRawSize, I) else
- begin
- I := J;
- SetLength(T, I);
- Move(FRawBuf^, Pointer(T)^, I);
- S := T;
- end;
- if I < FRawSize then
- Move(P^, FRawBuf^, FRawSize - I);
- Dec(FRawSize, I);
- FBuffer := FBuffer + S;
- Inc(L, Length(S));
- Until L >= Count;
- Result := True;
- end;
-
- procedure AUnicodeReader.Skip(const Count: Integer);
- begin
- if Count <= 0 then
- exit;
- if not BufferChars(Count) then
- ReadError;
- Inc(FBufPos, Count);
- end;
-
- function AUnicodeReader.SkipAll(const CharMatchFunc: WideCharMatchFunction): Integer;
- var P : PWideChar;
- begin
- Result := 0;
- While BufferChars(1) do
- begin
- P := Pointer(FBuffer);
- Inc(P, FBufPos);
- if not CharMatchFunc(P^) then
- exit;
- Inc(Result);
- end;
- end;
-
- function AUnicodeReader.MatchChar(const CharMatchFunc: WideCharMatchFunction; const Skip: Boolean): Boolean;
- var P : PWideChar;
- begin
- if not BufferChars(1) then
- Result := False else
- begin
- P := Pointer(FBuffer);
- Inc(P, FBufPos);
- Result := CharMatchFunc(P^);
- if Skip and Result then
- Inc(FBufPos);
- end;
- end;
-
- function AUnicodeReader.MatchChar(const Ch: WideChar; const Skip: Boolean): Boolean;
- var P : PWideChar;
- begin
- if not BufferChars(1) then
- Result := False else
- begin
- P := Pointer(FBuffer);
- Inc(P, FBufPos);
- Result := P^ = Ch;
- if Skip and Result then
- Inc(FBufPos);
- end;
- end;
-
- function AUnicodeReader.MatchChar(const Ch: Char; const Skip: Boolean): Boolean;
- begin
- Result := MatchChar(WideChar(Ch), Skip);
- end;
-
- function AUnicodeReader.MatchAnsiStr(const S: String; const CaseSensitive: Boolean; const Skip: Boolean): Boolean;
- var L : Integer;
- P : PWideChar;
- begin
- L := Length(S);
- if not BufferChars(L + 1) then
- begin
- Result := False;
- exit;
- end;
- P := Pointer(FBuffer);
- Inc(P, FBufPos);
- Result := WideMatchAnsiStr(S, P, CaseSensitive);
- if Skip and Result then
- Inc(FBufPos, L);
- end;
-
- function AUnicodeReader.MatchAnsiStrDelimited(const S: String; const CaseSensitive: Boolean; const Delimiter: WideCharMatchFunction; const Skip: Boolean): Boolean;
- var L : Integer;
- P : PWideChar;
- begin
- L := Length(S);
- if not BufferChars(L + 1) then
- begin
- Result := False;
- exit;
- end;
- P := Pointer(FBuffer);
- Inc(P, FBufPos);
- Result := WideMatchAnsiStr(S, P, CaseSensitive);
- if not Result then
- exit;
- Inc(P, L);
- Result := Delimiter (P^);
- if Skip and Result then
- Inc(FBufPos, L);
- end;
-
- function AUnicodeReader.PeekChar : WideChar;
- var P : PWideChar;
- begin
- if not BufferChars(1) then
- ReadError;
- P := Pointer(FBuffer);
- Inc(P, FBufPos);
- Result := P^;
- end;
-
- function AUnicodeReader.ReadChar : WideChar;
- var P : PWideChar;
- begin
- if not BufferChars(1) then
- ReadError;
- P := Pointer(FBuffer);
- Inc(P, FBufPos);
- Result := P^;
- Inc(FBufPos);
- end;
-
- function AUnicodeReader.ReadChars(const CharMatchFunc: WideCharMatchFunction): WideString;
- var P : PWideChar;
- L : Integer;
- begin
- L := 0;
- While BufferChars(L + 1) do
- begin
- P := Pointer(FBuffer);
- Inc(P, FBufPos + L);
- if not CharMatchFunc(P^) then
- break;
- Inc(L);
- end;
- if L = 0 then
- Result := '' else
- begin
- SetLength(Result, L);
- P := Pointer(FBuffer);
- Inc(P, FBufPos);
- Move(P^, Pointer(Result)^, Sizeof(WideChar) * L);
- Inc(FBufPos, L);
- end;
- end;
-
- function AUnicodeReader.ReadToAnsiStr(const S: String; const CaseSensitive: Boolean): WideString;
- var P : PWideChar;
- L, M : Integer;
- begin
- L := 0;
- M := Length(S);
- While BufferChars(L + M) do
- begin
- P := Pointer(FBuffer);
- Inc(P, FBufPos + L);
- if WideMatchAnsiStr(S, P, CaseSensitive) then
- break;
- Inc(L);
- end;
- if L = 0 then
- Result := '' else
- begin
- SetLength(Result, L);
- P := Pointer(FBuffer);
- Inc(P, FBufPos);
- Move(P^, Pointer(Result)^, Sizeof(WideChar) * L);
- Inc(FBufPos, L);
- end;
- end;
-
- function AUnicodeReader.ReadToChar(const C: CharSet): WideString;
- var P : PWideChar;
- L : Integer;
- begin
- L := 0;
- While BufferChars(L + 1) do
- begin
- P := Pointer(FBuffer);
- Inc(P, FBufPos + L);
- if (Ord(P^) < $80) and (Char(Ord(P^)) in C) then
- break;
- Inc(L);
- end;
- if L = 0 then
- Result := '' else
- begin
- SetLength(Result, L);
- P := Pointer(FBuffer);
- Inc(P, FBufPos);
- Move(P^, Pointer(Result)^, Sizeof(WideChar) * L);
- Inc(FBufPos, L);
- end;
- end;
-
-
-
- { }
- { TUnicodeMemoryReader }
- { }
- constructor TUnicodeMemoryReader.Create(const Data: Pointer; const Size: Integer);
- begin
- inherited Create(TMemoryReader.Create(Data, Size), True);
- end;
-
-
-
- { }
- { TUnicodeFileReader }
- { }
- constructor TUnicodeFileReader.Create(const FileName: String);
- begin
- inherited Create(TFileReader.Create(FileName), True);
- end;
-
-
-
- end.
-