From 42110e84719968a7405105f45c6d664ab4b886b0 Mon Sep 17 00:00:00 2001 From: Michael Schimmel Date: Mon, 25 Aug 2025 15:31:15 +0200 Subject: [PATCH] Data Types --- Src/Data/Myc.Data.Types.Arrays.pas | 146 ++++++++-- Src/Data/Myc.Data.Types.Enum.pas | 57 ++-- Src/Data/Myc.Data.Types.Float.pas | 114 ++++++-- Src/Data/Myc.Data.Types.Ordinal.pas | 137 +++++++-- Src/Data/Myc.Data.Types.Records.pas | 188 ++++++++++-- Src/Data/Myc.Data.Types.Text.pas | 73 +++-- Src/Data/Myc.Data.Types.Timestamp.pas | 35 +-- Src/Data/Myc.Data.Types.Tuple.pas | 396 ++++++++++++++++++++++++-- Src/Data/Myc.Data.Types.pas | 26 +- dirs.txt | 1 + 10 files changed, 980 insertions(+), 193 deletions(-) diff --git a/Src/Data/Myc.Data.Types.Arrays.pas b/Src/Data/Myc.Data.Types.Arrays.pas index 495f7bb..79d1fb1 100644 --- a/Src/Data/Myc.Data.Types.Arrays.pas +++ b/Src/Data/Myc.Data.Types.Arrays.pas @@ -8,12 +8,11 @@ uses Myc.Data.Types; type - TImplDataArrayValue = class; // fwd - // Implements the array data type. - TImplDataArrayType = class(TInterfacedObject, IDataType, IDataArrayType) + TDataArrayType = class(TInterfacedObject, IDataType, IDataArrayType) private FElementType: IDataType; + FEmptyValue: IDataArrayValue; // Cached empty array value for this type function GetElementType: IDataType; function GetName: String; function GetKind: TDataKind; @@ -22,8 +21,14 @@ type function CreateValue(const AItems: array of IDataValue): IDataArrayValue; end; +implementation + +uses + System.SyncObjs; + +type // Implements the array data value. - TImplDataArrayValue = class(TInterfacedObject, IDataValue, IDataArrayValue) + TDataArrayValue = class(TInterfacedObject, IDataValue, IDataArrayValue) private FArrayType: IDataArrayType; FItems: TArray; @@ -35,14 +40,34 @@ type constructor Create(const AArrayType: IDataArrayType; const AItems: array of IDataValue); end; -implementation + // Optimized implementation for an array with 0 elements. + TDataArrayValue0 = class(TInterfacedObject, IDataValue, IDataArrayValue) + private + FArrayType: IDataArrayType; + function GetDataType: IDataType; + function GetAsString: string; + function GetElementCount: Integer; + function GetItem(Idx: Integer): IDataValue; + public + constructor Create(const AArrayType: IDataArrayType); + end; -uses - System.SyncObjs; + // Optimized implementation for an array with 1 element. + TDataArrayValue1 = class(TInterfacedObject, IDataValue, IDataArrayValue) + private + FArrayType: IDataArrayType; + FItem0: IDataValue; + function GetDataType: IDataType; + function GetAsString: string; + function GetElementCount: Integer; + function GetItem(Idx: Integer): IDataValue; + public + constructor Create(const AArrayType: IDataArrayType; const AItems: array of IDataValue); + end; -{ TImplDataArrayValue } +{ TDataArrayValue (generic implementation for N > 1 elements) } -constructor TImplDataArrayValue.Create(const AArrayType: IDataArrayType; const AItems: array of IDataValue); +constructor TDataArrayValue.Create(const AArrayType: IDataArrayType; const AItems: array of IDataValue); var i: Integer; begin @@ -53,12 +78,12 @@ begin FItems[i] := AItems[i]; end; -function TImplDataArrayValue.GetDataType: IDataType; +function TDataArrayValue.GetDataType: IDataType; begin Result := FArrayType; end; -function TImplDataArrayValue.GetAsString: string; +function TDataArrayValue.GetAsString: string; var sb: TStringBuilder; i: Integer; @@ -79,28 +104,91 @@ begin end; end; -function TImplDataArrayValue.GetElementCount: Integer; +function TDataArrayValue.GetElementCount: Integer; begin Result := Length(FItems); end; -function TImplDataArrayValue.GetItem(Idx: Integer): IDataValue; +function TDataArrayValue.GetItem(Idx: Integer): IDataValue; begin Result := FItems[Idx]; end; -{ TImplDataArrayType } +{ TDataArrayValue0 } -constructor TImplDataArrayType.Create(const AElementType: IDataType); +constructor TDataArrayValue0.Create(const AArrayType: IDataArrayType); +begin + inherited Create; + FArrayType := AArrayType; +end; + +function TDataArrayValue0.GetAsString: string; +begin + Result := '[]'; +end; + +function TDataArrayValue0.GetDataType: IDataType; +begin + Result := FArrayType; +end; + +function TDataArrayValue0.GetElementCount: Integer; +begin + Result := 0; +end; + +function TDataArrayValue0.GetItem(Idx: Integer): IDataValue; +begin + raise EArgumentException.Create('Index out of bounds'); +end; + +{ TDataArrayValue1 } + +constructor TDataArrayValue1.Create(const AArrayType: IDataArrayType; const AItems: array of IDataValue); +begin + inherited Create; + FArrayType := AArrayType; + FItem0 := AItems[0]; +end; + +function TDataArrayValue1.GetAsString: string; +begin + Result := '[' + FItem0.AsString + ']'; +end; + +function TDataArrayValue1.GetDataType: IDataType; +begin + Result := FArrayType; +end; + +function TDataArrayValue1.GetElementCount: Integer; +begin + Result := 1; +end; + +function TDataArrayValue1.GetItem(Idx: Integer): IDataValue; +begin + case Idx of + 0: Result := FItem0; + else + raise EArgumentException.Create('Index out of bounds'); + end; +end; + +{ TDataArrayType } + +constructor TDataArrayType.Create(const AElementType: IDataType); begin inherited Create; FElementType := AElementType; + FEmptyValue := nil; end; -function TImplDataArrayType.CreateValue(const AItems: array of IDataValue): IDataArrayValue; +function TDataArrayType.CreateValue(const AItems: array of IDataValue): IDataArrayValue; var item: IDataValue; i: Integer; + newValue: IDataArrayValue; begin // Validate that all items match the element type of this array type. i := 0; @@ -112,20 +200,38 @@ begin [i, FElementType.Name, item.DataType.Name]); inc(i); end; - Result := TImplDataArrayValue.Create(Self, AItems); + + // Use optimized implementations for arrays with 0 or 1 elements. + case Length(AItems) of + 0: + begin + // Thread-safe lazy initialization for the cached empty array value. + if FEmptyValue = nil then + begin + newValue := TDataArrayValue0.Create(Self); + if TInterlocked.CompareExchange(Pointer(FEmptyValue), Pointer(newValue), nil) <> nil then + newValue := nil; // Another thread won, discard our instance. + end; + Result := FEmptyValue; + end; + 1: Result := TDataArrayValue1.Create(Self, AItems); + else + // Use the generic implementation for arrays with more than 1 element. + Result := TDataArrayValue.Create(Self, AItems); + end; end; -function TImplDataArrayType.GetElementType: IDataType; +function TDataArrayType.GetElementType: IDataType; begin Result := FElementType; end; -function TImplDataArrayType.GetName: String; +function TDataArrayType.GetName: String; begin Result := Format('Array<%s>', [FElementType.Name]); end; -function TImplDataArrayType.GetKind: TDataKind; +function TDataArrayType.GetKind: TDataKind; begin Result := dkArray; end; diff --git a/Src/Data/Myc.Data.Types.Enum.pas b/Src/Data/Myc.Data.Types.Enum.pas index a4a56ed..c45d999 100644 --- a/Src/Data/Myc.Data.Types.Enum.pas +++ b/Src/Data/Myc.Data.Types.Enum.pas @@ -8,18 +8,7 @@ uses Myc.Data.Types; type - TImplDataEnumValue = class(TInterfacedObject, IDataEnumValue) - private - FDataType: IDataEnumType; - FValue: Integer; - function GetDataType: IDataType; - function GetAsString: string; - function GetValue: Integer; - public - constructor Create(const ADataType: IDataEnumType; const AValue: Integer); - end; - - TImplDataEnumType = class(TInterfacedObject, IDataEnumType) + TDataEnumType = class(TInterfacedObject, IDataEnumType) private FName: string; FIdentifiers: TArray; @@ -38,9 +27,21 @@ type implementation -{ TImplDataEnumType } +type + TDataEnumValue = class(TInterfacedObject, IDataEnumValue) + private + FDataType: IDataEnumType; + FValue: Integer; + function GetDataType: IDataType; + function GetAsString: string; + function GetValue: Integer; + public + constructor Create(const ADataType: IDataEnumType; const AValue: Integer); + end; -constructor TImplDataEnumType.Create(const AName: string; const AIdentifiers: array of string); +{ TDataEnumType } + +constructor TDataEnumType.Create(const AName: string; const AIdentifiers: array of string); var i: Integer; begin @@ -57,46 +58,46 @@ begin end; end; -destructor TImplDataEnumType.Destroy; +destructor TDataEnumType.Destroy; begin FIdentifierMap.Free; inherited; end; -function TImplDataEnumType.GetName: String; +function TDataEnumType.GetName: String; begin Result := FName; end; -function TImplDataEnumType.GetKind: TDataKind; +function TDataEnumType.GetKind: TDataKind; begin Result := dkEnum; end; -function TImplDataEnumType.GetIdentifier(Idx: Integer): string; +function TDataEnumType.GetIdentifier(Idx: Integer): string; begin Result := FIdentifiers[Idx]; end; -function TImplDataEnumType.GetIdentifierCount: Integer; +function TDataEnumType.GetIdentifierCount: Integer; begin Result := Length(FIdentifiers); end; -function TImplDataEnumType.IndexOf(const AIdentifier: string): Integer; +function TDataEnumType.IndexOf(const AIdentifier: string): Integer; begin if not FIdentifierMap.TryGetValue(AIdentifier, Result) then Result := -1; end; -function TImplDataEnumType.CreateValue(const AValue: Integer): IDataEnumValue; +function TDataEnumType.CreateValue(const AValue: Integer): IDataEnumValue; begin if (AValue < 0) or (AValue >= Length(FIdentifiers)) then raise EArgumentException.Create('Invalid enum value'); - Result := TImplDataEnumValue.Create(Self, AValue); + Result := TDataEnumValue.Create(Self, AValue); end; -function TImplDataEnumType.CreateValue(const AIdentifier: string): IDataEnumValue; +function TDataEnumType.CreateValue(const AIdentifier: string): IDataEnumValue; var idx: Integer; begin @@ -106,25 +107,25 @@ begin Result := CreateValue(idx); end; -{ TImplDataEnumValue } +{ TDataEnumValue } -constructor TImplDataEnumValue.Create(const ADataType: IDataEnumType; const AValue: Integer); +constructor TDataEnumValue.Create(const ADataType: IDataEnumType; const AValue: Integer); begin FDataType := ADataType; FValue := AValue; end; -function TImplDataEnumValue.GetDataType: IDataType; +function TDataEnumValue.GetDataType: IDataType; begin Result := FDataType; end; -function TImplDataEnumValue.GetAsString: string; +function TDataEnumValue.GetAsString: string; begin Result := FDataType.Identifiers[FValue]; end; -function TImplDataEnumValue.GetValue: Integer; +function TDataEnumValue.GetValue: Integer; begin Result := FValue; end; diff --git a/Src/Data/Myc.Data.Types.Float.pas b/Src/Data/Myc.Data.Types.Float.pas index 1434870..77602ea 100644 --- a/Src/Data/Myc.Data.Types.Float.pas +++ b/Src/Data/Myc.Data.Types.Float.pas @@ -6,9 +6,30 @@ uses System.SysUtils, Myc.Data.Types; +type + // Implements the float data type. + TDataFloatType = class(TInterfacedObject, IDataType, IDataFloatType) + strict private + class var + FSingleton: IDataFloatType; + FZero: IDataFloatValue; + FNaN: IDataFloatValue; + class constructor CreateClass; + public + function GetName: String; + function GetKind: TDataKind; + function CreateValue(Init: Double): IDataFloatValue; + class property Singleton: IDataFloatType read FSingleton; + end; + +implementation + +uses + System.Math; + type // Implements the float data value. - TImplDataFloatValue = class(TInterfacedObject, IDataValue, IDataFloatValue) + TDataFloatValue = class(TInterfacedObject, IDataValue, IDataFloatValue) private FValue: Double; public @@ -22,64 +43,107 @@ type function GetValue: Double; end; - // Implements the float data type. - TImplDataFloatType = class(TInterfacedObject, IDataType, IDataFloatType) - strict private - class var - FSingleton: IDataFloatType; - class constructor CreateClass; + // Special implementation for the value 0.0 (Singleton) + TDataFloatValueZero = class(TInterfacedObject, IDataValue, IDataFloatValue) public - function GetName: String; - function GetKind: TDataKind; - function CreateValue(Init: Double): IDataFloatValue; - class property Singleton: IDataFloatType read FSingleton; + function GetDataType: IDataType; + function GetAsString: string; + function GetValue: Double; end; -implementation + // Special implementation for NaN (Not a Number) (Singleton) + TDataFloatValueNaN = class(TInterfacedObject, IDataValue, IDataFloatValue) + public + function GetDataType: IDataType; + function GetAsString: string; + function GetValue: Double; + end; -{ TImplDataFloatValue } +{ TDataFloatValue } -constructor TImplDataFloatValue.Create(const AValue: Double); +constructor TDataFloatValue.Create(const AValue: Double); begin inherited Create; FValue := AValue; end; -function TImplDataFloatValue.GetDataType: IDataType; +function TDataFloatValue.GetDataType: IDataType; begin - Result := TImplDataFloatType.Singleton; + Result := TDataFloatType.Singleton; end; -function TImplDataFloatValue.GetAsString: string; +function TDataFloatValue.GetAsString: string; begin Result := FloatToStr(FValue); end; -function TImplDataFloatValue.GetValue: Double; +function TDataFloatValue.GetValue: Double; begin Result := FValue; end; -{ TImplDataFloatType } +{ TDataFloatValueZero } -class constructor TImplDataFloatType.CreateClass; +function TDataFloatValueZero.GetAsString: string; begin - FSingleton := TImplDataFloatType.Create; + Result := '0'; end; -function TImplDataFloatType.GetName: String; +function TDataFloatValueZero.GetDataType: IDataType; +begin + Result := TDataFloatType.Singleton; +end; + +function TDataFloatValueZero.GetValue: Double; +begin + Result := 0.0; +end; + +{ TDataFloatValueNaN } + +function TDataFloatValueNaN.GetAsString: string; +begin + Result := 'NaN'; +end; + +function TDataFloatValueNaN.GetDataType: IDataType; +begin + Result := TDataFloatType.Singleton; +end; + +function TDataFloatValueNaN.GetValue: Double; +begin + Result := NaN; +end; + +{ TDataFloatType } + +class constructor TDataFloatType.CreateClass; +begin + FSingleton := TDataFloatType.Create; + FZero := TDataFloatValueZero.Create; + FNaN := TDataFloatValueNaN.Create; +end; + +function TDataFloatType.GetName: String; begin Result := 'Float'; end; -function TImplDataFloatType.GetKind: TDataKind; +function TDataFloatType.GetKind: TDataKind; begin Result := dkFloat; end; -function TImplDataFloatType.CreateValue(Init: Double): IDataFloatValue; +function TDataFloatType.CreateValue(Init: Double): IDataFloatValue; begin - Result := TImplDataFloatValue.Create(Init); + // Return singleton instances for 0.0 and NaN to avoid unnecessary allocations. + if (Init = 0.0) then + Result := FZero + else if IsNaN(Init) then + Result := FNaN + else + Result := TDataFloatValue.Create(Init); end; end. diff --git a/Src/Data/Myc.Data.Types.Ordinal.pas b/Src/Data/Myc.Data.Types.Ordinal.pas index 96e41e2..33728c6 100644 --- a/Src/Data/Myc.Data.Types.Ordinal.pas +++ b/Src/Data/Myc.Data.Types.Ordinal.pas @@ -6,9 +6,26 @@ uses Myc.Data.Types, System.SysUtils; +type + // Implements the ordinal data type. + TDataOrdinalType = class(TInterfacedObject, IDataType, IDataOrdinalType) + strict private + class var + FSingleton: IDataOrdinalType; + FMinusOne, FZero, FOne: IDataOrdinalValue; // Singletons for -1, 0, 1 + class constructor CreateClass; + public + function GetName: String; + function GetKind: TDataKind; + function CreateValue(Init: Int64): IDataOrdinalValue; + class property Singleton: IDataOrdinalType read FSingleton; + end; + +implementation + type // Implements the ordinal data value. - TImplDataOrdinalValue = class(TInterfacedObject, IDataValue, IDataOrdinalValue) + TDataOrdinalValue = class(TInterfacedObject, IDataValue, IDataOrdinalValue) private FValue: Int64; public @@ -22,64 +39,134 @@ type function GetValue: Int64; end; - // Implements the ordinal data type. - TImplDataOrdinalType = class(TInterfacedObject, IDataType, IDataOrdinalType) - strict private - class var - FSingleton: IDataOrdinalType; - class constructor CreateClass; + // Specialized implementation for the value -1. + TDataOrdinalValueMinusOne = class(TInterfacedObject, IDataValue, IDataOrdinalValue) public - function GetName: String; - function GetKind: TDataKind; - function CreateValue(Init: Int64): IDataOrdinalValue; - class property Singleton: IDataOrdinalType read FSingleton; + function GetDataType: IDataType; + function GetAsString: string; + function GetValue: Int64; end; -implementation + // Specialized implementation for the value 0. + TDataOrdinalValueZero = class(TInterfacedObject, IDataValue, IDataOrdinalValue) + public + function GetDataType: IDataType; + function GetAsString: string; + function GetValue: Int64; + end; -{ TImplDataOrdinalValue } + // Specialized implementation for the value 1. + TDataOrdinalValueOne = class(TInterfacedObject, IDataValue, IDataOrdinalValue) + public + function GetDataType: IDataType; + function GetAsString: string; + function GetValue: Int64; + end; -constructor TImplDataOrdinalValue.Create(const AValue: Int64); +{ TDataOrdinalValue } + +constructor TDataOrdinalValue.Create(const AValue: Int64); begin inherited Create; FValue := AValue; end; -function TImplDataOrdinalValue.GetDataType: IDataType; +function TDataOrdinalValue.GetDataType: IDataType; begin - Result := TImplDataOrdinalType.Singleton; + Result := TDataOrdinalType.Singleton; end; -function TImplDataOrdinalValue.GetAsString: string; +function TDataOrdinalValue.GetAsString: string; begin Result := FValue.ToString; end; -function TImplDataOrdinalValue.GetValue: Int64; +function TDataOrdinalValue.GetValue: Int64; begin Result := FValue; end; -{ TImplDataOrdinalType } +{ TDataOrdinalValueMinusOne } -class constructor TImplDataOrdinalType.CreateClass; +function TDataOrdinalValueMinusOne.GetDataType: IDataType; begin - FSingleton := TImplDataOrdinalType.Create; + Result := TDataOrdinalType.Singleton; end; -function TImplDataOrdinalType.GetName: String; +function TDataOrdinalValueMinusOne.GetAsString: string; +begin + Result := '-1'; +end; + +function TDataOrdinalValueMinusOne.GetValue: Int64; +begin + Result := -1; +end; + +{ TDataOrdinalValueZero } + +function TDataOrdinalValueZero.GetDataType: IDataType; +begin + Result := TDataOrdinalType.Singleton; +end; + +function TDataOrdinalValueZero.GetAsString: string; +begin + Result := '0'; +end; + +function TDataOrdinalValueZero.GetValue: Int64; +begin + Result := 0; +end; + +{ TDataOrdinalValueOne } + +function TDataOrdinalValueOne.GetDataType: IDataType; +begin + Result := TDataOrdinalType.Singleton; +end; + +function TDataOrdinalValueOne.GetAsString: string; +begin + Result := '1'; +end; + +function TDataOrdinalValueOne.GetValue: Int64; +begin + Result := 1; +end; + +{ TDataOrdinalType } + +class constructor TDataOrdinalType.CreateClass; +begin + FSingleton := TDataOrdinalType.Create; + FMinusOne := TDataOrdinalValueMinusOne.Create; + FZero := TDataOrdinalValueZero.Create; + FOne := TDataOrdinalValueOne.Create; +end; + +function TDataOrdinalType.GetName: String; begin Result := 'Integer'; end; -function TImplDataOrdinalType.GetKind: TDataKind; +function TDataOrdinalType.GetKind: TDataKind; begin Result := dkOrdinal; end; -function TImplDataOrdinalType.CreateValue(Init: Int64): IDataOrdinalValue; +function TDataOrdinalType.CreateValue(Init: Int64): IDataOrdinalValue; begin - Result := TImplDataOrdinalValue.Create(Init); + // Use specialized singletons for common values. + case Init of + -1: Result := FMinusOne; + 0: Result := FZero; + 1: Result := FOne; + else + Result := TDataOrdinalValue.Create(Init); + end; end; end. diff --git a/Src/Data/Myc.Data.Types.Records.pas b/Src/Data/Myc.Data.Types.Records.pas index 5cfe38c..16f650b 100644 --- a/Src/Data/Myc.Data.Types.Records.pas +++ b/Src/Data/Myc.Data.Types.Records.pas @@ -17,10 +17,8 @@ type function GetHashCode(const Value: TArray): Integer; reintroduce; end; - TImplDataRecordValue = class; // fwd - // Implements the record data type. - TImplDataRecordType = class(TInterfacedObject, IDataType, IDataRecordType) + TDataRecordType = class(TInterfacedObject, IDataType, IDataRecordType) private FFields: TArray; FFieldMap: TDictionary; // For fast lookups by name @@ -35,8 +33,14 @@ type function CreateValue(const AItems: array of IDataValue): IDataRecordValue; end; +implementation + +uses + System.SyncObjs; + +type // Implements the record data value. - TImplDataRecordValue = class(TInterfacedObject, IDataValue, IDataRecordValue) + TDataRecordValue = class(TInterfacedObject, IDataValue, IDataRecordValue) private FDataType: IDataRecordType; FItems: TArray; @@ -47,10 +51,40 @@ type constructor Create(const ADataType: IDataRecordType; const AItems: array of IDataValue); end; -implementation + // Optimized implementation for a record with 0 fields. + TDataRecordValue0 = class(TInterfacedObject, IDataValue, IDataRecordValue) + private + FDataType: IDataRecordType; + function GetDataType: IDataType; + function GetAsString: string; + function GetItem(Idx: Integer): IDataValue; + public + constructor Create(const ADataType: IDataRecordType); + end; -uses - System.SyncObjs; + // Optimized implementation for a record with 1 field. + TDataRecordValue1 = class(TInterfacedObject, IDataValue, IDataRecordValue) + private + FDataType: IDataRecordType; + FItem0: IDataValue; + function GetDataType: IDataType; + function GetAsString: string; + function GetItem(Idx: Integer): IDataValue; + public + constructor Create(const ADataType: IDataRecordType; const AItems: array of IDataValue); + end; + + // Optimized implementation for a record with 2 fields. + TDataRecordValue2 = class(TInterfacedObject, IDataValue, IDataRecordValue) + private + FDataType: IDataRecordType; + FItem0, FItem1: IDataValue; + function GetDataType: IDataType; + function GetAsString: string; + function GetItem(Idx: Integer): IDataValue; + public + constructor Create(const ADataType: IDataRecordType; const AItems: array of IDataValue); + end; { TRecordFieldComparer } @@ -80,9 +114,9 @@ begin end; end; -{ TImplDataRecordValue } +{ TDataRecordValue (generic implementation for N > 2 fields) } -constructor TImplDataRecordValue.Create(const ADataType: IDataRecordType; const AItems: array of IDataValue); +constructor TDataRecordValue.Create(const ADataType: IDataRecordType; const AItems: array of IDataValue); var i: Integer; begin @@ -93,12 +127,12 @@ begin FItems[i] := AItems[i]; end; -function TImplDataRecordValue.GetDataType: IDataType; +function TDataRecordValue.GetDataType: IDataType; begin Result := FDataType; end; -function TImplDataRecordValue.GetAsString: string; +function TDataRecordValue.GetAsString: string; var sb: TStringBuilder; i: Integer; @@ -123,14 +157,116 @@ begin end; end; -function TImplDataRecordValue.GetItem(Idx: Integer): IDataValue; +function TDataRecordValue.GetItem(Idx: Integer): IDataValue; begin Result := FItems[Idx]; end; -{ TImplDataRecordType } +{ TDataRecordValue0 } -constructor TImplDataRecordType.Create(const AFields: array of TRecordField); +constructor TDataRecordValue0.Create(const ADataType: IDataRecordType); +begin + inherited Create; + FDataType := ADataType; +end; + +function TDataRecordValue0.GetAsString: string; +begin + Result := '<>'; +end; + +function TDataRecordValue0.GetDataType: IDataType; +begin + Result := FDataType; +end; + +function TDataRecordValue0.GetItem(Idx: Integer): IDataValue; +begin + raise EArgumentException.Create('Index out of bounds'); +end; + +{ TDataRecordValue1 } + +constructor TDataRecordValue1.Create(const ADataType: IDataRecordType; const AItems: array of IDataValue); +begin + inherited Create; + FDataType := ADataType; + FItem0 := AItems[0]; +end; + +function TDataRecordValue1.GetAsString: string; +var + recordType: IDataRecordType; +begin + recordType := FDataType; + Result := Format('<%s: %s>', [recordType.Fields[0].Name, FItem0.AsString]); +end; + +function TDataRecordValue1.GetDataType: IDataType; +begin + Result := FDataType; +end; + +function TDataRecordValue1.GetItem(Idx: Integer): IDataValue; +begin + case Idx of + 0: Result := FItem0; + else + raise EArgumentException.Create('Index out of bounds'); + end; +end; + +{ TDataRecordValue2 } + +constructor TDataRecordValue2.Create(const ADataType: IDataRecordType; const AItems: array of IDataValue); +begin + inherited Create; + FDataType := ADataType; + FItem0 := AItems[0]; + FItem1 := AItems[1]; +end; + +function TDataRecordValue2.GetAsString: string; +var + recordType: IDataRecordType; + sb: TStringBuilder; +begin + recordType := FDataType; + sb := TStringBuilder.Create; + try + sb.Append('<'); + sb.Append(recordType.Fields[0].Name); + sb.Append(': '); + sb.Append(FItem0.AsString); + sb.Append(', '); + sb.Append(recordType.Fields[1].Name); + sb.Append(': '); + sb.Append(FItem1.AsString); + sb.Append('>'); + Result := sb.ToString; + finally + sb.Free; + end; +end; + +function TDataRecordValue2.GetDataType: IDataType; +begin + Result := FDataType; +end; + +function TDataRecordValue2.GetItem(Idx: Integer): IDataValue; +begin + case Idx of + 0: Result := FItem0; + 1: Result := FItem1; + else + raise EArgumentException.Create('Index out of bounds'); + end; +end; + +{ TDataRecordType } + +constructor TDataRecordType.Create(const AFields: array of TRecordField); var i: Integer; field: TRecordField; @@ -148,13 +284,13 @@ begin end; end; -destructor TImplDataRecordType.Destroy; +destructor TDataRecordType.Destroy; begin FFieldMap.Free; inherited; end; -function TImplDataRecordType.CreateValue(const AItems: array of IDataValue): IDataRecordValue; +function TDataRecordType.CreateValue(const AItems: array of IDataValue): IDataRecordValue; var i: Integer; begin @@ -168,20 +304,28 @@ begin 'Invalid data type for field ''%s'' at index %d. Expected ''%s'', but got ''%s''.', [FFields[i].Name, i, FFields[i].DataType.Name, AItems[i].DataType.Name]); - Result := TImplDataRecordValue.Create(Self, AItems); + // Use optimized implementations for records with 0, 1, or 2 fields. + case Length(FFields) of + 0: Result := TDataRecordValue0.Create(Self); + 1: Result := TDataRecordValue1.Create(Self, AItems); + 2: Result := TDataRecordValue2.Create(Self, AItems); + else + // Use the generic implementation for records with more than 2 fields. + Result := TDataRecordValue.Create(Self, AItems); + end; end; -function TImplDataRecordType.GetField(Idx: Integer): TRecordField; +function TDataRecordType.GetField(Idx: Integer): TRecordField; begin Result := FFields[Idx]; end; -function TImplDataRecordType.GetFieldCount: Integer; +function TDataRecordType.GetFieldCount: Integer; begin Result := Length(FFields); end; -function TImplDataRecordType.GetName: String; +function TDataRecordType.GetName: String; var i: Integer; sb: TStringBuilder; @@ -204,12 +348,12 @@ begin end; end; -function TImplDataRecordType.GetKind: TDataKind; +function TDataRecordType.GetKind: TDataKind; begin Result := dkRecord; end; -function TImplDataRecordType.IndexOf(const AName: string): Integer; +function TDataRecordType.IndexOf(const AName: string): Integer; begin if not FFieldMap.TryGetValue(AName, Result) then Result := -1; diff --git a/Src/Data/Myc.Data.Types.Text.pas b/Src/Data/Myc.Data.Types.Text.pas index 74237eb..0908f26 100644 --- a/Src/Data/Myc.Data.Types.Text.pas +++ b/Src/Data/Myc.Data.Types.Text.pas @@ -7,7 +7,7 @@ uses Myc.Data.Types; type - TImplDataTextType = class(TInterfacedObject, IDataType, IDataTextType) + TDataTextType = class(TInterfacedObject, IDataType, IDataTextType) strict private class var FSingleton: IDataTextType; @@ -19,7 +19,10 @@ type class property Singleton: IDataTextType read FSingleton; end; - TImplDataTextValue = class(TInterfacedObject, IDataValue, IDataTextValue) +implementation + +type + TDataTextValue = class(TInterfacedObject, IDataValue, IDataTextValue) private FValue: string; function GetDataType: IDataType; @@ -29,51 +32,89 @@ type constructor Create(const AValue: string); end; -implementation + // Singleton implementation for the empty string value. + TDataTextValueEmpty = class(TInterfacedObject, IDataValue, IDataTextValue) + strict private + class var + FSingleton: IDataTextValue; + class constructor CreateClass; + private + function GetDataType: IDataType; + function GetAsString: string; + function GetValue: string; + public + class property Singleton: IDataTextValue read FSingleton; + end; -{ TImplDataTextType } +{ TDataTextType } -class constructor TImplDataTextType.CreateClass; +class constructor TDataTextType.CreateClass; begin - FSingleton := TImplDataTextType.Create; + FSingleton := TDataTextType.Create; end; -function TImplDataTextType.CreateValue(const AValue: string): IDataTextValue; +function TDataTextType.CreateValue(const AValue: string): IDataTextValue; begin - Result := TImplDataTextValue.Create(AValue); + // Use the singleton for empty strings. + if (AValue = '') then + Result := TDataTextValueEmpty.Singleton + else + Result := TDataTextValue.Create(AValue); end; -function TImplDataTextType.GetName: String; +function TDataTextType.GetName: String; begin Result := 'Text'; end; -function TImplDataTextType.GetKind: TDataKind; +function TDataTextType.GetKind: TDataKind; begin Result := dkText; end; -{ TImplDataTextValue } +{ TDataTextValue } -constructor TImplDataTextValue.Create(const AValue: string); +constructor TDataTextValue.Create(const AValue: string); begin inherited Create; FValue := AValue; end; -function TImplDataTextValue.GetDataType: IDataType; +function TDataTextValue.GetDataType: IDataType; begin - Result := TImplDataTextType.Singleton; + Result := TDataTextType.Singleton; end; -function TImplDataTextValue.GetAsString: string; +function TDataTextValue.GetAsString: string; begin Result := FValue; end; -function TImplDataTextValue.GetValue: string; +function TDataTextValue.GetValue: string; begin Result := FValue; end; +{ TDataTextValueEmpty } + +class constructor TDataTextValueEmpty.CreateClass; +begin + FSingleton := TDataTextValueEmpty.Create; +end; + +function TDataTextValueEmpty.GetAsString: string; +begin + Result := ''; +end; + +function TDataTextValueEmpty.GetDataType: IDataType; +begin + Result := TDataTextType.Singleton; +end; + +function TDataTextValueEmpty.GetValue: string; +begin + Result := ''; +end; + end. diff --git a/Src/Data/Myc.Data.Types.Timestamp.pas b/Src/Data/Myc.Data.Types.Timestamp.pas index d18b959..9a50400 100644 --- a/Src/Data/Myc.Data.Types.Timestamp.pas +++ b/Src/Data/Myc.Data.Types.Timestamp.pas @@ -7,7 +7,7 @@ uses Myc.Data.Types; type - TImplDataTimestampType = class(TInterfacedObject, IDataType, IDataTimestampType) + TDataTimestampType = class(TInterfacedObject, IDataType, IDataTimestampType) strict private class var FSingleton: IDataTimestampType; @@ -19,7 +19,10 @@ type class property Singleton: IDataTimestampType read FSingleton; end; - TImplDataTimestampValue = class(TInterfacedObject, IDataValue, IDataTimestampValue) +implementation + +type + TDataTimestampValue = class(TInterfacedObject, IDataValue, IDataTimestampValue) private FValue: TDateTime; function GetDataType: IDataType; @@ -29,49 +32,47 @@ type constructor Create(const AValue: TDateTime); end; -implementation +{ TDataTimestampType } -{ TImplDataTimestampType } - -class constructor TImplDataTimestampType.CreateClass; +class constructor TDataTimestampType.CreateClass; begin - FSingleton := TImplDataTimestampType.Create; + FSingleton := TDataTimestampType.Create; end; -function TImplDataTimestampType.CreateValue(const AValue: TDateTime): IDataTimestampValue; +function TDataTimestampType.CreateValue(const AValue: TDateTime): IDataTimestampValue; begin - Result := TImplDataTimestampValue.Create(AValue); + Result := TDataTimestampValue.Create(AValue); end; -function TImplDataTimestampType.GetName: String; +function TDataTimestampType.GetName: String; begin Result := 'Timestamp'; end; -function TImplDataTimestampType.GetKind: TDataKind; +function TDataTimestampType.GetKind: TDataKind; begin Result := dkTimestamp; end; -{ TImplDataTimestampValue } +{ TDataTimestampValue } -constructor TImplDataTimestampValue.Create(const AValue: TDateTime); +constructor TDataTimestampValue.Create(const AValue: TDateTime); begin inherited Create; FValue := AValue; end; -function TImplDataTimestampValue.GetDataType: IDataType; +function TDataTimestampValue.GetDataType: IDataType; begin - Result := TImplDataTimestampType.Singleton; + Result := TDataTimestampType.Singleton; end; -function TImplDataTimestampValue.GetAsString: string; +function TDataTimestampValue.GetAsString: string; begin Result := DateTimeToStr(FValue); end; -function TImplDataTimestampValue.GetValue: TDateTime; +function TDataTimestampValue.GetValue: TDateTime; begin Result := FValue; end; diff --git a/Src/Data/Myc.Data.Types.Tuple.pas b/Src/Data/Myc.Data.Types.Tuple.pas index f905e20..7610672 100644 --- a/Src/Data/Myc.Data.Types.Tuple.pas +++ b/Src/Data/Myc.Data.Types.Tuple.pas @@ -7,20 +7,8 @@ uses Myc.Data.Types; type - // Implements the simple tuple data value. - TImplDataTupleValue = class(TInterfacedObject, IDataValue, IDataTupleValue) - private - FItems: TArray; - function GetDataType: IDataType; - function GetAsString: string; - function GetItemCount: Integer; - function GetItem(Idx: Integer): IDataValue; - public - constructor Create(const AItems: array of IDataValue); - end; - // Implements the singleton tuple data type. - TImplDataTupleType = class(TInterfacedObject, IDataType, IDataTupleType) + TDataTupleType = class(TInterfacedObject, IDataType, IDataTupleType) strict private class var FSingleton: IDataTupleType; @@ -35,9 +23,97 @@ type implementation -{ TImplDataTupleValue } +type + // Implements the simple tuple data value. + TDataTupleValue = class(TInterfacedObject, IDataValue, IDataTupleValue) + private + FItems: TArray; + function GetDataType: IDataType; + function GetAsString: string; + function GetItemCount: Integer; + function GetItem(Idx: Integer): IDataValue; + public + constructor Create(const AItems: array of IDataValue); + end; -constructor TImplDataTupleValue.Create(const AItems: array of IDataValue); + // Optimized singleton implementation for a tuple with 0 elements. + TDataTupleValue0 = class(TInterfacedObject, IDataValue, IDataTupleValue) + strict private + class var + FSingleton: IDataTupleValue; + class constructor CreateClass; + private + function GetDataType: IDataType; + function GetAsString: string; + function GetItemCount: Integer; + function GetItem(Idx: Integer): IDataValue; + public + class property Singleton: IDataTupleValue read FSingleton; + end; + + // Optimized implementation for a tuple with 1 element. + TDataTupleValue1 = class(TInterfacedObject, IDataValue, IDataTupleValue) + private + FItem0: IDataValue; + function GetDataType: IDataType; + function GetAsString: string; + function GetItemCount: Integer; + function GetItem(Idx: Integer): IDataValue; + public + constructor Create(const AItems: array of IDataValue); + end; + + // Optimized implementation for a tuple with 2 elements. + TDataTupleValue2 = class(TInterfacedObject, IDataValue, IDataTupleValue) + private + FItem0, FItem1: IDataValue; + function GetDataType: IDataType; + function GetAsString: string; + function GetItemCount: Integer; + function GetItem(Idx: Integer): IDataValue; + public + constructor Create(const AItems: array of IDataValue); + end; + + // Optimized implementation for a tuple with 3 elements. + TDataTupleValue3 = class(TInterfacedObject, IDataValue, IDataTupleValue) + private + FItem0, FItem1, FItem2: IDataValue; + function GetDataType: IDataType; + function GetAsString: string; + function GetItemCount: Integer; + function GetItem(Idx: Integer): IDataValue; + public + constructor Create(const AItems: array of IDataValue); + end; + + // Optimized implementation for a tuple with 4 elements. + TDataTupleValue4 = class(TInterfacedObject, IDataValue, IDataTupleValue) + private + FItem0, FItem1, FItem2, FItem3: IDataValue; + function GetDataType: IDataType; + function GetAsString: string; + function GetItemCount: Integer; + function GetItem(Idx: Integer): IDataValue; + public + constructor Create(const AItems: array of IDataValue); + end; + + // Optimized implementation for a tuple with 5 elements. + TDataTupleValue5 = class(TInterfacedObject, IDataValue, IDataTupleValue) + private + FItem0, FItem1, FItem2, FItem3, FItem4: IDataValue; + function GetDataType: IDataType; + function GetAsString: string; + function GetItemCount: Integer; + function GetItem(Idx: Integer): IDataValue; + public + constructor Create(const AItems: array of IDataValue); + end; + +{ TDataTupleValue (generic implementation for N > 5 elements) } + +constructor TDataTupleValue.Create(const AItems: array of IDataValue); var i: Integer; begin @@ -47,12 +123,12 @@ begin FItems[i] := AItems[i]; end; -function TImplDataTupleValue.GetDataType: IDataType; +function TDataTupleValue.GetDataType: IDataType; begin - Result := TImplDataTupleType.Singleton; + Result := TDataTupleType.Singleton; end; -function TImplDataTupleValue.GetAsString: string; +function TDataTupleValue.GetAsString: string; var sb: TStringBuilder; i: Integer; @@ -73,34 +149,300 @@ begin end; end; -function TImplDataTupleValue.GetItem(Idx: Integer): IDataValue; +function TDataTupleValue.GetItem(Idx: Integer): IDataValue; begin Result := FItems[Idx]; end; -function TImplDataTupleValue.GetItemCount: Integer; +function TDataTupleValue.GetItemCount: Integer; begin Result := Length(FItems); end; -{ TImplDataTupleType } +{ TDataTupleValue0 } -class constructor TImplDataTupleType.CreateClass; +class constructor TDataTupleValue0.CreateClass; begin - FSingleton := TImplDataTupleType.Create; + FSingleton := TDataTupleValue0.Create; end; -function TImplDataTupleType.CreateValue(const AItems: array of IDataValue): IDataTupleValue; +function TDataTupleValue0.GetAsString: string; begin - Result := TImplDataTupleValue.Create(AItems); + Result := '()'; end; -function TImplDataTupleType.GetName: String; +function TDataTupleValue0.GetDataType: IDataType; +begin + Result := TDataTupleType.Singleton; +end; + +function TDataTupleValue0.GetItem(Idx: Integer): IDataValue; +begin + raise EArgumentException.Create('Index out of bounds'); +end; + +function TDataTupleValue0.GetItemCount: Integer; +begin + Result := 0; +end; + +{ TDataTupleValue1 } + +constructor TDataTupleValue1.Create(const AItems: array of IDataValue); +begin + inherited Create; + FItem0 := AItems[0]; +end; + +function TDataTupleValue1.GetAsString: string; +begin + Result := '(' + FItem0.AsString + ')'; +end; + +function TDataTupleValue1.GetDataType: IDataType; +begin + Result := TDataTupleType.Singleton; +end; + +function TDataTupleValue1.GetItem(Idx: Integer): IDataValue; +begin + case Idx of + 0: Result := FItem0; + else + raise EArgumentException.Create('Index out of bounds'); + end; +end; + +function TDataTupleValue1.GetItemCount: Integer; +begin + Result := 1; +end; + +{ TDataTupleValue2 } + +constructor TDataTupleValue2.Create(const AItems: array of IDataValue); +begin + inherited Create; + FItem0 := AItems[0]; + FItem1 := AItems[1]; +end; + +function TDataTupleValue2.GetAsString: string; +begin + Result := '(' + FItem0.AsString + ', ' + FItem1.AsString + ')'; +end; + +function TDataTupleValue2.GetDataType: IDataType; +begin + Result := TDataTupleType.Singleton; +end; + +function TDataTupleValue2.GetItem(Idx: Integer): IDataValue; +begin + case Idx of + 0: Result := FItem0; + 1: Result := FItem1; + else + raise EArgumentException.Create('Index out of bounds'); + end; +end; + +function TDataTupleValue2.GetItemCount: Integer; +begin + Result := 2; +end; + +{ TDataTupleValue3 } + +constructor TDataTupleValue3.Create(const AItems: array of IDataValue); +begin + inherited Create; + FItem0 := AItems[0]; + FItem1 := AItems[1]; + FItem2 := AItems[2]; +end; + +function TDataTupleValue3.GetAsString: string; +var + sb: TStringBuilder; +begin + sb := TStringBuilder.Create; + try + sb.Append('('); + sb.Append(FItem0.AsString); + sb.Append(', '); + sb.Append(FItem1.AsString); + sb.Append(', '); + sb.Append(FItem2.AsString); + sb.Append(')'); + Result := sb.ToString; + finally + sb.Free; + end; +end; + +function TDataTupleValue3.GetDataType: IDataType; +begin + Result := TDataTupleType.Singleton; +end; + +function TDataTupleValue3.GetItem(Idx: Integer): IDataValue; +begin + case Idx of + 0: Result := FItem0; + 1: Result := FItem1; + 2: Result := FItem2; + else + raise EArgumentException.Create('Index out of bounds'); + end; +end; + +function TDataTupleValue3.GetItemCount: Integer; +begin + Result := 3; +end; + +{ TDataTupleValue4 } + +constructor TDataTupleValue4.Create(const AItems: array of IDataValue); +begin + inherited Create; + FItem0 := AItems[0]; + FItem1 := AItems[1]; + FItem2 := AItems[2]; + FItem3 := AItems[3]; +end; + +function TDataTupleValue4.GetAsString: string; +var + sb: TStringBuilder; +begin + sb := TStringBuilder.Create; + try + sb.Append('('); + sb.Append(FItem0.AsString); + sb.Append(', '); + sb.Append(FItem1.AsString); + sb.Append(', '); + sb.Append(FItem2.AsString); + sb.Append(', '); + sb.Append(FItem3.AsString); + sb.Append(')'); + Result := sb.ToString; + finally + sb.Free; + end; +end; + +function TDataTupleValue4.GetDataType: IDataType; +begin + Result := TDataTupleType.Singleton; +end; + +function TDataTupleValue4.GetItem(Idx: Integer): IDataValue; +begin + case Idx of + 0: Result := FItem0; + 1: Result := FItem1; + 2: Result := FItem2; + 3: Result := FItem3; + else + raise EArgumentException.Create('Index out of bounds'); + end; +end; + +function TDataTupleValue4.GetItemCount: Integer; +begin + Result := 4; +end; + +{ TDataTupleValue5 } + +constructor TDataTupleValue5.Create(const AItems: array of IDataValue); +begin + inherited Create; + FItem0 := AItems[0]; + FItem1 := AItems[1]; + FItem2 := AItems[2]; + FItem3 := AItems[3]; + FItem4 := AItems[4]; +end; + +function TDataTupleValue5.GetAsString: string; +var + sb: TStringBuilder; +begin + sb := TStringBuilder.Create; + try + sb.Append('('); + sb.Append(FItem0.AsString); + sb.Append(', '); + sb.Append(FItem1.AsString); + sb.Append(', '); + sb.Append(FItem2.AsString); + sb.Append(', '); + sb.Append(FItem3.AsString); + sb.Append(', '); + sb.Append(FItem4.AsString); + sb.Append(')'); + Result := sb.ToString; + finally + sb.Free; + end; +end; + +function TDataTupleValue5.GetDataType: IDataType; +begin + Result := TDataTupleType.Singleton; +end; + +function TDataTupleValue5.GetItem(Idx: Integer): IDataValue; +begin + case Idx of + 0: Result := FItem0; + 1: Result := FItem1; + 2: Result := FItem2; + 3: Result := FItem3; + 4: Result := FItem4; + else + raise EArgumentException.Create('Index out of bounds'); + end; +end; + +function TDataTupleValue5.GetItemCount: Integer; +begin + Result := 5; +end; + +{ TDataTupleType } + +class constructor TDataTupleType.CreateClass; +begin + FSingleton := TDataTupleType.Create; +end; + +function TDataTupleType.CreateValue(const AItems: array of IDataValue): IDataTupleValue; +begin + // Use optimized implementations for tuples with 0 to 5 elements. + case Length(AItems) of + 0: Result := TDataTupleValue0.Singleton; + 1: Result := TDataTupleValue1.Create(AItems); + 2: Result := TDataTupleValue2.Create(AItems); + 3: Result := TDataTupleValue3.Create(AItems); + 4: Result := TDataTupleValue4.Create(AItems); + 5: Result := TDataTupleValue5.Create(AItems); + else + // Use the generic implementation for tuples with more than 5 elements. + Result := TDataTupleValue.Create(AItems); + end; +end; + +function TDataTupleType.GetName: String; begin Result := 'Tuple'; end; -function TImplDataTupleType.GetKind: TDataKind; +function TDataTupleType.GetKind: TDataKind; begin Result := dkTuple; end; diff --git a/Src/Data/Myc.Data.Types.pas b/Src/Data/Myc.Data.Types.pas index 2dd14eb..96c82d0 100644 --- a/Src/Data/Myc.Data.Types.pas +++ b/Src/Data/Myc.Data.Types.pas @@ -231,7 +231,7 @@ begin try if not FArrayTypeRegistry.TryGetValue(AElementType, Result) then begin - Result := TImplDataArrayType.Create(AElementType); + Result := TDataArrayType.Create(AElementType); FArrayTypeRegistry.Add(AElementType, Result); end; finally @@ -241,7 +241,7 @@ end; class function TDataType.Float: IDataFloatType; begin - Result := TImplDataFloatType.Singleton; + Result := TDataFloatType.Singleton; end; function TDataType.GetName: String; @@ -254,7 +254,7 @@ end; class function TDataType.Ordinal: IDataOrdinalType; begin - Result := TImplDataOrdinalType.Singleton; + Result := TDataOrdinalType.Singleton; end; class function TDataType.RecordOf(const Fields: TArray): IDataRecordType; @@ -263,7 +263,7 @@ begin try if not FRecordTypeRegistry.TryGetValue(Fields, Result) then begin - Result := TImplDataRecordType.Create(Fields); + Result := TDataRecordType.Create(Fields); FRecordTypeRegistry.Add(Fields, Result); end; finally @@ -284,22 +284,22 @@ end; class function TDataType.EnumOf(const AName: string; const AIdentifiers: array of string): IDataEnumType; begin - Result := TImplDataEnumType.Create(AName, AIdentifiers); + Result := TDataEnumType.Create(AName, AIdentifiers); end; class function TDataType.Text: IDataTextType; begin - Result := TImplDataTextType.Singleton; + Result := TDataTextType.Singleton; end; class function TDataType.Timestamp: IDataTimestampType; begin - Result := TImplDataTimestampType.Singleton; + Result := TDataTimestampType.Singleton; end; class function TDataType.Tuple: IDataTupleType; begin - Result := TImplDataTupleType.Singleton; + Result := TDataTupleType.Singleton; end; class operator TDataType.Implicit(const A: TDataType): IDataType; @@ -377,27 +377,27 @@ end; class function TDataValue.FromOrdinal(const AValue: Int64): IDataOrdinalValue; begin - Result := TImplDataOrdinalType.Singleton.CreateValue(AValue); + Result := TDataOrdinalType.Singleton.CreateValue(AValue); end; class function TDataValue.FromFloat(const AValue: Double): IDataFloatValue; begin - Result := TImplDataFloatType.Singleton.CreateValue(AValue); + Result := TDataFloatType.Singleton.CreateValue(AValue); end; class function TDataValue.FromText(const AValue: string): IDataTextValue; begin - Result := TImplDataTextType.Singleton.CreateValue(AValue); + Result := TDataTextType.Singleton.CreateValue(AValue); end; class function TDataValue.FromTimestamp(const AValue: TDateTime): IDataTimestampValue; begin - Result := TImplDataTimestampType.Singleton.CreateValue(AValue); + Result := TDataTimestampType.Singleton.CreateValue(AValue); end; class function TDataValue.FromTuple(const AItems: array of IDataValue): IDataTupleValue; begin - Result := TImplDataTupleType.Singleton.CreateValue(AItems); + Result := TDataTupleType.Singleton.CreateValue(AItems); end; function TDataValue.GetDataType: IDataType; diff --git a/dirs.txt b/dirs.txt index 4c4ecf9..d60f15b 100644 --- a/dirs.txt +++ b/dirs.txt @@ -1,3 +1,4 @@ T:\Myc\Src +T:\Myc\Src\Data T:\Myc\Test T:\Myc\AuraTrader \ No newline at end of file