internal static RhCorElementTypeInfo GetRhCorElementTypeInfo(RuntimeImports.RhCorElementType elementType) { // The _lookupTable array only covers a subset of RhCorElementTypes, so we return a default // info when someone asks for an elementType which does not have an entry in the table. if ((int)elementType > s_lookupTable.Length) { return(default(RhCorElementTypeInfo)); } return(s_lookupTable[(int)elementType]); }
// // This is a port of InvokeUtil::CanPrimitiveWiden() in the desktop runtime. This is used by various apis such as Array.SetValue() // and Delegate.DynamicInvoke() which allow value-preserving widenings from one primitive type to another. // public bool CanWidenTo(RuntimeImports.RhCorElementType targetElementType) { // Caller expected to ensure that both sides are primitive before calling us. Debug.Assert(this.IsPrimitive); Debug.Assert(GetRhCorElementTypeInfo(targetElementType).IsPrimitive); // Once we've asserted that the target is a primitive, we can also assert that it is >= ET_BOOLEAN. Debug.Assert(targetElementType >= RuntimeImports.RhCorElementType.ELEMENT_TYPE_BOOLEAN); byte targetElementTypeAsByte = (byte)targetElementType; ushort mask = (ushort)(1 << targetElementTypeAsByte); // This is expected to overflow on larger ET_I and ET_U - this is ok and anticipated. if (0 != (_widenMask & mask)) { return(true); } return(false); }
private static Type ComputeUnderlyingType(Type enumType) { RuntimeImports.RhCorElementType corElementType = ComputeCorElementType(enumType); switch (corElementType) { case RuntimeImports.RhCorElementType.ELEMENT_TYPE_BOOLEAN: return(CommonRuntimeTypes.Boolean); case RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR: return(CommonRuntimeTypes.Char); case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I1: return(CommonRuntimeTypes.SByte); case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U1: return(CommonRuntimeTypes.Byte); case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I2: return(CommonRuntimeTypes.Int16); case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U2: return(CommonRuntimeTypes.UInt16); case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I4: return(CommonRuntimeTypes.Int32); case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U4: return(CommonRuntimeTypes.UInt32); case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I8: return(CommonRuntimeTypes.Int64); case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U8: return(CommonRuntimeTypes.UInt64); default: throw new NotSupportedException(); } }
// Special coersion rules for primitives, enums and pointer. private static Exception ConvertOrWidenPrimitivesEnumsAndPointersIfPossible(object srcObject, EETypePtr srcEEType, EETypePtr dstEEType, CheckArgumentSemantics semantics, out object dstObject) { if (semantics == CheckArgumentSemantics.SetFieldDirect && (srcEEType.IsEnum || dstEEType.IsEnum)) { dstObject = null; return(CreateChangeTypeException(srcEEType, dstEEType, semantics)); } if (dstEEType.IsPointer) { Exception exception = ConvertPointerIfPossible(srcObject, srcEEType, dstEEType, semantics, out IntPtr dstIntPtr); if (exception != null) { dstObject = null; return(exception); } dstObject = dstIntPtr; return(null); } if (!(srcEEType.IsPrimitive && dstEEType.IsPrimitive)) { dstObject = null; return(CreateChangeTypeException(srcEEType, dstEEType, semantics)); } RuntimeImports.RhCorElementType dstCorElementType = dstEEType.CorElementType; if (!srcEEType.CorElementTypeInfo.CanWidenTo(dstCorElementType)) { dstObject = null; return(CreateChangeTypeArgumentException(srcEEType, dstEEType)); } switch (dstCorElementType) { case RuntimeImports.RhCorElementType.ELEMENT_TYPE_BOOLEAN: bool boolValue = Convert.ToBoolean(srcObject); dstObject = dstEEType.IsEnum ? Enum.ToObject(dstEEType, boolValue ? 1 : 0) : boolValue; break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR: char charValue = Convert.ToChar(srcObject); dstObject = dstEEType.IsEnum ? Enum.ToObject(dstEEType, charValue) : charValue; break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I1: sbyte sbyteValue = Convert.ToSByte(srcObject); dstObject = dstEEType.IsEnum ? Enum.ToObject(dstEEType, sbyteValue) : sbyteValue; break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I2: short shortValue = Convert.ToInt16(srcObject); dstObject = dstEEType.IsEnum ? Enum.ToObject(dstEEType, shortValue) : shortValue; break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I4: int intValue = Convert.ToInt32(srcObject); dstObject = dstEEType.IsEnum ? Enum.ToObject(dstEEType, intValue) : intValue; break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I8: long longValue = Convert.ToInt64(srcObject); dstObject = dstEEType.IsEnum ? Enum.ToObject(dstEEType, longValue) : longValue; break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U1: byte byteValue = Convert.ToByte(srcObject); dstObject = dstEEType.IsEnum ? Enum.ToObject(dstEEType, byteValue) : byteValue; break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U2: ushort ushortValue = Convert.ToUInt16(srcObject); dstObject = dstEEType.IsEnum ? Enum.ToObject(dstEEType, ushortValue) : ushortValue; break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U4: uint uintValue = Convert.ToUInt32(srcObject); dstObject = dstEEType.IsEnum ? Enum.ToObject(dstEEType, uintValue) : uintValue; break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U8: ulong ulongValue = Convert.ToUInt64(srcObject); dstObject = dstEEType.IsEnum ? Enum.ToObject(dstEEType, (long)ulongValue) : ulongValue; break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_R4: if (srcEEType.CorElementType == RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR) { dstObject = (float)(char)srcObject; } else { dstObject = Convert.ToSingle(srcObject); } break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_R8: if (srcEEType.CorElementType == RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR) { dstObject = (double)(char)srcObject; } else { dstObject = Convert.ToDouble(srcObject); } break; default: Debug.Fail("Unexpected CorElementType: " + dstCorElementType + ": Not a valid widening target."); dstObject = null; return(CreateChangeTypeException(srcEEType, dstEEType, semantics)); } Debug.Assert(dstObject.EETypePtr == dstEEType); return(null); }
internal static RhCorElementTypeInfo GetRhCorElementTypeInfo(RuntimeImports.RhCorElementType elementType) { return(RhCorElementTypeInfo.GetRhCorElementTypeInfo(elementType)); }
// Special coersion rules for primitives, enums and pointer. private static Exception ConvertOrWidenPrimitivesEnumsAndPointersIfPossible(object srcObject, EETypePtr srcEEType, EETypePtr dstEEType, CheckArgumentSemantics semantics, out object dstObject) { if (semantics == CheckArgumentSemantics.SetFieldDirect && (srcEEType.IsEnum || dstEEType.IsEnum)) { dstObject = null; return(CreateChangeTypeException(srcEEType, dstEEType, semantics)); } if (dstEEType.IsPointer) { Exception exception = ConvertPointerIfPossible(srcObject, srcEEType, dstEEType, semantics, out IntPtr dstIntPtr); if (exception != null) { dstObject = null; return(exception); } dstObject = dstIntPtr; return(null); } if (!(srcEEType.IsPrimitive && dstEEType.IsPrimitive)) { dstObject = null; return(CreateChangeTypeException(srcEEType, dstEEType, semantics)); } RuntimeImports.RhCorElementType dstCorElementType = dstEEType.CorElementType; if (!srcEEType.CorElementTypeInfo.CanWidenTo(dstCorElementType)) { dstObject = null; return(CreateChangeTypeArgumentException(srcEEType, dstEEType)); } switch (dstCorElementType) { case RuntimeImports.RhCorElementType.ELEMENT_TYPE_BOOLEAN: dstObject = Convert.ToBoolean(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR: dstObject = Convert.ToChar(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I1: dstObject = Convert.ToSByte(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I2: dstObject = Convert.ToInt16(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I4: dstObject = Convert.ToInt32(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I8: dstObject = Convert.ToInt64(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U1: dstObject = Convert.ToByte(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U2: dstObject = Convert.ToUInt16(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U4: dstObject = Convert.ToUInt32(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U8: dstObject = Convert.ToUInt64(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_R4: if (srcEEType.CorElementType == RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR) { dstObject = (float)(char)srcObject; } else { dstObject = Convert.ToSingle(srcObject); } break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_R8: if (srcEEType.CorElementType == RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR) { dstObject = (double)(char)srcObject; } else { dstObject = Convert.ToDouble(srcObject); } break; default: Debug.Assert(false, "Unexpected CorElementType: " + dstCorElementType + ": Not a valid widening target."); dstObject = null; return(CreateChangeTypeException(srcEEType, dstEEType, semantics)); } if (dstEEType.IsEnum) { Type dstType = ReflectionCoreNonPortable.GetRuntimeTypeForEEType(dstEEType); dstObject = Enum.ToObject(dstType, dstObject); } Debug.Assert(dstObject.EETypePtr == dstEEType); return(null); }
// // Note: This works on both Enum's and underlying integer values. // // // This returns the underlying enum values as "ulong" regardless of the actual underlying type. Signed integral // types get sign-extended into the 64-bit value, unsigned types get zero-extended. // // The return value is "bool" if "value" is not an enum or an "integer type" as defined by the BCL Enum apis. // private static bool TryGetUnboxedValueOfEnumOrInteger(Object value, out ulong result) { EETypePtr eeType = value.EETypePtr; // For now, this check is required to flush out pointers. RuntimeImports.RhEETypeClassification classification = RuntimeImports.RhGetEETypeClassification(eeType); if (classification != RuntimeImports.RhEETypeClassification.Regular) { result = 0; return(false); } RuntimeImports.RhCorElementType corElementType = eeType.CorElementType; unsafe { fixed(IntPtr *pEEType = &value.m_pEEType) { IntPtr pValue = Object.GetAddrOfPinnedObjectFromEETypeField(pEEType); switch (corElementType) { case RuntimeImports.RhCorElementType.ELEMENT_TYPE_BOOLEAN: result = (*(bool *)pValue) ? 1UL : 0UL; return(true); case RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR: result = (ulong)(long)(*(char *)pValue); return(true); case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I1: result = (ulong)(long)(*(sbyte *)pValue); return(true); case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U1: result = (ulong)(long)(*(byte *)pValue); return(true); case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I2: result = (ulong)(long)(*(short *)pValue); return(true); case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U2: result = (ulong)(long)(*(ushort *)pValue); return(true); case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I4: result = (ulong)(long)(*(int *)pValue); return(true); case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U4: result = (ulong)(long)(*(uint *)pValue); return(true); case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I8: result = (ulong)(long)(*(long *)pValue); return(true); case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U8: result = (ulong)(long)(*(ulong *)pValue); return(true); default: result = 0; return(false); } } } }
// // Helper for Enum.Format(,,"x") // private static String DoFormatX(ulong rawValue, RuntimeImports.RhCorElementType corElementType) { switch (corElementType) { case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I1: { Byte result = (byte)(sbyte)rawValue; return(result.ToString("X2", null)); } case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U1: { Byte result = (byte)rawValue; return(result.ToString("X2", null)); } case RuntimeImports.RhCorElementType.ELEMENT_TYPE_BOOLEAN: { // direct cast from bool to byte is not allowed Byte result = (byte)rawValue; return(result.ToString("X2", null)); } case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I2: { UInt16 result = (UInt16)(Int16)rawValue; return(result.ToString("X4", null)); } case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U2: { UInt16 result = (UInt16)rawValue; return(result.ToString("X4", null)); } case RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR: { UInt16 result = (UInt16)(Char)rawValue; return(result.ToString("X4", null)); } case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U4: { UInt32 result = (UInt32)rawValue; return(result.ToString("X8", null)); } case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I4: { UInt32 result = (UInt32)(int)rawValue; return(result.ToString("X8", null)); } case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U8: { UInt64 result = (UInt64)rawValue; return(result.ToString("X16", null)); } case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I8: { UInt64 result = (UInt64)(Int64)rawValue; return(result.ToString("X16", null)); } default: Contract.Assert(false, "Invalid Object type in Format"); throw new InvalidOperationException(SR.InvalidOperation_UnknownEnumType); } }
private static bool TryParseAsInteger(EETypePtr enumEEType, String value, out Object result) { result = null; if (value.Length == 0) { return(false); } if (!(Char.IsDigit(value[0]) || value[0] == '+' || value[0] == '-')) { return(false); } RuntimeImports.RhCorElementType corElementType = enumEEType.CorElementType; unsafe { switch (corElementType) { case RuntimeImports.RhCorElementType.ELEMENT_TYPE_BOOLEAN: { Boolean v; if (!Boolean.TryParse(value, out v)) { return(false); } result = RuntimeImports.RhBox(enumEEType, &v); return(true); } case RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR: { Char v; if (!Char.TryParse(value, out v)) { return(false); } result = RuntimeImports.RhBox(enumEEType, &v); return(true); } case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I1: { SByte v; if (!SByte.TryParse(value, out v)) { return(false); } result = RuntimeImports.RhBox(enumEEType, &v); return(true); } case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U1: { Byte v; if (!Byte.TryParse(value, out v)) { return(false); } result = RuntimeImports.RhBox(enumEEType, &v); return(true); } case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I2: { Int16 v; if (!Int16.TryParse(value, out v)) { return(false); } result = RuntimeImports.RhBox(enumEEType, &v); return(true); } case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U2: { UInt16 v; if (!UInt16.TryParse(value, out v)) { return(false); } result = RuntimeImports.RhBox(enumEEType, &v); return(true); } case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I4: { Int32 v; if (!Int32.TryParse(value, out v)) { return(false); } result = RuntimeImports.RhBox(enumEEType, &v); return(true); } case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U4: { UInt32 v; if (!UInt32.TryParse(value, out v)) { return(false); } result = RuntimeImports.RhBox(enumEEType, &v); return(true); } case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I8: { Int64 v; if (!Int64.TryParse(value, out v)) { return(false); } result = RuntimeImports.RhBox(enumEEType, &v); return(true); } case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U8: { UInt64 v; if (!UInt64.TryParse(value, out v)) { return(false); } result = RuntimeImports.RhBox(enumEEType, &v); return(true); } default: throw new NotSupportedException(); } } }
internal static Object CheckArgument(Object srcObject, EETypePtr dstEEType, CheckArgumentSemantics semantics) { if (srcObject == null) { // null -> default(T) if (dstEEType.IsValueType && !dstEEType.IsNullable) { return(Runtime.RuntimeImports.RhNewObject(dstEEType)); } else { return(null); } } else { EETypePtr srcEEType = srcObject.EETypePtr; if (RuntimeImports.AreTypesAssignable(srcEEType, dstEEType)) { return(srcObject); } if (dstEEType.IsInterface) { ICastable castable = srcObject as ICastable; Exception castError; if (castable != null && castable.IsInstanceOfInterface(new RuntimeTypeHandle(dstEEType), out castError)) { return(srcObject); } } if (!((srcEEType.IsEnum || srcEEType.IsPrimitive) && (dstEEType.IsEnum || dstEEType.IsPrimitive))) { throw CreateChangeTypeException(srcEEType, dstEEType, semantics); } RuntimeImports.RhCorElementType dstCorElementType = dstEEType.CorElementType; if (!srcEEType.CorElementTypeInfo.CanWidenTo(dstCorElementType)) { throw CreateChangeTypeArgumentException(srcEEType, dstEEType); } Object dstObject; switch (dstCorElementType) { case RuntimeImports.RhCorElementType.ELEMENT_TYPE_BOOLEAN: dstObject = Convert.ToBoolean(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR: dstObject = Convert.ToChar(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I1: dstObject = Convert.ToSByte(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I2: dstObject = Convert.ToInt16(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I4: dstObject = Convert.ToInt32(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I8: dstObject = Convert.ToInt64(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U1: dstObject = Convert.ToByte(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U2: dstObject = Convert.ToUInt16(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U4: dstObject = Convert.ToUInt32(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U8: dstObject = Convert.ToUInt64(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_R4: if (srcEEType.CorElementType == RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR) { dstObject = (float)(char)srcObject; } else { dstObject = Convert.ToSingle(srcObject); } break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_R8: if (srcEEType.CorElementType == RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR) { dstObject = (double)(char)srcObject; } else { dstObject = Convert.ToDouble(srcObject); } break; default: Debug.Assert(false, "Unexpected CorElementType: " + dstCorElementType + ": Not a valid widening target."); throw CreateChangeTypeException(srcEEType, dstEEType, semantics); } if (dstEEType.IsEnum) { Type dstType = ReflectionCoreNonPortable.GetRuntimeTypeForEEType(dstEEType); dstObject = Enum.ToObject(dstType, dstObject); } Debug.Assert(dstObject.EETypePtr == dstEEType); return(dstObject); } }