unit uInterpreteDeParametros;
interface

uses
  SysUtils, Classes, matreal;

type
  TPar = class
    nombre, valor: string;
    constructor Create(xNombre, xValor: string);
  end;

  { TInterpreteParametros }

  TInterpreteParametros = class(TList)
    constructor Create( archiSalaObligatorio: boolean  = false );

    // si el parámetro no esta definido retorna ''
    function valStr(nombre: string; defval: string = '' ): string;

    // si el parámetro no esta definido retorna '-1'
    function valFlt(nombre: string; defval: double = -1 ): double;

    // si el parámetro no esta definido retorna '-1'
    function valInt(nombre: string; defval: integer = -1 ): integer;

    // si el parámetro no esta definido retorna 'nil'
    // espera un string SIN ESPACIOS con números en punto flotante separados por ";"
    function valVectR(nombre: string; defval: TVectR = nil ): TVectR;

    // si el parámetro no esta definido retorna 'False'
    function valBoolean(nombre: string; defval: Boolean = False ): Boolean;

    function valDateTime(nombre: string; defval: double = 0 ): TDateTime; overload;
    function valDateTime(nombre: string;
      formato:TFormatSettings; defval: double = 0 ): TDateTime; overload;

    // retorna el índice del Parametro si lo encuentra o -1 si no
    function buscar(nombre: string): integer;
    destructor destroy; override;

    // add or replace
    procedure addor( aPar: TPar ); overload;

    // add or replace
    procedure addor( Nombre, valor: string ); overload;

    function getcmdline_str: string;
  end;

implementation


constructor TPar.Create(xNombre, xValor: string);
begin
  Nombre:= AnsiLowerCase( xNombre );
  Valor:= xValor;
end;

constructor TInterpreteParametros.Create( archiSalaObligatorio: boolean );
var
  i, k:      integer;
  Name, val: string;
  nPars:     integer;
//  a: TPar;
  s: string;

begin

  inherited Create;

  //Valores por defecto
  add(TPar.Create('monitores', ''));
  add(TPar.Create('nhilos', '-1'));
  add(TPar.Create('ntareas', '-1'));

  nPars := ParamCount;
  for k := 1 to nPars do
  begin
    s:= ParamStr(k);
    i := pos('=', s);
    if i > 0 then
    begin
      Name := copy(s, 1, i - 1);
      if i < length(s) then
        val := copy(s, i + 1, length(s) - i)
      else
        val := '';
      val:= trim( val );
      if ( pos( '"', val ) = 1 )
         and ( ( length( val ) > 1 ) and (val[length(val )] = '"'))
         then
      begin
        system.delete( val, 1, 1 );
        system.delete( val, length(val), 1 );
      end;
    end
    else
    begin
      Name := s;
      val  := 'sin valor';
    end;
    addor(TPar.Create( AnsiLowerCase( name ), val));
  end;

  if (archiSalaObligatorio) then
  begin
    if buscar('sala') < 0 then
    begin
      Free;
      writeln( 'El parametro sala es obligatorio' );
      raise Exception.Create('El parametro "sala" es obligatorio.');
    end
    else
    begin
      val := ValStr('sala');
      if not FileExists( val ) then
      begin
        Free;
        raise Exception.Create('No se encuentra el archivo de sala: ' + val);
      end;
    end;
  end;
end;


function TInterpreteParametros.valStr(nombre: string; defval: string = ''): string;
var
  k: integer;
begin
  k:= buscar( nombre );
  if k < 0 then
    result:= defval
  else
    result:= TPar( items[k] ).valor;
end;

function TInterpreteParametros.valFlt(nombre: string; defval: double): double;
var
  k: integer;
begin
  k:= buscar( nombre );
  if k < 0 then
    result:= defval
  else
    result:= StrToFloat( TPar( items[k] ).valor );
end;

function TInterpreteParametros.valInt(nombre: string; defval: integer = -1 ): integer;
var
  k: integer;
begin
  k:= buscar( nombre );
  if k < 0 then
    result:= defval
  else
    result:= StrToInt( TPar( items[k] ).valor );
end;

function TInterpreteParametros.valVectR(nombre: string; defval: TVectR): TVectR;
var
  res: TVectR;
  s: string;
  k: integer;
begin
  k:= buscar( nombre );
  if k < 0 then
    result:= nil
  else
  begin
    res:= TVectR.Create_unserialize_data( Tpar( items[k] ).valor );
    result:= res;
  end;
end;

function TInterpreteParametros.valBoolean(nombre: string; defval: Boolean
  ): Boolean;
var
  k: integer;
begin
  k:= buscar( nombre );
  if k < 0 then
    result:= defval
  else
    result:= StrToBool( TPar( items[k] ).valor );
end;

function TInterpreteParametros.valDateTime(nombre: string; defval: double
  ): TDateTime;
var
  k: integer;
begin
  k:= buscar( nombre );
  if k < 0 then
    result:= defval
  else
    result:= StrToDateTime( TPar( items[k] ).valor);
end;

function TInterpreteParametros.valDateTime(nombre: string;
  formato: TFormatSettings; defval: double): TDateTime;
var
  k: integer;
begin
  k:= buscar( nombre );
  if k < 0 then
    result:= defval
  else
    result:= StrToDateTime( TPar( items[k] ).valor,formato);
end;

// retorna el índice del Par si lo encuentra o -1 si no
function TInterpreteParametros.buscar(nombre: string): integer;
var
  k: integer;
  buscando: boolean;
  pal: string;
  a: TPar;

begin
  k:= 0;
  buscando:= true;
  pal:= AnsiLowerCase( nombre );
  while buscando and ( k < Count ) do
  begin
    a:= TPar( items[k] );
    if pal = a.nombre then
      buscando:= false
    else
      inc( k );
  end;
  if buscando then
    result:= -1
  else
    result:= k;
end;

// insert or replace
procedure TInterpreteParametros.addor(aPar: TPar);
var
  k: integer;
begin
  k:= buscar( aPar.Nombre );
  if k < 0 then
    add( aPar )
  else
  begin
    TPar( items[k] ).valor:= aPar.valor;
    aPar.Free;
  end;
end;

procedure TInterpreteParametros.addor(Nombre, valor: string);
begin
  addor( TPar.Create( nombre, valor ) );
end;

function TInterpreteParametros.getcmdline_str: string;
var
  k: integer;
  s: string;
  res: string;
  aPar: TPar;
begin
  res:= '';
  for k := 0 to Count - 1 do
  begin
    aPar:= items[k];
    s:= aPar.valor;
    if pos( ' ', s ) <> 0 then
      if s[1] <> '"' then
        s:= '"' + s+'"';
    res:= res+' '+aPar.nombre+'='+s;
  end;
  result:= res;
end;


destructor TInterpreteParametros.destroy;
var
  k: integer;
begin
  for k := 0 to Count - 1 do
    TPar(items[k]).Free;
  inherited destroy;
end;


end.

