variant.inc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  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. operator :=(const source : currency) dest : variant;
  191. begin
  192. VariantManager.VarFromCurr(Dest,Source);
  193. end;
  194. operator :=(const source : tdatetime) dest : variant;
  195. begin
  196. VariantManager.VarFromTDateTime(Dest,Source);
  197. end;
  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. {$ifdef HASOVERLOADASSIGNBYUNIQUERESULT}
  308. operator :=(const source : variant) dest : tdatetime;
  309. begin
  310. dest:=variantmanager.vartotdatetime(source);
  311. end;
  312. {$endif HASOVERLOADASSIGNBYUNIQUERESULT}
  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 **(const op1,op2 : variant) dest : variant;
  367. begin
  368. dest:=op1;
  369. variantmanager.varop(dest,op2,oppower);
  370. end;
  371. operator div(const op1,op2 : variant) dest : variant;
  372. begin
  373. dest:=op1;
  374. variantmanager.varop(dest,op2,opintdivide);
  375. end;
  376. operator mod(const op1,op2 : variant) dest : variant;
  377. begin
  378. dest:=op1;
  379. variantmanager.varop(dest,op2,opmodulus);
  380. end;
  381. operator -(const op : variant) dest : variant;
  382. begin
  383. dest:=op;
  384. variantmanager.varneg(dest);
  385. end;
  386. operator =(const op1,op2 : variant) dest : boolean;
  387. begin
  388. dest:=variantmanager.cmpop(op1,op2,opcmpeq);
  389. end;
  390. operator <(const op1,op2 : variant) dest : boolean;
  391. begin
  392. dest:=variantmanager.cmpop(op1,op2,opcmplt);
  393. end;
  394. operator >(const op1,op2 : variant) dest : boolean;
  395. begin
  396. dest:=variantmanager.cmpop(op1,op2,opcmpgt);
  397. end;
  398. operator >=(const op1,op2 : variant) dest : boolean;
  399. begin
  400. dest:=variantmanager.cmpop(op1,op2,opcmpge);
  401. end;
  402. operator <=(const op1,op2 : variant) dest : boolean;
  403. begin
  404. dest:=variantmanager.cmpop(op1,op2,opcmplt);
  405. end;
  406. procedure VarArrayRedim(var A: Variant; HighBound: SizeInt);
  407. begin
  408. variantmanager.vararrayredim(a,highbound);
  409. end;
  410. {**********************************************************************
  411. Variant manager functions
  412. **********************************************************************}
  413. procedure GetVariantManager(var VarMgr: TVariantManager);
  414. begin
  415. VarMgr:=VariantManager;
  416. end;
  417. procedure SetVariantManager(const VarMgr: TVariantManager);
  418. begin
  419. VariantManager:=VarMgr;
  420. end;
  421. function IsVariantManagerSet: Boolean;
  422. var
  423. i : longint;
  424. begin
  425. I:=0;
  426. Result:=True;
  427. While Result and (I<(sizeof(tvariantmanager) div sizeof(pointer))-1) do
  428. begin
  429. Result:=Pointer(ppointer(@variantmanager+i*sizeof(pointer))^)<>Pointer(@invalidvariantop);
  430. Inc(I);
  431. end;
  432. end;
  433. procedure initvariantmanager;
  434. var
  435. i : longint;
  436. begin
  437. VarDispProc:=@vardisperror;
  438. DispCallByIDProc:=@vardisperror;
  439. tvardata(Unassigned).VType:=varEmpty;
  440. tvardata(Null).VType:=varNull;
  441. for i:=0 to (sizeof(tvariantmanager) div sizeof(pointer))-1 do
  442. ppointer(@variantmanager+i*sizeof(pointer))^:=@invalidvariantop;
  443. pointer(variantmanager.varclear):=@varclear
  444. end;
  445. {
  446. $Log$
  447. Revision 1.30 2005-04-28 19:34:19 florian
  448. + variant<->currency/tdatetime operators
  449. Revision 1.29 2005/04/10 20:24:31 florian
  450. + basic operators (int, real and string) for variants implemented
  451. Revision 1.28 2005/04/10 09:22:38 florian
  452. + varrarrayredim added and implemented
  453. Revision 1.27 2005/03/28 13:38:05 florian
  454. + a lot of vararray stuff
  455. Revision 1.26 2005/03/25 19:02:59 florian
  456. + more vararray stuff
  457. Revision 1.25 2005/02/24 22:36:36 florian
  458. + some variant stuff fixed and added
  459. Revision 1.24 2005/02/14 17:13:29 peter
  460. * truncate log
  461. Revision 1.23 2005/02/01 20:22:24 florian
  462. + interface <-> variant conversion from Danny Milosavljevic
  463. Revision 1.22 2005/01/15 18:47:26 florian
  464. * several variant init./final. stuff fixed
  465. Revision 1.21 2005/01/08 20:43:44 florian
  466. + init/cleaning code for variants added
  467. Revision 1.20 2005/01/07 21:15:46 florian
  468. + basic rtl support for variant <-> interface implemented
  469. }