diff --git a/src/shared/xparser.pas b/src/shared/xparser.pas
index fe17d0c8a700aa1dc656c899534901f151d390ad..7263b7db60037eef69dba6c49ffa9b6cac5a3108 100644 (file)
--- a/src/shared/xparser.pas
+++ b/src/shared/xparser.pas
// ////////////////////////////////////////////////////////////////////////// //
type
TFileTextParser = class(TTextParser)
+ private
+ const BufSize = 65536;
+
private
mFile: TStream;
+ mBuffer: PChar;
+ mBufLen: Integer;
+ mBufPos: Integer;
protected
procedure loadNextChar (); override; // loads next char into mNextChar; #0 means 'eof'
public
constructor Create (const fname: AnsiString; loadToken: Boolean=true);
+ constructor Create (st: TStream; loadToken: Boolean=true); // will take ownership on st
destructor Destroy (); override;
end;
SysUtils, utils;
+// ////////////////////////////////////////////////////////////////////////// //
+function StrEqu (const a, b: AnsiString): Boolean; inline; begin result := (a = b); end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
var
wc2shitmap: array[0..65535] of AnsiChar;
wc2shitmapInited: Boolean = false;
procedure TTextParser.expectId (const aid: AnsiString);
begin
- if (mTokType <> TTId) or (CompareText(mTokStr, aid) <> 0) then raise Exception.Create('identifier '''+aid+''' expected');
+ if (mTokType <> TTId) or (not StrEqu(mTokStr, aid)) then raise Exception.Create('identifier '''+aid+''' expected');
skipToken();
end;
function TTextParser.eatId (const aid: AnsiString): Boolean;
begin
result := false;
- if (mTokType <> TTId) or (CompareText(mTokStr, aid) <> 0) then exit;
+ if (mTokType <> TTId) or (not StrEqu(mTokStr, aid)) then exit;
result := true;
skipToken();
end;
// ////////////////////////////////////////////////////////////////////////// //
constructor TFileTextParser.Create (const fname: AnsiString; loadToken: Boolean=true);
begin
+ mBuffer := nil;
mFile := openDiskFileRO(fname);
+ GetMem(mBuffer, BufSize);
+ mBufPos := 0;
+ mBufLen := mFile.Read(mBuffer^, BufSize);
+ if (mBufLen < 0) then raise Exception.Create('TFileTextParser: read error');
+ inherited Create(loadToken);
+end;
+
+
+constructor TFileTextParser.Create (st: TStream; loadToken: Boolean=true);
+begin
+ if (st = nil) then raise Exception.Create('cannot create parser for nil stream');
+ mFile := st;
+ GetMem(mBuffer, BufSize);
+ mBufPos := 0;
+ mBufLen := mFile.Read(mBuffer^, BufSize);
+ if (mBufLen < 0) then raise Exception.Create('TFileTextParser: read error');
inherited Create(loadToken);
end;
destructor TFileTextParser.Destroy ();
begin
+ if (mBuffer <> nil) then FreeMem(mBuffer);
mFile.Free();
inherited;
end;
procedure TFileTextParser.loadNextChar ();
-var
- rd: Integer;
begin
- rd := mFile.Read(mNextChar, 1);
- if (rd = 0) then begin mNextChar := #0; exit; end;
+ if (mBufLen = 0) then begin mNextChar := #0; exit; end;
+ if (mBufPos >= mBufLen) then
+ begin
+ mBufLen := mFile.Read(mBuffer^, BufSize);
+ if (mBufLen < 0) then raise Exception.Create('TFileTextParser: read error');
+ if (mBufLen = 0) then begin mNextChar := #0; exit; end;
+ mBufPos := 0;
+ end;
+ assert(mBufPos < mBufLen);
+ mNextChar := mBuffer[mBufPos];
+ Inc(mBufPos);
if (mNextChar = #0) then mNextChar := ' ';
end;