// $Id: fsys.pas,v 1.7 2001/07/04 16:24:02 druid Exp $
unit fsys;
interface
uses
Classes,
SysUtils;
const
BUFSIZE = 65536 * 16;
MAX_LINESIZE = 1024;
type
GFileReader = class
fp : TFileStream;
fname : string;
buffer : array[0..BUFSIZE] of char;
fpos, fsize : integer;
feol : boolean;
line : integer;
function readChar : char;
function eof() : boolean;
function eol() : boolean;
procedure seek(pos : integer);
function readLine() : string;
function readInteger() : integer;
function readCardinal() : cardinal;
function readToken() : string;
procedure flush;
constructor Create(fn : string);
destructor Destroy; override;
end;
implementation
uses
dtypes;
constructor GFileReader.Create(fn : string);
begin
inherited Create;
fp := TFileStream.Create(fn, fmOpenRead);
fname := fn;
fsize := fp.Read(buffer, BUFSIZE);
if (fsize = 0) then
raise GException.Create('fsys.pas:GFileReader.Create', '0 length file');
fpos := 0;
line := 1;
feol := false;
end;
destructor GFileReader.Destroy;
begin
fp.Free;
inherited Destroy;
end;
function GFileReader.readChar : char;
var c : char;
begin
c := buffer[fpos];
inc(fpos);
if (fpos >= BUFSIZE) then
begin
fsize := fp.Read(buffer, BUFSIZE);
fpos := 0;
end;
if (c = #13) then
begin
readChar;
inc(line);
feol := true;
end
else
feol := false;
readChar := c;
end;
function GFileReader.eof : boolean;
begin
eof := (fpos >= fsize) or (buffer[fpos] = #0);
end;
function GFileReader.eol : boolean;
begin
Result := feol;
end;
procedure GFileReader.seek(pos : integer);
begin
{ avoid pos+pos<0, don't want to get tangled in a bug
*lazy coders grin* - Grimlord }
if (fpos + pos >= 0) then
inc(fpos,pos);
end;
function GFileReader.readLine : string;
var
chars : array[0..MAX_LINESIZE] of char;
pos : integer;
c : char;
begin
c := ' ';
pos := 0;
while (not eof()) do
begin
c := readChar;
if (c <> #13) then
begin
chars[pos] := c;
inc(pos);
if (pos >= MAX_LINESIZE) then
begin
raise GException.Create('fsys.pas:GFileReader.Create', 'max linesize exceeded in ' + fname);
pos := MAX_LINESIZE;
break;
end;
end
else
break;
end;
chars[pos] := #0;
readLine := chars
;
end;
function GFileReader.readInteger : integer;
var c : char;
number : integer;
sign : boolean;
begin
c := ' ';
while (c in [' ', #13]) do
begin
if (eof) then
begin
Result := 0;
exit;
end;
c := readChar;
end;
number := 0;
sign := false;
if (c = '+') then
c := readChar
else
if (c = '-') then
begin
sign := true;
c := readChar;
end;
if not (c in ['0'..'9']) then
begin
Result := 0;
exit;
end;
while (c in ['0'..'9']) do
begin
if (eof) then
begin
Result := number;
exit;
end;
number := number * 10 + byte(c) - byte('0');
c := readChar;
end;
if (sign) then
number := 0 - number;
if (c = '|') then
inc(number, readInteger);
Result := number;
end;
function GFileReader.readCardinal : cardinal;
var c : char;
number : cardinal;
sign : boolean;
begin
c := ' ';
while (c in [' ', #13]) do
begin
if (eof) then
begin
Result := 0;
exit;
end;
c := readChar;
end;
number := 0;
sign := false;
if (c = '+') then
c := readChar
else
if (c = '-') then
begin
sign := true;
c := readChar;
end;
if not (c in ['0'..'9']) then
begin
Result := 0;
exit;
end;
while (c in ['0'..'9']) do
begin
if (eof) then
begin
Result := number;
exit;
end;
number := number * 10 + byte(c) - byte('0');
c := readChar;
end;
if (sign) then
number := 0 - number;
if (c = '|') then
inc(number, readCardinal);
Result := number;
end;
function GFileReader.readToken() : string;
var
word : array[0..255] of char;
quoted : boolean;
pword : pchar;
c : char;
begin
c := ' ';
while (c in [' ', #13]) do
begin
if (eof) then
begin
Result := '';
exit;
end;
c := readChar;
end;
if (c = '''') or (c = '"') then
begin
quoted := true;
pword := @word[0];
end
else
begin
quoted := false;
word[0] := c;
pword := @word[1];
end;
repeat
if (eof) then
begin
pword^ := #0;
Result := word;
exit;
end;
pword^ := readChar;
if (quoted) and (pword^ in ['''', '"', #13]) then
begin
pword^ := #0;
Result := word;
exit;
end
else
if (not quoted) and (pword^ in [' ', #13]) then
begin
pword^ := #0;
Result := word;
exit;
end;
inc(pword);
until (pword > word + 255);
Result := '';
end;
procedure GFileReader.flush;
begin
if (buffer = nil) then
exit;
fillchar(buffer, BUFSIZE, 0);
end;
end.