-
Notifications
You must be signed in to change notification settings - Fork 58
/
SysVariantD5.inc
211 lines (177 loc) · 5.28 KB
/
SysVariantD5.inc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
const
oleaut = 'oleaut32.dll';
MaxDimCount=16;
function SafeArrayGetElement(VarArray: PVarArray; Indices,
Data: Pointer): Integer; stdcall;
external oleaut name 'SafeArrayGetElement';
function SafeArrayPutElement(VarArray: PVarArray; Indices,
Data: Pointer): Integer; stdcall;
external oleaut name 'SafeArrayPutElement';
function SafeArrayPtrOfIndex(VarArray: PVarArray; Indices: Pointer;
var pvData: Pointer): HResult; stdcall;
external oleaut name 'SafeArrayPtrOfIndex';
type
TVarArrayBoundArray = array[0..MaxDimCount-1] of TVarArrayBound;
function GetVarArray(const A: Variant): PVarArray;
begin
if TVarData(A).VType and varByRef <> 0 then
Result := PVarArray(TVarData(A).VPointer^) else
Result := TVarData(A).VArray;
end;
function _VarArrayGet(var A: Variant; IndexCount: Integer;
Indices: Integer): Variant; cdecl;
var
VarArrayPtr: PVarArray;
VarType: Integer;
P: Pointer;
begin
if TVarData(A).VType and varArray = 0 then
raise Exception.Create(reVarNotArray);
VarArrayPtr := GetVarArray(A);
if VarArrayPtr^.DimCount <> IndexCount then
raise Exception.Create(reVarArrayBounds);
VarType := TVarData(A).VType and varTypeMask;
VarClear(Result);
if VarType = varVariant then
begin
{$IFDEF WINDOWS}
if SafeArrayPtrOfIndex(VarArrayPtr, @Indices, P) <> 0 then
{$ELSE}
if SafeArrayPtrOfIndex(VarArrayPtr, PVarArrayCoorArray(@Indices), P) <> 0 then
{$ENDIF}
raise Exception.Create(reVarArrayBounds);
Result := PVariant(P)^;
end
else
begin
{$IFDEF WINDOWS}
if SafeArrayGetElement(VarArrayPtr, @Indices,
@TVarData(Result).VPointer) <> 0 then
{$ELSE}
if SafeArrayGetElement(VarArrayPtr, PVarArrayCoorArray(@Indices),
@TVarData(Result).VPointer) <> 0 then
{$ENDIF}
raise Exception.Create(reVarArrayBounds);
TVarData(Result).VType := VarType;
end;
end;
procedure VarStringToOleStr(var Dest: Variant; const Source: Variant);
var
OleStrPtr: PWideChar;
begin
OleStrPtr := StringToOleStr(string(TVarData(Source).VString));
VarClear(Dest);
TVarData(Dest).VType := varOleStr;
TVarData(Dest).VOleStr := OleStrPtr;
end;
procedure _VarArrayPut(var A: Variant; const Value: Variant;
IndexCount: Integer; Indices: Integer); cdecl;
var
VarArrayPtr: PVarArray;
VarType: Integer;
P: Pointer;
Temp: TVarData;
begin
if TVarData(A).VType and varArray = 0 then
raise Exception.Create(reVarNotArray);
VarArrayPtr := GetVarArray(A);
if VarArrayPtr^.DimCount <> IndexCount then
raise Exception.Create(reVarArrayBounds);
VarType := TVarData(A).VType and varTypeMask;
if (VarType = varVariant) and (TVarData(Value).VType <> varString) then
begin
{$IFDEF WINDOWS}
if SafeArrayPtrOfIndex(VarArrayPtr, @Indices, P) <> 0 then
{$ELSE}
if SafeArrayPtrOfIndex(VarArrayPtr, PVarArrayCoorArray(@Indices), P) <> 0 then
{$ENDIF}
raise Exception.Create(reVarArrayBounds);
PVariant(P)^ := Value;
end
else
begin
Temp.VType := varEmpty;
try
if VarType = varVariant then
begin
VarStringToOleStr(Variant(Temp), Value);
P := @Temp;
end
else
begin
VarCast(Variant(Temp), Value, VarType);
case VarType of
varOleStr, varDispatch, varUnknown:
P := Temp.VPointer;
else
P := @Temp.VPointer;
end;
end;
{$IFDEF WINDOWS}
if SafeArrayPutElement(VarArrayPtr, @Indices, P) <> 0 then
{$ELSE}
if SafeArrayPutElement(VarArrayPtr, PVarArrayCoorArray(@Indices), P) <> 0 then
{$ENDIF}
raise Exception.Create(reVarArrayBounds);
finally
VarClear(Variant(Temp));
end;
end;
end;
function VarArrayGet(const A: Variant; const Indices: array of Integer): Variant;
asm
{ ->EAX Pointer to A }
{ EDX Pointer to Indices }
{ ECX High bound of Indices }
{ [EBP+8] Pointer to result }
PUSH EBX
MOV EBX,ECX
INC EBX
JLE @@endLoop
@@loop:
PUSH [EDX+ECX*4].Integer
DEC ECX
JNS @@loop
@@endLoop:
PUSH EBX
PUSH EAX
MOV EAX,[EBP+8]
PUSH EAX
CALL _VarArrayGet
LEA ESP,[ESP+EBX*4+3*4]
POP EBX
end;
procedure VarArrayPut(var A: Variant; const Value: Variant; const Indices: array of Integer);
asm
{ ->EAX Pointer to A }
{ EDX Pointer to Value }
{ ECX Pointer to Indices }
{ [EBP+8] High bound of Indices }
PUSH EBX
MOV EBX,[EBP+8]
TEST EBX,EBX
JS @@endLoop
@@loop:
PUSH [ECX+EBX*4].Integer
DEC EBX
JNS @@loop
@@endLoop:
MOV EBX,[EBP+8]
INC EBX
PUSH EBX
PUSH EDX
PUSH EAX
CALL _VarArrayPut
LEA ESP,[ESP+EBX*4+3*4]
POP EBX
end;
function VarTypeIsNumeric(const AVarType: Word): Boolean;
begin
Result := AVarType in [varSmallInt, varInteger, varBoolean,
varByte, varSingle,varDouble,varCurrency];
end;
function VarIsNumeric(const V: Variant): Boolean;
begin
Result := VarTypeIsNumeric(TVarData(V).VType);
end;
{$HINTS ON}