{*******************************************************}
{                                                       }
{       Tocsg.Convert                                   }
{                                                       }
{       Copyright (C) 2022 kkuzil                       }
{                                                       }
{*******************************************************}

unit Tocsg.Convert;

interface

uses
  Winapi.Windows, System.SysUtils, Tocsg.Obj, System.Classes;

type
  TTgRtti = class(TTgObject)
  public
    class function Int64ToSetType<T>(aInt: Int64): T;
    class function SetTypeToInt64<T>(aSet: T): Int64;
    class function SetTypeToStr<T>(aSet: T): String;
    class function StrToSetType<T>(aStr: String): T;
  end;

function ByteSizeToStr(ullSize: ULONGLONG): String; inline;
function BooleanToStr(const bVal: Boolean; const sTrue, sFalse: String): String; inline;
function BooleanToInt(const bVal: Boolean; const nTrue, nFalse: Integer): Integer; inline;
function BooleanToFloat(const bVal: Boolean; const fTrue, fFalse: Double): Double; inline;

function FileToBase64(sPath: String): String;

implementation

uses
  Tocsg.Binary, System.Rtti, Soap.EncdDecd, Tocsg.Exception, Tocsg.Safe;

{ TTgRtti }

class function TTgRtti.Int64ToSetType<T>(aInt: Int64): T;
var
  v: TValue;
begin
  TValue.Make(nil, TypeInfo(T), v);
  TValueData(v).FAsSInt64 := aInt;
  Result := v.AsType<T>;
end;

class function TTgRtti.SetTypeToInt64<T>(aSet: T): Int64;
var
  v: TValue;
begin
  v := TValue.From<T>(aSet);
  Result := TValueData(v).FAsSInt64;
end;

class function TTgRtti.SetTypeToStr<T>(aSet: T): String;
var
  nSize: Integer;
  pBuf: Pointer;
begin
  nSize := SizeOf(aSet);
  pBuf := AllocMem(nSize);
  try
    CopyMemory(pBuf, @aSet, nSize);
    Result := ConvBytesToHexStr(pBuf, nSize);
  finally
    FreeMem(pBuf);
  end;
end;

class function TTgRtti.StrToSetType<T>(aStr: String): T;
var
  nSize: Integer;
  pBuf: TBytes;
begin
  ConvHexStrToBytes(aStr, pBuf);
  nSize := Length(pBuf);
  if nSize = SizeOf(Result) then
    CopyMemory(@Result, pBuf, nSize);
end;

function ByteSizeToStr(ullSize: ULONGLONG): String;
begin
  if (ullSize >= 1024) and (ullSize <= 1048576) then
    Result := Format('%d KB', [Round(ullSize / 1024)])
  else if (ullSize >= 1048576) and (ullSize < 1073741824) then
    Result := Format('%d MB', [Round(ullSize / 1048576)])
  else if (ullSize >= 1073741824) and (ullSize < 1099511627776) then
    Result := Format('%d GB', [Round(ullSize / 1073741824)])
  else if ullSize >= 1099511627776 then
    Result := Format('%d TB', [Round(ullSize / 1099511627776)])
  else
    Result := Format('%d Byte', [ullSize]);
end;

function BooleanToStr(const bVal: Boolean; const sTrue, sFalse: String): String;
begin
  if bVal then
    Result := sTrue
  else
    Result := sFalse;
end;

function BooleanToInt(const bVal: Boolean; const nTrue, nFalse: Integer): Integer;
begin
  if bVal then
    Result := nTrue
  else
    Result := nFalse;
end;

function BooleanToFloat(const bVal: Boolean; const fTrue, fFalse: Double): Double;
begin
  if bVal then
    Result := fTrue
  else
    Result := fFalse;
end;

function FileToBase64(sPath: String): String;
var
  ms: TMemoryStream;
begin
  Result := '';
  try
    if not FileExists(sPath) then
      exit;
    Guard(ms, TMemoryStream.Create);
    ms.LoadFromFile(sPath);
    Result := EncodeBase64(ms.Memory, ms.Size);
  except
    on E: Exception do
      ETgException.TraceException(E, 'Fail .. FileToBase64()');
  end;
end;

end.
