From e37e1ac687a5b5e46610df51458ac15ba19820e2 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Sat, 5 Sep 2020 06:02:13 -0700 Subject: [PATCH] FieldInfo SetValue/GetValue with Variant support --- BeefLibs/corlib/src/Reflection/FieldInfo.bf | 222 +++++++++++++++++--- IDEHelper/Tests/src/Reflection.bf | 28 +++ 2 files changed, 221 insertions(+), 29 deletions(-) diff --git a/BeefLibs/corlib/src/Reflection/FieldInfo.bf b/BeefLibs/corlib/src/Reflection/FieldInfo.bf index 4da02322..31adddd2 100644 --- a/BeefLibs/corlib/src/Reflection/FieldInfo.bf +++ b/BeefLibs/corlib/src/Reflection/FieldInfo.bf @@ -106,7 +106,7 @@ namespace System.Reflection return .Ok; } - public Result SetValue(Object obj, Variant value) + public Result SetValue(Object obj, Variant value) { void* dataAddr = ((uint8*)Internal.UnsafeCastToPtr(obj)); if (mTypeInstance.IsStruct) @@ -124,7 +124,7 @@ namespace System.Reflection } } if (!typeMatched) - return .Err;//("Invalid target type"); + return .Err(.InvalidTargetType); } dataAddr = (void*)((int)dataAddr + mFieldData.mData); @@ -140,7 +140,94 @@ namespace System.Reflection return .Ok; } else - return .Err;//("Invalid type"); + return .Err(.InvalidValueType); + } + + value.CopyValueData(dataAddr); + + return .Ok; + } + + public Result SetValue(Variant target, Object value) + { + var target; + var targetType = target.VariantType; + void* dataAddr = target.DataPtr; + if (targetType != mTypeInstance) + { + if ((!targetType.IsPointer) || (targetType.UnderlyingType.IsSubtypeOf(mTypeInstance))) + return .Err(.InvalidTargetType); // Invalid target type + dataAddr = target.Get(); + } + dataAddr = (void*)((int)dataAddr + mFieldData.mData); + + Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId); + + if (value == null) + { + if ((fieldType.IsValueType) && (!fieldType.IsPointer)) + { + return .Err(.InvalidValueType); + } + else + { + *((int*)dataAddr) = 0; + return .Ok; + } + } + + Type rawValueType = value.[Friend]RawGetType(); + void* valueDataAddr = ((uint8*)Internal.UnsafeCastToPtr(value)) + rawValueType.[Friend]mMemberDataOffset; + if (rawValueType.IsBoxedStructPtr) + valueDataAddr = *(void**)valueDataAddr; + + Type valueType = value.GetType(); + + if ((valueType != fieldType) && (valueType.IsTypedPrimitive)) + valueType = valueType.UnderlyingType; + + if (valueType == fieldType) + { + if (valueType.IsObject) + *((void**)dataAddr) = Internal.UnsafeCastToPtr(value); + else + Internal.MemCpy(dataAddr, valueDataAddr, fieldType.[Friend]mSize); + } + else + { + return .Err(.InvalidValueType); + } + + return .Ok; + } + + public Result SetValue(Variant target, Variant value) + { + var target; + var targetType = target.VariantType; + void* dataAddr = target.DataPtr; + if (targetType != mTypeInstance) + { + if ((!targetType.IsPointer) || (targetType.UnderlyingType.IsSubtypeOf(mTypeInstance))) + return .Err(.InvalidTargetType); + dataAddr = target.Get(); + } + + dataAddr = (void*)((int)dataAddr + mFieldData.mData); + + Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId); + + let variantType = value.VariantType; + if (variantType != fieldType) + { + if ((variantType.IsPointer) && (variantType.UnderlyingType == fieldType)) + { + void* srcPtr = value.Get(); + Internal.MemCpy(dataAddr, srcPtr, fieldType.Size); + return .Ok; + } + else + return .Err(.InvalidValueType); } value.CopyValueData(dataAddr); @@ -161,9 +248,6 @@ namespace System.Reflection void* GetDataPtrAndType(Object value, out Type type) { type = value.[Friend]RawGetType(); - /*if (type.IsStruct) - return &value;*/ - if (type.IsBoxedStructPtr) return *(void**)(((uint8*)Internal.UnsafeCastToPtr(value)) + type.[Friend]mMemberDataOffset); if (type.IsBoxed) @@ -171,7 +255,7 @@ namespace System.Reflection return ((uint8*)Internal.UnsafeCastToPtr(value)); } - public Result GetValue(Object target, out TMember value) + public Result GetValue(Object target, out TMember value) { value = default(TMember); @@ -181,11 +265,11 @@ namespace System.Reflection if (mFieldData.mFlags.HasFlag(FieldFlags.Const)) { // Unhandled - return .Err; + return .Err(.InvalidTargetType); } if (!mFieldData.mFlags.HasFlag(FieldFlags.Static)) - return .Err; + return .Err(.InvalidTargetType); targetDataAddr = null; } @@ -195,7 +279,7 @@ namespace System.Reflection targetDataAddr = GetDataPtrAndType(target, out tTarget); if (!tTarget.IsSubtypeOf(mTypeInstance)) - return .Err; //"Invalid type"); + return .Err(.InvalidTargetType); //"Invalid type"); } Type tMember = typeof(TMember); @@ -214,18 +298,18 @@ namespace System.Reflection } else { - return .Err; + return .Err(.InvalidValueType); } return .Ok; } - public Result GetValue(Object target) + Result GetValue(void* startTargetDataAddr, Type tTarget) { Variant value = Variant(); - void* targetDataAddr; - if (target == null) + void* targetDataAddr = startTargetDataAddr; + if (targetDataAddr == null) { if (mFieldData.mFlags.HasFlag(FieldFlags.Const)) { @@ -234,14 +318,9 @@ namespace System.Reflection if (!mFieldData.mFlags.HasFlag(FieldFlags.Static)) return .Err; - - targetDataAddr = null; } else { - Type tTarget; - targetDataAddr = GetDataPtrAndType(target, out tTarget); - if (!tTarget.IsSubtypeOf(mTypeInstance)) return .Err; //Invalid type; } @@ -254,11 +333,11 @@ namespace System.Reflection if (typeCode == TypeCode.Enum) typeCode = fieldType.UnderlyingType.[Friend]mTypeCode; - if (typeCode == TypeCode.Object) - { + if (typeCode == TypeCode.Object) + { value.[Friend]mStructType = 0; - value.[Friend]mData = *(int*)targetDataAddr; - } + value.[Friend]mData = *(int*)targetDataAddr; + } else { value = Variant.Create(fieldType, targetDataAddr); @@ -267,12 +346,12 @@ namespace System.Reflection return value; } - public Result GetValueReference(Object target) + public Result GetValueReference(void* startTargetDataAddr, Type tTarget) { Variant value = Variant(); - void* targetDataAddr; - if (target == null) + void* targetDataAddr = startTargetDataAddr; + if (targetDataAddr == null) { if (mFieldData.mFlags.HasFlag(FieldFlags.Const)) { @@ -286,9 +365,6 @@ namespace System.Reflection } else { - Type tTarget; - targetDataAddr = GetDataPtrAndType(target, out tTarget); - if (!tTarget.IsSubtypeOf(mTypeInstance)) return .Err; //Invalid type; } @@ -306,6 +382,94 @@ namespace System.Reflection return value; } + public Result GetValue(Object target) + { + void* targetDataAddr; + if (target == null) + { + if (mFieldData.mFlags.HasFlag(FieldFlags.Const)) + { + return Variant.Create(FieldType, &mFieldData.mData); + } + + if (!mFieldData.mFlags.HasFlag(FieldFlags.Static)) + return .Err; + + return GetValue(null, null); + } + else + { + Type tTarget; + targetDataAddr = GetDataPtrAndType(target, out tTarget); + return GetValue(targetDataAddr, tTarget); + } + } + + public Result GetValue(Variant target) + { + if (!target.HasValue) + { + if (mFieldData.mFlags.HasFlag(FieldFlags.Const)) + { + return Variant.Create(FieldType, &mFieldData.mData); + } + + if (!mFieldData.mFlags.HasFlag(FieldFlags.Static)) + return .Err; + + return GetValue(null, null); + } + else + { + var target; + return GetValue(target.DataPtr, target.VariantType); + } + } + + public Result GetValueReference(Object target) + { + void* targetDataAddr; + if (target == null) + { + if (mFieldData.mFlags.HasFlag(FieldFlags.Const)) + { + return Variant.Create(FieldType, &mFieldData.mData); + } + + if (!mFieldData.mFlags.HasFlag(FieldFlags.Static)) + return .Err; + + return GetValueReference(null, null); + } + else + { + Type tTarget; + targetDataAddr = GetDataPtrAndType(target, out tTarget); + return GetValueReference(targetDataAddr, tTarget); + } + } + + public Result GetValueReference(Variant target) + { + if (!target.HasValue) + { + if (mFieldData.mFlags.HasFlag(FieldFlags.Const)) + { + return Variant.Create(FieldType, &mFieldData.mData); + } + + if (!mFieldData.mFlags.HasFlag(FieldFlags.Static)) + return .Err; + + return GetValueReference(null, null); + } + else + { + var target; + return GetValueReference(target.DataPtr, target.VariantType); + } + } + public struct Enumerator : IEnumerator { BindingFlags mBindingFlags; diff --git a/IDEHelper/Tests/src/Reflection.bf b/IDEHelper/Tests/src/Reflection.bf index ffb6d906..fc1e4336 100644 --- a/IDEHelper/Tests/src/Reflection.bf +++ b/IDEHelper/Tests/src/Reflection.bf @@ -494,6 +494,9 @@ namespace Tests sb.mB = "Struct B"; sb.mC = .() { mA = 1.2f, mB = 2.3f }; + Variant sbVariant = .Create(sb); + defer sbVariant.Dispose(); + let type = sb.GetType() as TypeInstance; let fields = type.GetFields(); int fieldIdx = 0; @@ -501,8 +504,13 @@ namespace Tests { var fieldVal = field.GetValue(sb).Value; defer fieldVal.Dispose(); + var fieldVal2 = field.GetValue(&sb).Value; defer fieldVal2.Dispose(); + + var fieldVal3 = field.GetValue(sbVariant).Value; + defer fieldVal3.Dispose(); + switch (fieldIdx) { case 0: @@ -514,6 +522,26 @@ namespace Tests Test.Assert(fieldVal2.Get() == 25); field.SetValue(&sb, newVal); Test.Assert(sb.mA == 32); + + Test.Assert(fieldVal3.Get() == 25); + field.SetValue(&sb, newVal); + Test.Assert(sb.mA == 32); + + field.SetValue(sbVariant, 34); + fieldVal3.Dispose(); + fieldVal3 = field.GetValue(sbVariant).Value; + Test.Assert(fieldVal3.Get() == 34); + + Variant varInt = .Create(45); + field.SetValue(sbVariant, varInt); + fieldVal3.Dispose(); + fieldVal3 = field.GetValue(sbVariant).Value; + Test.Assert(fieldVal3.Get() == 45); + + field.SetValue(&sb, varInt); + fieldVal2.Dispose(); + fieldVal2 = field.GetValue(&sb).Value; + Test.Assert(fieldVal2.Get() == 45); case 1: Test.Assert(fieldVal.Get() === "Struct B"); field.SetValue(&sb, "Struct C");