Variant.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FXUpdate3074 / FXUpdate3074 / 1.1 / untmp / whidbey / QFE / ndp / clr / src / BCL / System / Variant.cs / 1 / Variant.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*============================================================
** 
** Class:  Variant 
**
** 
** Purpose: The CLR implementation of Variant.
**
**
===========================================================*/ 
namespace System {
 
    using System; 
    using System.Reflection;
    using System.Threading; 
    using System.Runtime.InteropServices;
    using System.Globalization;
    using System.Runtime.CompilerServices;
 
    [Serializable()]
    [StructLayout(LayoutKind.Sequential)] 
    internal struct Variant { 

        //Do Not change the order of these fields. 
        //They are mapped to the native VariantData * data structure.
        private Object m_objref;
        private int m_data1;
        private int m_data2; 
        private int m_flags;
 
 
        // The following will call the internal routines to initalize the
        //  native side of variant. 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private extern static void InitVariant();
        static Variant() {
            InitVariant(); 
        }
 
        private static Type _voidPtr = null; 

        // The following bits have been taken up as follows 
        // bits 0-15    - Type code
        // bit  16      - Array
        // bits 19-23   - Enums
        // bits 24-31   - Optional VT code (for roundtrip VT preservation) 

 
        //What are the consequences of making this an enum? 
        ///////////////////////////////////////////////////////////////////////
        // If you update this, update the corresponding stuff in OAVariantLib.cs, 
        // COMOAVariant.cpp (2 tables, forwards and reverse), and perhaps OleVariant.h
        ///////////////////////////////////////////////////////////////////////
        internal const int CV_EMPTY=0x0;
        internal const int CV_VOID=0x1; 
        internal const int CV_BOOLEAN=0x2;
        internal const int CV_CHAR=0x3; 
        internal const int CV_I1=0x4; 
        internal const int CV_U1=0x5;
        internal const int CV_I2=0x6; 
        internal const int CV_U2=0x7;
        internal const int CV_I4=0x8;
        internal const int CV_U4=0x9;
        internal const int CV_I8=0xa; 
        internal const int CV_U8=0xb;
        internal const int CV_R4=0xc; 
        internal const int CV_R8=0xd; 
        internal const int CV_STRING=0xe;
        internal const int CV_PTR=0xf; 
        internal const int CV_DATETIME = 0x10;
        internal const int CV_TIMESPAN = 0x11;
        internal const int CV_OBJECT=0x12;
        internal const int CV_DECIMAL = 0x13; 
        internal const int CV_ENUM=0x15;
        internal const int CV_MISSING=0x16; 
        internal const int CV_NULL=0x17; 
        internal const int CV_LAST=0x18;
 
        internal const int TypeCodeBitMask=0xffff;
        internal const int VTBitMask=unchecked((int)0xff000000);
        internal const int VTBitShift=24;
        internal const int ArrayBitMask =0x10000; 

        // Enum enum and Mask 
        internal const int EnumI1           =0x100000; 
        internal const int EnumU1           =0x200000;
        internal const int EnumI2           =0x300000; 
        internal const int EnumU2           =0x400000;
        internal const int EnumI4           =0x500000;
        internal const int EnumU4           =0x600000;
        internal const int EnumI8           =0x700000; 
        internal const int EnumU8           =0x800000;
        internal const int EnumMask     =0xF00000; 
 
        internal static readonly Type [] ClassTypes = {
            typeof(System.Empty), 
            typeof(void),
            typeof(Boolean),
            typeof(Char),
            typeof(SByte), 
            typeof(Byte),
            typeof(Int16), 
            typeof(UInt16), 
            typeof(Int32),
            typeof(UInt32), 
            typeof(Int64),
            typeof(UInt64),
            typeof(Single),
            typeof(Double), 
            typeof(String),
            typeof(void),           // ptr for the moment 
            typeof(DateTime), 
            typeof(TimeSpan),
            typeof(Object), 
            typeof(Decimal),
            typeof(Object),     // Treat enum as Object
            typeof(System.Reflection.Missing),
            typeof(System.DBNull), 
        };
 
        internal static readonly Variant Empty = new Variant(); 
        internal static readonly Variant Missing = new Variant(Variant.CV_MISSING, Type.Missing, 0, 0);
        internal static readonly Variant DBNull = new Variant(Variant.CV_NULL, System.DBNull.Value, 0, 0); 

        //
        // Native Methods
        // 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal extern double GetR8FromVar(); 
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal extern float  GetR4FromVar();
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal extern void   SetFieldsR4(float val);
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal extern void   SetFieldsR8(double val);
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal extern void SetFieldsObject(Object val);
 
        // Use this function instead of an ECALL - saves about 150 clock cycles 
        // by avoiding the ecall transition and because the JIT inlines this.
        // Ends up only taking about 1/8 the time of the ECALL version. 
        internal long GetI8FromVar()
        {
            return ((long)m_data2<<32 | ((long)m_data1 & 0xFFFFFFFFL));
        } 

        // 
        // Constructors 
        //
 
        internal Variant(int flags, Object or, int data1, int data2) {
            m_flags = flags;
            m_objref=or;
            m_data1=data1; 
            m_data2=data2;
        } 
 
        public Variant(bool val) {
            m_objref= null; 
            m_flags = CV_BOOLEAN;
            m_data1 = (val)?Boolean.True:Boolean.False;
            m_data2 = 0;
        } 

        public Variant(sbyte val) { 
            m_objref=null; 
            m_flags=CV_I1;
            m_data1=(int)val; 
            m_data2=(int)(((long)val)>>32);
        }

 
        public Variant(byte val) {
            m_objref=null; 
            m_flags=CV_U1; 
            m_data1=(int)val;
            m_data2=0; 
        }

        public Variant(short val) {
            m_objref=null; 
            m_flags=CV_I2;
            m_data1=(int)val; 
            m_data2=(int)(((long)val)>>32); 
        }
 
        public Variant(ushort val) {
            m_objref=null;
            m_flags=CV_U2;
            m_data1=(int)val; 
            m_data2=0;
        } 
 
        public Variant(char val) {
            m_objref=null; 
            m_flags=CV_CHAR;
            m_data1=(int)val;
            m_data2=0;
        } 

        public Variant(int val) { 
            m_objref=null; 
            m_flags=CV_I4;
            m_data1=val; 
            m_data2=val >> 31;
        }

        public Variant(uint val) { 
            m_objref=null;
            m_flags=CV_U4; 
            m_data1=(int)val; 
            m_data2=0;
        } 

        public Variant(long val) {
            m_objref=null;
            m_flags=CV_I8; 
            m_data1 = (int)val;
            m_data2 = (int)(val >> 32); 
        } 

        public Variant(ulong val) { 
            m_objref=null;
            m_flags=CV_U8;
            m_data1 = (int)val;
            m_data2 = (int)(val >> 32); 
        }
 
        public Variant(float val) { 
            m_objref=null;
            m_flags=CV_R4; 
            m_data1=0;
            m_data2=0;
            SetFieldsR4(val);
        } 

        public Variant(double val) { 
            m_objref=null; 
            m_flags=CV_R8;
            m_data1=0; 
            m_data2=0;
            SetFieldsR8(val);
        }
 
        public Variant(DateTime val) {
            m_objref=null; 
            m_flags=CV_DATETIME; 
            ulong ticks = (ulong)val.Ticks;
            m_data1 = (int)ticks; 
            m_data2 = (int)(ticks>>32);
        }

        public Variant(Decimal val) { 
            m_objref = (Object)val;
            m_flags = CV_DECIMAL; 
            m_data1=0; 
            m_data2=0;
        } 

        public Variant(Object obj) {
            m_data1=0;
            m_data2=0; 

            VarEnum vt = VarEnum.VT_EMPTY; 
 
            if (obj is DateTime) {
                m_objref=null; 
                m_flags=CV_DATETIME;
                ulong ticks = (ulong)((DateTime)obj).Ticks;
                m_data1 = (int)ticks;
                m_data2 = (int)(ticks>>32); 
                return;
            } 
 
            if (obj is String) {
                m_flags=CV_STRING; 
                m_objref=obj;
                return;
            }
 
            if (obj == null) {
                this = Empty; 
                return; 
            }
            if (obj == System.DBNull.Value) { 
                this = DBNull;
                return;
            }
            if (obj == Type.Missing) { 
                this = Missing;
                return; 
            } 

            if (obj is Array) { 
                m_flags=CV_OBJECT | ArrayBitMask;
                m_objref=obj;
                return;
            } 

            // Compiler appeasement 
            m_flags = CV_EMPTY; 
            m_objref = null;
 
#if FEATURE_COMINTEROP
            // Check to see if the object passed in is a wrapper object.
            if (obj is UnknownWrapper)
            { 
                vt = VarEnum.VT_UNKNOWN;
                obj = ((UnknownWrapper)obj).WrappedObject; 
            } 
            else if (obj is DispatchWrapper)
            { 
                vt = VarEnum.VT_DISPATCH;
                obj = ((DispatchWrapper)obj).WrappedObject;
            }
            else if (obj is ErrorWrapper) 
            {
                vt = VarEnum.VT_ERROR; 
                obj = (Object)(((ErrorWrapper)obj).ErrorCode); 
                BCLDebug.Assert(obj != null, "obj != null");
            } 
            else if (obj is CurrencyWrapper)
            {
                vt = VarEnum.VT_CY;
                obj = (Object)(((CurrencyWrapper)obj).WrappedObject); 
                BCLDebug.Assert(obj != null, "obj != null");
            } 
            else if (obj is BStrWrapper) 
            {
                vt = VarEnum.VT_BSTR; 
                obj = (Object)(((BStrWrapper)obj).WrappedObject);
            }
#endif //FEATURE_COMINTEROP
 
            if (obj != null)
            { 
                SetFieldsObject(obj); 
            }
 
            // If the object passed in is one of the wrappers then set the VARIANT type.
            if (vt != VarEnum.VT_EMPTY)
                m_flags |= ((int)vt << VTBitShift);
        } 

 
        unsafe public Variant(void* voidPointer,Type pointerType) { 
            if (pointerType == null)
                throw new ArgumentNullException("pointerType"); 
            if (!pointerType.IsPointer)
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBePointer"),"pointerType");

            m_objref = pointerType; 
            m_flags=CV_PTR;
            m_data1=(int)voidPointer; 
            m_data2=0; 

        } 

        //This is a family-only accessor for the CVType.
        //This is never to be exposed externally.
        internal int CVType { 
            get {
                return (m_flags&TypeCodeBitMask); 
            } 
        }
 
        public Object ToObject() {
            switch (CVType) {
            case CV_EMPTY:
                return null; 
            case CV_BOOLEAN:
                return (Object)(m_data1!=0); 
            case CV_I1: 
                return (Object)((sbyte)m_data1);
            case CV_U1: 
                return (Object)((byte)m_data1);
            case CV_CHAR:
                return (Object)((char)m_data1);
            case CV_I2: 
                return (Object)((short)m_data1);
            case CV_U2: 
                return (Object)((ushort)m_data1); 
            case CV_I4:
                return (Object)(m_data1); 
            case CV_U4:
                return (Object)((uint)m_data1);
            case CV_I8:
                return (Object)(GetI8FromVar()); 
            case CV_U8:
                return (Object)((ulong)GetI8FromVar()); 
            case CV_R4: 
                return (Object)(GetR4FromVar());
            case CV_R8: 
                return (Object)(GetR8FromVar());
            case CV_DATETIME:
                return new DateTime(GetI8FromVar());
            case CV_TIMESPAN: 
                return new TimeSpan(GetI8FromVar());
            case CV_ENUM: 
                return BoxEnum(); 
            case CV_MISSING:
                return Type.Missing; 
            case CV_NULL:
                return System.DBNull.Value;
            case CV_DECIMAL:
            case CV_STRING: 
            case CV_OBJECT:
            default: 
                return m_objref; 
            }
        } 


        // This routine will return an boxed enum.
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        private extern Object BoxEnum();
 
 
        // Helper code for marshaling managed objects to VARIANT's (we use
        // managed variants as an intermediate type. 
        internal static void MarshalHelperConvertObjectToVariant(Object o, ref Variant v)
        {
            IConvertible ic = System.Runtime.Remoting.RemotingServices.IsTransparentProxy(o) ? null : o as IConvertible;
            if (o == null) 
            {
                v = Empty; 
            } 
            else if (ic == null)
            { 
                // This path should eventually go away. But until
                // the work is done to have all of our wrapper types implement
                // IConvertible, this is a cheapo way to get the work done.
                v = new Variant(o); 
            }
            else 
            { 
                IFormatProvider provider = CultureInfo.InvariantCulture;
                switch (ic.GetTypeCode()) 
                {
                    case TypeCode.Empty:
                        v = Empty;
                        break; 

                    case TypeCode.Object: 
                        v = new Variant((Object)o); 
                        break;
 
                    case TypeCode.DBNull:
                        v = DBNull;
                        break;
 
                    case TypeCode.Boolean:
                        v = new Variant(ic.ToBoolean(provider)); 
                        break; 

                    case TypeCode.Char: 
                        v = new Variant(ic.ToChar(provider));
                        break;

                    case TypeCode.SByte: 
                        v = new Variant(ic.ToSByte(provider));
                        break; 
 
                    case TypeCode.Byte:
                        v = new Variant(ic.ToByte(provider)); 
                        break;

                    case TypeCode.Int16:
                        v = new Variant(ic.ToInt16(provider)); 
                        break;
 
                    case TypeCode.UInt16: 
                        v = new Variant(ic.ToUInt16(provider));
                        break; 

                    case TypeCode.Int32:
                        v = new Variant(ic.ToInt32(provider));
                        break; 

                    case TypeCode.UInt32: 
                        v = new Variant(ic.ToUInt32(provider)); 
                        break;
 
                    case TypeCode.Int64:
                        v = new Variant(ic.ToInt64(provider));
                        break;
 
                    case TypeCode.UInt64:
                        v = new Variant(ic.ToUInt64(provider)); 
                        break; 

                    case TypeCode.Single: 
                        v = new Variant(ic.ToSingle(provider));
                        break;

                    case TypeCode.Double: 
                        v = new Variant(ic.ToDouble(provider));
                        break; 
 
                    case TypeCode.Decimal:
                        v = new Variant(ic.ToDecimal(provider)); 
                        break;

                    case TypeCode.DateTime:
                        v = new Variant(ic.ToDateTime(provider)); 
                        break;
 
                    case TypeCode.String: 
                        v = new Variant(ic.ToString(provider));
                        break; 

                    default:
                        throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("NotSupported_UnknownTypeCode"), ic.GetTypeCode()));
                } 
            }
        } 
 
        // Helper code for marshaling VARIANTS to managed objects (we use
        // managed variants as an intermediate type. 
        internal static Object MarshalHelperConvertVariantToObject(ref Variant v)
        {
            return v.ToObject();
        } 

        // Helper code: on the back propagation path where a VT_BYREF VARIANT* 
        // is marshaled to a "ref Object", we use this helper to force the 
        // updated object back to the original type.
        internal static void MarshalHelperCastVariant(Object pValue, int vt, ref Variant v) 
        {
            IConvertible iv = pValue as IConvertible;
            if (iv == null)
            { 
                switch (vt)
                { 
#if FEATURE_COMINTEROP 
                    case 9: /*VT_DISPATCH*/
                        v = new Variant(new DispatchWrapper(pValue)); 
                        break;
#endif

                    case 12: /*VT_VARIANT*/ 
                        v = new Variant(pValue);
                        break; 
 
#if FEATURE_COMINTEROP
                    case 13: /*VT_UNKNOWN*/ 
                        v = new Variant(new UnknownWrapper(pValue));
                        break;
#endif
 
                    case 36: /*VT_RECORD*/
                        v = new Variant(pValue); 
                        break; 

                    case 8: /*VT_BSTR*/ 
                        if (pValue == null)
                        {
                            v = new Variant(null);
                            v.m_flags = CV_STRING; 
                        }
                        else 
                        { 
                            throw new InvalidCastException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("InvalidCast_CannotCoerceByRefVariant")));
                        } 
                        break;

                    default:
                        throw new InvalidCastException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("InvalidCast_CannotCoerceByRefVariant"))); 
                }
            } 
            else 
            {
                IFormatProvider provider = CultureInfo.InvariantCulture; 
                switch (vt)
                {
                    case 0: /*VT_EMPTY*/
                        v = Empty; 
                        break;
 
                    case 1: /*VT_NULL*/ 
                        v = DBNull;
                        break; 

                    case 2: /*VT_I2*/
                        v = new Variant(iv.ToInt16(provider));
                        break; 

                    case 3: /*VT_I4*/ 
                        v = new Variant(iv.ToInt32(provider)); 
                        break;
 
                    case 4: /*VT_R4*/
                        v = new Variant(iv.ToSingle(provider));
                        break;
 
                    case 5: /*VT_R8*/
                        v = new Variant(iv.ToDouble(provider)); 
                        break; 

#if FEATURE_COMINTEROP 
                    case 6: /*VT_CY*/
                        v = new Variant(new CurrencyWrapper(iv.ToDecimal(provider)));
                        break;
#endif 

                    case 7: /*VT_DATE*/ 
                        v = new Variant(iv.ToDateTime(provider)); 
                        break;
 
                    case 8: /*VT_BSTR*/
                        v = new Variant(iv.ToString(provider));
                        break;
 
#if FEATURE_COMINTEROP
                    case 9: /*VT_DISPATCH*/ 
                        v = new Variant(new DispatchWrapper((Object)iv)); 
                        break;
 
                    case 10: /*VT_ERROR*/
                        v = new Variant(new ErrorWrapper(iv.ToInt32(provider)));
                        break;
#endif 

                    case 11: /*VT_BOOL*/ 
                        v = new Variant(iv.ToBoolean(provider)); 
                        break;
 
                    case 12: /*VT_VARIANT*/
                        v = new Variant((Object)iv);
                        break;
 
#if FEATURE_COMINTEROP
                    case 13: /*VT_UNKNOWN*/ 
                        v = new Variant(new UnknownWrapper((Object)iv)); 
                        break;
#endif 

                    case 14: /*VT_DECIMAL*/
                        v = new Variant(iv.ToDecimal(provider));
                        break; 

                    // case 15: /*unused*/ 
                    //  NOT SUPPORTED 

                    case 16: /*VT_I1*/ 
                        v = new Variant(iv.ToSByte(provider));
                        break;

                    case 17: /*VT_UI1*/ 
                        v = new Variant(iv.ToByte(provider));
                        break; 
 
                    case 18: /*VT_UI2*/
                        v = new Variant(iv.ToUInt16(provider)); 
                        break;

                    case 19: /*VT_UI4*/
                        v = new Variant(iv.ToUInt32(provider)); 
                        break;
 
                    case 20: /*VT_I8*/ 
                        v = new Variant(iv.ToInt64(provider));
                        break; 

                    case 21: /*VT_UI8*/
                        v = new Variant(iv.ToUInt64(provider));
                        break; 

                    case 22: /*VT_INT*/ 
                        v = new Variant(iv.ToInt32(provider)); 
                        break;
 
                    case 23: /*VT_UINT*/
                        v = new Variant(iv.ToUInt32(provider));
                        break;
 
                    default:
                        throw new InvalidCastException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("InvalidCast_CannotCoerceByRefVariant"))); 
                } 
            }
        } 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK