unit fileutils;
{-----------}
{By SVSD_VAL}
{-----------}
interface

uses sysutils, classes;

Const
  USER_CONFIG     = 1;
  USER_DIR_CONFIG = 2;

type
  TSetOfChar = set of Char;

  TEntry  = class
    Attrib : Array of Record
     Name,Value : String;
    end;
    Child  : Array of TEntry;
    procedure ParseList(FText:TStringList; var line:integer);
    Function GetString (const s:String; const def : string = ''):String;
  end;

  TConfig = class
    FText    : TStringList;
  public
    Entry    : TEntry;

    constructor Create(filename: String);
  end;

Procedure OpenLog( S : String);
Procedure SendToLog( S:String; ID:Integer=0 );
Procedure CloseLog();

implementation
{ TFile }
var
   Log : TextFile;

Procedure OpenLog( S : String);
begin
  AssignFile( Log, S );
  {$i-}
       Append(Log);
  {$i+}
  if IOresult <> 0 then
Rewrite(Log);
  WriteLn(Log,'-----------------');
  WriteLn(Log,'By SVSD_VAL');
  WriteLn(Log,'Site http://rtbt.ru');
  WriteLn(Log,'Jabber: svsd_val@jabber.ru / svsd_val@qip.ru');
  WriteLn(Log,'Mail : valdim_05@mail.ru');
end;

Procedure CloseLog();
begin
  CloseFile( Log );
end;

Procedure SendToLog( S:String; ID:Integer=0 );
begin
  case ID of
    0 : begin
          WriteLn( Log , S + ' ..Ok' );
          WriteLn( S + ' ..Ok' );
    end;
   -1 : begin
          WriteLn( Log , S + ' ..Err!!' );
          WriteLn( S + ' ..Err!!' );
    end;
   else
          WriteLn( Log , S);
          WriteLn( S);
  end;

  Flush(Log);
end;

function PathFormat(const S: string): string;
var
  i : Integer;
begin
  Result := S;
  for i := 1 to Length(Result) do
  {$ifdef win32}
    if Result[i]  = '/' then Result[i] := '\';{$else}
    if Result[i]  = '\' then Result[i] := '/';
  {$endif}
end;

function StrToFloat(const Str: string; const Def: Single = 0): Single;
var
  Code : Integer;
begin
  Val(Str, Result, Code);
  if Code <> 0 then
    Result := Def;
end;



 Procedure Parse(const S:String; var SL:TStringList);
 var
 sp, i,l : integer;
 const
  WhiteSpace : set of Char = [ #0, #9, #10, #13, ' ' ];
  LineBreak : String = '//';
 begin
  l := pos(LineBreak, S);
  if l <1 then
  l := Length(S);

  i   := 1;
  SL.Clear;
  while (i <= l) do
  begin
   while (i <= l) and (S[i] in WhiteSpace) do inc(i);
    sp:=i;

   while (i <= l) and (not (S[i] in WhiteSpace)) do
     inc(i);
     if i-Sp >0 then SL.Add ( Copy( S,Sp,i-Sp) );
  end;

 end;

Procedure TEntry.ParseList(FText:TStringList; var line:integer);
var j,k, ai,ci,ei : Integer;
 SL : TStringList;
begin

  SL    := TStringList.Create;

  j:=0;
  k:=0;
  While ( Line < FText.Count) do
    begin
      Parse(Ftext.Strings[ Line ], SL);

      if (SL.Count >0) and  (Sl.Strings[0] = '}')
      then
      begin
        break;
      end;

      if (SL.Count >0) then
      begin

          if SL.Strings[0] = '{' then
          begin

            ci := Length(Child );
               SetLength(Child, ci+1);
                         Child[ci] := TEntry.Create;

            ai := Length(Child[ci].Attrib);
               SetLength(Child[ci].Attrib, ai+1);
            Child[ci].Attrib[ai].Name := SL.Strings[1];
//                SendToLog('Open entry ['+Child[ci].Attrib[ai].Name+'] !! { ' + inttostr(line));

            if SL.Count >2 then begin
              Child[ci].Attrib[ai].Value:= SL.Strings[2];
              for j := 3 to Sl.Count - 1 do
              Child[ci].Attrib[ai].Value:= Child[ci].Attrib[ai].Value +' '+ SL.Strings[j];
            end;
//                SendToLog('Add entry !! ['+ Child[ci].Attrib[ai].Name + '] ['+ Child[ci].Attrib[ai].value+']' );
                inc(line);
                Child[ci].ParseList(Ftext, Line );

          end else
          begin
            ai := Length(Attrib);
               SetLength(Attrib, ai+1);
            Attrib[ai].Name := SL.Strings[0];
            if SL.Count >1 then
            begin
              Attrib[ai].Value:= SL.Strings[1];
              for j := 2 to Sl.Count - 1 do
              Attrib[ai].Value:= Attrib[ai].Value +' '+ SL.Strings[j];
            end;
//                SendToLog('Add option ['+ Attrib[ai].Name + '] ['+ Attrib[ai].value+']' );
          end;
      end;
     inc(Line);
    end;
  SL.Free;
end;

Function TEntry.GetString (const s:String; const def : string = ''):String;
var i :integer;
begin
  for i := 0 to high(Attrib) do
    if Attrib[i].Name = S then
    begin
      Result := Attrib[i].Value;
      exit;
    end;
    result := def;
    SendToLog('no match for :'+s, -1);
end;



constructor TConfig.Create(FileName : String);
var i,j,k, ai,ci,ei : Integer;
begin
  inherited Create;
  FText := TStringList.Create;
  FText.LoadFromFile(FileName);
      i := 0;
  Entry := TEntry.Create;
  Entry.ParseList(Ftext,i);
  FText.Free;
end;

end.