Files
MycLib/Src/Data/Myc.Data.Value.pas
T
Michael Schimmel 3c8be92b4a TDecimal fix
2025-09-12 15:30:45 +02:00

228 lines
6.7 KiB
ObjectPascal

unit Myc.Data.Value;
interface
uses
System.SysUtils,
Myc.Data.Scalar,
Myc.Data.Series;
type
TDataValueKind = (vkVoid, vkScalar, vkInterface, vkText, vkSeries, vkRecordSeries, vkRecord, vkMemberSeries, vkGeneric);
TDataValue = record
public
type
TVal<T> = class(TInterfacedObject)
Value: T;
constructor Create(const AValue: T);
end;
private
var
FKind: TDataValueKind;
FScalar: TScalar;
FInterface: IInterface;
function GetKind: TDataValueKind; inline;
function GetIsVoid: Boolean; inline;
public
class operator Initialize(out Dest: TDataValue);
class function Void: TDataValue; inline; static;
class operator Implicit(const AValue: TScalar): TDataValue; overload; inline;
class operator Implicit(const AValue: String): TDataValue; overload; inline;
class operator Implicit(const AValue: IInterface): TDataValue; overload; inline;
class function From<T: record>(const [ref] AValue: T): TDataValue; static; inline;
function AsVal<T: record>: TVal<T>; inline;
class function FromSeries(const [ref] AValue: TScalarSeries): TDataValue; static; inline;
class function FromRecordSeries(const [ref] AValue: TScalarRecordSeries): TDataValue; static; inline;
class function FromRecord(const [ref] AValue: TScalarRecord): TDataValue; static; inline;
class function FromMemberSeries(const [ref] AValue: TScalarMemberSeries): TDataValue; static; inline;
function AsScalar: TScalar; inline;
function AsInterface: IInterface; inline;
function AsText: String; inline;
function AsRecordSeries: TVal<TScalarRecordSeries>; inline;
function AsRecord: TVal<TScalarRecord>; inline;
function AsMemberSeries: TVal<TScalarMemberSeries>; inline;
function AsSeries: TVal<TScalarSeries>; inline;
procedure SetVoid;
function ToString: String;
property IsVoid: Boolean read GetIsVoid;
property Kind: TDataValueKind read GetKind;
end;
implementation
uses
TypInfo;
{ TDataValue.TVal<T> }
constructor TDataValue.TVal<T>.Create(const AValue: T);
begin
inherited Create;
Value := AValue;
end;
{ TDataValue }
class operator TDataValue.Initialize(out Dest: TDataValue);
begin
Dest.FKind := vkVoid;
Dest.FInterface := nil;
end;
function TDataValue.AsInterface: IInterface;
begin
if (FKind <> vkInterface) then
raise EInvalidCast.Create('Cannot read value as an Interface.');
Result := FInterface;
end;
function TDataValue.AsMemberSeries: TVal<TScalarMemberSeries>;
begin
if (FKind <> vkMemberSeries) then
raise EInvalidCast.Create('Cannot read value as MemberSeries.');
Result := TVal<TScalarMemberSeries>(FInterface);
end;
function TDataValue.AsVal<T>: TVal<T>;
begin
if (FKind <> vkGeneric) then
raise EInvalidCast.Create('Cannot read value as ' + String(PTypeInfo(TypeInfo(T)).Name) + '.');
Result := TVal<T>(FInterface);
end;
function TDataValue.AsRecord: TVal<TScalarRecord>;
begin
if (FKind <> vkRecord) then
raise EInvalidCast.Create('Cannot read value as Record.');
Result := (FInterface as TVal<TScalarRecord>);
end;
function TDataValue.AsRecordSeries: TVal<TScalarRecordSeries>;
begin
if (FKind <> vkRecordSeries) then
raise EInvalidCast.Create('Cannot read value as RecordSeries.');
Result := TVal<TScalarRecordSeries>(FInterface);
end;
function TDataValue.AsScalar: TScalar;
begin
if (FKind <> vkScalar) then
raise EInvalidCast.Create('Cannot read value as a Scalar.');
Result := FScalar;
end;
function TDataValue.AsSeries: TVal<TScalarSeries>;
begin
if (FKind <> vkSeries) then
raise EInvalidCast.Create('Cannot read value as Series.');
Result := TVal<TScalarSeries>(FInterface);
end;
function TDataValue.AsText: String;
begin
if (FKind <> vkText) then
raise EInvalidCast.Create('Cannot read value as Text.');
Result := (FInterface as TVal<String>).Value;
end;
class function TDataValue.From<T>(const [ref] AValue: T): TDataValue;
begin
Result.FKind := vkGeneric;
Result.FInterface := TVal<T>.Create(AValue);
end;
class function TDataValue.FromMemberSeries(const [ref] AValue: TScalarMemberSeries): TDataValue;
begin
Result.FKind := vkMemberSeries;
Result.FInterface := TVal<TScalarMemberSeries>.Create(AValue);
Result.FScalar := Default(TScalar);
end;
class function TDataValue.FromRecord(const [ref] AValue: TScalarRecord): TDataValue;
begin
Result.FKind := vkRecord;
Result.FInterface := TVal<TScalarRecord>.Create(AValue);
Result.FScalar := Default(TScalar);
end;
class function TDataValue.FromRecordSeries(const [ref] AValue: TScalarRecordSeries): TDataValue;
begin
Result.FKind := vkRecordSeries;
Result.FInterface := TVal<TScalarRecordSeries>.Create(AValue);
Result.FScalar := Default(TScalar);
end;
class function TDataValue.FromSeries(const [ref] AValue: TScalarSeries): TDataValue;
begin
Result.FKind := vkSeries;
Result.FInterface := TVal<TScalarSeries>.Create(AValue);
Result.FScalar := Default(TScalar);
end;
class operator TDataValue.Implicit(const AValue: IInterface): TDataValue;
begin
Result.FKind := vkInterface;
Result.FInterface := AValue;
Result.FScalar := Default(TScalar);
end;
class operator TDataValue.Implicit(const AValue: TScalar): TDataValue;
begin
Result.FKind := vkScalar;
Result.FScalar := AValue;
Result.FInterface := nil;
end;
class operator TDataValue.Implicit(const AValue: String): TDataValue;
begin
Result.FKind := vkText;
Result.FInterface := TVal<String>.Create(AValue);
Result.FScalar := Default(TScalar);
end;
function TDataValue.GetIsVoid: Boolean;
begin
Result := FKind = vkVoid;
end;
function TDataValue.GetKind: TDataValueKind;
begin
Result := FKind;
end;
procedure TDataValue.SetVoid;
begin
FKind := vkVoid;
FInterface := nil;
end;
function TDataValue.ToString: String;
begin
case FKind of
vkScalar: Result := FScalar.ToString;
vkInterface: Result := '<interface>';
vkText: Result := AsText;
vkSeries: Result := '<series>';
vkRecordSeries: Result := '<record_series>';
vkRecord: Result := '<record>';
vkMemberSeries: Result := '<member_series>';
vkVoid: Result := '<void>';
else
Result := '[Unknown DataValue]';
end;
end;
class function TDataValue.Void: TDataValue;
begin
Result := Default(TDataValue);
end;
end.