146 lines
4.4 KiB
ObjectPascal
146 lines
4.4 KiB
ObjectPascal
unit Myc.Trade.DataConverter;
|
|
|
|
interface
|
|
|
|
uses
|
|
Myc.Signals,
|
|
Myc.Trade.Types,
|
|
Myc.Trade.DataPoint;
|
|
|
|
type
|
|
// Interface helper for IMycConverter<S,T> providing the null object pattern.
|
|
TConverter<S, T> = record
|
|
type
|
|
IConverter = interface(IMycProcessor<S>)
|
|
function GetSender: TDataProvider<T>.IDataProvider;
|
|
property Sender: TDataProvider<T>.IDataProvider read GetSender;
|
|
end;
|
|
|
|
{$REGION 'private'}
|
|
strict private
|
|
class var
|
|
FNull: IConverter;
|
|
class constructor CreateClass;
|
|
private
|
|
FConverter: IConverter;
|
|
function GetSender: TDataProvider<T>; inline;
|
|
{$ENDREGION}
|
|
public
|
|
constructor Create(const AConverter: IConverter);
|
|
|
|
// Managed record operators
|
|
class operator Initialize(out Dest: TConverter<S, T>);
|
|
class operator Implicit(const A: IConverter): TConverter<S, T>; overload;
|
|
class operator Implicit(const A: TConverter<S, T>): IConverter; overload;
|
|
|
|
class function CreateGeneric(const Func: TConstFunc<S, T>): TConverter<S, T>; static;
|
|
|
|
// Wrapper for IMycProcessor.ProcessData
|
|
function ProcessData(const Value: S): TState; inline;
|
|
|
|
function Chain<R>(const Next: TConverter<T, R>): TConverter<T, R>; overload; inline;
|
|
function Chain<R>(const Func: TConstFunc<T, R>): TConverter<T, R>; overload; inline;
|
|
|
|
function Field<R>(const FieldName: String): TConverter<T, R>; overload; inline;
|
|
|
|
// Provides access to the null object instance.
|
|
class property Null: IConverter read FNull;
|
|
// Wrapper for IMycConverter.Sender
|
|
property Sender: TDataProvider<T> read GetSender;
|
|
end;
|
|
|
|
TConverter = record
|
|
class function CreateCounter<T>: TConverter<T, Int64>; static;
|
|
class function CreateTicker<T>: TConverter<TArray<T>, T>; static;
|
|
class function CreateRecordField<S, T>(const FieldName: String): TConverter<S, T>; static;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
Myc.Trade.Core.DataConverter;
|
|
|
|
{ TConverter<S, T> }
|
|
|
|
class constructor TConverter<S, T>.CreateClass;
|
|
begin
|
|
// Create the singleton null object instance.
|
|
FNull := TNullConverter<S, T>.Create;
|
|
end;
|
|
|
|
constructor TConverter<S, T>.Create(const AConverter: IConverter);
|
|
begin
|
|
FConverter := AConverter;
|
|
// Ensure that the internal interface is never nil.
|
|
if not Assigned(FConverter) then
|
|
FConverter := FNull;
|
|
end;
|
|
|
|
function TConverter<S, T>.Chain<R>(const Next: TConverter<T, R>): TConverter<T, R>;
|
|
begin
|
|
FConverter.Sender.Link(Next);
|
|
Result := Next;
|
|
end;
|
|
|
|
function TConverter<S, T>.Chain<R>(const Func: TConstFunc<T, R>): TConverter<T, R>;
|
|
begin
|
|
Result := Chain<R>(TMycGenericConverter<T, R>.Create(Func));
|
|
end;
|
|
|
|
class function TConverter<S, T>.CreateGeneric(const Func: TConstFunc<S, T>): TConverter<S, T>;
|
|
begin
|
|
Result := TMycGenericConverter<S, T>.Create(Func);
|
|
end;
|
|
|
|
function TConverter<S, T>.Field<R>(const FieldName: String): TConverter<T, R>;
|
|
begin
|
|
Result := Chain<R>(TMycRecordFieldReader<T, R>.Create(FieldName));
|
|
end;
|
|
|
|
function TConverter<S, T>.GetSender: TDataProvider<T>;
|
|
begin
|
|
// Forward the call to the wrapped interface.
|
|
Result := FConverter.Sender;
|
|
end;
|
|
|
|
class operator TConverter<S, T>.Initialize(out Dest: TConverter<S, T>);
|
|
begin
|
|
// Initialize new record instances with the null object.
|
|
Dest.FConverter := FNull;
|
|
end;
|
|
|
|
class operator TConverter<S, T>.Implicit(const A: IConverter): TConverter<S, T>;
|
|
begin
|
|
// Allow implicit conversion from the interface to the helper.
|
|
Result.Create(A);
|
|
end;
|
|
|
|
class operator TConverter<S, T>.Implicit(const A: TConverter<S, T>): IConverter;
|
|
begin
|
|
// Allow implicit conversion from the helper to the interface.
|
|
Result := A.FConverter;
|
|
end;
|
|
|
|
function TConverter<S, T>.ProcessData(const Value: S): TState;
|
|
begin
|
|
// Forward the call to the wrapped interface.
|
|
Result := FConverter.ProcessData(Value);
|
|
end;
|
|
|
|
class function TConverter.CreateCounter<T>: TConverter<T, Int64>;
|
|
begin
|
|
Result := TMycDataCounter<T>.Create;
|
|
end;
|
|
|
|
class function TConverter.CreateRecordField<S, T>(const FieldName: String): TConverter<S, T>;
|
|
begin
|
|
Result := TMycRecordFieldReader<S, T>.Create(FieldName);
|
|
end;
|
|
|
|
class function TConverter.CreateTicker<T>: TConverter<TArray<T>, T>;
|
|
begin
|
|
Result := TMycTicker<T>.Create;
|
|
end;
|
|
|
|
end.
|