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.22 2005-01-15 18:47:26 florian
  425. * several variant init./final. stuff fixed
  426. Revision 1.21 2005/01/08 20:43:44 florian
  427. + init/cleaning code for variants added
  428. Revision 1.20 2005/01/07 21:15:46 florian
  429. + basic rtl support for variant <-> interface implemented
  430. Revision 1.19 2004/12/05 11:49:06 florian
  431. * implemented helper for variant<->dyn. array type cast
  432. Revision 1.18 2004/08/18 21:03:35 florian
  433. * sparc uses wait4 as well
  434. Revision 1.17 2004/05/31 20:25:04 peter
  435. * removed warnings
  436. Revision 1.16 2003/12/10 01:36:39 florian
  437. * real functions ifdef'ed depending on the supported types
  438. Revision 1.15 2003/11/05 15:26:37 florian
  439. + currency type can be assigned to variants now
  440. Revision 1.14 2003/10/04 23:40:42 florian
  441. * write helper comproc for variants fixed
  442. Revision 1.13 2003/09/03 14:09:37 florian
  443. * arm fixes to the common rtl code
  444. * some generic math code fixed
  445. * ...
  446. Revision 1.12 2002/10/10 19:24:28 florian
  447. + write(ln) support for variants added
  448. Revision 1.11 2002/10/09 20:13:26 florian
  449. * hopefully last fix to get things working :/
  450. Revision 1.10 2002/10/09 19:56:01 florian
  451. * variant assignments don't work yet, commented out
  452. Revision 1.9 2002/10/09 19:08:22 florian
  453. + Variant constants Unassigned and Null added
  454. Revision 1.8 2002/10/07 15:10:45 florian
  455. + variant wrappers for cmp operators added
  456. Revision 1.7 2002/10/07 10:27:45 florian
  457. + more variant wrappers added
  458. Revision 1.6 2002/10/06 22:13:55 florian
  459. * wrappers for xor, or and and operator with variants added
  460. Revision 1.5 2002/09/07 15:07:46 peter
  461. * old logs removed and tabs fixed
  462. }