* fixed big endian bugs in variant dispatching

* fixed size calculation of vardatetime arguments on 32 bit systems with
    variant dispatching

git-svn-id: trunk@29319 -
This commit is contained in:
Jonas Maebe 2014-12-24 14:13:49 +00:00
parent ee82b6ea0b
commit 476e3fabb7
2 changed files with 133 additions and 28 deletions

View File

@ -4004,6 +4004,8 @@ var
arg_ptr: pointer;
arg_data: PVarData;
dummy_data: TVarData;
arg_advanced: boolean;
const
argtype_mask = $7F;
argref_mask = $80;
@ -4032,22 +4034,46 @@ begin
Inc(arg_ptr,sizeof(Pointer));
end
else
case arg_type of
varError:
arg_data^.vError:=VAR_PARAMNOTFOUND;
varVariant:
begin
begin
arg_advanced:=false;
case arg_type of
varError:
begin
arg_data^.vError:=VAR_PARAMNOTFOUND;
arg_advanced := true;
end;
varVariant:
arg_data^ := PVarData(PPointer(arg_ptr)^)^;
Inc(arg_ptr,sizeof(Pointer));
end;
varDouble, varCurrency, varInt64, varQWord:
begin
arg_data^.vQWord := PQWord(arg_ptr)^; // 64bit on all platforms
inc(arg_ptr,sizeof(qword))
end
else
arg_data^.vAny := PPointer(arg_ptr)^; // 32 or 64bit
inc(arg_ptr,sizeof(pointer))
varDouble, varCurrency, varDate, varInt64, varQWord:
begin
arg_data^.vQWord := PQWord(arg_ptr)^; // 64bit on all platforms
inc(arg_ptr,sizeof(QWord));
arg_advanced := true;
end;
{ values potentially smaller than sizeof(pointer) must be handled
explicitly to guarantee endian safety and to prevent copying/
skipping data (they are always copied into a 4 byte element
by the compiler, although it will still skip sizeof(pointer)
bytes afterwards) }
varSingle:
arg_data^.vSingle := PSingle(arg_ptr)^;
varSmallint:
arg_data^.vSmallInt := PLongint(arg_ptr)^;
varInteger:
arg_data^.vInteger := PLongint(arg_ptr)^;
varBoolean:
arg_data^.vBoolean := WordBool(PLongint(arg_ptr)^);
varShortInt:
arg_data^.vShortInt := PLongint(arg_ptr)^;
varByte:
arg_data^.vByte := PLongint(arg_ptr)^;
varWord:
arg_data^.vWord := PLongint(arg_ptr)^;
else
arg_data^.vAny := PPointer(arg_ptr)^; // 32 or 64bit
end;
if not arg_advanced then
inc(arg_ptr,sizeof(pointer));
end;
end;
end;

View File

@ -49,10 +49,22 @@ function TSampleVariant.GetProperty(var Dest: TVarData; const V: TVarData;
const Name: string): Boolean;
begin
assert(V.VType=varType);
if Name='AnyField' then begin
variant(Dest) := V.VInt64;
result := true;
end else
if Name='IntField' then
begin
variant(Dest) := V.VInt64;
result := true;
end
else if Name='FloatField' then
begin
variant(Dest) := V.VDouble;
result := true;
end
else if Name='BoolField' then
begin
variant(Dest) := V.VBoolean;
result := true;
end
else
result := false;
end;
@ -60,23 +72,90 @@ function TSampleVariant.SetProperty(var V: TVarData; const Name: string;
const Value: TVarData): Boolean;
begin
assert(V.VType=varType);
if Name='AnyField' then begin
PVarData(@V)^.VInt64 := variant(Value);
result := true;
end else
if Name='IntField' then
begin
PVarData(@V)^.VInt64 := variant(Value);
result := true;
end
else if Name='FloatField' then
begin
PVarData(@V)^.VDouble := variant(Value);
result := true;
end
else if Name='BoolField' then
begin
PVarData(@V)^.VBoolean := variant(Value);
result := true;
end
else
result := false;
end;
var
SampleVariant: TSampleVariant;
v: Variant;
GB1 : Byte;
GS1 : Shortint;
GW : Word;
GL : longint;
gsi : single;
gd : double;
gi64 : int64;
gdate: tdatetime;
gb: boolean;
begin
SampleVariant:=TSampleVariant.Create;
v := null;
TVarData(v).VType:=SampleVariant.VarType;
v.AnyField := 100;
if v.AnyField=100 then
Halt(0)
else
v.IntField := 100;
if v.IntField<>100 then
halt(1);
end.
gb1:=128;
gs1:=127;
gw:=32768;
gl:=longint($b100dbad);
gsi:=12345789.5;
gd:=999991234889879.5;
gi64:=$813245678901234;
gdate:=now;
gb:=false;
v.IntField:=gb1;
if v.IntField<>gb1 then
halt(2);
v.IntField:=gs1;
if v.IntField<>gs1 then
halt(3);
v.IntField:=gw;
if v.IntField<>gw then
halt(4);
v.IntField:=gl;
if v.IntField<>gl then
halt(5);
v.FloatField:=gsi;
if v.FloatField<>gsi then
halt(6);
v.FloatField:=gd;
if v.FloatField<>gd then
halt(7);
v.IntField:=gi64;
if v.IntField<>gi64 then
halt(8);
v.FloatField:=gdate;
if v.FloatField<>gdate then
halt(9);
v.BoolField:=gb;
if boolean(v.BoolField)<>gb then
halt(10);
end.