variant.inc 14 KB

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