Generic indicator factory

This commit is contained in:
Michael Schimmel
2025-07-27 20:31:25 +02:00
parent ecee8b37bc
commit 7842c3bd87
6 changed files with 173 additions and 116 deletions
+52 -22
View File
@@ -18,6 +18,7 @@ type
FTypeInfo: PtypeInfo;
FName: string;
FOffset: Integer;
FSize: Integer;
procedure FromType(const [ref] Buffer: TBytes; const Src);
procedure ToType(const [ref] Buffer: TBytes; var Dst);
@@ -30,7 +31,7 @@ type
property Offset: Integer read FOffset;
constructor Create(const AName: string; AFieldType: TFieldType; ATypeInfo: PTypeInfo; AOffset: Integer);
constructor Create(const AName: string; AFieldType: TFieldType; ATypeInfo: PTypeInfo; AOffset, ASize: Integer);
procedure Copy(Src, Dst: Pointer);
@@ -115,10 +116,6 @@ implementation
uses
System.Rtti;
const
DataSize: array[TDataRecord.TFieldType] of Integer =
(sizeof(Double), sizeof(Int64), sizeof(String), sizeof(TDateTime), sizeof(TDataRecord));
{ TDataRecord }
constructor TDataRecord.Create(const ALayout: TLayout; const ABuffer: TBytes);
@@ -246,12 +243,13 @@ begin
Dest.Layout.Fields[i].FinalizeField(Dest.FBuffer);
end;
constructor TDataRecord.TField.Create(const AName: string; AFieldType: TFieldType; ATypeInfo: PTypeInfo; AOffset: Integer);
constructor TDataRecord.TField.Create(const AName: string; AFieldType: TFieldType; ATypeInfo: PTypeInfo; AOffset, ASize: Integer);
begin
FName := AName;
FFieldType := AFieldType;
FOffset := AOffset;
FTypeInfo := ATypeInfo;
FSize := ASize;
end;
procedure TDataRecord.TField.InitField(const [ref] Buffer: TBytes);
@@ -289,6 +287,9 @@ begin
end;
function TDataRecord.TField.GetSize: Integer;
const
DataSize: array[TDataRecord.TFieldType] of Integer =
(sizeof(Double), sizeof(Int64), sizeof(String), sizeof(TDateTime), sizeof(TDataRecord));
begin
Result := DataSize[FFieldType];
end;
@@ -425,6 +426,9 @@ begin
end;
class function TDataRecord.TLayout.Construct(const Def: TArray<TFieldDef>): TLayout;
const
DataSize: array[TDataRecord.TFieldType] of Integer =
(sizeof(Double), sizeof(Int64), sizeof(String), sizeof(TDateTime), sizeof(TDataRecord));
var
Fields: TArray<TField>;
begin
@@ -432,7 +436,7 @@ begin
var ofs := 0;
for var i := 0 to High(Fields) do
begin
var ti: PTypeInfo;
var ti: PTypeInfo := nil;
case Def[i].FieldType of
dfFloat: ti := TypeInfo(Double);
dfInteger: ti := TypeInfo(Int64);
@@ -441,7 +445,7 @@ begin
dfRecord: ti := TypeInfo(TDataRecord);
end;
Fields[i] := TField.Create(Def[i].Name, Def[i].FieldType, ti, ofs);
Fields[i] := TField.Create(Def[i].Name, Def[i].FieldType, ti, ofs, DataSize[Def[i].FieldType]);
inc(ofs, Fields[i].AlignedSize);
end;
@@ -477,33 +481,59 @@ begin
begin
var rf := rttiFields[i];
var ft: TFieldType := Default(TFieldType);
var supported := true;
var size: Integer := 0;
case rf.FieldType.TypeKind of
tkInt64: ft := dfInteger;
tkInteger:
begin
ft := dfInteger;
size := sizeof(Integer);
end;
tkInt64:
begin
ft := dfInteger;
size := sizeof(Int64);
end;
tkFloat:
if rf.FieldType.HasName(GetTypeName(TypeInfo(TDateTime))) then
ft := dfTimestamp
else if GetTypeData(rf.FieldType.Handle).FloatType = ftDouble then
ft := dfFloat
begin
ft := dfTimestamp;
size := sizeof(TDateTime);
end
else
supported := false;
tkString, tkWString, tkLString, tkUString: ft := dfString;
begin
case GetTypeData(rf.FieldType.Handle).FloatType of
ftSingle:
begin
ft := dfFloat;
size := sizeof(Single);
end;
ftDouble:
begin
ft := dfFloat;
size := sizeof(Double);
end;
end;
end;
tkString, tkWString, tkLString, tkUString:
begin
ft := dfString;
size := sizeof(String);
end;
tkMRecord:
begin
if rf.FieldType.HasName(GetTypeName(TypeInfo(TDataRecord))) then
ft := dfRecord
else
supported := false;
begin
ft := dfRecord;
size := sizeof(TDataRecord);
end
end;
else
supported := false;
end;
if not supported then
if size = 0 then
raise Exception.Create('Type ' + rf.FieldType.Name + ' not supported in data records');
fields[i] := TField.Create(rf.Name, ft, rf.FieldType.Handle, rf.Offset);
fields[i] := TField.Create(rf.Name, ft, rf.FieldType.Handle, rf.Offset, size);
end;
Result.Create(fields);