/
CVS/
boards/CVS/
clans/
gmc/CVS/
help/CVS/
include/CVS/
players/
progs/CVS/
races/CVS/
system/CVS/
text/
text/CVS/
todo/
todo/CVS/
units/CVS/
// $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.