variant.inc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2001 by the Free Pascal development team
  4. This include file contains the implementation for variants
  5. support in FPC as far as it is part of the system unit
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. var
  13. variantmanager : tvariantmanager;
  14. procedure printmissingvariantunit;
  15. begin
  16. writeln(stderr);
  17. writeln(stderr,'Program needs probably the variants unit.');
  18. writeln(stderr,'Include the variants unit in your uses statements');
  19. writeln(stderr,'as one of the first units.');
  20. writeln(stderr);
  21. end;
  22. procedure invalidvariantop;
  23. begin
  24. printmissingvariantunit;
  25. HandleErrorFrame(221,get_frame);
  26. end;
  27. procedure invalidvariantopnovariants;
  28. begin
  29. printmissingvariantunit;
  30. HandleErrorFrame(221,get_frame);
  31. end;
  32. procedure vardisperror;
  33. begin
  34. printmissingvariantunit;
  35. HandleErrorFrame(222,get_frame);
  36. end;
  37. { ---------------------------------------------------------------------
  38. Compiler helper routines.
  39. ---------------------------------------------------------------------}
  40. procedure varclear(var v : tvardata);
  41. begin
  42. if not(v.vtype in [varempty,varerror,varnull]) then
  43. invalidvariantop;
  44. end;
  45. procedure variant_init(var v : tvardata);[Public,Alias:'FPC_VARIANT_INIT'];
  46. begin
  47. { calling the variant manager here is a problem because the static/global variants
  48. are initialized while the variant manager isn't assigned }
  49. fillchar(v,sizeof(variant),0);
  50. end;
  51. procedure variant_clear(var v : tvardata);[Public,Alias:'FPC_VARIANT_CLEAR'];
  52. begin
  53. if assigned(VarClearProc) then
  54. VarClearProc(v);
  55. end;
  56. procedure variant_addref(var v : tvardata);[Public,Alias:'FPC_VARIANT_ADDREF'];
  57. begin
  58. if assigned(VarAddRefProc) then
  59. VarAddRefProc(v);
  60. end;
  61. { using pointers as argument here makes life for the compiler easier }
  62. procedure fpc_variant_copy(d,s : pointer);compilerproc;
  63. begin
  64. if assigned(VarCopyProc) then
  65. VarCopyProc(tvardata(d^),tvardata(s^));
  66. end;
  67. Procedure fpc_write_text_variant(Len : Longint;var f : Text;const v : variant); iocheck; [Public,Alias:'FPC_WRITE_TEXT_VARIANT']; compilerproc;
  68. begin
  69. if (InOutRes<>0) then
  70. exit;
  71. case TextRec(f).mode of
  72. { fmAppend gets changed to fmOutPut in do_open (JM) }
  73. fmOutput:
  74. if len=-1 then
  75. variantmanager.write0variant(f,v)
  76. else
  77. variantmanager.writevariant(f,v,len);
  78. fmInput:
  79. InOutRes:=105
  80. else InOutRes:=103;
  81. end;
  82. end;
  83. procedure fpc_vararray_get(var d : variant;const s : variant;indices : psizeint;len : sizeint);compilerproc;
  84. begin
  85. d:=variantmanager.vararrayget(s,len,indices);
  86. end;
  87. procedure fpc_vararray_put(var d : variant;const s : variant;indices : psizeint;len : sizeint);compilerproc;
  88. begin
  89. variantmanager.vararrayput(d,s,len,indices);
  90. end;
  91. function fpc_variant_to_dynarray(const v : variant;typeinfo : pointer) : pointer;compilerproc;
  92. begin
  93. variantmanager.vartodynarray(result,v,typeinfo);
  94. end;
  95. function fpc_dynarray_to_variant(dynarr : pointer;typeinfo : pointer) : variant;compilerproc;
  96. begin
  97. variantmanager.varfromdynarray(result,dynarr,typeinfo);
  98. end;
  99. function fpc_variant_to_interface(const v : variant) : iinterface;compilerproc;
  100. begin
  101. variantmanager.vartointf(result,v);
  102. end;
  103. function fpc_interface_to_variant(const i : iinterface) : variant;compilerproc;
  104. begin
  105. variantmanager.varfromintf(result,i);
  106. end;
  107. { ---------------------------------------------------------------------
  108. Overloaded operators.
  109. ---------------------------------------------------------------------}
  110. { Integer }
  111. operator :=(const source : byte) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  112. begin
  113. Variantmanager.varfromInt(Dest,Source,1);
  114. end;
  115. operator :=(const source : shortint) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  116. begin
  117. Variantmanager.varfromInt(Dest,Source,-1);
  118. end;
  119. operator :=(const source : word) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  120. begin
  121. Variantmanager.varfromInt(Dest,Source,2);
  122. end;
  123. operator :=(const source : smallint) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  124. begin
  125. Variantmanager.varfromInt(Dest,Source,-2);
  126. end;
  127. operator :=(const source : dword) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  128. begin
  129. Variantmanager.varfromInt(Dest,Source,4);
  130. end;
  131. operator :=(const source : longint) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  132. begin
  133. Variantmanager.varfromInt(Dest,Source,-4);
  134. end;
  135. operator :=(const source : qword) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  136. begin
  137. Variantmanager.varfromWord64(Dest,Source);
  138. end;
  139. operator :=(const source : int64) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  140. begin
  141. Variantmanager.varfromInt64(Dest,Source);
  142. end;
  143. { Boolean }
  144. operator :=(const source : boolean) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  145. begin
  146. Variantmanager.varfromBool(Dest,Source);
  147. end;
  148. operator :=(const source : wordbool) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  149. begin
  150. Variantmanager.varfromBool(Dest,Boolean(Source));
  151. end;
  152. operator :=(const source : longbool) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  153. begin
  154. Variantmanager.varfromBool(Dest,Boolean(Source));
  155. end;
  156. { Chars }
  157. operator :=(const source : char) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  158. begin
  159. VariantManager.VarFromPStr(Dest,Source);
  160. end;
  161. operator :=(const source : widechar) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  162. begin
  163. VariantManager.VarFromWStr(Dest,Source);
  164. end;
  165. { Strings }
  166. operator :=(const source : shortstring) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  167. begin
  168. VariantManager.VarFromPStr(Dest,Source);
  169. end;
  170. operator :=(const source : ansistring) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  171. begin
  172. VariantManager.VarFromLStr(Dest,Source);
  173. end;
  174. operator :=(const source : widestring) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  175. begin
  176. VariantManager.VarFromWStr(Dest,Source);
  177. end;
  178. { Floats }
  179. {$ifdef SUPPORT_SINGLE}
  180. operator :=(const source : single) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  181. begin
  182. VariantManager.VarFromReal(Dest,Source);
  183. end;
  184. {$endif SUPPORT_SINGLE}
  185. {$ifdef SUPPORT_DOUBLE}
  186. operator :=(const source : double) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  187. begin
  188. VariantManager.VarFromReal(Dest,Source);
  189. end;
  190. {$endif SUPPORT_DOUBLE}
  191. {$ifdef SUPPORT_EXTENDED}
  192. operator :=(const source : extended) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  193. begin
  194. VariantManager.VarFromReal(Dest,Source);
  195. end;
  196. {$endif SUPPORT_EXTENDED}
  197. {$ifdef SUPPORT_COMP}
  198. Operator :=(const source : comp) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  199. begin
  200. VariantManager.VarFromReal(Dest,Source);
  201. end;
  202. {$endif SUPPORT_COMP}
  203. { Misc. }
  204. operator :=(const source : currency) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  205. begin
  206. VariantManager.VarFromCurr(Dest,Source);
  207. end;
  208. operator :=(const source : tdatetime) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  209. begin
  210. VariantManager.VarFromTDateTime(Dest,Source);
  211. end;
  212. {**********************************************************************
  213. from Variant assignments
  214. **********************************************************************}
  215. { Integer }
  216. operator :=(const source : variant) dest : byte;{$ifdef SYSTEMINLINE}inline;{$endif}
  217. begin
  218. dest:=variantmanager.vartoint(source);
  219. end;
  220. operator :=(const source : variant) dest : shortint;{$ifdef SYSTEMINLINE}inline;{$endif}
  221. begin
  222. dest:=variantmanager.vartoint(source);
  223. end;
  224. operator :=(const source : variant) dest : word;{$ifdef SYSTEMINLINE}inline;{$endif}
  225. begin
  226. dest:=variantmanager.vartoint(source);
  227. end;
  228. operator :=(const source : variant) dest : smallint;{$ifdef SYSTEMINLINE}inline;{$endif}
  229. begin
  230. dest:=variantmanager.vartoint(source);
  231. end;
  232. operator :=(const source : variant) dest : dword;{$ifdef SYSTEMINLINE}inline;{$endif}
  233. begin
  234. dest:=variantmanager.vartoint(source);
  235. end;
  236. operator :=(const source : variant) dest : longint;{$ifdef SYSTEMINLINE}inline;{$endif}
  237. begin
  238. dest:=variantmanager.vartoint(source);
  239. end;
  240. operator :=(const source : variant) dest : qword;{$ifdef SYSTEMINLINE}inline;{$endif}
  241. begin
  242. dest:=variantmanager.vartoword64(source);
  243. end;
  244. operator :=(const source : variant) dest : int64;{$ifdef SYSTEMINLINE}inline;{$endif}
  245. begin
  246. dest:=variantmanager.vartoint64(source);
  247. end;
  248. { Boolean }
  249. operator :=(const source : variant) dest : boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  250. begin
  251. dest:=variantmanager.vartobool(source);
  252. end;
  253. operator :=(const source : variant) dest : wordbool;{$ifdef SYSTEMINLINE}inline;{$endif}
  254. begin
  255. dest:=variantmanager.vartobool(source);
  256. end;
  257. operator :=(const source : variant) dest : longbool;{$ifdef SYSTEMINLINE}inline;{$endif}
  258. begin
  259. dest:=variantmanager.vartobool(source);
  260. end;
  261. { Chars }
  262. operator :=(const source : variant) dest : char;{$ifdef SYSTEMINLINE}inline;{$endif}
  263. Var
  264. S : String;
  265. begin
  266. VariantManager.VarToPStr(S,Source);
  267. If Length(S)>0 then
  268. Dest:=S[1];
  269. end;
  270. operator :=(const source : variant) dest : widechar;{$ifdef SYSTEMINLINE}inline;{$endif}
  271. Var
  272. WS : WideString;
  273. begin
  274. VariantManager.VarToWStr(WS,Source);
  275. If Length(WS)>0 then
  276. Dest:=WS[1];
  277. end;
  278. { Strings }
  279. operator :=(const source : variant) dest : shortstring;{$ifdef SYSTEMINLINE}inline;{$endif}
  280. begin
  281. VariantManager.VarToPStr(Dest,Source);
  282. end;
  283. operator :=(const source : variant) dest : ansistring;{$ifdef SYSTEMINLINE}inline;{$endif}
  284. begin
  285. VariantManager.vartolstr(dest,source);
  286. end;
  287. operator :=(const source : variant) dest : widestring;{$ifdef SYSTEMINLINE}inline;{$endif}
  288. begin
  289. variantmanager.vartowstr(dest,source);
  290. end;
  291. { Floats }
  292. {$ifdef SUPPORT_SINGLE}
  293. operator :=(const source : variant) dest : single;{$ifdef SYSTEMINLINE}inline;{$endif}
  294. begin
  295. dest:=variantmanager.vartoreal(source);
  296. end;
  297. {$endif SUPPORT_SINGLE}
  298. {$ifdef SUPPORT_DOUBLE}
  299. operator :=(const source : variant) dest : double;{$ifdef SYSTEMINLINE}inline;{$endif}
  300. begin
  301. dest:=variantmanager.vartoreal(source);
  302. end;
  303. {$endif SUPPORT_DOUBLE}
  304. {$ifdef SUPPORT_EXTENDED}
  305. operator :=(const source : variant) dest : extended;{$ifdef SYSTEMINLINE}inline;{$endif}
  306. begin
  307. dest:=variantmanager.vartoreal(source);
  308. end;
  309. {$endif SUPPORT_EXTENDED}
  310. {$ifdef SUPPORT_COMP}
  311. operator :=(const source : variant) dest : comp;{$ifdef SYSTEMINLINE}inline;{$endif}
  312. begin
  313. dest:=comp(variantmanager.vartoreal(source));
  314. end;
  315. {$endif SUPPORT_COMP}
  316. { Misc. }
  317. operator :=(const source : variant) dest : currency;{$ifdef SYSTEMINLINE}inline;{$endif}
  318. begin
  319. dest:=variantmanager.vartocurr(source);
  320. end;
  321. operator :=(const source : variant) dest : tdatetime;{$ifdef SYSTEMINLINE}inline;{$endif}
  322. begin
  323. dest:=variantmanager.vartotdatetime(source);
  324. end;
  325. operator :=(const source : olevariant) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  326. begin
  327. tvardata(result):=tvardata(source);
  328. end;
  329. operator :=(const source : variant) dest : olevariant;{$ifdef SYSTEMINLINE}inline;{$endif}
  330. begin
  331. variantmanager.olevarfromvar(dest,source);
  332. end;
  333. {**********************************************************************
  334. Operators
  335. **********************************************************************}
  336. operator or(const op1,op2 : variant) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  337. begin
  338. dest:=op1;
  339. variantmanager.varop(dest,op2,opor);
  340. end;
  341. operator and(const op1,op2 : variant) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  342. begin
  343. dest:=op1;
  344. variantmanager.varop(dest,op2,opand);
  345. end;
  346. operator xor(const op1,op2 : variant) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  347. begin
  348. dest:=op1;
  349. variantmanager.varop(dest,op2,opxor);
  350. end;
  351. operator not(const op : variant) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  352. begin
  353. dest:=op;
  354. variantmanager.varnot(dest);
  355. end;
  356. operator shl(const op1,op2 : variant) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  357. begin
  358. dest:=op1;
  359. variantmanager.varop(dest,op2,opshiftleft);
  360. end;
  361. operator shr(const op1,op2 : variant) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  362. begin
  363. dest:=op1;
  364. variantmanager.varop(dest,op2,opshiftright);
  365. end;
  366. operator +(const op1,op2 : variant) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  367. begin
  368. dest:=op1;
  369. variantmanager.varop(dest,op2,opadd);
  370. end;
  371. operator -(const op1,op2 : variant) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  372. begin
  373. dest:=op1;
  374. variantmanager.varop(dest,op2,opsubtract);
  375. end;
  376. operator *(const op1,op2 : variant) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  377. begin
  378. dest:=op1;
  379. variantmanager.varop(dest,op2,opmultiply);
  380. end;
  381. operator /(const op1,op2 : variant) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  382. begin
  383. dest:=op1;
  384. variantmanager.varop(dest,op2,opdivide);
  385. end;
  386. operator **(const op1,op2 : variant) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  387. begin
  388. dest:=op1;
  389. variantmanager.varop(dest,op2,oppower);
  390. end;
  391. operator div(const op1,op2 : variant) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  392. begin
  393. dest:=op1;
  394. variantmanager.varop(dest,op2,opintdivide);
  395. end;
  396. operator mod(const op1,op2 : variant) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  397. begin
  398. dest:=op1;
  399. variantmanager.varop(dest,op2,opmodulus);
  400. end;
  401. operator -(const op : variant) dest : variant;{$ifdef SYSTEMINLINE}inline;{$endif}
  402. begin
  403. dest:=op;
  404. variantmanager.varneg(dest);
  405. end;
  406. operator =(const op1,op2 : variant) dest : boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  407. begin
  408. dest:=variantmanager.cmpop(op1,op2,opcmpeq);
  409. end;
  410. operator <(const op1,op2 : variant) dest : boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  411. begin
  412. dest:=variantmanager.cmpop(op1,op2,opcmplt);
  413. end;
  414. operator >(const op1,op2 : variant) dest : boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  415. begin
  416. dest:=variantmanager.cmpop(op1,op2,opcmpgt);
  417. end;
  418. operator >=(const op1,op2 : variant) dest : boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  419. begin
  420. dest:=variantmanager.cmpop(op1,op2,opcmpge);
  421. end;
  422. operator <=(const op1,op2 : variant) dest : boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  423. begin
  424. dest:=variantmanager.cmpop(op1,op2,opcmplt);
  425. end;
  426. procedure VarArrayRedim(var A: Variant; HighBound: SizeInt);
  427. begin
  428. variantmanager.vararrayredim(a,highbound);
  429. end;
  430. procedure VarCast(var dest : variant;const source : variant;vartype : longint);
  431. begin
  432. variantmanager.varcast(dest,source,vartype);
  433. end;
  434. {**********************************************************************
  435. Variant manager functions
  436. **********************************************************************}
  437. procedure GetVariantManager(var VarMgr: TVariantManager);
  438. begin
  439. VarMgr:=VariantManager;
  440. end;
  441. procedure SetVariantManager(const VarMgr: TVariantManager);
  442. begin
  443. VariantManager:=VarMgr;
  444. end;
  445. function IsVariantManagerSet: Boolean;
  446. var
  447. i : longint;
  448. begin
  449. I:=0;
  450. Result:=True;
  451. While Result and (I<(sizeof(tvariantmanager) div sizeof(pointer))-1) do
  452. begin
  453. Result:=Pointer(ppointer(@variantmanager+i*sizeof(pointer))^)<>Pointer(@invalidvariantop);
  454. Inc(I);
  455. end;
  456. end;
  457. procedure initvariantmanager;
  458. var
  459. i : longint;
  460. begin
  461. VarDispProc:=@vardisperror;
  462. DispCallByIDProc:=@vardisperror;
  463. tvardata(Unassigned).VType:=varEmpty;
  464. tvardata(Null).VType:=varNull;
  465. for i:=0 to (sizeof(tvariantmanager) div sizeof(pointer))-1 do
  466. ppointer(@variantmanager+i*sizeof(pointer))^:=@invalidvariantopnovariants;
  467. pointer(variantmanager.varclear):=@varclear
  468. end;