Snippets

Stefan Glienke Converter proposal

Created by Stefan Glienke last modified
unit Converters;

{$I Spring.inc}

interface

uses
  Spring,
  SysUtils,
  TypInfo;

type
  TConversion<TSource,TTarget> = function(const value: TSource): TTarget;

  TConverter = record
  private
    class function SingleToStr(const value: Single): string; static; inline;
    class function DoubleToStr(const value: Double): string; static; inline;
    class function CurrToStr(const value: Currency): string; static; inline;
  public
    function Convert<TSource,TTarget>(const value: TSource): TTarget; inline;
  end;

  TConverter<T> = record
  private
    class function EnumToStr(const value: Integer): string; static; inline;
  end;

  TConverter<TSource,TTarget> = record
  strict private
    class function GetDefault: TConversion<TSource,TTarget>; static; inline;
  public
    class property Default: TConversion<TSource,TTarget> read GetDefault;
  end;

implementation

{ TConverter }

function TConverter.Convert<TSource, TTarget>(
  const value: TSource): TTarget;
begin
//  if FindConverter then
//    ...
//  else
  Result := TConversion<TSource,TTarget>(TConverter<TSource, TTarget>.Default)(value);
end;

class function TConverter.CurrToStr(const value: Currency): string;
var
  Buffer: array[0..63] of Char;
begin
  SetString(Result, Buffer, FloatToText(Buffer, Value, fvCurrency,
    ffGeneral, 0, 0, FormatSettings));
end;

class function TConverter.DoubleToStr(const value: Double): string;
begin
  Result := FloatToStr(value, FormatSettings);
end;

class function TConverter.SingleToStr(const value: Single): string;
begin
  Result := FloatToStr(value, FormatSettings);
end;

{ TConverter<T> }

class function TConverter<T>.EnumToStr(const value: Integer): string;
begin
  Result := GetEnumName(TypeInfo(T), value);
end;

{ TConverter<TSource, TTarget> }

class function TConverter<TSource, TTarget>.GetDefault: TConversion<TSource, TTarget>;
begin
  case {$IFDEF DELPHIXE7_UP}System.GetTypeKind(TSource){$ELSE}GetTypeKind(TypeInfo(TSource)){$ENDIF} of
    tkInteger:
      case {$IFDEF DELPHIXE7_UP}System.GetTypeKind(TTarget){$ELSE}GetTypeKind(TypeInfo(TTarget)){$ENDIF} of
        tkUString: TConversion<Integer,string>(Result) := @IntToStr;
      end;
    tkEnumeration:
      case {$IFDEF DELPHIXE7_UP}System.GetTypeKind(TTarget){$ELSE}GetTypeKind(TypeInfo(TTarget)){$ENDIF} of
        tkUString: TConversion<Integer,string>(Result) := TConverter<TSource>.EnumToStr;
      end;
    tkFloat:
      case {$IFDEF DELPHIXE7_UP}System.GetTypeKind(TTarget){$ELSE}GetTypeKind(TypeInfo(TTarget)){$ENDIF} of
        tkUString:
        case SizeOf(TSource) of
          10: TConversion<Single,string>(Result) := @FloatToStr;
          SizeOf(Single): TConversion<Single,string>(Result) := TConverter.SingleToStr;
          SizeOf(Double):
            if TypeInfo(TSource) = TypeInfo(Double) then
              TConversion<Double,string>(Result) := TConverter.DoubleToStr
            else if TypeInfo(TSource) = TypeInfo(Currency) then
              TConversion<Currency,string>(Result) := TConverter.CurrToStr
            else
              case GetTypeData(PTypeInfo(TypeInfo(TSource))).FloatType of
                ftDouble: TConversion<Double,string>(Result) := TConverter.DoubleToStr;
                ftCurr: TConversion<Currency,string>(Result) := TConverter.CurrToStr;
              end;
        end;
      end;
    tkUString:
      case {$IFDEF DELPHIXE7_UP}System.GetTypeKind(TTarget){$ELSE}GetTypeKind(TypeInfo(TTarget)){$ENDIF} of
        tkInteger: TConversion<string,Integer>(Result) := StrToInt;
      end;
  end;
end;

end.

program Converter;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  SysUtils,
  Converters in 'Converters.pas';

type
  MyDouble = type Double;
  MyCurrency = type Currency;

{$SCOPEDENUMS ON}
{$MINENUMSIZE 1}
  TByteEnum = (Element);
{$MINENUMSIZE 2}
  TWordEnum = (Element);
{$MINENUMSIZE 4}
  TLongEnum = (Element);

procedure Main;
var
  s: string;
  i: Integer;
  c: TConverter;
  f: Single;
begin
  try
    s := TConverter<Integer,string>.Default(42);
    Writeln(s);

    s := c.Convert<Integer,string>(42);
    Writeln(s);

    i := TConverter<string,Integer>.Default('42');
    Writeln(i);


    s := TConverter<Double,string>.Default(3.14);

    s := TConverter<MyDouble,string>.Default(3.14);

    s := TConverter<Currency,string>.Default(3.14);

    s := TConverter<MyCurrency,string>.Default(3.14);

    s := TConverter<Single, string>.Default(3.14);

    f := 3.14;
    s := FloatToStr(f);

    s := TConverter<TByteEnum,string>.Default(TByteEnum.Element);

    s := TConverter<TWordEnum,string>.Default(TWordEnum.Element);

    s := TConverter<TLongEnum,string>.Default(TLongEnum.Element);
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end;

begin
  Main;
end.

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.