IScalarRecord

This commit is contained in:
Michael Schimmel
2025-12-09 13:55:09 +01:00
parent 76c92fa355
commit 5376f8924a
4 changed files with 86 additions and 101 deletions
+63 -55
View File
@@ -146,20 +146,18 @@ type
IScalarRecord = IKeywordMapping<TScalar>;
TScalarRecordRegistry = TKeywordMappingRegistry<TScalar.TKind>;
// A record of scalar values, based on a definition.
TScalarRecord = record
public
constructor Create(const ADef: IScalarRecordDefinition; const AFields: TArray<TScalar.TValue>);
function GetDef: IScalarRecordDefinition; inline;
function GetFields: TArray<TScalar.TValue>; inline;
function GetKeys(const Key: IKeyword): TScalar;
property Def: IScalarRecordDefinition read GetDef;
property Fields: TArray<TScalar.TValue> read GetFields;
property Keys[const Key: IKeyword]: TScalar read GetKeys; default;
strict private
TScalarRecord = class(TInterfacedObject, IScalarRecord)
private
FDef: IScalarRecordDefinition;
FFields: TArray<TScalar.TValue>;
end deprecated;
FData: TArray<TScalar.TValue>;
function IndexOf(const Key: IKeyword): Integer;
function GetCount: Integer;
function GetItems(Idx: Integer): TPair<IKeyword, TScalar>;
function GetFields(const Key: IKeyword): TScalar;
public
constructor Create(const ADef: IScalarRecordDefinition; const AData: TArray<TScalar.TValue>);
end;
ISeries = interface
{$region 'private'}
@@ -197,7 +195,7 @@ type
function GetTotalCount: Int64;
function GetFields(const Key: IKeyword): ISeries;
{$endregion}
procedure Add(const Item: TScalarRecord; Lookback: Int64 = -1);
procedure Add(const Item: IScalarRecord; Lookback: Int64 = -1);
procedure AddRaw(const Data; Lookback: Int64 = -1);
property Count: Int64 read GetCount;
property Def: IScalarRecordDefinition read GetDef;
@@ -233,7 +231,7 @@ type
public
constructor Create(const ADef: IScalarRecordDefinition);
destructor Destroy; override;
procedure Add(const Item: TScalarRecord; Lookback: Int64 = -1);
procedure Add(const Item: IScalarRecord; Lookback: Int64 = -1);
// Copies data directly from the Data reference (zero-copy wrapper)
procedure AddRaw(const Data; Lookback: Int64 = -1);
@@ -801,36 +799,6 @@ begin
Items := AItems;
end;
{ TScalarRecord }
constructor TScalarRecord.Create(const ADef: IScalarRecordDefinition; const AFields: TArray<TScalar.TValue>);
begin
Assert(ADef.Count = Length(AFields), 'Field definition and value count must match.');
FDef := ADef;
FFields := AFields;
end;
function TScalarRecord.GetDef: IScalarRecordDefinition;
begin
Result := FDef;
end;
function TScalarRecord.GetFields: TArray<TScalar.TValue>;
begin
Result := FFields;
end;
function TScalarRecord.GetKeys(const Key: IKeyword): TScalar;
var
idx: Integer;
begin
idx := FDef.IndexOf(Key);
if idx < 0 then
raise EArgumentException.CreateFmt('Field ":%s" not found in record definition.', [Key.Name]);
Result.Create(FDef[idx].Value, FFields[idx]);
end;
{ TScalarRecordSeries }
constructor TScalarRecordSeries.Create(const ADef: IScalarRecordDefinition);
@@ -850,22 +818,23 @@ begin
inherited;
end;
procedure TScalarRecordSeries.Add(const Item: TScalarRecord; Lookback: Int64 = -1);
procedure TScalarRecordSeries.Add(const Item: IScalarRecord; Lookback: Int64 = -1);
begin
FArray.Add(Item.Fields, FDef.Count * Integer(Lookback));
var lb := FDef.Count * Integer(Lookback);
for var i := 0 to FDef.Count - 1 do
FArray.Add(Item[i].Value.Value, lb);
inc(FTotalCount);
end;
procedure TScalarRecordSeries.AddRaw(const Data; Lookback: Int64 = -1);
type
TValueArr = array[0..MaxInt div SizeOf(TScalar.TValue) - 1] of TScalar.TValue;
PValueArr = ^TValueArr;
var
len: Integer;
begin
len := FDef.Count;
// Use Slice to pass the raw data as an open array without copying.
FArray.Add(Slice(PValueArr(@Data)^, len), len * Integer(Lookback));
var lb := FDef.Count * Integer(Lookback);
var P: TScalar.PValue := @Data;
for var i := 0 to FDef.Count - 1 do
begin
FArray.Add(P^, lb);
inc(P);
end;
inc(FTotalCount);
end;
@@ -1042,6 +1011,45 @@ begin
Result := TScalar.FromInt64(sourceIndex);
end;
{ TScalarRecord }
constructor TScalarRecord.Create(const ADef: IScalarRecordDefinition; const AData: TArray<TScalar.TValue>);
begin
inherited Create;
FDef := ADef;
FData := AData;
end;
function TScalarRecord.GetCount: Integer;
begin
Result := FDef.Count;
end;
function TScalarRecord.GetFields(const Key: IKeyword): TScalar;
var
idx: Integer;
begin
idx := FDef.IndexOf(Key);
if idx < 0 then
exit(Default(TScalar));
// Return the raw TValue at the offset
Result.Kind := FDef[idx].Value;
Result.Value := FData[idx];
end;
function TScalarRecord.GetItems(Idx: Integer): TPair<IKeyword, TScalar>;
begin
Result.Key := FDef[Idx].Key;
Result.Value.Kind := FDef[idx].Value;
Result.Value.Value := FData[idx];
end;
function TScalarRecord.IndexOf(const Key: IKeyword): Integer;
begin
Result := FDef.IndexOf(Key);
end;
initialization
Assert(sizeof(TScalar.TValue) = 8);