Einzelnen Beitrag anzeigen

Satty67

Registriert seit: 24. Feb 2007
Ort: Baden
1.566 Beiträge
 
Delphi 2007 Professional
 
#1

Multiple Typ-Konvertierung (eleganter, als mein Weg?)

  Alt 26. Apr 2009, 21:10
Hallo,

ich benötige eine Typ-Konvertierung in alle Richtungen. Dabei soll jede Umwandlung ein Ergebnis liefern, also z.B. auch Boolean nach TDateTime (Hier gibt True Now zurück).

Die Daten liegen in einem SpeicherPuffer, stehen als Quelle somit als Cast(Pointer) bereit. Bei der Rückgabe benötige ich einmal einen Weg, wieder in den Puffer zu schreiben (Puffergröße ist immer ausreichend), als auch eine Funktions-Rückgabe mit korrektem Daten-Typ (allerdings ohne Bereichs-Prüfung, Byte := LongInt reicht also).

Ich hab' es inzwischen gelöst, aber je öfter ich mir den Code anschaue, desto mehr denke ich, das ist umständlich
Kann man das auch eleganter lösen?

Hier mal mein Werk (wenn es zu lang ist, klemme ich es als Anlage an, einfach was sagen):
Delphi-Quellcode:
unit stTypChange;

interface

uses SysUtils, stConst, stTypes;

procedure ConvertPtr(SourcePtr, TargetPtr : Pointer; SourceTyp, TargetTyp : TstDataTyp; TargetSize: Integer);

function Pointer2String (aPtr : Pointer; AsTyp : TstDataTyp; Size : Integer): AnsiString;
function Pointer2Boolean (aPtr : Pointer; AsTyp : TstDataTyp; Size : Integer): Boolean;
function Pointer2Integer (aPtr : Pointer; AsTyp : TstDataTyp; Size : Integer): Int64;
function Pointer2Float (aPtr : Pointer; AsTyp : TstDataTyp; Size : Integer): Double;
function Pointer2Currency (aPtr : Pointer; AsTyp : TstDataTyp; Size : Integer): Currency;
function Pointer2DateTime (aPtr : Pointer; AsTyp : TstDataTyp; Size : Integer): TDateTime;

function DateTimeToStrDef(DateTime: TDateTime; Default: String) : String;
function StrToDateTimeDef(Text : String; Default : TDateTime): TDateTime;
function StrToFloatDef(Text : String; Default : Double): Double;
function StrToCurrDef(Text : String; Default : Currency) : Currency;

implementation

procedure ConvertPtr(SourcePtr, TargetPtr : Pointer; SourceTyp, TargetTyp : TstDataTyp; TargetSize: Integer);
begin
  case TargetTyp of
   st_Boolean : Boolean(TargetPtr^) := Pointer2Boolean (SourcePtr, SourceTyp, TargetSize);
   st_Byte : Byte(TargetPtr^) := Pointer2Integer (SourcePtr, SourceTyp, TargetSize);
   st_Word : Word(TargetPtr^) := Pointer2Integer (SourcePtr, SourceTyp, TargetSize);
   st_SmallInt : SmallInt(TargetPtr^) := Pointer2Integer (SourcePtr, SourceTyp, TargetSize);
   st_Integer : LongInt(TargetPtr^) := Pointer2Integer (SourcePtr, SourceTyp, TargetSize);
   st_LargeInt : Int64(TargetPtr^) := Pointer2Integer (SourcePtr, SourceTyp, TargetSize);
   st_Real48 : Real48(TargetPtr^) := Pointer2Float (SourcePtr, SourceTyp, TargetSize);
   st_Double : Double(TargetPtr^) := Pointer2Float (SourcePtr, SourceTyp, TargetSize);
   st_DateTime : TDateTime(TargetPtr^):= Pointer2DateTime(SourcePtr, SourceTyp, TargetSize);
   st_Currency : Currency(TargetPtr^) := Pointer2Currency(SourcePtr, SourceTyp, TargetSize);
   st_Chars : StrCopy(PChar(TargetPtr), PChar(SourcePtr));
   st_ShortStr : ShortString(TargetPtr^) := PChar(SourcePtr);
  end;
end;

{<--- TO STRING --->}
function Pointer2String(aPtr : Pointer; AsTyp : TstDataTyp; Size : Integer): AnsiString;
begin
  case AsTyp of
    st_Boolean : if Boolean(aPtr^) then Result := BoolTrueString else Result := BoolFalseString;
    st_Byte : Result := IntToStr(Byte(aPtr^));
    st_Word : Result := IntToStr(Word(aPtr^));
    st_SmallInt : Result := IntToStr(SmallInt(aPtr^));
    st_Integer : Result := IntToStr(Integer(aPtr^));
    st_LargeInt : Result := IntToStr(Int64(aPtr^));
    st_Real48 : Result := FloatToStrF(Real48(aPtr^), ffFixed, 15, Size);
    st_Double : Result := FloatToStrF(Double(aPtr^), ffFixed, 15, Size);
    st_DateTime : Result := DateTimeToStrDef(TDateTime(aPtr^),'');
    st_Currency : Result := Format('%m',[Currency(aPtr^)]);
    st_Chars : Result := PChar(aPtr);
    st_ShortStr : Result := ShortString(aPtr^);
  end;
end;

{<--- TO BOOLEAN --->}
function Pointer2Boolean(aPtr : Pointer; AsTyp : TstDataTyp; Size : Integer): Boolean;
begin
  case AsTyp of
    st_Boolean : Result := Boolean(aPtr^);
    st_Byte : Result := Byte(aPtr^) <> 0;
    st_Word : Result := Word(aPtr^) <> 0;
    st_SmallInt : Result := SmallInt(aPtr^) <> 0;
    st_Integer : Result := Integer(aPtr^) <> 0;
    st_LargeInt : Result := Int64(aPtr^) <> 0;
    st_Real48 : Result := Real48(aPtr^) <> 0;
    st_Double : Result := Double(aPtr^) <> 0;
    st_DateTime : Result := Double(aPtr^) <> 0;
    st_Currency : Result := Currency(aPtr^) <> 0;
    st_Chars : Result := UpperCase(PChar(aPtr)) = UpperCase(BoolTrueString);
    st_ShortStr : Result := UpperCase(ShortString(aPtr^)) = UpperCase(BoolTrueString);
  else
    Result := False;
  end;
end;

{<--- TO INTEGER --->}
function Pointer2Integer(aPtr : Pointer; AsTyp : TstDataTyp; Size : Integer): Int64;
begin
  case AsTyp of
    st_Boolean : if Boolean(aPtr^) then Result := 1 else Result := 0;
    st_Byte : Result := Byte(aPtr^);
    st_Word : Result := Word(aPtr^);
    st_SmallInt : Result := SmallInt(aPtr^);
    st_Integer : Result := Integer(aPtr^);
    st_LargeInt : Result := Int64(aPtr^);
    st_Real48 : Result := Trunc(Real48(aPtr^));
    st_Double : Result := Trunc(Double(aPtr^));
    st_DateTime : Result := Trunc(Double(aPtr^));
    st_Currency : Result := Trunc(Currency(aPtr^));
    st_Chars : Result := StrToInt64Def(PChar(aPtr), 0);
    st_ShortStr : Result := StrToInt64Def(ShortString(aPtr^),0);
  else
    Result := 0;
  end;
end;

{<--- TO FLOAT --->}
function Pointer2Float(aPtr : Pointer; AsTyp : TstDataTyp; Size : Integer): Double;
begin
  case AsTyp of
    st_Boolean : if Boolean(aPtr^) then Result := 1 else Result := 0;
    st_Byte : Result := Byte(aPtr^);
    st_Word : Result := Word(aPtr^);
    st_SmallInt : Result := SmallInt(aPtr^);
    st_Integer : Result := Integer(aPtr^);
    st_LargeInt : Result := Int64(aPtr^);
    st_Real48 : Result := Real48(aPtr^);
    st_Double : Result := Double(aPtr^);
    st_DateTime : Result := Double(aPtr^);
    st_Currency : Result := Currency(aPtr^);
    st_Chars : Result := StrToFloatDef(PChar(aPtr),0);
    st_ShortStr : Result := StrToFloatDef(ShortString(aPtr^),0);
  else
    Result := 0;
  end;
end;

{<--- TO CURRENCY --->}
function Pointer2Currency(aPtr : Pointer; AsTyp : TstDataTyp; Size : Integer): Currency;
begin
  case AsTyp of
    st_Boolean : if Boolean(aPtr^) then Result := 1 else Result := 0;
    st_Byte : Result := Byte(aPtr^);
    st_Word : Result := Word(aPtr^);
    st_SmallInt : Result := SmallInt(aPtr^);
    st_Integer : Result := Integer(aPtr^);
    st_LargeInt : Result := Int64(aPtr^);
    st_Real48 : Result := Real48(aPtr^);
    st_Double : Result := Double(aPtr^);
    st_DateTime : Result := Double(aPtr^);
    st_Currency : Result := Currency(aPtr^);
    st_Chars : Result := StrToCurrDef(PChar(aPtr), 0);
    st_ShortStr : Result := StrToCurrDef(ShortString(aPtr^), 0);
  else
    Result := 0;
  end;
end;

{<--- TO DATETIME --->}
function Pointer2DateTime (aPtr : Pointer; AsTyp : TstDataTyp; Size : Integer): TDateTime;
begin
  case AsTyp of
    st_Boolean : if Boolean(aPtr^) then Result := Now else Result := 0;
    st_Byte : Result := Byte(aPtr^);
    st_Word : Result := Word(aPtr^);
    st_SmallInt : Result := SmallInt(aPtr^);
    st_Integer : Result := Integer(aPtr^);
    st_LargeInt : Result := Int64(aPtr^);
    st_Real48 : Result := Real48(aPtr^);
    st_Double : Result := Double(aPtr^);
    st_DateTime : Result := Double(aPtr^);
    st_Currency : Result := Currency(aPtr^);
    st_Chars : Result := StrToDateTimeDef(PChar(aPtr), 0);
    st_ShortStr : Result := StrToDateTimeDef(ShortString(aPtr^), 0);
  else
    Result := 0;
  end;
end;

{********************************************************
  StringUmwandlung mit Exception-Behandlung und Default
********************************************************}


{<--- DateTime > String --->}
function DateTimeToStrDef(DateTime: TDateTime; Default: String) : String;
begin
  try
    Result := DateTimeToStr(DateTime)
  except
    on EInvalidOp do Result := Default;
  end;
end;

{<--- String > DateTime --->}
function StrToDateTimeDef(Text : String; Default : TDateTime): TDateTime;
begin
  try
    Result := StrToDateTime(Text)
  except
    on EConvertError do Result := default;
  end;
end;

{<--- String > Float --->}
function StrToFloatDef(Text : String; Default : Double): Double;
begin
  try
    Result := StrToFloat(Text)
  except
    on EConvertError do Result := Default;
  end;
end;

{<--- String > Currency --->}
function CleanCurrStr(Str : String): String;
var
  i : Integer;
begin
  Result := Str;
  for i := Length(Result) downto 1 do
    if Pos(Result[i],'+-0123456789'+DecimalSeparator) < 1 then Delete(Result, i,1);
  (*
  Result := '';
  for i := 1 to Length(Str) do
    if Pos(Str[i],'+-0123456789'+DecimalSeparator) > 0 then Result := Result + Str[i];
  *)

end;

function StrToCurrDef(Text : String; Default : Currency) : Currency;
begin
  try
    Result := StrToCurr(CleanCurrStr(Text))
  except
    on EConvertError do Result := default;
  end;
end;

end.
PS: st_Chars ist entweder @String[1] oder ein PChar
PPS: TargetSize ist z.Z. noch irreführend. Größe muss nicht (mehr) beschränkt werden. Dient z.Z. noch als optionale Angabe, z.B. für Nachkommastellen.
  Mit Zitat antworten Zitat