mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-11 18:25:58 +02:00
* rework TValueDataIntImpl to work more as it does in Delphi (especially important for GetReferenceToRawData); note: the class avoids the use of an allocation in case it's a managed pointer type
git-svn-id: trunk@36963 -
This commit is contained in:
parent
6672e77222
commit
95523157e5
@ -273,10 +273,14 @@ type
|
|||||||
|
|
||||||
TValueDataIntImpl = class(TInterfacedObject, IValueData)
|
TValueDataIntImpl = class(TInterfacedObject, IValueData)
|
||||||
private
|
private
|
||||||
FDataSize: integer;
|
FBuffer: Pointer;
|
||||||
FBuffer: pointer;
|
FDataSize: SizeInt;
|
||||||
|
FTypeInfo: PTypeInfo;
|
||||||
|
FIsCopy: Boolean;
|
||||||
|
FUseAddRef: Boolean;
|
||||||
public
|
public
|
||||||
constructor Create(ACopyFromBuffer: Pointer; ALen: integer);
|
constructor CreateCopy(ACopyFromBuffer: Pointer; ALen: SizeInt; ATypeInfo: PTypeInfo; AAddRef: Boolean);
|
||||||
|
constructor CreateRef(AData: Pointer; ATypeInfo: PTypeInfo; AAddRef: Boolean);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
procedure ExtractRawData(ABuffer: pointer);
|
procedure ExtractRawData(ABuffer: pointer);
|
||||||
procedure ExtractRawDataNoCopy(ABuffer: pointer);
|
procedure ExtractRawDataNoCopy(ABuffer: pointer);
|
||||||
@ -417,31 +421,71 @@ end;
|
|||||||
|
|
||||||
{ TValueDataIntImpl }
|
{ TValueDataIntImpl }
|
||||||
|
|
||||||
constructor TValueDataIntImpl.create(ACopyFromBuffer: Pointer; ALen: integer);
|
procedure IntFinalize(APointer, ATypeInfo: Pointer);
|
||||||
|
external name 'FPC_FINALIZE';
|
||||||
|
procedure IntAddRef(APointer, ATypeInfo: Pointer);
|
||||||
|
external name 'FPC_ADDREF';
|
||||||
|
|
||||||
|
constructor TValueDataIntImpl.CreateCopy(ACopyFromBuffer: Pointer; ALen: SizeInt; ATypeInfo: PTypeInfo; AAddRef: Boolean);
|
||||||
begin
|
begin
|
||||||
|
FTypeInfo := ATypeInfo;
|
||||||
FDataSize:=ALen;
|
FDataSize:=ALen;
|
||||||
if ALen>0 then
|
if ALen>0 then
|
||||||
begin
|
begin
|
||||||
Getmem(FBuffer,FDataSize);
|
Getmem(FBuffer,FDataSize);
|
||||||
system.move(ACopyFromBuffer^,FBuffer^,FDataSize);
|
system.move(ACopyFromBuffer^,FBuffer^,FDataSize);
|
||||||
end;
|
end;
|
||||||
|
FIsCopy := True;
|
||||||
|
FUseAddRef := AAddRef;
|
||||||
|
if AAddRef and (ALen > 0) then
|
||||||
|
IntAddRef(FBuffer, FTypeInfo);
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TValueDataIntImpl.CreateRef(AData: Pointer; ATypeInfo: PTypeInfo; AAddRef: Boolean);
|
||||||
|
begin
|
||||||
|
FTypeInfo := ATypeInfo;
|
||||||
|
FDataSize := SizeOf(Pointer);
|
||||||
|
FBuffer := PPointer(AData)^;
|
||||||
|
FIsCopy := False;
|
||||||
|
FUseAddRef := AAddRef;
|
||||||
|
if AAddRef then
|
||||||
|
IntAddRef(@FBuffer, FTypeInfo);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TValueDataIntImpl.Destroy;
|
destructor TValueDataIntImpl.Destroy;
|
||||||
begin
|
begin
|
||||||
if assigned(FBuffer) then
|
if Assigned(FBuffer) then begin
|
||||||
Freemem(FBuffer);
|
if FUseAddRef then
|
||||||
|
if FIsCopy then
|
||||||
|
IntFinalize(FBuffer, FTypeInfo)
|
||||||
|
else
|
||||||
|
IntFinalize(@FBuffer, FTypeInfo);
|
||||||
|
if FIsCopy then
|
||||||
|
Freemem(FBuffer);
|
||||||
|
end;
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TValueDataIntImpl.ExtractRawData(ABuffer: pointer);
|
procedure TValueDataIntImpl.ExtractRawData(ABuffer: pointer);
|
||||||
begin
|
begin
|
||||||
system.move(FBuffer^,ABuffer^,FDataSize);
|
if FDataSize = 0 then
|
||||||
|
Exit;
|
||||||
|
if FIsCopy then
|
||||||
|
System.Move(FBuffer^, ABuffer^, FDataSize)
|
||||||
|
else
|
||||||
|
System.Move(FBuffer{!}, ABuffer^, FDataSize);
|
||||||
|
if FUseAddRef then
|
||||||
|
IntAddRef(ABuffer, FTypeInfo);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TValueDataIntImpl.ExtractRawDataNoCopy(ABuffer: pointer);
|
procedure TValueDataIntImpl.ExtractRawDataNoCopy(ABuffer: pointer);
|
||||||
begin
|
begin
|
||||||
system.move(FBuffer^,ABuffer^,FDataSize);
|
if FDataSize = 0 then
|
||||||
|
Exit;
|
||||||
|
if FIsCopy then
|
||||||
|
system.move(FBuffer^, ABuffer^, FDataSize)
|
||||||
|
else
|
||||||
|
System.Move(FBuffer{!}, ABuffer^, FDataSize);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TValueDataIntImpl.GetDataSize: integer;
|
function TValueDataIntImpl.GetDataSize: integer;
|
||||||
@ -451,7 +495,10 @@ end;
|
|||||||
|
|
||||||
function TValueDataIntImpl.GetReferenceToRawData: pointer;
|
function TValueDataIntImpl.GetReferenceToRawData: pointer;
|
||||||
begin
|
begin
|
||||||
result := FBuffer;
|
if FIsCopy then
|
||||||
|
result := FBuffer
|
||||||
|
else
|
||||||
|
result := @FBuffer;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TRttiFloatType }
|
{ TRttiFloatType }
|
||||||
@ -478,8 +525,8 @@ type
|
|||||||
begin
|
begin
|
||||||
result.FData.FTypeInfo:=ATypeInfo;
|
result.FData.FTypeInfo:=ATypeInfo;
|
||||||
case ATypeInfo^.Kind of
|
case ATypeInfo^.Kind of
|
||||||
tkSString : result.FData.FValueData := TValueDataIntImpl.Create(@PShortString(ABuffer)^[1],Length(PShortString(ABuffer)^));
|
tkSString : result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, Length(PShortString(ABuffer)^) + 1, ATypeInfo, True);
|
||||||
tkAString : result.FData.FValueData := TValueDataIntImpl.Create(@PAnsiString(ABuffer)^[1],length(PAnsiString(ABuffer)^));
|
tkAString : result.FData.FValueData := TValueDataIntImpl.CreateRef(ABuffer, ATypeInfo, True);
|
||||||
tkClass : result.FData.FAsObject := PPointer(ABuffer)^;
|
tkClass : result.FData.FAsObject := PPointer(ABuffer)^;
|
||||||
tkClassRef : result.FData.FAsClass := PClass(ABuffer)^;
|
tkClassRef : result.FData.FAsClass := PClass(ABuffer)^;
|
||||||
tkInt64 : result.FData.FAsSInt64 := PInt64(ABuffer)^;
|
tkInt64 : result.FData.FAsSInt64 := PInt64(ABuffer)^;
|
||||||
@ -551,11 +598,10 @@ var
|
|||||||
s: string;
|
s: string;
|
||||||
begin
|
begin
|
||||||
case Kind of
|
case Kind of
|
||||||
tkSString,
|
tkSString:
|
||||||
tkAString : begin
|
s := PShortString(FData.FValueData.GetReferenceToRawData)^;
|
||||||
setlength(s,FData.FValueData.GetDataSize);
|
tkAString:
|
||||||
system.move(FData.FValueData.GetReferenceToRawData^,s[1],FData.FValueData.GetDataSize);
|
s := PAnsiString(FData.FValueData.GetReferenceToRawData)^;
|
||||||
end;
|
|
||||||
else
|
else
|
||||||
raise EInvalidCast.Create(SErrInvalidTypecast);
|
raise EInvalidCast.Create(SErrInvalidTypecast);
|
||||||
end;
|
end;
|
||||||
|
Loading…
Reference in New Issue
Block a user