variant.inc 13 KB

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