variant.inc 14 KB

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