varutils.pp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. Interface and OS-independent part of variant support
  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. {$MODE ObjFPC}
  13. Unit varutils;
  14. Interface
  15. Uses sysutils;
  16. Type
  17. // Types needed to make this work. These should be moved to the system unit.
  18. currency = int64;
  19. HRESULT = Longint;
  20. PSmallInt = ^Smallint;
  21. PLongint = ^Longint;
  22. PSingle = ^Single;
  23. PDouble = ^Double;
  24. PCurrency = ^Currency;
  25. TDateTime = Double;
  26. PDate = ^TDateTime;
  27. PPWideChar = ^PWideChar;
  28. Error = Longint;
  29. PError = ^Error;
  30. PWordBool = ^WordBool;
  31. PByte = ^Byte;
  32. EVarianterror = Class(Exception)
  33. ErrCode : longint;
  34. Constructor CreateCode(Code : Longint);
  35. end;
  36. TVarArrayBound = packed record
  37. ElementCount: Longint;
  38. LowBound: Longint;
  39. end;
  40. TVarArrayBoundArray = Array [0..0] of TVarArrayBound;
  41. PVarArrayBoundArray = ^TVarArrayBoundArray;
  42. TVarArrayCoorArray = Array [0..0] of Longint;
  43. PVarArrayCoorArray = ^TVarArrayCoorArray;
  44. PVarArray = ^TVarArray;
  45. TVarArray = packed record
  46. DimCount: Word;
  47. Flags: Word;
  48. ElementSize: Longint;
  49. LockCount: Integer;
  50. Data: Pointer;
  51. Bounds: TVarArrayBoundArray;
  52. end;
  53. TVarType = Word;
  54. PVarData = ^TVarData;
  55. TVarData = packed record
  56. VType: TVarType;
  57. case Integer of
  58. 0: (Reserved1: Word;
  59. case Integer of
  60. 0: (Reserved2, Reserved3: Word;
  61. case Integer of
  62. varSmallInt: (VSmallInt: SmallInt);
  63. varInteger: (VInteger: Longint);
  64. varSingle: (VSingle: Single);
  65. varDouble: (VDouble: Double);
  66. varCurrency: (VCurrency: Currency);
  67. varDate: (VDate: Double);
  68. varOleStr: (VOleStr: PWideChar);
  69. varDispatch: (VDispatch: Pointer);
  70. varError: (VError: LongWord);
  71. varBoolean: (VBoolean: WordBool);
  72. varUnknown: (VUnknown: Pointer);
  73. varByte: (VByte: Byte);
  74. varString: (VString: Pointer);
  75. varAny: (VAny: Pointer);
  76. varArray: (VArray: PVarArray);
  77. varByRef: (VPointer: Pointer);
  78. );
  79. 1: (VLongs: array[0..2] of LongInt);
  80. );
  81. 2: (VWords: array [0..6] of Word);
  82. 3: (VBytes: array [0..13] of Byte);
  83. end;
  84. Variant = TVarData;
  85. PVariant = ^Variant;
  86. { Variant functions }
  87. function VariantChangeTypeEx(var VargDest: TVarData; const VargSrc: TVarData; LCID: Integer; Flags: Word; VarType: Word): HRESULT; stdcall;
  88. function VariantClear(var Varg: TVarData): HRESULT; stdcall;
  89. function VariantCopy(var VargDest: TVarData; const VargSrc: TVarData): HRESULT; stdcall;
  90. function VariantCopyInd(var VargDest: TVarData; const VargSrc: TVarData): HRESULT; stdcall;
  91. function VariantInit(var Varg: TVarData): HRESULT; stdcall;
  92. { Variant array functions }
  93. function SafeArrayAccessData(psa: PVarArray; var ppvdata: Pointer): HRESULT; stdcall;
  94. function SafeArrayAllocData(psa: PVarArray): HRESULT; stdcall;
  95. function SafeArrayAllocDescriptor(DimCount: Integer; var psa: PVarArray): HRESULT; stdcall;
  96. function SafeArrayCopy(psa: PVarArray; var psaout: PVarArray): HRESULT; stdcall;
  97. function SafeArrayCopyData(psa, psaOut: PVarArray): HRESULT; stdcall;
  98. function SafeArrayCreate(VarType, Dim: Integer; const Bounds: TVarArrayBoundArray): PVarArray; stdcall;
  99. function SafeArrayDestroy(psa: PVarArray): HRESULT; stdcall;
  100. function SafeArrayDestroyData(psa: PVarArray): HRESULT; stdcall;
  101. function SafeArrayDestroyDescriptor(psa: PVarArray): HRESULT; stdcall;
  102. function SafeArrayGetDim(psa: PVarArray): Integer; stdcall;
  103. function SafeArrayGetElemSize(psa: PVarArray): LongWord; stdcall;
  104. function SafeArrayGetElement(psa: PVarArray; Indices: PVarArrayCoorArray; Data: Pointer): HRESULT; stdcall;
  105. function SafeArrayGetLBound(psa: PVarArray; Dim: Integer; var LBound: Integer): HRESULT; stdcall;
  106. function SafeArrayGetUBound(psa: PVarArray; Dim: Integer; var UBound: Integer): HRESULT; stdcall;
  107. function SafeArrayLock(psa: PVarArray): HRESULT; stdcall;
  108. function SafeArrayPtrOfIndex(psa: PVarArray; Indices: PVarArrayCoorArray; var Address: Pointer): HRESULT; stdcall;
  109. function SafeArrayPutElement(psa: PVarArray; Indices: PVarArrayCoorArray; const Data: Pointer): HRESULT; stdcall;
  110. function SafeArrayRedim(psa: PVarArray; const NewBound: TVarArrayBound): HRESULT; stdcall;
  111. function SafeArrayUnaccessData(psa: PVarArray): HRESULT; stdcall;
  112. function SafeArrayUnlock(psa: PVarArray): HRESULT; stdcall;
  113. { Conversion routines NOT in windows oleaut }
  114. Function VariantToSmallInt(Const VargSrc : TVarData) : SmallInt;
  115. Function VariantToLongint(Const VargSrc : TVarData) : Longint;
  116. Function VariantToSingle(Const VargSrc : TVarData) : Single;
  117. Function VariantToDouble(Const VargSrc : TVarData) : Double;
  118. Function VariantToCurrency(Const VargSrc : TVarData) : Currency;
  119. Function VariantToDate(Const VargSrc : TVarData) : TDateTime;
  120. Function VariantToBoolean(Const VargSrc : TVarData) : Boolean;
  121. Function VariantToByte(Const VargSrc : TVarData) : Byte;
  122. // Names match the ones in Borland varutils unit.
  123. const
  124. VAR_OK = HRESULT($00000000);
  125. VAR_TYPEMISMATCH = HRESULT($80020005);
  126. VAR_BADVARTYPE = HRESULT($80020008);
  127. VAR_EXCEPTION = HRESULT($80020009);
  128. VAR_OVERFLOW = HRESULT($8002000A);
  129. VAR_BADINDEX = HRESULT($8002000B);
  130. VAR_ARRAYISLOCKED = HRESULT($8002000D);
  131. VAR_NOTIMPL = HRESULT($80004001);
  132. VAR_OUTOFMEMORY = HRESULT($8007000E);
  133. VAR_INVALIDARG = HRESULT($80070057);
  134. VAR_UNEXPECTED = HRESULT($8000FFFF);
  135. ARR_NONE = $0000;
  136. ARR_FIXEDSIZE = $0010;
  137. ARR_OLESTR = $0100;
  138. ARR_UNKNOWN = $0200;
  139. ARR_DISPATCH = $0400;
  140. ARR_VARIANT = $0800;
  141. Implementation
  142. Resourcestring
  143. SNoWidestrings = 'No widestrings supported';
  144. SNoInterfaces = 'No interfaces supported';
  145. Procedure NoWidestrings;
  146. begin
  147. Raise Exception.Create(SNoWideStrings);
  148. end;
  149. Procedure NoInterfaces;
  150. begin
  151. Raise Exception.Create(SNoInterfaces);
  152. end;
  153. Constructor EVariantError.CreateCode (Code : longint);
  154. begin
  155. ErrCode:=Code;
  156. end;
  157. Procedure VariantTypeMismatch;
  158. begin
  159. Raise EVariantError.CreateCode(VAR_TYPEMISMATCH);
  160. end;
  161. Function ExceptionToVariantError (E : Exception): HResult;
  162. begin
  163. If E is EoutOfMemory then
  164. Result:=VAR_OUTOFMEMORY
  165. else
  166. Result:=VAR_EXCEPTION;
  167. end;
  168. {$i varutils.inc}
  169. { ---------------------------------------------------------------------
  170. OS-independent functions not present in Windows
  171. ---------------------------------------------------------------------}
  172. Function VariantToSmallInt(Const VargSrc : TVarData) : SmallInt;
  173. begin
  174. With VargSrc do
  175. Case (VType and VarTypeMask) of
  176. VarSmallInt: Result:=VSmallInt;
  177. VarInteger : Result:=VInteger;
  178. VarSingle : Result:=Round(VSingle);
  179. VarDouble : Result:=Round(VDouble);
  180. VarCurrency: Result:=Round(VCurrency);
  181. VarDate : Result:=Round(VDate);
  182. VarOleStr : NoWideStrings;
  183. VarBoolean : Result:=SmallInt(VBoolean);
  184. VarByte : Result:=VByte;
  185. else
  186. VariantTypeMismatch;
  187. end;
  188. end;
  189. Function VariantToLongint(Const VargSrc : TVarData) : Longint;
  190. begin
  191. With VargSrc do
  192. Case (VType and VarTypeMask) of
  193. VarSmallInt: Result:=VSmallInt;
  194. VarInteger : Result:=VInteger;
  195. VarSingle : Result:=Round(VSingle);
  196. VarDouble : Result:=Round(VDouble);
  197. VarCurrency: Result:=Round(VCurrency);
  198. VarDate : Result:=Round(VDate);
  199. VarOleStr : NoWideStrings;
  200. VarBoolean : Result:=Longint(VBoolean);
  201. VarByte : Result:=VByte;
  202. else
  203. VariantTypeMismatch;
  204. end;
  205. end;
  206. Function VariantToSingle(Const VargSrc : TVarData) : Single;
  207. begin
  208. With VargSrc do
  209. Case (VType and VarTypeMask) of
  210. VarSmallInt: Result:=VSmallInt;
  211. VarInteger : Result:=VInteger;
  212. VarSingle : Result:=VSingle;
  213. VarDouble : Result:=VDouble;
  214. VarCurrency: Result:=VCurrency;
  215. VarDate : Result:=VDate;
  216. VarOleStr : NoWideStrings;
  217. VarBoolean : Result:=Longint(VBoolean);
  218. VarByte : Result:=VByte;
  219. else
  220. VariantTypeMismatch;
  221. end;
  222. end;
  223. Function VariantToDouble(Const VargSrc : TVarData) : Double;
  224. begin
  225. With VargSrc do
  226. Case (VType and VarTypeMask) of
  227. VarSmallInt: Result:=VSmallInt;
  228. VarInteger : Result:=VInteger;
  229. VarSingle : Result:=VSingle;
  230. VarDouble : Result:=VDouble;
  231. VarCurrency: Result:=VCurrency;
  232. VarDate : Result:=VDate;
  233. VarOleStr : NoWideStrings;
  234. VarBoolean : Result:=Longint(VBoolean);
  235. VarByte : Result:=VByte;
  236. else
  237. VariantTypeMismatch;
  238. end;
  239. end;
  240. Function VariantToCurrency(Const VargSrc : TVarData) : Currency;
  241. begin
  242. Try
  243. With VargSrc do
  244. Case (VType and VarTypeMask) of
  245. VarSmallInt: Result:=VSmallInt;
  246. VarInteger : Result:=VInteger;
  247. VarSingle : Result:=FloatToCurr(VSingle);
  248. VarDouble : Result:=FloatToCurr(VDouble);
  249. VarCurrency: Result:=VCurrency;
  250. VarDate : Result:=FloatToCurr(VDate);
  251. VarOleStr : NoWideStrings;
  252. VarBoolean : Result:=Longint(VBoolean);
  253. VarByte : Result:=VByte;
  254. else
  255. VariantTypeMismatch;
  256. end;
  257. except
  258. On EConvertError do
  259. VariantTypeMismatch;
  260. else
  261. Raise;
  262. end;
  263. end;
  264. Function VariantToDate(Const VargSrc : TVarData) : TDateTime;
  265. begin
  266. Try
  267. With VargSrc do
  268. Case (VType and VarTypeMask) of
  269. VarSmallInt: Result:=FloatToDateTime(VSmallInt);
  270. VarInteger : Result:=FloatToDateTime(VInteger);
  271. VarSingle : Result:=FloatToDateTime(VSingle);
  272. VarDouble : Result:=FloatToDateTime(VDouble);
  273. VarCurrency: Result:=FloatToDateTime(VCurrency);
  274. VarDate : Result:=VDate;
  275. VarOleStr : NoWideStrings;
  276. VarBoolean : Result:=FloatToDateTime(Longint(VBoolean));
  277. VarByte : Result:=FloatToDateTime(VByte);
  278. else
  279. VariantTypeMismatch;
  280. end;
  281. except
  282. On EConvertError do
  283. VariantTypeMismatch;
  284. else
  285. Raise;
  286. end;
  287. end;
  288. Function VariantToBoolean(Const VargSrc : TVarData) : Boolean;
  289. begin
  290. With VargSrc do
  291. Case (VType and VarTypeMask) of
  292. VarSmallInt: Result:=VSmallInt<>0;
  293. VarInteger : Result:=VInteger<>0;
  294. VarSingle : Result:=VSingle<>0;
  295. VarDouble : Result:=VDouble<>0;
  296. VarCurrency: Result:=VCurrency<>0;
  297. VarDate : Result:=VDate<>0;
  298. VarOleStr : NoWideStrings;
  299. VarBoolean : Result:=VBoolean;
  300. VarByte : Result:=VByte<>0;
  301. else
  302. VariantTypeMismatch;
  303. end;
  304. end;
  305. Function VariantToByte(Const VargSrc : TVarData) : Byte;
  306. begin
  307. Try
  308. With VargSrc do
  309. Case (VType and VarTypeMask) of
  310. VarSmallInt: Result:=VSmallInt;
  311. VarInteger : Result:=VInteger;
  312. VarSingle : Result:=Round(VSingle);
  313. VarDouble : Result:=Round(VDouble);
  314. VarCurrency: Result:=Round(VCurrency);
  315. VarDate : Result:=Round(VDate);
  316. VarOleStr : NoWideStrings;
  317. VarBoolean : Result:=Longint(VBoolean);
  318. VarByte : Result:=VByte;
  319. else
  320. VariantTypeMismatch;
  321. end;
  322. except
  323. On EConvertError do
  324. VariantTypeMismatch;
  325. else
  326. Raise;
  327. end;
  328. end;
  329. end.