|
@@ -76,6 +76,8 @@ type
|
|
14: (FAsSInt64: Int64);
|
|
14: (FAsSInt64: Int64);
|
|
15: (FAsMethod: TMethod);
|
|
15: (FAsMethod: TMethod);
|
|
16: (FAsPointer: Pointer);
|
|
16: (FAsPointer: Pointer);
|
|
|
|
+ { FPC addition for open arrays }
|
|
|
|
+ 17: (FArrLength: SizeInt; FElSize: SizeInt);
|
|
end;
|
|
end;
|
|
|
|
|
|
{ TValue }
|
|
{ TValue }
|
|
@@ -91,10 +93,15 @@ type
|
|
public
|
|
public
|
|
class function Empty: TValue; static;
|
|
class function Empty: TValue; static;
|
|
class procedure Make(ABuffer: pointer; ATypeInfo: PTypeInfo; out result: TValue); static;
|
|
class procedure Make(ABuffer: pointer; ATypeInfo: PTypeInfo; out result: TValue); static;
|
|
|
|
+ { Note: a TValue based on an open array is only valid until the routine having the open array parameter is left! }
|
|
|
|
+ class procedure MakeOpenArray(AArray: Pointer; ALength: SizeInt; ATypeInfo: PTypeInfo; out Result: TValue); static;
|
|
{$ifndef NoGenericMethods}
|
|
{$ifndef NoGenericMethods}
|
|
generic class function From<T>(constref aValue: T): TValue; static; inline;
|
|
generic class function From<T>(constref aValue: T): TValue; static; inline;
|
|
|
|
+ { Note: a TValue based on an open array is only valid until the routine having the open array parameter is left! }
|
|
|
|
+ generic class function FromOpenArray<T>(constref aValue: array of T): TValue; static; inline;
|
|
{$endif}
|
|
{$endif}
|
|
function IsArray: boolean; inline;
|
|
function IsArray: boolean; inline;
|
|
|
|
+ function IsOpenArray: Boolean; inline;
|
|
function AsString: string; inline;
|
|
function AsString: string; inline;
|
|
function AsUnicodeString: UnicodeString;
|
|
function AsUnicodeString: UnicodeString;
|
|
function AsAnsiString: AnsiString;
|
|
function AsAnsiString: AnsiString;
|
|
@@ -436,6 +443,10 @@ procedure FreeCallback(aCallback: TFunctionCallCallback; aCallConv: TCallConv);
|
|
|
|
|
|
function IsManaged(TypeInfo: PTypeInfo): boolean;
|
|
function IsManaged(TypeInfo: PTypeInfo): boolean;
|
|
|
|
|
|
|
|
+{$ifndef InLazIDE}
|
|
|
|
+generic function OpenArrayToDynArrayValue<T>(constref aArray: array of T): TValue;
|
|
|
|
+{$endif}
|
|
|
|
+
|
|
{ these resource strings are needed by units implementing function call managers }
|
|
{ these resource strings are needed by units implementing function call managers }
|
|
resourcestring
|
|
resourcestring
|
|
SErrInvokeNotImplemented = 'Invoke functionality is not implemented';
|
|
SErrInvokeNotImplemented = 'Invoke functionality is not implemented';
|
|
@@ -794,6 +805,19 @@ begin
|
|
Result := false;
|
|
Result := false;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+{$ifndef InLazIDE}
|
|
|
|
+generic function OpenArrayToDynArrayValue<T>(constref aArray: array of T): TValue;
|
|
|
|
+var
|
|
|
|
+ arr: specialize TArray<T>;
|
|
|
|
+ i: SizeInt;
|
|
|
|
+begin
|
|
|
|
+ SetLength(arr, Length(aArray));
|
|
|
|
+ for i := 0 to High(aArray) do
|
|
|
|
+ arr[i] := aArray[i];
|
|
|
|
+ Result := TValue.specialize From<specialize TArray<T>>(arr);
|
|
|
|
+end;
|
|
|
|
+{$endif}
|
|
|
|
+
|
|
{ TRttiPointerType }
|
|
{ TRttiPointerType }
|
|
|
|
|
|
function TRttiPointerType.GetReferredType: TRttiType;
|
|
function TRttiPointerType.GetReferredType: TRttiType;
|
|
@@ -1467,11 +1491,48 @@ begin
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+class procedure TValue.MakeOpenArray(AArray: Pointer; ALength: SizeInt; ATypeInfo: PTypeInfo; out Result: TValue);
|
|
|
|
+var
|
|
|
|
+ el: TValue;
|
|
|
|
+begin
|
|
|
|
+ Result.FData.FTypeInfo := ATypeInfo;
|
|
|
|
+ { resets the whole variant part; FValueData is already Nil }
|
|
|
|
+{$if SizeOf(TMethod) > SizeOf(QWord)}
|
|
|
|
+ Result.FData.FAsMethod.Code := Nil;
|
|
|
|
+ Result.FData.FAsMethod.Data := Nil;
|
|
|
|
+{$else}
|
|
|
|
+ Result.FData.FAsUInt64 := 0;
|
|
|
|
+{$endif}
|
|
|
|
+ if not Assigned(ATypeInfo) then
|
|
|
|
+ Exit;
|
|
|
|
+ if ATypeInfo^.Kind <> tkArray then
|
|
|
|
+ Exit;
|
|
|
|
+ if not Assigned(AArray) then
|
|
|
|
+ Exit;
|
|
|
|
+ if ALength < 0 then
|
|
|
|
+ Exit;
|
|
|
|
+ Result.FData.FValueData := TValueDataIntImpl.CreateRef(@AArray, ATypeInfo, False);
|
|
|
|
+ Result.FData.FArrLength := ALength;
|
|
|
|
+ Make(Nil, Result.TypeData^.ArrayData.ElType, el);
|
|
|
|
+ Result.FData.FElSize := el.DataSize;
|
|
|
|
+end;
|
|
|
|
+
|
|
{$ifndef NoGenericMethods}
|
|
{$ifndef NoGenericMethods}
|
|
generic class function TValue.From<T>(constref aValue: T): TValue;
|
|
generic class function TValue.From<T>(constref aValue: T): TValue;
|
|
begin
|
|
begin
|
|
TValue.Make(@aValue, System.TypeInfo(T), Result);
|
|
TValue.Make(@aValue, System.TypeInfo(T), Result);
|
|
end;
|
|
end;
|
|
|
|
+
|
|
|
|
+generic class function TValue.FromOpenArray<T>(constref aValue: array of T): TValue;
|
|
|
|
+var
|
|
|
|
+ arrdata: Pointer;
|
|
|
|
+begin
|
|
|
|
+ if Length(aValue) > 0 then
|
|
|
|
+ arrdata := @aValue[0]
|
|
|
|
+ else
|
|
|
|
+ arrdata := Nil;
|
|
|
|
+ TValue.MakeOpenArray(arrdata, Length(aValue), System.TypeInfo(aValue), Result);
|
|
|
|
+end;
|
|
{$endif}
|
|
{$endif}
|
|
|
|
|
|
function TValue.GetTypeDataProp: PTypeData;
|
|
function TValue.GetTypeDataProp: PTypeData;
|
|
@@ -1586,6 +1647,14 @@ begin
|
|
result := kind in [tkArray, tkDynArray];
|
|
result := kind in [tkArray, tkDynArray];
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+function TValue.IsOpenArray: Boolean;
|
|
|
|
+var
|
|
|
|
+ td: PTypeData;
|
|
|
|
+begin
|
|
|
|
+ td := TypeData;
|
|
|
|
+ Result := (Kind = tkArray) and (td^.ArrayData.Size = 0) and (td^.ArrayData.ElCount = 0)
|
|
|
|
+end;
|
|
|
|
+
|
|
function TValue.AsString: string;
|
|
function TValue.AsString: string;
|
|
begin
|
|
begin
|
|
if System.GetTypeKind(String) = tkUString then
|
|
if System.GetTypeKind(String) = tkUString then
|
|
@@ -1795,19 +1864,27 @@ begin
|
|
end;
|
|
end;
|
|
|
|
|
|
function TValue.GetArrayLength: SizeInt;
|
|
function TValue.GetArrayLength: SizeInt;
|
|
|
|
+var
|
|
|
|
+ td: PTypeData;
|
|
begin
|
|
begin
|
|
if not IsArray then
|
|
if not IsArray then
|
|
raise EInvalidCast.Create(SErrInvalidTypecast);
|
|
raise EInvalidCast.Create(SErrInvalidTypecast);
|
|
if Kind = tkDynArray then
|
|
if Kind = tkDynArray then
|
|
Result := DynArraySize(PPointer(FData.FValueData.GetReferenceToRawData)^)
|
|
Result := DynArraySize(PPointer(FData.FValueData.GetReferenceToRawData)^)
|
|
- else
|
|
|
|
- Result := TypeData^.ArrayData.ElCount;
|
|
|
|
|
|
+ else begin
|
|
|
|
+ td := TypeData;
|
|
|
|
+ if (td^.ArrayData.Size = 0) and (td^.ArrayData.ElCount = 0) then
|
|
|
|
+ Result := FData.FArrLength
|
|
|
|
+ else
|
|
|
|
+ Result := td^.ArrayData.ElCount;
|
|
|
|
+ end;
|
|
end;
|
|
end;
|
|
|
|
|
|
function TValue.GetArrayElement(AIndex: SizeInt): TValue;
|
|
function TValue.GetArrayElement(AIndex: SizeInt): TValue;
|
|
var
|
|
var
|
|
data: Pointer;
|
|
data: Pointer;
|
|
eltype: PTypeInfo;
|
|
eltype: PTypeInfo;
|
|
|
|
+ elsize: SizeInt;
|
|
td: PTypeData;
|
|
td: PTypeData;
|
|
begin
|
|
begin
|
|
if not IsArray then
|
|
if not IsArray then
|
|
@@ -1818,7 +1895,15 @@ begin
|
|
end else begin
|
|
end else begin
|
|
td := TypeData;
|
|
td := TypeData;
|
|
eltype := td^.ArrayData.ElType;
|
|
eltype := td^.ArrayData.ElType;
|
|
- data := PByte(FData.FValueData.GetReferenceToRawData) + AIndex * (td^.ArrayData.Size div td^.ArrayData.ElCount);
|
|
|
|
|
|
+ { open array? }
|
|
|
|
+ if (td^.ArrayData.Size = 0) and (td^.ArrayData.ElCount = 0) then begin
|
|
|
|
+ data := PPointer(FData.FValueData.GetReferenceToRawData)^;
|
|
|
|
+ elsize := FData.FElSize
|
|
|
|
+ end else begin
|
|
|
|
+ data := FData.FValueData.GetReferenceToRawData;
|
|
|
|
+ elsize := td^.ArrayData.Size div td^.ArrayData.ElCount;
|
|
|
|
+ end;
|
|
|
|
+ data := PByte(data) + AIndex * elsize;
|
|
end;
|
|
end;
|
|
{ MakeWithoutCopy? }
|
|
{ MakeWithoutCopy? }
|
|
Make(data, eltype, Result);
|
|
Make(data, eltype, Result);
|
|
@@ -1828,6 +1913,7 @@ procedure TValue.SetArrayElement(AIndex: SizeInt; constref AValue: TValue);
|
|
var
|
|
var
|
|
data: Pointer;
|
|
data: Pointer;
|
|
eltype: PTypeInfo;
|
|
eltype: PTypeInfo;
|
|
|
|
+ elsize: SizeInt;
|
|
td, tdv: PTypeData;
|
|
td, tdv: PTypeData;
|
|
begin
|
|
begin
|
|
if not IsArray then
|
|
if not IsArray then
|
|
@@ -1838,7 +1924,15 @@ begin
|
|
end else begin
|
|
end else begin
|
|
td := TypeData;
|
|
td := TypeData;
|
|
eltype := td^.ArrayData.ElType;
|
|
eltype := td^.ArrayData.ElType;
|
|
- data := PByte(FData.FValueData.GetReferenceToRawData) + AIndex * (td^.ArrayData.Size div td^.ArrayData.ElCount);
|
|
|
|
|
|
+ { open array? }
|
|
|
|
+ if (td^.ArrayData.Size = 0) and (td^.ArrayData.ElCount = 0) then begin
|
|
|
|
+ data := PPointer(FData.FValueData.GetReferenceToRawData)^;
|
|
|
|
+ elsize := FData.FElSize
|
|
|
|
+ end else begin
|
|
|
|
+ data := FData.FValueData.GetReferenceToRawData;
|
|
|
|
+ elsize := td^.ArrayData.Size div td^.ArrayData.ElCount;
|
|
|
|
+ end;
|
|
|
|
+ data := PByte(data) + AIndex * elsize;
|
|
end;
|
|
end;
|
|
{ maybe we'll later on allow some typecasts, but for now be restrictive }
|
|
{ maybe we'll later on allow some typecasts, but for now be restrictive }
|
|
if eltype^.Kind <> AValue.Kind then
|
|
if eltype^.Kind <> AValue.Kind then
|