/
clans/
include/CVS/
manual/CVS/
races/CVS/
system/CVS/
text/
text/CVS/
todo/
todo/CVS/
units/CVS/
unit fsys;

interface

uses
    Classes,
    SysUtils;

const
    BUFSIZE = 65536;

type
    GFileReader = class
      fp : TFileStream;
      buffer : array[0..BUFSIZE] of char;
      fpos, fsize : integer;
      feol : boolean;
      line : integer;

      function readChar : char;
      function eof : boolean;
      procedure seek(pos : integer);

      function readLine : string;
      function readInteger : integer;
      function readCardinal : cardinal;
      function readWord : string;
      function readQuoted : string;

      procedure flush;

      constructor Create(fn : string);
      destructor Destroy; override;
    end;

implementation

constructor GFileReader.Create(fn : string);
begin
  inherited Create;

  fp := TFileStream.Create(fn, fmOpenRead);

  fsize := fp.Read(buffer, BUFSIZE);

  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;

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 buf : string;
    c : char;
begin
  c := ' ';
  buf := '';

  while (c <> #13) do
    begin
    c := readChar;

    if (c <> #13) then
      buf := buf + c;
    end;

  readLine := buf;
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.readWord : string;
var word : array[0..255] of char;
    pword : pchar;
    c : char;
begin
  c := ' ';

  while (c in [' ', #13]) do
    begin
    if (eof) then
      begin
      readWord := '';
      exit;
      end;

    c := readChar;
    end;

  if (c = '''') or (c = '"') then
    pword := @word[0]
  else
    begin
    word[0] := c;
    pword := @word[1];
    end;

  repeat
    if (eof) then
      begin
      pword^ := #0;
      readWord := word;
      exit;
      end;

    pword^ := readChar;

    if (pword^ in [' ', '''', #13]) then
      begin
      pword^ := #0;
      readWord := word;
      exit;
      end;

    inc(pword);
  until (pword > word + 255);

  readWord := '';
end;

function GFileReader.readQuoted : string;
var word : array[0..255] of char;
    pword : pchar;
    c : char;
begin
  c := ' ';

  while (c in [' ', #13]) do
    begin
    if (eof) then
      begin
      readQuoted := '';
      exit;
      end;

    if (feol) then
      exit;

    c := readChar;
    end;

  if (c = '''') or (c = '"') then
    pword := @word[0]
  else
    begin
    word[0] := c;
    pword := @word[1];
    end;

  repeat
    if (eof) then
      begin
      pword^ := #0;
      readQuoted := word;
      exit;
      end;

    pword^ := readChar;

    if (pword^ in ['''', #13]) then
      begin
      pword^ := #0;
      readQuoted := word;
      exit;
      end;

    inc(pword);
  until (pword > word + 255);

  readQuoted := '';
end;

procedure GFileReader.flush;
begin
  if (buffer = nil) then
    exit;

  fillchar(buffer, BUFSIZE, 0);
end;

end.