Advertisement
Guest User

Untitled

a guest
Mar 21st, 2019
52
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.29 KB | None | 0 0
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4.  
  5. using System.Diagnostics;
  6. using System.Runtime;
  7. using System.Runtime.CompilerServices;
  8. using Internal.Runtime.CompilerServices;
  9. using Internal.Runtime.Augments;
  10. using Internal.Reflection.Augments;
  11.  
  12. using CorElementType = System.Runtime.RuntimeImports.RhCorElementType;
  13.  
  14. namespace System
  15. {
  16. public abstract partial class Enum : ValueType, IComparable, IFormattable, IConvertible
  17. {
  18. private static TypeValuesAndNames GetCachedValuesAndNames(Type enumType, bool getNames)
  19. {
  20. TypeValuesAndNames entry = null;// TODO: Add GenericCache to Type?: enumType.GenericCache as TypeValuesAndNames;
  21.  
  22. if (entry == null || (getNames && entry.Names == null))
  23. {
  24. var info = GetEnumInfo(enumType);
  25. bool isFlags = enumType.IsDefined(typeof(FlagsAttribute), inherit: false);
  26. entry = new TypeValuesAndNames(isFlags, info.RawValues, info.RawNames);
  27. // TODO: save to the cache
  28. }
  29.  
  30. return entry;
  31. }
  32.  
  33. private static Type ValidateRuntimeType(Type enumType)
  34. {
  35. if (enumType == null)
  36. throw new ArgumentNullException(nameof(enumType));
  37. if (!enumType.IsEnum)
  38. throw new ArgumentException(SR.Arg_MustBeEnum, nameof(enumType));
  39. return enumType;
  40. }
  41.  
  42. private static object InternalBoxEnum(Type enumType, long value)
  43. {
  44. return ToObject(enumType.EETypePtr, value);
  45. }
  46.  
  47. private int InternalCompareTo(Enum enumObj, object target)
  48. {
  49. if (target == null)
  50. return 1;
  51.  
  52. if (target == this)
  53. return 0;
  54.  
  55. if (enumObj.EETypePtr != target.EETypePtr)
  56. {
  57. throw new ArgumentException(SR.Format(SR.Arg_EnumAndObjectMustBeSameType, target.GetType().ToString(), enumObj.GetType().ToString()));
  58. }
  59.  
  60. ref byte pThisValue = ref enumObj.GetRawData();
  61. ref byte pTargetValue = ref target.GetRawData();
  62.  
  63. switch (enumObj.EETypePtr.CorElementType)
  64. {
  65. case CorElementType.ELEMENT_TYPE_I1:
  66. return (Unsafe.As<byte, sbyte>(ref pThisValue) == Unsafe.As<byte, sbyte>(ref pTargetValue)) ?
  67. 0 : (Unsafe.As<byte, sbyte>(ref pThisValue) < Unsafe.As<byte, sbyte>(ref pTargetValue)) ? -1 : 1;
  68.  
  69. case CorElementType.ELEMENT_TYPE_U1:
  70. case CorElementType.ELEMENT_TYPE_BOOLEAN:
  71. return (Unsafe.As<byte, byte>(ref pThisValue) == Unsafe.As<byte, byte>(ref pTargetValue)) ?
  72. 0 : (Unsafe.As<byte, byte>(ref pThisValue) < Unsafe.As<byte, byte>(ref pTargetValue)) ? -1 : 1;
  73.  
  74. case CorElementType.ELEMENT_TYPE_I2:
  75. return (Unsafe.As<byte, short>(ref pThisValue) == Unsafe.As<byte, short>(ref pTargetValue)) ?
  76. 0 : (Unsafe.As<byte, short>(ref pThisValue) < Unsafe.As<byte, short>(ref pTargetValue)) ? -1 : 1;
  77.  
  78. case CorElementType.ELEMENT_TYPE_U2:
  79. case CorElementType.ELEMENT_TYPE_CHAR:
  80. return (Unsafe.As<byte, ushort>(ref pThisValue) == Unsafe.As<byte, ushort>(ref pTargetValue)) ?
  81. 0 : (Unsafe.As<byte, ushort>(ref pThisValue) < Unsafe.As<byte, ushort>(ref pTargetValue)) ? -1 : 1;
  82.  
  83. case CorElementType.ELEMENT_TYPE_I4:
  84. return (Unsafe.As<byte, int>(ref pThisValue) == Unsafe.As<byte, int>(ref pTargetValue)) ?
  85. 0 : (Unsafe.As<byte, int>(ref pThisValue) < Unsafe.As<byte, int>(ref pTargetValue)) ? -1 : 1;
  86.  
  87. case CorElementType.ELEMENT_TYPE_U4:
  88. return (Unsafe.As<byte, uint>(ref pThisValue) == Unsafe.As<byte, uint>(ref pTargetValue)) ?
  89. 0 : (Unsafe.As<byte, uint>(ref pThisValue) < Unsafe.As<byte, uint>(ref pTargetValue)) ? -1 : 1;
  90.  
  91. case CorElementType.ELEMENT_TYPE_I8:
  92. return (Unsafe.As<byte, long>(ref pThisValue) == Unsafe.As<byte, long>(ref pTargetValue)) ?
  93. 0 : (Unsafe.As<byte, long>(ref pThisValue) < Unsafe.As<byte, long>(ref pTargetValue)) ? -1 : 1;
  94.  
  95. case CorElementType.ELEMENT_TYPE_U8:
  96. return (Unsafe.As<byte, ulong>(ref pThisValue) == Unsafe.As<byte, ulong>(ref pTargetValue)) ?
  97. 0 : (Unsafe.As<byte, ulong>(ref pThisValue) < Unsafe.As<byte, ulong>(ref pTargetValue)) ? -1 : 1;
  98.  
  99. default:
  100. Environment.FailFast("Unexpected enum underlying type");
  101. return 0;
  102. }
  103. }
  104.  
  105. public override bool Equals(object obj)
  106. {
  107. if (obj == null)
  108. return false;
  109. EETypePtr eeType = this.EETypePtr;
  110. if (!eeType.FastEquals(obj.EETypePtr))
  111. return false;
  112.  
  113. ref byte pThisValue = ref this.GetRawData();
  114. ref byte pOtherValue = ref obj.GetRawData();
  115.  
  116. RuntimeImports.RhCorElementTypeInfo corElementTypeInfo = eeType.CorElementTypeInfo;
  117. switch (corElementTypeInfo.Log2OfSize)
  118. {
  119. case 0:
  120. return Unsafe.As<byte, byte>(ref pThisValue) == Unsafe.As<byte, byte>(ref pOtherValue);
  121. case 1:
  122. return Unsafe.As<byte, ushort>(ref pThisValue) == Unsafe.As<byte, ushort>(ref pOtherValue);
  123. case 2:
  124. return Unsafe.As<byte, uint>(ref pThisValue) == Unsafe.As<byte, uint>(ref pOtherValue);
  125. case 3:
  126. return Unsafe.As<byte, ulong>(ref pThisValue) == Unsafe.As<byte, ulong>(ref pOtherValue);
  127. default:
  128. Environment.FailFast("Unexpected enum underlying type");
  129. return false;
  130. }
  131. }
  132.  
  133. private CorElementType InternalGetCorElementType() => this.EETypePtr.CorElementType;
  134.  
  135. [Intrinsic]
  136. public bool HasFlag(Enum flag)
  137. {
  138. if (flag == null)
  139. throw new ArgumentNullException(nameof(flag));
  140.  
  141. if (!(this.EETypePtr == flag.EETypePtr))
  142. throw new ArgumentException(SR.Format(SR.Argument_EnumTypeDoesNotMatch, flag.GetType(), this.GetType()));
  143.  
  144. ref byte pThisValue = ref this.GetRawData();
  145. ref byte pFlagValue = ref flag.GetRawData();
  146.  
  147. switch (this.EETypePtr.CorElementTypeInfo.Log2OfSize)
  148. {
  149. case 0:
  150. return (Unsafe.As<byte, byte>(ref pThisValue) & Unsafe.As<byte, byte>(ref pFlagValue)) == Unsafe.As<byte, byte>(ref pFlagValue);
  151. case 1:
  152. return (Unsafe.As<byte, ushort>(ref pThisValue) & Unsafe.As<byte, ushort>(ref pFlagValue)) == Unsafe.As<byte, ushort>(ref pFlagValue);
  153. case 2:
  154. return (Unsafe.As<byte, uint>(ref pThisValue) & Unsafe.As<byte, uint>(ref pFlagValue)) == Unsafe.As<byte, uint>(ref pFlagValue);
  155. case 3:
  156. return (Unsafe.As<byte, ulong>(ref pThisValue) & Unsafe.As<byte, ulong>(ref pFlagValue)) == Unsafe.As<byte, ulong>(ref pFlagValue);
  157. default:
  158. Environment.FailFast("Unexpected enum underlying type");
  159. return false;
  160. }
  161. }
  162.  
  163. internal static EnumInfo GetEnumInfo(Type enumType)
  164. {
  165. Debug.Assert(enumType != null);
  166. Debug.Assert(enumType.IsRuntimeImplemented());
  167. Debug.Assert(enumType.IsEnum);
  168.  
  169. return ReflectionAugments.ReflectionCoreCallbacks.GetEnumInfo(enumType);
  170. }
  171.  
  172. [Conditional("BIGENDIAN")]
  173. private static unsafe void AdjustForEndianness(ref byte* pValue, EETypePtr enumEEType)
  174. {
  175. // On Debug builds, include the big-endian code to help deter bitrot (the "Conditional("BIGENDIAN")" will prevent it from executing on little-endian).
  176. // On Release builds, exclude code to deter IL bloat and toolchain work.
  177. #if BIGENDIAN || DEBUG
  178. CorElementType corElementType = enumEEType.CorElementType;
  179. switch (corElementType)
  180. {
  181. case CorElementType.ELEMENT_TYPE_I1:
  182. case CorElementType.ELEMENT_TYPE_U1:
  183. pValue += sizeof(long) - sizeof(byte);
  184. break;
  185.  
  186. case CorElementType.ELEMENT_TYPE_I2:
  187. case CorElementType.ELEMENT_TYPE_U2:
  188. pValue += sizeof(long) - sizeof(short);
  189. break;
  190.  
  191. case CorElementType.ELEMENT_TYPE_I4:
  192. case CorElementType.ELEMENT_TYPE_U4:
  193. pValue += sizeof(long) - sizeof(int);
  194. break;
  195.  
  196. case CorElementType.ELEMENT_TYPE_I8:
  197. case CorElementType.ELEMENT_TYPE_U8:
  198. break;
  199.  
  200. default:
  201. throw new NotSupportedException();
  202. }
  203. #endif //BIGENDIAN || DEBUG
  204. }
  205.  
  206. #region ToObject
  207.  
  208. // Common helper for the non-boxing Enum.ToObject() overloads.
  209. private static object ToObjectWorker(Type enumType, long value)
  210. {
  211. if (enumType == null)
  212. throw new ArgumentNullException(nameof(enumType));
  213.  
  214. if (!enumType.IsEnum)
  215. throw new ArgumentException(SR.Arg_MustBeEnum, nameof(enumType));
  216.  
  217. if (!enumType.IsRuntimeImplemented())
  218. throw new ArgumentException(SR.Arg_MustBeType, nameof(enumType));
  219.  
  220. // Check for the unfortunate "typeof(Outer<>).InnerEnum" corner case.
  221. if (enumType.ContainsGenericParameters)
  222. throw new InvalidOperationException(SR.Format(SR.Arg_OpenType, enumType.ToString()));
  223.  
  224. EETypePtr enumEEType = enumType.TypeHandle.ToEETypePtr();
  225. return ToObject(enumEEType, value);
  226. }
  227.  
  228. internal unsafe static object ToObject(EETypePtr enumEEType, long value)
  229. {
  230. Debug.Assert(enumEEType.IsEnum);
  231.  
  232. byte* pValue = (byte*)&value;
  233. AdjustForEndianness(ref pValue, enumEEType);
  234. return RuntimeImports.RhBox(enumEEType, pValue);
  235. }
  236. #endregion
  237. }
  238. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement