{ $Id$ This file is part of the Free Pascal run time library. Copyright (c) 2000,2001 by the Free Pascal development team Interface and OS-dependent part of variant support See the file COPYING.FPC, included in this distribution, for details about the copyright. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. **********************************************************************} {$ifdef HASVARIANT} Resourcestring SNoWidestrings = 'No widestrings supported'; SNoInterfaces = 'No interfaces supported'; Procedure NoWidestrings; begin Raise Exception.Create(SNoWideStrings); end; Procedure NoInterfaces; begin Raise Exception.Create(SNoInterfaces); end; Constructor EVariantError.CreateCode (Code : longint); begin ErrCode:=Code; end; Procedure VariantTypeMismatch; begin Raise EVariantError.CreateCode(VAR_TYPEMISMATCH); end; Function ExceptionToVariantError (E : Exception): HResult; begin If E is EoutOfMemory then Result:=VAR_OUTOFMEMORY else Result:=VAR_EXCEPTION; end; { --------------------------------------------------------------------- OS-independent functions not present in Windows ---------------------------------------------------------------------} Function VariantToSmallInt(Const VargSrc : TVarData) : SmallInt; begin With VargSrc do Case (VType and VarTypeMask) of VarSmallInt: Result:=VSmallInt; VarShortInt: Result:=VShortInt; VarInteger : Result:=VInteger; VarSingle : Result:=Round(VSingle); VarDouble : Result:=Round(VDouble); VarCurrency: Result:=Round(VCurrency); VarDate : Result:=Round(VDate); VarOleStr : Result:=StrToInt(WideCharToString(vOleStr)); VarBoolean : Result:=SmallInt(VBoolean); VarByte : Result:=VByte; VarWord : Result:=VWord; VarLongWord : Result:=VLongWord; VarInt64 : Result:=VInt64; VarQword : Result:=VQWord; else VariantTypeMismatch; end; end; Function VariantToShortInt(Const VargSrc : TVarData) : ShortInt; begin With VargSrc do Case (VType and VarTypeMask) of VarSmallInt: Result:=VSmallInt; VarShortInt: Result:=VShortInt; VarInteger : Result:=VInteger; VarSingle : Result:=Round(VSingle); VarDouble : Result:=Round(VDouble); VarCurrency: Result:=Round(VCurrency); VarDate : Result:=Round(VDate); VarOleStr : Result:=StrToInt(WideCharToString(vOleStr)); VarBoolean : Result:=SmallInt(VBoolean); VarByte : Result:=VByte; VarWord : Result:=VWord; VarLongWord : Result:=VLongWord; VarInt64 : Result:=VInt64; VarQword : Result:=VQWord; else VariantTypeMismatch; end; end; Function VariantToLongint(Const VargSrc : TVarData) : Longint; begin With VargSrc do Case (VType and VarTypeMask) of VarSmallInt: Result:=VSmallInt; VarShortInt: Result:=VShortInt; VarInteger : Result:=VInteger; VarSingle : Result:=Round(VSingle); VarDouble : Result:=Round(VDouble); VarCurrency: Result:=Round(VCurrency); VarDate : Result:=Round(VDate); VarOleStr : Result:=StrToInt(WideCharToString(vOleStr)); VarBoolean : Result:=Longint(VBoolean); VarByte : Result:=VByte; VarWord : Result:=VWord; VarLongWord : Result:=VLongWord; VarInt64 : Result:=VInt64; VarQword : Result:=VQWord; else VariantTypeMismatch; end; end; Function VariantToCardinal(Const VargSrc : TVarData) : Cardinal; begin With VargSrc do Case (VType and VarTypeMask) of VarSmallInt: Result:=VSmallInt; VarShortInt: Result:=VShortInt; VarInteger : Result:=VInteger; VarSingle : Result:=Round(VSingle); VarDouble : Result:=Round(VDouble); VarCurrency: Result:=Round(VCurrency); VarDate : Result:=Round(VDate); VarOleStr : Result:=StrToInt(WideCharToString(vOleStr)); VarBoolean : Result:=Longint(VBoolean); VarByte : Result:=VByte; VarWord : Result:=VWord; VarLongWord : Result:=VLongWord; VarInt64 : Result:=VInt64; VarQword : Result:=VQWord; else VariantTypeMismatch; end; end; Function VariantToSingle(Const VargSrc : TVarData) : Single; begin With VargSrc do Case (VType and VarTypeMask) of VarSmallInt: Result:=VSmallInt; VarShortInt: Result:=VShortInt; VarInteger : Result:=VInteger; VarSingle : Result:=VSingle; VarDouble : Result:=VDouble; VarCurrency: Result:=VCurrency; VarDate : Result:=VDate; VarOleStr : NoWideStrings; VarBoolean : Result:=Longint(VBoolean); VarByte : Result:=VByte; VarWord : Result:=VWord; VarLongWord : Result:=VLongWord; VarInt64 : Result:=VInt64; VarQword : Result:=VQWord; else VariantTypeMismatch; end; end; Function VariantToDouble(Const VargSrc : TVarData) : Double; begin With VargSrc do Case (VType and VarTypeMask) of VarSmallInt: Result:=VSmallInt; VarShortInt: Result:=VShortInt; VarInteger : Result:=VInteger; VarSingle : Result:=VSingle; VarDouble : Result:=VDouble; VarCurrency: Result:=VCurrency; VarDate : Result:=VDate; VarOleStr : NoWideStrings; VarBoolean : Result:=Longint(VBoolean); VarByte : Result:=VByte; VarWord : Result:=VWord; VarLongWord : Result:=VLongWord; VarInt64 : Result:=VInt64; VarQword : Result:=VQWord; else VariantTypeMismatch; end; end; Function VariantToCurrency(Const VargSrc : TVarData) : Currency; begin Try With VargSrc do Case (VType and VarTypeMask) of VarSmallInt: Result:=VSmallInt; VarShortInt: Result:=VShortInt; VarInteger : Result:=VInteger; VarSingle : Result:=FloatToCurr(VSingle); VarDouble : Result:=FloatToCurr(VDouble); VarCurrency: Result:=VCurrency; VarDate : Result:=FloatToCurr(VDate); VarOleStr : NoWideStrings; VarBoolean : Result:=Longint(VBoolean); VarByte : Result:=VByte; VarWord : Result:=VWord; VarLongWord : Result:=VLongWord; VarInt64 : Result:=VInt64; VarQword : Result:=VQWord; else VariantTypeMismatch; end; except On EConvertError do VariantTypeMismatch; else Raise; end; end; Function VariantToDate(Const VargSrc : TVarData) : TDateTime; begin Try With VargSrc do Case (VType and VarTypeMask) of VarSmallInt: Result:=FloatToDateTime(VSmallInt); VarShortInt: Result:=FloatToDateTime(VShortInt); VarInteger : Result:=FloatToDateTime(VInteger); VarSingle : Result:=FloatToDateTime(VSingle); VarDouble : Result:=FloatToDateTime(VDouble); VarCurrency: Result:=FloatToDateTime(VCurrency); VarDate : Result:=VDate; VarOleStr : NoWideStrings; VarBoolean : Result:=FloatToDateTime(Longint(VBoolean)); VarByte : Result:=FloatToDateTime(VByte); VarWord : Result:=FloatToDateTime(VWord); VarLongWord : Result:=FloatToDateTime(VLongWord); VarInt64 : Result:=FloatToDateTime(VInt64); VarQWord : Result:=FloatToDateTime(VQword); else VariantTypeMismatch; end; except On EConvertError do VariantTypeMismatch; else Raise; end; end; Function VariantToBoolean(Const VargSrc : TVarData) : Boolean; begin With VargSrc do Case (VType and VarTypeMask) of VarSmallInt: Result:=VSmallInt<>0; VarShortInt: Result:=VShortInt<>0; VarInteger : Result:=VInteger<>0; VarSingle : Result:=VSingle<>0; VarDouble : Result:=VDouble<>0; VarCurrency: Result:=VCurrency<>0; VarDate : Result:=VDate<>0; VarOleStr : NoWideStrings; VarBoolean : Result:=VBoolean; VarByte : Result:=VByte<>0; VarWord : Result:=VWord<>0; VarLongWord : Result:=VLongWord<>0; VarInt64 : Result:=Vint64<>0; VarQword : Result:=VQWord<>0; else VariantTypeMismatch; end; end; Function VariantToByte(Const VargSrc : TVarData) : Byte; begin Try With VargSrc do Case (VType and VarTypeMask) of VarSmallInt: Result:=VSmallInt; VarShortInt: Result:=VShortInt; VarInteger : Result:=VInteger; VarSingle : Result:=Round(VSingle); VarDouble : Result:=Round(VDouble); VarCurrency: Result:=Round(VCurrency); VarDate : Result:=Round(VDate); VarOleStr : NoWideStrings; VarBoolean : Result:=Longint(VBoolean); VarByte : Result:=VByte; VarWord : Result:=VWord; VarLongWord : Result:=VLongWord; VarInt64 : Result:=Vint64; VarQword : Result:=VQWord; else VariantTypeMismatch; end; except On EConvertError do VariantTypeMismatch; else Raise; end; end; Function VariantToInt64(Const VargSrc : TVarData) : Int64; begin Try With VargSrc do Case (VType and VarTypeMask) of VarSmallInt: Result:=VSmallInt; VarShortInt: Result:=VShortInt; VarInteger : Result:=VInteger; VarSingle : Result:=Trunc(VSingle); VarDouble : Result:=Trunc(VDouble); {$ifdef HASCURRENCY} VarCurrency: Result:=Trunc(VCurrency); {$else} VarCurrency: Result:=VCurrency; {$endif} VarDate : Result:=Trunc(VDate); VarOleStr : NoWideStrings; VarBoolean : Result:=Longint(VBoolean); VarByte : Result:=VByte; VarWord : Result:=VWord; VarLongWord : Result:=VLongWord; VarInt64 : Result:=VInt64; VarQword : Result:=VQWord; else VariantTypeMismatch; end; except On EConvertError do VariantTypeMismatch; else Raise; end; end; Function VariantToQWord(Const VargSrc : TVarData) : QWord; begin Try With VargSrc do Case (VType and VarTypeMask) of VarSmallInt: Result:=VSmallint; VarShortInt: Result:=VShortInt; VarInteger : Result:=VInteger; VarSingle : Result:=Trunc(VSingle); VarDouble : Result:=Trunc(VDouble); {$ifdef HASCURRENCY} VarCurrency: Result:=Trunc(VCurrency); {$else} VarCurrency: Result:=VCurrency; {$endif} VarDate : Result:=Trunc(VDate); VarOleStr : NoWideStrings; VarBoolean : Result:=Longint(VBoolean); VarByte : Result:=VByte; VarWord : Result:=VWord; VarLongWord : Result:=VLongWord; VarInt64 : Result:=VInt64; VarQword : Result:=VQWord; else VariantTypeMismatch; end; except On EConvertError do VariantTypeMismatch; else Raise; end; end; Function VariantToWideString(Const VargSrc : TVarData) : WideString; Const BS : Array[Boolean] of WideString = ('False','True'); begin Try With VargSrc do Case (VType and VarTypeMask) of VarSmallInt : Result:=IntTostr(VSmallint); VarShortInt : Result:=IntToStr(VShortInt); VarInteger : Result:=IntToStr(VInteger); VarSingle : Result:=FloatToStr(VSingle); VarDouble : Result:=FloatToStr(VDouble); VarCurrency : Result:=FloatToStr(VCurrency); VarDate : Result:=DateTimeToStr(VDate); VarOleStr : Result:=WideString(Pointer(VOleStr)); VarBoolean : Result:=BS[VBoolean]; VarByte : Result:=IntToStr(VByte); VarWord : Result:=IntToStr(VWord); VarLongWord : Result:=IntToStr(VLongWord); VarInt64 : Result:=IntToStr(VInt64); VarQword : Result:=IntToStr(VQWord); else VariantTypeMismatch; end; except On EConvertError do VariantTypeMismatch; else Raise; end; end; Function VariantToAnsiString(Const VargSrc : TVarData) : AnsiString; Const BS : Array[Boolean] of AnsiString = ('False','True'); begin Try With VargSrc do Case (VType and VarTypeMask) of VarSmallInt : Result:=IntTostr(VSmallint); VarShortInt : Result:=IntToStr(VShortInt); VarInteger : Result:=IntToStr(VInteger); VarSingle : Result:=FloatToStr(VSingle); VarDouble : Result:=FloatToStr(VDouble); VarCurrency : Result:=FloatToStr(VCurrency); VarDate : Result:=DateTimeToStr(VDate); VarOleStr : Result:=WideCharToString(VOleStr); VarBoolean : Result:=BS[VBoolean]; VarByte : Result:=IntToStr(VByte); VarWord : Result:=IntToStr(VWord); VarLongWord : Result:=IntToStr(VLongWord); VarInt64 : Result:=IntToStr(VInt64); VarQword : Result:=IntToStr(VQWord); else VariantTypeMismatch; end; except On EConvertError do VariantTypeMismatch; else Raise; end; end; Function VariantToShortString(Const VargSrc : TVarData) : ShortString; Var S : AnsiString; begin S:=VariantToAnsiString(VArgSrc); Result:=S; end; { --------------------------------------------------------------------- Some debug routines ---------------------------------------------------------------------} Procedure DumpVariant(Const VArgSrc : TVarData); begin DumpVariant(Output,VArgSrc); end; (* tvardata = packed record vtype : tvartype; case integer of 0:(res1 : word; case integer of 0: (res2,res3 : word; case word of varsmallint : (vsmallint : smallint); varinteger : (vinteger : longint); varsingle : (vsingle : single); vardouble : (vdouble : double); varcurrency : (vcurrency : currency); vardate : (vdate : tdatetime); varolestr : (volestr : pwidechar); vardispatch : (vdispatch : pointer); varerror : (verror : dword); varboolean : (vboolean : wordbool); varunknown : (vunknown : pointer); // vardecimal : ( : ); varshortint : (vshortint : shortint); varbyte : (vbyte : byte); varword : (vword : word); varlongword : (vlongword : dword); varint64 : (vint64 : int64); varqword : (vqword : qword); varword64 : (vword64 : qword); varstring : (vstring : pointer); varany : (vany : pointer); vararray : (varray : pvararray); varbyref : (vpointer : pointer); ); 1: (vlongs : array[0..2] of longint); ); 1:(vwords : array[0..6] of word); 2:(vbytes : array[0..13] of byte); end; *) Const VarTypeStrings : Array [varEmpty..varqword] of string = ( 'empty', 'null', 'smallint', 'integer', 'single', 'double', 'currency', 'date', 'olestr', 'dispatch', 'error', 'boolean', 'variant', 'unknown', 'unknown','decimal', 'shortint', 'byte', 'word', 'longword', 'int64', 'qword'); Procedure DumpVariant(Var F : Text; Const VArgSrc : TVarData); Var W : WideString; begin If VArgSrc.vType in [varEmpty..varqword] then Writeln(F,'Variant has type : ',VarTypeStrings[VArgSrc.vType]) else if (VArgSrc.vType=VarArray) Then begin Write(F,'Variant is array.'); exit; end else if (VargSrc.vType=VarByRef) then begin Writeln(F,'Variant is by reference.'); exit; end else begin Writeln(F,'Variant has unknown type: ', VargSrc.vType); Exit; end; If VArgSrc.vType<>varEmpty then With VArgSrc do begin Write(F,'Value is: ') ; Case vtype of varnull : Write(F,'Null'); varsmallint : Write(F,vsmallint); varinteger : Write(F,vinteger); varsingle : Write(F,vsingle); vardouble : Write(F,vdouble); varcurrency : Write(F,vcurrency) ; vardate : Write(F,vdate) ; varolestr : begin W:=vOleStr; Write(F,W) ; end; vardispatch : Write(F,'Not suppordted') ; varerror : Write(F,'Error') ; varboolean : Write(F,vboolean) ; varvariant : Write(F,'Unsupported') ; varunknown : Write(F,'Unsupported') ; vardecimal : Write(F,'Unsupported') ; varshortint : Write(F,vshortint) ; varbyte : Write(F,vbyte) ; varword : Write(F,vword) ; varlongword : Write(F,vlongword) ; varint64 : Write(F,vint64) ; varqword : Write(F,vqword) ; end; Writeln(f); end; end; {$endif HASVARIANT} { $Log$ Revision 1.10 2003-11-04 23:15:58 michael Support for ansistring and better debug outpu Revision 1.9 2003/11/04 22:53:55 michael + Removed debug statements Revision 1.8 2003/11/04 22:27:43 michael + Some fixes for string support Revision 1.7 2002/09/07 16:01:22 peter * old logs removed and tabs fixed Revision 1.6 2002/07/01 16:25:10 peter * currency updates }