uses
  sysutils;

var
  ExceptionCount: Integer = 0;
  WrongValueCount: Integer = 0;


procedure Fail(E: Exception);
begin
  Inc(ExceptionCount);
  writeln('FAIL !! : ',E.ToString);
end;

procedure Fail(Value: QWord);
begin
  Inc(WrongValueCount);
  writeln('FAIL !!  [',Value,']')
end;

{$PUSH}
{$R+}
function TryStrToByte_RangeCheck_ON(const S: String; out B: Byte): Boolean;
var
  Err: Integer;
begin
  Val(S, B, Err);
  Result := (Err = 0);
end;
{$R-}
function TryStrToByte_RangeCheck_OFF(const S: String; out B: Byte): Boolean;
var
  Err: Integer;
begin
  Val(S, B, Err);
  Result := (Err = 0);
end;
{$POP}


{$PUSH}
{$R+}
function TryStrToByte_SS_RangeCheck_ON(const S: ShortString; out B: Byte): Boolean;
var
  Err: Integer;
begin
  Val(S, B, Err);
  Result := (Err = 0);
end;
{$R-}
function TryStrToByte_SS_RangeCheck_OFF(const S: ShortString; out B: Byte): Boolean;
var
  Err: Integer;
begin
  Val(S, B, Err);
  Result := (Err = 0);
end;
{$POP}


//-------------------------------------------------------


{$PUSH}
{$R+}
function TryStrToWord_RangeCheck_ON(const S: String; out W: Word): Boolean;
var
  Err: Integer;
begin
  Val(S, W, Err);
  Result := (Err = 0);
end;
{$R-}
function TryStrToWord_RangeCheck_OFF(const S: String; out W: Word): Boolean;
var
  Err: Integer;
begin
  Val(S, W, Err);
  Result := (Err = 0);
end;
{$POP}


{$PUSH}
{$R+}
function TryStrToWord_SS_RangeCheck_ON(const S: ShortString; out W: Word): Boolean;
var
  Err: Integer;
begin
  Val(S, W, Err);
  Result := (Err = 0);
end;
{$R-}
function TryStrToWord_SS_RangeCheck_OFF(const S: ShortString; out W: Word): Boolean;
var
  Err: Integer;
begin
  Val(S, W, Err);
  Result := (Err = 0);
end;
{$POP}



//-----------------------------------------

{$PUSH}
{$R+}
function TryStrToDWord_RangeCheck_ON(const S: String; out DW: DWord): Boolean;
var
  Err: Integer;
begin
  Val(S, DW, Err);
  Result := (Err = 0);
end;
{$R-}
function TryStrToDWord_RangeCheck_OFF(const S: String; out DW: DWord): Boolean;
var
  Err: Integer;
begin
  Val(S, DW, Err);
  Result := (Err = 0);
end;
{$POP}



{$PUSH}
{$R+}
function TryStrToDWord_SS_RangeCheck_ON(const S: ShortString; out DW: DWord): Boolean;
var
  Err: Integer;
begin
  Val(S, DW, Err);
  Result := (Err = 0);
end;
{$R-}
function TryStrToDWord_SS_RangeCheck_OFF(const S: ShortString; out DW: DWord): Boolean;
var
  Err: Integer;
begin
  Val(S, DW, Err);
  Result := (Err = 0);
end;
{$POP}




//-----------------------------------------

{$PUSH}
{$R+}
function TryStrToQWord_RangeCheck_ON(const S: String; out QW: QWord): Boolean;
var
  Err: Integer;
begin
  Val(S, QW, Err);
  Result := (Err = 0);
end;
{$R-}
function TryStrToQWord_RangeCheck_OFF(const S: String; out QW: QWord): Boolean;
var
  Err: Integer;
begin
  Val(S, QW, Err);
  Result := (Err = 0);
end;
{$POP}



{$PUSH}
{$R+}
function TryStrToQWord_SS_RangeCheck_ON(const S: ShortString; out QW: QWord): Boolean;
var
  Err: Integer;
begin
  Val(S, QW, Err);
  Result := (Err = 0);
end;
{$R-}
function TryStrToQWord_SS_RangeCheck_OFF(const S: ShortString; out QW: QWord): Boolean;
var
  Err: Integer;
begin
  Val(S, QW, Err);
  Result := (Err = 0);
end;
{$POP}





var
  B: Byte;
  W: Word;
  DW: DWORD;
  QW: QWord;
  Err: Integer;
begin
  {$PUSH}
  {$R+}
  writeln('Val(Byte)');
  writeln('RangeCheck ON');
  Val('256', B, Err);
  writeln('Err=',Err);
  if (Err=0) then writeln('B=',B);
  {$R-}
  writeln('RangeCheck OFF');
  Val('256', B, Err);
  writeln('Err=',Err);
  if (Err=0) then writeln('B=',B);
  {$POP}





  writeln;

  writeln('TryStrToByte_RangeCheck_ON');
  try
    if TryStrToByte_RangeCheck_ON('256', B) then Fail(B) else writeln('NOT a Byte');
  except
    on E: Exception do Fail(E);
  end;

  writeln('TryStrToByte_RangeCheck_OFF');
  try
    if TryStrToByte_RangeCheck_OFF('256', B) then Fail(B) else writeln('NOT a Byte');
  except
    on E: Exception do Fail(E);
  end;

  writeln('TryStrToByte_SS_RangeCheck_ON');
  try
    if TryStrToByte_SS_RangeCheck_ON('256', B) then Fail(B) else writeln('NOT a Byte');
  except
    on E: Exception do Fail(E);
  end;

  writeln('TryStrToByte_SS_RangeCheck_OFF');
  try
    if TryStrToByte_SS_RangeCheck_OFF('256', B) then Fail(B) else writeln('NOT a Byte');
  except
    on E: Exception do Fail(E);
  end;

  //--------------------------------------------------------
  writeln;
  writeln('--------------------------------------------------');

  {$PUSH}
  {$R+}
  writeln('Val(Word)');
  writeln('RangeCheck ON');
  Val('65536', W, Err);
  writeln('Err=',Err);
  if (Err=0) then writeln('W=',W);
  {$R-}
  writeln('RangeCheck OFF');
  Val('65536', W, Err);
  writeln('Err=',Err);
  if (Err=0) then writeln('W=',W);
  {$POP}

  writeln('TryStrToWord_RangeCheck_ON');
  try
    if TryStrToWord_RangeCheck_ON('65536', W) then Fail(W) else writeln('NOT a Word');
  except
    on E: Exception do Fail(E);
  end;

  writeln('TryStrToByte_RangeCheck_OFF');
  try
    if TryStrToWord_RangeCheck_OFF('65536', W) then Fail(W) else writeln('NOT a Word');
  except
    on E: Exception do Fail(E);
  end;

  writeln('TryStrToByte_SS_RangeCheck_ON');
  try
    if TryStrToWord_SS_RangeCheck_ON('65536', W) then Fail(W) else writeln('NOT a Word');
  except
    on E: Exception do Fail(E);
  end;

  writeln('TryStrToByte_SS_RangeCheck_OFF');
  try
    if TryStrToWord_SS_RangeCheck_OFF('65536', W) then Fail(W) else writeln('NOT a Word');
  except
    on E: Exception do Fail(E);
  end;

  //-------------------------------------------
  //4294967295

  writeln;
  writeln('--------------------------------------------------');

  {$PUSH}
  {$R+}
  writeln('Val(DWord)');
  writeln('RangeCheck ON');
  Val('4294967296', DW, Err);
  writeln('Err=',Err);
  if (Err=0) then writeln('W=',W);
  {$R-}
  writeln('RangeCheck OFF');
  Val('4294967296', DW, Err);
  writeln('Err=',Err);
  if (Err=0) then writeln('W=',W);
  {$POP}

  writeln('TryStrToDWord_RangeCheck_ON');
  try
    if TryStrToDWord_RangeCheck_ON('4294967296', DW) then Fail(DW) else writeln('NOT a DWord');
  except
    on E: Exception do Fail(E);
  end;

  writeln('TryStrToDWord_RangeCheck_OFF');
  try
    if TryStrToDWord_RangeCheck_OFF('4294967296', DW) then Fail(DW) else writeln('NOT a DWord');
  except
    on E: Exception do Fail(E);
  end;

  writeln('TryStrToDWord_SS_RangeCheck_ON');
  try
    if TryStrToDWord_SS_RangeCheck_ON('4294967296', DW) then Fail(DW) else writeln('NOT a DWord');
  except
    on E: Exception do Fail(E);
  end;

  writeln('TryStrToDWord_SS_RangeCheck_OFF');
  try
    if TryStrToDWord_SS_RangeCheck_OFF('4294967296', DW) then Fail(DW) else writeln('NOT a DWord');
  except
    on E: Exception do Fail(E);
  end;


  //-------------------------------------



  writeln;
  writeln('--------------------------------------------------');

  //18446744073709551616
  {$PUSH}
  {$R+}
  writeln('Val(QWord)');
  writeln('RangeCheck ON');
  Val('18446744073709551616', DW, Err);
  writeln('Err=',Err);
  if (Err=0) then writeln('W=',W);
  {$R-}
  writeln('RangeCheck OFF');
  Val('18446744073709551616', DW, Err);
  writeln('Err=',Err);
  if (Err=0) then writeln('W=',W);
  {$POP}

  writeln('TryStrToQWord_RangeCheck_ON');
  try
    if TryStrToQWord_RangeCheck_ON('18446744073709551616', QW) then Fail(QW) else writeln('NOT a QWord');
  except
    on E: Exception do Fail(E);
  end;

  writeln('TryStrQWord_RangeCheck_OFF');
  try
    if TryStrToQWord_RangeCheck_OFF('18446744073709551616', QW) then Fail(QW) else writeln('NOT a QWord');
  except
    on E: Exception do Fail(E);
  end;

  writeln('TryStrToQWord_SS_RangeCheck_ON');
  try
    if TryStrToQWord_SS_RangeCheck_ON('18446744073709551616', QW) then Fail(QW) else writeln('NOT a QWord');
  except
    on E: Exception do Fail(E);
  end;

  writeln('TryStrToQWord_SS_RangeCheck_OFF');
  try
    if TryStrToQWord_SS_RangeCheck_OFF('18446744073709551616', QW) then Fail(QW) else writeln('NOT a QWord');
  except
    on E: Exception do Fail(E);
  end;

  writeln;
  if (ExceptionCount <> 0) then
    writeln('ExceptionCount : ',ExceptionCount);
  if (WrongValueCount <> 0) then
    writeln('WrongValueCount: ',WrongValueCount);

  ExitCode := WrongValueCount + ExceptionCount;

end.
