Unit refactoring

Fixed massive heap corruption bug in TDataRecord
This commit is contained in:
Michael Schimmel
2025-07-25 11:54:53 +02:00
parent 6b18d95570
commit aa53a88953
13 changed files with 461 additions and 359 deletions
+11 -24
View File
@@ -5,7 +5,6 @@ interface
uses
Myc.Signals,
Myc.Mutable,
Myc.Trade.Types,
Myc.Data.Series,
Myc.Data.Records;
@@ -31,6 +30,10 @@ type
property Consumer: IConsumer<S> read GetConsumer;
end;
TConvertFunc<S, T> = reference to function(const Value: S): T;
TBroadcastFunc<T> = reference to function(const Value: T): TState;
TAggregateFunc<S, T> = reference to function(const Value: S; const Broadcast: TBroadcastFunc<T>): TState;
// Interface helper for IProducer providing the null object pattern nad subscriptions for linked consumers.
TProducer<T> = record
public
@@ -64,7 +67,7 @@ type
// Chain consumers
function Chain(const Next: IConsumer<T>): IConsumer<T>; overload; inline;
function Chain<R>(const Next: IConverter<T, R>): TProducer<R>; overload; inline;
function Chain<R>(const Func: TConstFunc<T, R>): TProducer<R>; overload; inline;
function Chain<R>(const Func: TConvertFunc<T, R>): TProducer<R>; overload; inline;
// Extracts the field of a record by it's name (using RTTI).
function Field<R>(const FieldName: String): TProducer<R>; inline;
@@ -76,9 +79,6 @@ type
// Interface helper for IConverter<S,T> providing the null object pattern.
TConverter<S, T> = record
public
type
TBroadcastProc = reference to function(const Value: T): TState;
private
FConverter: IConverter<S, T>;
function GetConsumer: IConsumer<S>; inline;
@@ -94,8 +94,8 @@ type
class function Construct(const Consumer: IConsumer<S>; const Producer: TProducer<T>): TConverter<S, T>; static;
class function CreateConverter(const Func: TConstFunc<S, T>): TConverter<S, T>; static;
class function CreateAggregation(const Func: TConstFunc<S, TBroadcastProc, TState>): TConverter<S, T>; static;
class function CreateConverter(const Func: TConvertFunc<S, T>): TConverter<S, T>; static;
class function CreateAggregation(const Func: TAggregateFunc<S, T>): TConverter<S, T>; static;
property Consumer: IConsumer<S> read GetConsumer;
property Producer: TProducer<T> read GetProducer;
@@ -114,9 +114,6 @@ type
class function CreateTicker<T>: TConverter<TArray<T>, T>; static;
class function CreateIdentity<T>: TConverter<T, T>; static;
class function CreateTickAggregation(Timeframe: TTimeframe): TConverter<TDataPoint<Double>, TDataPoint<TOhlcItem>>; static;
class function CreateOhlcAggregation(Timeframe: TTimeframe): TConverter<TDataPoint<TOhlcItem>, TDataPoint<TOhlcItem>>; static;
class function CreateEndpoint<T>(Lookback: Int64; out Series: TLazy<TSeries<T>>): IConsumer<T>; static;
class function Join<T>(const Producers: TArray<TProducer<T>>): TProducer<TArray<T>>; static;
@@ -188,7 +185,7 @@ begin
Result := Next;
end;
function TProducer<T>.Chain<R>(const Func: TConstFunc<T, R>): TProducer<R>;
function TProducer<T>.Chain<R>(const Func: TConvertFunc<T, R>): TProducer<R>;
begin
Result := Chain<R>(TMycGenericConverter<T, R>.Create(Func));
end;
@@ -251,12 +248,12 @@ begin
Result := TMycComposedConverter<S, T>.Create(Consumer, Producer);
end;
class function TConverter<S, T>.CreateAggregation(const Func: TConstFunc<S, TBroadcastProc, TState>): TConverter<S, T>;
class function TConverter<S, T>.CreateAggregation(const Func: TAggregateFunc<S, T>): TConverter<S, T>;
begin
Result := TMycGenericAggregator<S, T>.Create(Func);
end;
class function TConverter<S, T>.CreateConverter(const Func: TConstFunc<S, T>): TConverter<S, T>;
class function TConverter<S, T>.CreateConverter(const Func: TConvertFunc<S, T>): TConverter<S, T>;
begin
Result := TMycGenericConverter<S, T>.Create(Func);
end;
@@ -291,11 +288,6 @@ begin
Result := A.FConverter;
end;
class function TConverter.CreateTickAggregation(Timeframe: TTimeframe): TConverter<TDataPoint<Double>, TDataPoint<TOhlcItem>>;
begin
Result := TTickAggregation.Create(Timeframe);
end;
{ TConverter }
class function TConverter.CreateCounter<T>: TConverter<T, Int64>;
@@ -318,11 +310,6 @@ begin
Result := TMycTicker<T>.Create;
end;
class function TConverter.CreateOhlcAggregation(Timeframe: TTimeframe): TConverter<TDataPoint<TOhlcItem>, TDataPoint<TOhlcItem>>;
begin
Result := TOhlcAggregation.Create(Timeframe);
end;
class function TConverter.DataMapping(
const Inputs: TArray<TRecordMapping>;
const Output: TDataRecord.TLayout
@@ -350,7 +337,7 @@ begin
Result := TDataRecord.Create(Output);
for var i := 0 to High(Idxs) do
for var j := 0 to High(Idxs[i]) do
Inputs[i].CopyField(Idxs[i][j].FromIdx, Result, Idxs[i][j].ToIdx);
Result.CopyValue(Inputs[i], Idxs[i][j].FromIdx, Idxs[i][j].ToIdx);
end
);
end;