variant.inc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  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;
  112. begin
  113. Variantmanager.varfromInt(Dest,Source,1);
  114. end;
  115. operator :=(const source : shortint) dest : variant;
  116. begin
  117. Variantmanager.varfromInt(Dest,Source,-1);
  118. end;
  119. operator :=(const source : word) dest : variant;
  120. begin
  121. Variantmanager.varfromInt(Dest,Source,2);
  122. end;
  123. operator :=(const source : smallint) dest : variant;
  124. begin
  125. Variantmanager.varfromInt(Dest,Source,-2);
  126. end;
  127. operator :=(const source : dword) dest : variant;
  128. begin
  129. Variantmanager.varfromInt(Dest,Source,4);
  130. end;
  131. operator :=(const source : longint) dest : variant;
  132. begin
  133. Variantmanager.varfromInt(Dest,Source,-4);
  134. end;
  135. operator :=(const source : qword) dest : variant;
  136. begin
  137. Variantmanager.varfromWord64(Dest,Source);
  138. end;
  139. operator :=(const source : int64) dest : variant;
  140. begin
  141. Variantmanager.varfromInt64(Dest,Source);
  142. end;
  143. { Boolean }
  144. operator :=(const source : boolean) dest : variant;
  145. begin
  146. Variantmanager.varfromBool(Dest,Source);
  147. end;
  148. operator :=(const source : wordbool) dest : variant;
  149. begin
  150. Variantmanager.varfromBool(Dest,Boolean(Source));
  151. end;
  152. operator :=(const source : longbool) dest : variant;
  153. begin
  154. Variantmanager.varfromBool(Dest,Boolean(Source));
  155. end;
  156. { Chars }
  157. operator :=(const source : char) dest : variant;
  158. begin
  159. VariantManager.VarFromPStr(Dest,Source);
  160. end;
  161. operator :=(const source : widechar) dest : variant;
  162. begin
  163. VariantManager.VarFromWStr(Dest,Source);
  164. end;
  165. { Strings }
  166. operator :=(const source : shortstring) dest : variant;
  167. begin
  168. VariantManager.VarFromPStr(Dest,Source);
  169. end;
  170. operator :=(const source : ansistring) dest : variant;
  171. begin
  172. VariantManager.VarFromLStr(Dest,Source);
  173. end;
  174. operator :=(const source : widestring) dest : variant;
  175. begin
  176. VariantManager.VarFromWStr(Dest,Source);
  177. end;
  178. { Floats }
  179. {$ifdef SUPPORT_SINGLE}
  180. operator :=(const source : single) dest : variant;
  181. begin
  182. VariantManager.VarFromReal(Dest,Source);
  183. end;
  184. {$endif SUPPORT_SINGLE}
  185. {$ifdef SUPPORT_DOUBLE}
  186. operator :=(const source : double) dest : variant;
  187. begin
  188. VariantManager.VarFromReal(Dest,Source);
  189. end;
  190. {$endif SUPPORT_DOUBLE}
  191. {$ifdef SUPPORT_EXTENDED}
  192. operator :=(const source : extended) dest : variant;
  193. begin
  194. VariantManager.VarFromReal(Dest,Source);
  195. end;
  196. {$endif SUPPORT_EXTENDED}
  197. {$ifdef SUPPORT_COMP}
  198. Operator :=(const source : comp) dest : variant;
  199. begin
  200. VariantManager.VarFromReal(Dest,Source);
  201. end;
  202. {$endif SUPPORT_COMP}
  203. { Misc. }
  204. operator :=(const source : currency) dest : variant;
  205. begin
  206. VariantManager.VarFromCurr(Dest,Source);
  207. end;
  208. operator :=(const source : tdatetime) dest : variant;
  209. begin
  210. VariantManager.VarFromTDateTime(Dest,Source);
  211. end;
  212. {**********************************************************************
  213. from Variant assignments
  214. **********************************************************************}
  215. { Integer }
  216. operator :=(const source : variant) dest : byte;
  217. begin
  218. dest:=variantmanager.vartoint(source);
  219. end;
  220. operator :=(const source : variant) dest : shortint;
  221. begin
  222. dest:=variantmanager.vartoint(source);
  223. end;
  224. operator :=(const source : variant) dest : word;
  225. begin
  226. dest:=variantmanager.vartoint(source);
  227. end;
  228. operator :=(const source : variant) dest : smallint;
  229. begin
  230. dest:=variantmanager.vartoint(source);
  231. end;
  232. operator :=(const source : variant) dest : dword;
  233. begin
  234. dest:=variantmanager.vartoint(source);
  235. end;
  236. operator :=(const source : variant) dest : longint;
  237. begin
  238. dest:=variantmanager.vartoint(source);
  239. end;
  240. operator :=(const source : variant) dest : qword;
  241. begin
  242. dest:=variantmanager.vartoword64(source);
  243. end;
  244. operator :=(const source : variant) dest : int64;
  245. begin
  246. dest:=variantmanager.vartoint64(source);
  247. end;
  248. { Boolean }
  249. operator :=(const source : variant) dest : boolean;
  250. begin
  251. dest:=variantmanager.vartobool(source);
  252. end;
  253. operator :=(const source : variant) dest : wordbool;
  254. begin
  255. dest:=variantmanager.vartobool(source);
  256. end;
  257. operator :=(const source : variant) dest : longbool;
  258. begin
  259. dest:=variantmanager.vartobool(source);
  260. end;
  261. { Chars }
  262. operator :=(const source : variant) dest : char;
  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;
  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;
  280. begin
  281. VariantManager.VarToPStr(Dest,Source);
  282. end;
  283. operator :=(const source : variant) dest : ansistring;
  284. begin
  285. VariantManager.vartolstr(dest,source);
  286. end;
  287. operator :=(const source : variant) dest : widestring;
  288. begin
  289. variantmanager.vartowstr(dest,source);
  290. end;
  291. { Floats }
  292. {$ifdef SUPPORT_SINGLE}
  293. operator :=(const source : variant) dest : single;
  294. begin
  295. dest:=variantmanager.vartoreal(source);
  296. end;
  297. {$endif SUPPORT_SINGLE}
  298. {$ifdef SUPPORT_DOUBLE}
  299. operator :=(const source : variant) dest : double;
  300. begin
  301. dest:=variantmanager.vartoreal(source);
  302. end;
  303. {$endif SUPPORT_DOUBLE}
  304. {$ifdef SUPPORT_EXTENDED}
  305. operator :=(const source : variant) dest : extended;
  306. begin
  307. dest:=variantmanager.vartoreal(source);
  308. end;
  309. {$endif SUPPORT_EXTENDED}
  310. {$ifdef SUPPORT_COMP}
  311. operator :=(const source : variant) dest : comp;
  312. begin
  313. dest:=comp(variantmanager.vartoreal(source));
  314. end;
  315. {$endif SUPPORT_COMP}
  316. { Misc. }
  317. operator :=(const source : variant) dest : currency;
  318. begin
  319. dest:=variantmanager.vartocurr(source);
  320. end;
  321. operator :=(const source : variant) dest : tdatetime;
  322. begin
  323. dest:=variantmanager.vartotdatetime(source);
  324. end;
  325. {**********************************************************************
  326. Operators
  327. **********************************************************************}
  328. operator or(const op1,op2 : variant) dest : variant;
  329. begin
  330. dest:=op1;
  331. variantmanager.varop(dest,op2,opor);
  332. end;
  333. operator and(const op1,op2 : variant) dest : variant;
  334. begin
  335. dest:=op1;
  336. variantmanager.varop(dest,op2,opand);
  337. end;
  338. operator xor(const op1,op2 : variant) dest : variant;
  339. begin
  340. dest:=op1;
  341. variantmanager.varop(dest,op2,opxor);
  342. end;
  343. operator not(const op : variant) dest : variant;
  344. begin
  345. dest:=op;
  346. variantmanager.varnot(dest);
  347. end;
  348. operator shl(const op1,op2 : variant) dest : variant;
  349. begin
  350. dest:=op1;
  351. variantmanager.varop(dest,op2,opshiftleft);
  352. end;
  353. operator shr(const op1,op2 : variant) dest : variant;
  354. begin
  355. dest:=op1;
  356. variantmanager.varop(dest,op2,opshiftright);
  357. end;
  358. operator +(const op1,op2 : variant) dest : variant;
  359. begin
  360. dest:=op1;
  361. variantmanager.varop(dest,op2,opadd);
  362. end;
  363. operator -(const op1,op2 : variant) dest : variant;
  364. begin
  365. dest:=op1;
  366. variantmanager.varop(dest,op2,opsubtract);
  367. end;
  368. operator *(const op1,op2 : variant) dest : variant;
  369. begin
  370. dest:=op1;
  371. variantmanager.varop(dest,op2,opmultiply);
  372. end;
  373. operator /(const op1,op2 : variant) dest : variant;
  374. begin
  375. dest:=op1;
  376. variantmanager.varop(dest,op2,opdivide);
  377. end;
  378. operator **(const op1,op2 : variant) dest : variant;
  379. begin
  380. dest:=op1;
  381. variantmanager.varop(dest,op2,oppower);
  382. end;
  383. operator div(const op1,op2 : variant) dest : variant;
  384. begin
  385. dest:=op1;
  386. variantmanager.varop(dest,op2,opintdivide);
  387. end;
  388. operator mod(const op1,op2 : variant) dest : variant;
  389. begin
  390. dest:=op1;
  391. variantmanager.varop(dest,op2,opmodulus);
  392. end;
  393. operator -(const op : variant) dest : variant;
  394. begin
  395. dest:=op;
  396. variantmanager.varneg(dest);
  397. end;
  398. operator =(const op1,op2 : variant) dest : boolean;
  399. begin
  400. dest:=variantmanager.cmpop(op1,op2,opcmpeq);
  401. end;
  402. operator <(const op1,op2 : variant) dest : boolean;
  403. begin
  404. dest:=variantmanager.cmpop(op1,op2,opcmplt);
  405. end;
  406. operator >(const op1,op2 : variant) dest : boolean;
  407. begin
  408. dest:=variantmanager.cmpop(op1,op2,opcmpgt);
  409. end;
  410. operator >=(const op1,op2 : variant) dest : boolean;
  411. begin
  412. dest:=variantmanager.cmpop(op1,op2,opcmpge);
  413. end;
  414. operator <=(const op1,op2 : variant) dest : boolean;
  415. begin
  416. dest:=variantmanager.cmpop(op1,op2,opcmplt);
  417. end;
  418. procedure VarArrayRedim(var A: Variant; HighBound: SizeInt);
  419. begin
  420. variantmanager.vararrayredim(a,highbound);
  421. end;
  422. procedure VarCast(var dest : variant;const source : variant;vartype : longint);
  423. begin
  424. variantmanager.varcast(dest,source,vartype);
  425. end;
  426. {**********************************************************************
  427. Variant manager functions
  428. **********************************************************************}
  429. procedure GetVariantManager(var VarMgr: TVariantManager);
  430. begin
  431. VarMgr:=VariantManager;
  432. end;
  433. procedure SetVariantManager(const VarMgr: TVariantManager);
  434. begin
  435. VariantManager:=VarMgr;
  436. end;
  437. function IsVariantManagerSet: Boolean;
  438. var
  439. i : longint;
  440. begin
  441. I:=0;
  442. Result:=True;
  443. While Result and (I<(sizeof(tvariantmanager) div sizeof(pointer))-1) do
  444. begin
  445. Result:=Pointer(ppointer(@variantmanager+i*sizeof(pointer))^)<>Pointer(@invalidvariantop);
  446. Inc(I);
  447. end;
  448. end;
  449. procedure initvariantmanager;
  450. var
  451. i : longint;
  452. begin
  453. VarDispProc:=@vardisperror;
  454. DispCallByIDProc:=@vardisperror;
  455. tvardata(Unassigned).VType:=varEmpty;
  456. tvardata(Null).VType:=varNull;
  457. for i:=0 to (sizeof(tvariantmanager) div sizeof(pointer))-1 do
  458. ppointer(@variantmanager+i*sizeof(pointer))^:=@invalidvariantopnovariants;
  459. pointer(variantmanager.varclear):=@varclear
  460. end;