variant.inc 14 KB

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