2007-10-27 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / class / corlib / System / Variant.cs
1 //
2 // System.Variant
3 //
4 // Authors:
5 //   Jonathan Chambers <jonathan.chambers@ansys.com>
6 //
7 // Copyright (C) 2006 Novell (http://www.novell.com)
8 //
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System.Runtime.InteropServices;
31
32 namespace System
33 {
34         [StructLayout(LayoutKind.Explicit, Size = 16)]
35         internal unsafe struct Variant
36         {
37                 [FieldOffset(0)]
38                 public short vt;
39
40                 [FieldOffset(2)]
41                 public ushort wReserved1;
42
43                 [FieldOffset(4)]
44                 public ushort wReserved2;
45
46                 [FieldOffset(6)]
47                 public ushort wReserved3;
48
49                 [FieldOffset(8)]
50                 public long llVal;
51
52                 [FieldOffset(8)]
53                 public int lVal;
54
55                 [FieldOffset(8)]
56                 public byte bVal;
57
58                 [FieldOffset(8)]
59                 public short iVal;
60
61                 [FieldOffset(8)]
62                 public float fltVal;
63
64                 [FieldOffset(8)]
65                 public double dblVal;
66
67                 [FieldOffset(8)]
68                 public short boolVal;
69
70                 [FieldOffset(8)]
71                 public IntPtr bstrVal;
72
73                 [FieldOffset(8)]
74                 public sbyte cVal;
75
76                 [FieldOffset(8)]
77                 public ushort uiVal;
78
79                 [FieldOffset(8)]
80                 public uint ulVal;
81
82                 [FieldOffset(8)]
83                 public ulong ullVal;
84
85                 [FieldOffset(8)]
86                 public int intVal;
87
88                 [FieldOffset(8)]
89                 public uint uintVal;
90
91         [FieldOffset(8)]
92         public IntPtr pdispVal;
93
94                 public void SetValue(object obj) {
95                         vt = (short)VarEnum.VT_EMPTY;
96                         if (obj == null)
97                                 return;
98
99                         Type t = obj.GetType();
100                         if (t == typeof(sbyte))
101                         {
102                                 vt = (short)VarEnum.VT_I1;
103                                 cVal = (sbyte)obj;
104                         }
105                         else if (t == typeof(byte))
106                         {
107                                 vt = (short)VarEnum.VT_UI1;
108                                 bVal = (byte)obj;
109                         }
110                         else if (t == typeof(short))
111                         {
112                                 vt = (short)VarEnum.VT_I2;
113                                 iVal = (short)obj;
114                         }
115                         else if (t == typeof(ushort))
116                         {
117                                 vt = (short)VarEnum.VT_UI2;
118                                 uiVal = (ushort)obj;
119                         }
120                         else if (t == typeof(int))
121                         {
122                                 vt = (short)VarEnum.VT_I4;
123                                 lVal = (int)obj;
124                         }
125                         else if (t == typeof(uint))
126                         {
127                                 vt = (short)VarEnum.VT_UI4;
128                                 ulVal = (uint)obj;
129                         }
130                         else if (t == typeof(long))
131                         {
132                                 vt = (short)VarEnum.VT_I8;
133                                 llVal = (long)obj;
134                         }
135                         else if (t == typeof(ulong))
136                         {
137                                 vt = (short)VarEnum.VT_UI8;
138                                 ullVal = (ulong)obj;
139                         }
140                         else if (t == typeof(float))
141                         {
142                                 vt = (short)VarEnum.VT_R4;
143                                 fltVal = (float)obj;
144                         }
145                         else if (t == typeof(double))
146                         {
147                                 vt = (short)VarEnum.VT_R8;
148                                 dblVal = (double)obj;
149                         }
150                         else if (t == typeof(string))
151                         {
152                                 vt = (short)VarEnum.VT_BSTR;
153                                 bstrVal = Marshal.StringToBSTR((string)obj);
154             }
155             else if (t == typeof(bool))
156             {
157                 vt = (short)VarEnum.VT_BOOL;
158                 lVal = ((bool)obj) ? -1 : 0;
159             }
160             else
161             {
162                 try 
163                 {
164                     vt = (short)VarEnum.VT_DISPATCH;
165                     pdispVal = Marshal.GetIUnknownForObject(obj);
166                 }
167                 catch (Exception ex)
168                 {
169                     throw new NotImplementedException(string.Format("Variant couldn't handle object of type {0}", obj.GetType()), ex);
170                 }
171                         }
172                 }
173
174                 public object GetValue() {
175                         object obj = null;
176                         switch ((VarEnum)vt)
177                         {
178                         case VarEnum.VT_I1:
179                         obj = cVal;
180                         break;
181                         case VarEnum.VT_UI1:
182                                 obj = bVal;
183                                 break;
184                         case VarEnum.VT_I2:
185                                 obj = iVal;
186                                 break;
187                         case VarEnum.VT_UI2:
188                                 obj = uiVal;
189                                 break;
190                         case VarEnum.VT_I4:
191                                 obj = lVal;
192                                 break;
193                         case VarEnum.VT_UI4:
194                                 obj = ulVal;
195                                 break;
196                         case VarEnum.VT_I8:
197                                 obj = llVal;
198                                 break;
199                         case VarEnum.VT_UI8:
200                                 obj = ullVal;
201                                 break;
202                         case VarEnum.VT_R4:
203                                 obj = fltVal;
204                                 break;
205                         case VarEnum.VT_R8:
206                                 obj = dblVal;
207                                 break;
208                         case VarEnum.VT_BOOL:
209                                 obj = !(lVal == 0);
210                                 break;
211                         case VarEnum.VT_BSTR:
212                                 obj = Marshal.PtrToStringBSTR(bstrVal);
213                                 break;
214             case VarEnum.VT_UNKNOWN:
215             case VarEnum.VT_DISPATCH:
216                 obj = Marshal.GetObjectForIUnknown(pdispVal);
217                 break;
218                         }
219                         return obj;
220                 }\r
221 \r
222                 public void Clear ()\r
223                 {\r
224                         if ((VarEnum)vt == VarEnum.VT_BSTR) {\r
225                                 Marshal.FreeBSTR (bstrVal);\r
226                         }\r
227                         else if ((VarEnum)vt == VarEnum.VT_DISPATCH || (VarEnum)vt == VarEnum.VT_UNKNOWN) {\r
228                                 if (pdispVal != IntPtr.Zero)\r
229                                         Marshal.Release (pdispVal);
230             }
231                 }
232         }
233 }