variant.inc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  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. Procedure fpc_write_text_variant(Len : Longint;var f : Text;const v : variant); iocheck; [Public,Alias:'FPC_WRITE_TEXT_VARIANT']; compilerproc;
  48. Begin
  49. If (InOutRes<>0) then
  50. exit;
  51. case TextRec(f).mode of
  52. { fmAppend gets changed to fmOutPut in do_open (JM) }
  53. fmOutput:
  54. if len=-1 then
  55. variantmanager.write0variant(f,v)
  56. else
  57. variantmanager.writevariant(f,v,len);
  58. fmInput:
  59. InOutRes:=105
  60. else InOutRes:=103;
  61. end;
  62. End;
  63. function fpc_variant_to_dynarray(const v : variant;typeinfo : pointer) : pointer;compilerproc;
  64. begin
  65. variantmanager.vartodynarray(result,v,typeinfo);
  66. end;
  67. function fpc_dynarray_to_variant(dynarr : pointer;typeinfo : pointer) : variant;compilerproc;
  68. begin
  69. variantmanager.varfromdynarray(result,dynarr,typeinfo);
  70. end;
  71. function fpc_variant_to_interface(const v : variant) : iinterface;compilerproc;
  72. begin
  73. variantmanager.vartointf(result,v);
  74. end;
  75. function fpc_interface_to_variant(const i : iinterface) : variant;compilerproc;
  76. begin
  77. variantmanager.varfromintf(result,i);
  78. end;
  79. { ---------------------------------------------------------------------
  80. Overloaded operators.
  81. ---------------------------------------------------------------------}
  82. { Integer }
  83. operator :=(const source : byte) dest : variant;
  84. begin
  85. Variantmanager.varfromInt(Dest,Source,1);
  86. end;
  87. operator :=(const source : shortint) dest : variant;
  88. begin
  89. Variantmanager.varfromInt(Dest,Source,-1);
  90. end;
  91. operator :=(const source : word) dest : variant;
  92. begin
  93. Variantmanager.varfromInt(Dest,Source,2);
  94. end;
  95. operator :=(const source : smallint) dest : variant;
  96. begin
  97. Variantmanager.varfromInt(Dest,Source,-2);
  98. end;
  99. operator :=(const source : dword) dest : variant;
  100. begin
  101. Variantmanager.varfromInt(Dest,Source,4);
  102. end;
  103. operator :=(const source : longint) dest : variant;
  104. begin
  105. Variantmanager.varfromInt(Dest,Source,-4);
  106. end;
  107. operator :=(const source : qword) dest : variant;
  108. begin
  109. Variantmanager.varfromWord64(Dest,Source);
  110. end;
  111. operator :=(const source : int64) dest : variant;
  112. begin
  113. Variantmanager.varfromInt64(Dest,Source);
  114. end;
  115. { Boolean }
  116. operator :=(const source : boolean) dest : variant;
  117. begin
  118. Variantmanager.varfromBool(Dest,Source);
  119. end;
  120. operator :=(const source : wordbool) dest : variant;
  121. begin
  122. Variantmanager.varfromBool(Dest,Boolean(Source));
  123. end;
  124. operator :=(const source : longbool) dest : variant;
  125. begin
  126. Variantmanager.varfromBool(Dest,Boolean(Source));
  127. end;
  128. { Chars }
  129. operator :=(const source : char) dest : variant;
  130. begin
  131. VariantManager.VarFromPStr(Dest,Source);
  132. end;
  133. operator :=(const source : widechar) dest : variant;
  134. begin
  135. VariantManager.VarFromWStr(Dest,Source);
  136. end;
  137. { Strings }
  138. operator :=(const source : shortstring) dest : variant;
  139. begin
  140. VariantManager.VarFromPStr(Dest,Source);
  141. end;
  142. operator :=(const source : ansistring) dest : variant;
  143. begin
  144. VariantManager.VarFromLStr(Dest,Source);
  145. end;
  146. operator :=(const source : widestring) dest : variant;
  147. begin
  148. VariantManager.VarFromWStr(Dest,Source);
  149. end;
  150. { Floats }
  151. {$ifdef SUPPORT_SINGLE}
  152. operator :=(const source : single) dest : variant;
  153. begin
  154. VariantManager.VarFromReal(Dest,Source);
  155. end;
  156. {$endif SUPPORT_SINGLE}
  157. {$ifdef SUPPORT_DOUBLE}
  158. operator :=(const source : double) dest : variant;
  159. begin
  160. VariantManager.VarFromReal(Dest,Source);
  161. end;
  162. {$endif SUPPORT_DOUBLE}
  163. {$ifdef SUPPORT_EXTENDED}
  164. operator :=(const source : extended) dest : variant;
  165. begin
  166. VariantManager.VarFromReal(Dest,Source);
  167. end;
  168. {$endif SUPPORT_EXTENDED}
  169. {$ifdef SUPPORT_COMP}
  170. Operator :=(const source : comp) dest : variant;
  171. begin
  172. VariantManager.VarFromReal(Dest,Source);
  173. end;
  174. {$endif SUPPORT_COMP}
  175. { Misc. }
  176. { Fixme!!!
  177. operator :=(const source : currency) dest : variant;
  178. begin
  179. end;
  180. operator :=(const source : tdatetime) dest : variant;
  181. begin
  182. end;
  183. }
  184. {**********************************************************************
  185. from Variant assignments
  186. **********************************************************************}
  187. { Integer }
  188. operator :=(const source : variant) dest : byte;
  189. begin
  190. dest:=variantmanager.vartoint(source);
  191. end;
  192. operator :=(const source : variant) dest : shortint;
  193. begin
  194. dest:=variantmanager.vartoint(source);
  195. end;
  196. operator :=(const source : variant) dest : word;
  197. begin
  198. dest:=variantmanager.vartoint(source);
  199. end;
  200. operator :=(const source : variant) dest : smallint;
  201. begin
  202. dest:=variantmanager.vartoint(source);
  203. end;
  204. operator :=(const source : variant) dest : dword;
  205. begin
  206. dest:=variantmanager.vartoint(source);
  207. end;
  208. operator :=(const source : variant) dest : longint;
  209. begin
  210. dest:=variantmanager.vartoint(source);
  211. end;
  212. operator :=(const source : variant) dest : qword;
  213. begin
  214. dest:=variantmanager.vartoword64(source);
  215. end;
  216. operator :=(const source : variant) dest : int64;
  217. begin
  218. dest:=variantmanager.vartoint64(source);
  219. end;
  220. { Boolean }
  221. operator :=(const source : variant) dest : boolean;
  222. begin
  223. dest:=variantmanager.vartobool(source);
  224. end;
  225. operator :=(const source : variant) dest : wordbool;
  226. begin
  227. dest:=variantmanager.vartobool(source);
  228. end;
  229. operator :=(const source : variant) dest : longbool;
  230. begin
  231. dest:=variantmanager.vartobool(source);
  232. end;
  233. { Chars }
  234. operator :=(const source : variant) dest : char;
  235. Var
  236. S : String;
  237. begin
  238. VariantManager.VarToPStr(S,Source);
  239. If Length(S)>0 then
  240. Dest:=S[1];
  241. end;
  242. operator :=(const source : variant) dest : widechar;
  243. Var
  244. WS : WideString;
  245. begin
  246. VariantManager.VarToWStr(WS,Source);
  247. If Length(WS)>0 then
  248. Dest:=WS[1];
  249. end;
  250. { Strings }
  251. operator :=(const source : variant) dest : shortstring;
  252. begin
  253. VariantManager.VarToPStr(Dest,Source);
  254. end;
  255. operator :=(const source : variant) dest : ansistring;
  256. begin
  257. VariantManager.vartolstr(dest,source);
  258. end;
  259. operator :=(const source : variant) dest : widestring;
  260. begin
  261. variantmanager.vartowstr(dest,source);
  262. end;
  263. { Floats }
  264. {$ifdef SUPPORT_SINGLE}
  265. operator :=(const source : variant) dest : single;
  266. begin
  267. dest:=variantmanager.vartoreal(source);
  268. end;
  269. {$endif SUPPORT_SINGLE}
  270. {$ifdef SUPPORT_DOUBLE}
  271. operator :=(const source : variant) dest : double;
  272. begin
  273. dest:=variantmanager.vartoreal(source);
  274. end;
  275. {$endif SUPPORT_DOUBLE}
  276. {$ifdef SUPPORT_EXTENDED}
  277. operator :=(const source : variant) dest : extended;
  278. begin
  279. dest:=variantmanager.vartoreal(source);
  280. end;
  281. {$endif SUPPORT_EXTENDED}
  282. {$ifdef SUPPORT_COMP}
  283. operator :=(const source : variant) dest : comp;
  284. begin
  285. dest:=comp(variantmanager.vartoreal(source));
  286. end;
  287. {$endif SUPPORT_COMP}
  288. { Misc. }
  289. operator :=(const source : variant) dest : currency;
  290. begin
  291. dest:=variantmanager.vartocurr(source);
  292. end;
  293. (* FIXME !!!
  294. operator :=(const source : variant) dest : tdatetime;
  295. begin
  296. dest:=variantmanager.currtovar(source);
  297. end;
  298. *)
  299. {**********************************************************************
  300. Operators
  301. **********************************************************************}
  302. operator or(const op1,op2 : variant) dest : variant;
  303. begin
  304. dest:=op1;
  305. variantmanager.varop(dest,op2,opor);
  306. end;
  307. operator and(const op1,op2 : variant) dest : variant;
  308. begin
  309. dest:=op1;
  310. variantmanager.varop(dest,op2,opand);
  311. end;
  312. operator xor(const op1,op2 : variant) dest : variant;
  313. begin
  314. dest:=op1;
  315. variantmanager.varop(dest,op2,opxor);
  316. end;
  317. operator not(const op : variant) dest : variant;
  318. begin
  319. dest:=op;
  320. variantmanager.varnot(dest);
  321. end;
  322. operator shl(const op1,op2 : variant) dest : variant;
  323. begin
  324. dest:=op1;
  325. variantmanager.varop(dest,op2,opshiftleft);
  326. end;
  327. operator shr(const op1,op2 : variant) dest : variant;
  328. begin
  329. dest:=op1;
  330. variantmanager.varop(dest,op2,opshiftright);
  331. end;
  332. operator +(const op1,op2 : variant) dest : variant;
  333. begin
  334. dest:=op1;
  335. variantmanager.varop(dest,op2,opadd);
  336. end;
  337. operator -(const op1,op2 : variant) dest : variant;
  338. begin
  339. dest:=op1;
  340. variantmanager.varop(dest,op2,opsubtract);
  341. end;
  342. operator *(const op1,op2 : variant) dest : variant;
  343. begin
  344. dest:=op1;
  345. variantmanager.varop(dest,op2,opmultiply);
  346. end;
  347. operator /(const op1,op2 : variant) dest : variant;
  348. begin
  349. dest:=op1;
  350. variantmanager.varop(dest,op2,opdivide);
  351. end;
  352. operator div(const op1,op2 : variant) dest : variant;
  353. begin
  354. dest:=op1;
  355. variantmanager.varop(dest,op2,opintdivide);
  356. end;
  357. operator mod(const op1,op2 : variant) dest : variant;
  358. begin
  359. dest:=op1;
  360. variantmanager.varop(dest,op2,opmodulus);
  361. end;
  362. operator -(const op : variant) dest : variant;
  363. begin
  364. dest:=op;
  365. variantmanager.varneg(dest);
  366. end;
  367. operator =(const op1,op2 : variant) dest : boolean;
  368. begin
  369. dest:=variantmanager.cmpop(op1,op2,opcmpeq);
  370. end;
  371. operator <(const op1,op2 : variant) dest : boolean;
  372. begin
  373. dest:=variantmanager.cmpop(op1,op2,opcmplt);
  374. end;
  375. operator >(const op1,op2 : variant) dest : boolean;
  376. begin
  377. dest:=variantmanager.cmpop(op1,op2,opcmpgt);
  378. end;
  379. operator >=(const op1,op2 : variant) dest : boolean;
  380. begin
  381. dest:=variantmanager.cmpop(op1,op2,opcmpge);
  382. end;
  383. operator <=(const op1,op2 : variant) dest : boolean;
  384. begin
  385. dest:=variantmanager.cmpop(op1,op2,opcmplt);
  386. end;
  387. {**********************************************************************
  388. Variant manager functions
  389. **********************************************************************}
  390. procedure GetVariantManager(var VarMgr: TVariantManager);
  391. begin
  392. VarMgr:=VariantManager;
  393. end;
  394. procedure SetVariantManager(const VarMgr: TVariantManager);
  395. begin
  396. VariantManager:=VarMgr;
  397. end;
  398. function IsVariantManagerSet: Boolean;
  399. var
  400. i : longint;
  401. begin
  402. I:=0;
  403. Result:=True;
  404. While Result and (I<(sizeof(tvariantmanager) div sizeof(pointer))-1) do
  405. begin
  406. Result:=Pointer(ppointer(@variantmanager+i*sizeof(pointer))^)<>Pointer(@invalidvariantop);
  407. Inc(I);
  408. end;
  409. end;
  410. procedure initvariantmanager;
  411. var
  412. i : longint;
  413. begin
  414. VarDispProc:=@vardisperror;
  415. DispCallByIDProc:=@vardisperror;
  416. tvardata(Unassigned).VType:=varEmpty;
  417. tvardata(Null).VType:=varNull;
  418. for i:=0 to (sizeof(tvariantmanager) div sizeof(pointer))-1 do
  419. ppointer(@variantmanager+i*sizeof(pointer))^:=@invalidvariantop;
  420. pointer(variantmanager.varclear):=@varclear
  421. end;
  422. {
  423. $Log$
  424. Revision 1.23 2005-02-01 20:22:24 florian
  425. + interface <-> variant conversion from Danny Milosavljevic
  426. Revision 1.22 2005/01/15 18:47:26 florian
  427. * several variant init./final. stuff fixed
  428. Revision 1.21 2005/01/08 20:43:44 florian
  429. + init/cleaning code for variants added
  430. Revision 1.20 2005/01/07 21:15:46 florian
  431. + basic rtl support for variant <-> interface implemented
  432. Revision 1.19 2004/12/05 11:49:06 florian
  433. * implemented helper for variant<->dyn. array type cast
  434. Revision 1.18 2004/08/18 21:03:35 florian
  435. * sparc uses wait4 as well
  436. Revision 1.17 2004/05/31 20:25:04 peter
  437. * removed warnings
  438. Revision 1.16 2003/12/10 01:36:39 florian
  439. * real functions ifdef'ed depending on the supported types
  440. Revision 1.15 2003/11/05 15:26:37 florian
  441. + currency type can be assigned to variants now
  442. Revision 1.14 2003/10/04 23:40:42 florian
  443. * write helper comproc for variants fixed
  444. Revision 1.13 2003/09/03 14:09:37 florian
  445. * arm fixes to the common rtl code
  446. * some generic math code fixed
  447. * ...
  448. Revision 1.12 2002/10/10 19:24:28 florian
  449. + write(ln) support for variants added
  450. Revision 1.11 2002/10/09 20:13:26 florian
  451. * hopefully last fix to get things working :/
  452. Revision 1.10 2002/10/09 19:56:01 florian
  453. * variant assignments don't work yet, commented out
  454. Revision 1.9 2002/10/09 19:08:22 florian
  455. + Variant constants Unassigned and Null added
  456. Revision 1.8 2002/10/07 15:10:45 florian
  457. + variant wrappers for cmp operators added
  458. Revision 1.7 2002/10/07 10:27:45 florian
  459. + more variant wrappers added
  460. Revision 1.6 2002/10/06 22:13:55 florian
  461. * wrappers for xor, or and and operator with variants added
  462. Revision 1.5 2002/09/07 15:07:46 peter
  463. * old logs removed and tabs fixed
  464. }