Free cookie consent management tool by TermsFeed Policy Generator

source: branches/RemoveBackwardsCompatibility/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory-5.5.0/Utils/CSharpPrimitiveCast.cs @ 13401

Last change on this file since 13401 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 19.8 KB
Line 
1// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4// software and associated documentation files (the "Software"), to deal in the Software
5// without restriction, including without limitation the rights to use, copy, modify, merge,
6// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7// to whom the Software is furnished to do so, subject to the following conditions:
8//
9// The above copyright notice and this permission notice shall be included in all copies or
10// substantial portions of the Software.
11//
12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17// DEALINGS IN THE SOFTWARE.
18
19using System;
20
21namespace ICSharpCode.NRefactory.Utils
22{
23  /// <summary>
24  /// Static helper method for converting between primitive types.
25  /// </summary>
26  public static class CSharpPrimitiveCast
27  {
28    /// <summary>
29    /// Performs a conversion between primitive types.
30    /// Unfortunately we cannot use Convert.ChangeType because it has different semantics
31    /// (e.g. rounding behavior for floats, overflow, etc.), so we write down every possible primitive C# cast
32    /// and let the compiler figure out the exact semantics.
33    /// And we have to do everything twice, once in a checked-block, once in an unchecked-block.
34    /// </summary>
35    /// <exception cref="OverflowException">Overflow checking is enabled and an overflow occurred.</exception>
36    /// <exception cref="InvalidCastException">The cast is invalid, e.g. casting a boolean to an integer.</exception>
37    public static object Cast(TypeCode targetType, object input, bool checkForOverflow)
38    {
39      if (input == null)
40        return null;
41      if (checkForOverflow)
42        return CSharpPrimitiveCastChecked(targetType, input);
43      else
44        return CSharpPrimitiveCastUnchecked(targetType, input);
45    }
46   
47    static object CSharpPrimitiveCastChecked(TypeCode targetType, object input)
48    {
49      checked {
50        TypeCode sourceType = Type.GetTypeCode(input.GetType());
51        if (sourceType == targetType)
52          return input;
53        switch (targetType) {
54          case TypeCode.Char:
55            switch (sourceType) {
56                case TypeCode.SByte:   return (char)(sbyte)input;
57                case TypeCode.Byte:    return (char)(byte)input;
58                case TypeCode.Int16:   return (char)(short)input;
59                case TypeCode.UInt16:  return (char)(ushort)input;
60                case TypeCode.Int32:   return (char)(int)input;
61                case TypeCode.UInt32:  return (char)(uint)input;
62                case TypeCode.Int64:   return (char)(long)input;
63                case TypeCode.UInt64:  return (char)(ulong)input;
64                case TypeCode.Single:  return (char)(float)input;
65                case TypeCode.Double:  return (char)(double)input;
66                case TypeCode.Decimal: return (char)(decimal)input;
67            }
68            break;
69          case TypeCode.SByte:
70            switch (sourceType) {
71                case TypeCode.Char:    return (sbyte)(char)input;
72                case TypeCode.Byte:    return (sbyte)(byte)input;
73                case TypeCode.Int16:   return (sbyte)(short)input;
74                case TypeCode.UInt16:  return (sbyte)(ushort)input;
75                case TypeCode.Int32:   return (sbyte)(int)input;
76                case TypeCode.UInt32:  return (sbyte)(uint)input;
77                case TypeCode.Int64:   return (sbyte)(long)input;
78                case TypeCode.UInt64:  return (sbyte)(ulong)input;
79                case TypeCode.Single:  return (sbyte)(float)input;
80                case TypeCode.Double:  return (sbyte)(double)input;
81                case TypeCode.Decimal: return (sbyte)(decimal)input;
82            }
83            break;
84          case TypeCode.Byte:
85            switch (sourceType) {
86                case TypeCode.Char:    return (byte)(char)input;
87                case TypeCode.SByte:   return (byte)(sbyte)input;
88                case TypeCode.Int16:   return (byte)(short)input;
89                case TypeCode.UInt16:  return (byte)(ushort)input;
90                case TypeCode.Int32:   return (byte)(int)input;
91                case TypeCode.UInt32:  return (byte)(uint)input;
92                case TypeCode.Int64:   return (byte)(long)input;
93                case TypeCode.UInt64:  return (byte)(ulong)input;
94                case TypeCode.Single:  return (byte)(float)input;
95                case TypeCode.Double:  return (byte)(double)input;
96                case TypeCode.Decimal: return (byte)(decimal)input;
97            }
98            break;
99          case TypeCode.Int16:
100            switch (sourceType) {
101                case TypeCode.Char:    return (short)(char)input;
102                case TypeCode.SByte:   return (short)(sbyte)input;
103                case TypeCode.Byte:    return (short)(byte)input;
104                case TypeCode.UInt16:  return (short)(ushort)input;
105                case TypeCode.Int32:   return (short)(int)input;
106                case TypeCode.UInt32:  return (short)(uint)input;
107                case TypeCode.Int64:   return (short)(long)input;
108                case TypeCode.UInt64:  return (short)(ulong)input;
109                case TypeCode.Single:  return (short)(float)input;
110                case TypeCode.Double:  return (short)(double)input;
111                case TypeCode.Decimal: return (short)(decimal)input;
112            }
113            break;
114          case TypeCode.UInt16:
115            switch (sourceType) {
116                case TypeCode.Char:    return (ushort)(char)input;
117                case TypeCode.SByte:   return (ushort)(sbyte)input;
118                case TypeCode.Byte:    return (ushort)(byte)input;
119                case TypeCode.Int16:   return (ushort)(short)input;
120                case TypeCode.Int32:   return (ushort)(int)input;
121                case TypeCode.UInt32:  return (ushort)(uint)input;
122                case TypeCode.Int64:   return (ushort)(long)input;
123                case TypeCode.UInt64:  return (ushort)(ulong)input;
124                case TypeCode.Single:  return (ushort)(float)input;
125                case TypeCode.Double:  return (ushort)(double)input;
126                case TypeCode.Decimal: return (ushort)(decimal)input;
127            }
128            break;
129          case TypeCode.Int32:
130            switch (sourceType) {
131                case TypeCode.Char:    return (int)(char)input;
132                case TypeCode.SByte:   return (int)(sbyte)input;
133                case TypeCode.Byte:    return (int)(byte)input;
134                case TypeCode.Int16:   return (int)(short)input;
135                case TypeCode.UInt16:  return (int)(ushort)input;
136                case TypeCode.UInt32:  return (int)(uint)input;
137                case TypeCode.Int64:   return (int)(long)input;
138                case TypeCode.UInt64:  return (int)(ulong)input;
139                case TypeCode.Single:  return (int)(float)input;
140                case TypeCode.Double:  return (int)(double)input;
141                case TypeCode.Decimal: return (int)(decimal)input;
142            }
143            break;
144          case TypeCode.UInt32:
145            switch (sourceType) {
146                case TypeCode.Char:    return (uint)(char)input;
147                case TypeCode.SByte:   return (uint)(sbyte)input;
148                case TypeCode.Byte:    return (uint)(byte)input;
149                case TypeCode.Int16:   return (uint)(short)input;
150                case TypeCode.UInt16:  return (uint)(ushort)input;
151                case TypeCode.Int32:   return (uint)(int)input;
152                case TypeCode.Int64:   return (uint)(long)input;
153                case TypeCode.UInt64:  return (uint)(ulong)input;
154                case TypeCode.Single:  return (uint)(float)input;
155                case TypeCode.Double:  return (uint)(double)input;
156                case TypeCode.Decimal: return (uint)(decimal)input;
157            }
158            break;
159          case TypeCode.Int64:
160            switch (sourceType) {
161                case TypeCode.Char:    return (long)(char)input;
162                case TypeCode.SByte:   return (long)(sbyte)input;
163                case TypeCode.Byte:    return (long)(byte)input;
164                case TypeCode.Int16:   return (long)(short)input;
165                case TypeCode.UInt16:  return (long)(ushort)input;
166                case TypeCode.Int32:   return (long)(int)input;
167                case TypeCode.UInt32:  return (long)(uint)input;
168                case TypeCode.UInt64:  return (long)(ulong)input;
169                case TypeCode.Single:  return (long)(float)input;
170                case TypeCode.Double:  return (long)(double)input;
171                case TypeCode.Decimal: return (long)(decimal)input;
172            }
173            break;
174          case TypeCode.UInt64:
175            switch (sourceType) {
176                case TypeCode.Char:    return (ulong)(char)input;
177                case TypeCode.SByte:   return (ulong)(sbyte)input;
178                case TypeCode.Byte:    return (ulong)(byte)input;
179                case TypeCode.Int16:   return (ulong)(short)input;
180                case TypeCode.UInt16:  return (ulong)(ushort)input;
181                case TypeCode.Int32:   return (ulong)(int)input;
182                case TypeCode.UInt32:  return (ulong)(uint)input;
183                case TypeCode.Int64:   return (ulong)(long)input;
184                case TypeCode.Single:  return (ulong)(float)input;
185                case TypeCode.Double:  return (ulong)(double)input;
186                case TypeCode.Decimal: return (ulong)(decimal)input;
187            }
188            break;
189          case TypeCode.Single:
190            switch (sourceType) {
191                case TypeCode.Char:    return (float)(char)input;
192                case TypeCode.SByte:   return (float)(sbyte)input;
193                case TypeCode.Byte:    return (float)(byte)input;
194                case TypeCode.Int16:   return (float)(short)input;
195                case TypeCode.UInt16:  return (float)(ushort)input;
196                case TypeCode.Int32:   return (float)(int)input;
197                case TypeCode.UInt32:  return (float)(uint)input;
198                case TypeCode.Int64:   return (float)(long)input;
199                case TypeCode.UInt64:  return (float)(ulong)input;
200                case TypeCode.Double:  return (float)(double)input;
201                case TypeCode.Decimal: return (float)(decimal)input;
202            }
203            break;
204          case TypeCode.Double:
205            switch (sourceType) {
206                case TypeCode.Char:    return (double)(char)input;
207                case TypeCode.SByte:   return (double)(sbyte)input;
208                case TypeCode.Byte:    return (double)(byte)input;
209                case TypeCode.Int16:   return (double)(short)input;
210                case TypeCode.UInt16:  return (double)(ushort)input;
211                case TypeCode.Int32:   return (double)(int)input;
212                case TypeCode.UInt32:  return (double)(uint)input;
213                case TypeCode.Int64:   return (double)(long)input;
214                case TypeCode.UInt64:  return (double)(ulong)input;
215                case TypeCode.Single:  return (double)(float)input;
216                case TypeCode.Decimal: return (double)(decimal)input;
217            }
218            break;
219          case TypeCode.Decimal:
220            switch (sourceType) {
221                case TypeCode.Char:    return (decimal)(char)input;
222                case TypeCode.SByte:   return (decimal)(sbyte)input;
223                case TypeCode.Byte:    return (decimal)(byte)input;
224                case TypeCode.Int16:   return (decimal)(short)input;
225                case TypeCode.UInt16:  return (decimal)(ushort)input;
226                case TypeCode.Int32:   return (decimal)(int)input;
227                case TypeCode.UInt32:  return (decimal)(uint)input;
228                case TypeCode.Int64:   return (decimal)(long)input;
229                case TypeCode.UInt64:  return (decimal)(ulong)input;
230                case TypeCode.Single:  return (decimal)(float)input;
231                case TypeCode.Double:  return (decimal)(double)input;
232            }
233            break;
234        }
235        throw new InvalidCastException("Cast from " + sourceType + " to " + targetType + "not supported.");
236      }
237    }
238   
239    static object CSharpPrimitiveCastUnchecked(TypeCode targetType, object input)
240    {
241      unchecked {
242        TypeCode sourceType = Type.GetTypeCode(input.GetType());
243        if (sourceType == targetType)
244          return input;
245        switch (targetType) {
246          case TypeCode.Char:
247            switch (sourceType) {
248                case TypeCode.SByte:   return (char)(sbyte)input;
249                case TypeCode.Byte:    return (char)(byte)input;
250                case TypeCode.Int16:   return (char)(short)input;
251                case TypeCode.UInt16:  return (char)(ushort)input;
252                case TypeCode.Int32:   return (char)(int)input;
253                case TypeCode.UInt32:  return (char)(uint)input;
254                case TypeCode.Int64:   return (char)(long)input;
255                case TypeCode.UInt64:  return (char)(ulong)input;
256                case TypeCode.Single:  return (char)(float)input;
257                case TypeCode.Double:  return (char)(double)input;
258                case TypeCode.Decimal: return (char)(decimal)input;
259            }
260            break;
261          case TypeCode.SByte:
262            switch (sourceType) {
263                case TypeCode.Char:    return (sbyte)(char)input;
264                case TypeCode.Byte:    return (sbyte)(byte)input;
265                case TypeCode.Int16:   return (sbyte)(short)input;
266                case TypeCode.UInt16:  return (sbyte)(ushort)input;
267                case TypeCode.Int32:   return (sbyte)(int)input;
268                case TypeCode.UInt32:  return (sbyte)(uint)input;
269                case TypeCode.Int64:   return (sbyte)(long)input;
270                case TypeCode.UInt64:  return (sbyte)(ulong)input;
271                case TypeCode.Single:  return (sbyte)(float)input;
272                case TypeCode.Double:  return (sbyte)(double)input;
273                case TypeCode.Decimal: return (sbyte)(decimal)input;
274            }
275            break;
276          case TypeCode.Byte:
277            switch (sourceType) {
278                case TypeCode.Char:    return (byte)(char)input;
279                case TypeCode.SByte:   return (byte)(sbyte)input;
280                case TypeCode.Int16:   return (byte)(short)input;
281                case TypeCode.UInt16:  return (byte)(ushort)input;
282                case TypeCode.Int32:   return (byte)(int)input;
283                case TypeCode.UInt32:  return (byte)(uint)input;
284                case TypeCode.Int64:   return (byte)(long)input;
285                case TypeCode.UInt64:  return (byte)(ulong)input;
286                case TypeCode.Single:  return (byte)(float)input;
287                case TypeCode.Double:  return (byte)(double)input;
288                case TypeCode.Decimal: return (byte)(decimal)input;
289            }
290            break;
291          case TypeCode.Int16:
292            switch (sourceType) {
293                case TypeCode.Char:    return (short)(char)input;
294                case TypeCode.SByte:   return (short)(sbyte)input;
295                case TypeCode.Byte:    return (short)(byte)input;
296                case TypeCode.UInt16:  return (short)(ushort)input;
297                case TypeCode.Int32:   return (short)(int)input;
298                case TypeCode.UInt32:  return (short)(uint)input;
299                case TypeCode.Int64:   return (short)(long)input;
300                case TypeCode.UInt64:  return (short)(ulong)input;
301                case TypeCode.Single:  return (short)(float)input;
302                case TypeCode.Double:  return (short)(double)input;
303                case TypeCode.Decimal: return (short)(decimal)input;
304            }
305            break;
306          case TypeCode.UInt16:
307            switch (sourceType) {
308                case TypeCode.Char:    return (ushort)(char)input;
309                case TypeCode.SByte:   return (ushort)(sbyte)input;
310                case TypeCode.Byte:    return (ushort)(byte)input;
311                case TypeCode.Int16:   return (ushort)(short)input;
312                case TypeCode.Int32:   return (ushort)(int)input;
313                case TypeCode.UInt32:  return (ushort)(uint)input;
314                case TypeCode.Int64:   return (ushort)(long)input;
315                case TypeCode.UInt64:  return (ushort)(ulong)input;
316                case TypeCode.Single:  return (ushort)(float)input;
317                case TypeCode.Double:  return (ushort)(double)input;
318                case TypeCode.Decimal: return (ushort)(decimal)input;
319            }
320            break;
321          case TypeCode.Int32:
322            switch (sourceType) {
323                case TypeCode.Char:    return (int)(char)input;
324                case TypeCode.SByte:   return (int)(sbyte)input;
325                case TypeCode.Byte:    return (int)(byte)input;
326                case TypeCode.Int16:   return (int)(short)input;
327                case TypeCode.UInt16:  return (int)(ushort)input;
328                case TypeCode.UInt32:  return (int)(uint)input;
329                case TypeCode.Int64:   return (int)(long)input;
330                case TypeCode.UInt64:  return (int)(ulong)input;
331                case TypeCode.Single:  return (int)(float)input;
332                case TypeCode.Double:  return (int)(double)input;
333                case TypeCode.Decimal: return (int)(decimal)input;
334            }
335            break;
336          case TypeCode.UInt32:
337            switch (sourceType) {
338                case TypeCode.Char:    return (uint)(char)input;
339                case TypeCode.SByte:   return (uint)(sbyte)input;
340                case TypeCode.Byte:    return (uint)(byte)input;
341                case TypeCode.Int16:   return (uint)(short)input;
342                case TypeCode.UInt16:  return (uint)(ushort)input;
343                case TypeCode.Int32:   return (uint)(int)input;
344                case TypeCode.Int64:   return (uint)(long)input;
345                case TypeCode.UInt64:  return (uint)(ulong)input;
346                case TypeCode.Single:  return (uint)(float)input;
347                case TypeCode.Double:  return (uint)(double)input;
348                case TypeCode.Decimal: return (uint)(decimal)input;
349            }
350            break;
351          case TypeCode.Int64:
352            switch (sourceType) {
353                case TypeCode.Char:    return (long)(char)input;
354                case TypeCode.SByte:   return (long)(sbyte)input;
355                case TypeCode.Byte:    return (long)(byte)input;
356                case TypeCode.Int16:   return (long)(short)input;
357                case TypeCode.UInt16:  return (long)(ushort)input;
358                case TypeCode.Int32:   return (long)(int)input;
359                case TypeCode.UInt32:  return (long)(uint)input;
360                case TypeCode.UInt64:  return (long)(ulong)input;
361                case TypeCode.Single:  return (long)(float)input;
362                case TypeCode.Double:  return (long)(double)input;
363                case TypeCode.Decimal: return (long)(decimal)input;
364            }
365            break;
366          case TypeCode.UInt64:
367            switch (sourceType) {
368                case TypeCode.Char:    return (ulong)(char)input;
369                case TypeCode.SByte:   return (ulong)(sbyte)input;
370                case TypeCode.Byte:    return (ulong)(byte)input;
371                case TypeCode.Int16:   return (ulong)(short)input;
372                case TypeCode.UInt16:  return (ulong)(ushort)input;
373                case TypeCode.Int32:   return (ulong)(int)input;
374                case TypeCode.UInt32:  return (ulong)(uint)input;
375                case TypeCode.Int64:   return (ulong)(long)input;
376                case TypeCode.Single:  return (ulong)(float)input;
377                case TypeCode.Double:  return (ulong)(double)input;
378                case TypeCode.Decimal: return (ulong)(decimal)input;
379            }
380            break;
381          case TypeCode.Single:
382            switch (sourceType) {
383                case TypeCode.Char:    return (float)(char)input;
384                case TypeCode.SByte:   return (float)(sbyte)input;
385                case TypeCode.Byte:    return (float)(byte)input;
386                case TypeCode.Int16:   return (float)(short)input;
387                case TypeCode.UInt16:  return (float)(ushort)input;
388                case TypeCode.Int32:   return (float)(int)input;
389                case TypeCode.UInt32:  return (float)(uint)input;
390                case TypeCode.Int64:   return (float)(long)input;
391                case TypeCode.UInt64:  return (float)(ulong)input;
392                case TypeCode.Double:  return (float)(double)input;
393                case TypeCode.Decimal: return (float)(decimal)input;
394            }
395            break;
396          case TypeCode.Double:
397            switch (sourceType) {
398                case TypeCode.Char:    return (double)(char)input;
399                case TypeCode.SByte:   return (double)(sbyte)input;
400                case TypeCode.Byte:    return (double)(byte)input;
401                case TypeCode.Int16:   return (double)(short)input;
402                case TypeCode.UInt16:  return (double)(ushort)input;
403                case TypeCode.Int32:   return (double)(int)input;
404                case TypeCode.UInt32:  return (double)(uint)input;
405                case TypeCode.Int64:   return (double)(long)input;
406                case TypeCode.UInt64:  return (double)(ulong)input;
407                case TypeCode.Single:  return (double)(float)input;
408                case TypeCode.Decimal: return (double)(decimal)input;
409            }
410            break;
411          case TypeCode.Decimal:
412            switch (sourceType) {
413                case TypeCode.Char:    return (decimal)(char)input;
414                case TypeCode.SByte:   return (decimal)(sbyte)input;
415                case TypeCode.Byte:    return (decimal)(byte)input;
416                case TypeCode.Int16:   return (decimal)(short)input;
417                case TypeCode.UInt16:  return (decimal)(ushort)input;
418                case TypeCode.Int32:   return (decimal)(int)input;
419                case TypeCode.UInt32:  return (decimal)(uint)input;
420                case TypeCode.Int64:   return (decimal)(long)input;
421                case TypeCode.UInt64:  return (decimal)(ulong)input;
422                case TypeCode.Single:  return (decimal)(float)input;
423                case TypeCode.Double:  return (decimal)(double)input;
424            }
425            break;
426        }
427        throw new InvalidCastException("Cast from " + sourceType + " to " + targetType + " not supported.");
428      }
429    }
430  }
431}
Note: See TracBrowser for help on using the repository browser.