1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 04:22:20 +02:00

FieldInfo SetValue/GetValue with Variant support

This commit is contained in:
Brian Fiete 2020-09-05 06:02:13 -07:00
parent 8591172bb2
commit e37e1ac687
2 changed files with 221 additions and 29 deletions

View file

@ -106,7 +106,7 @@ namespace System.Reflection
return .Ok; return .Ok;
} }
public Result<void> SetValue(Object obj, Variant value) public Result<void, Error> SetValue(Object obj, Variant value)
{ {
void* dataAddr = ((uint8*)Internal.UnsafeCastToPtr(obj)); void* dataAddr = ((uint8*)Internal.UnsafeCastToPtr(obj));
if (mTypeInstance.IsStruct) if (mTypeInstance.IsStruct)
@ -124,7 +124,7 @@ namespace System.Reflection
} }
} }
if (!typeMatched) if (!typeMatched)
return .Err;//("Invalid target type"); return .Err(.InvalidTargetType);
} }
dataAddr = (void*)((int)dataAddr + mFieldData.mData); dataAddr = (void*)((int)dataAddr + mFieldData.mData);
@ -140,7 +140,94 @@ namespace System.Reflection
return .Ok; return .Ok;
} }
else else
return .Err;//("Invalid type"); return .Err(.InvalidValueType);
}
value.CopyValueData(dataAddr);
return .Ok;
}
public Result<void, Error> 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<void*>();
}
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<void, Error> 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<void*>();
}
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<void*>();
Internal.MemCpy(dataAddr, srcPtr, fieldType.Size);
return .Ok;
}
else
return .Err(.InvalidValueType);
} }
value.CopyValueData(dataAddr); value.CopyValueData(dataAddr);
@ -161,9 +248,6 @@ namespace System.Reflection
void* GetDataPtrAndType(Object value, out Type type) void* GetDataPtrAndType(Object value, out Type type)
{ {
type = value.[Friend]RawGetType(); type = value.[Friend]RawGetType();
/*if (type.IsStruct)
return &value;*/
if (type.IsBoxedStructPtr) if (type.IsBoxedStructPtr)
return *(void**)(((uint8*)Internal.UnsafeCastToPtr(value)) + type.[Friend]mMemberDataOffset); return *(void**)(((uint8*)Internal.UnsafeCastToPtr(value)) + type.[Friend]mMemberDataOffset);
if (type.IsBoxed) if (type.IsBoxed)
@ -171,7 +255,7 @@ namespace System.Reflection
return ((uint8*)Internal.UnsafeCastToPtr(value)); return ((uint8*)Internal.UnsafeCastToPtr(value));
} }
public Result<void> GetValue<TMember>(Object target, out TMember value) public Result<void, Error> GetValue<TMember>(Object target, out TMember value)
{ {
value = default(TMember); value = default(TMember);
@ -181,11 +265,11 @@ namespace System.Reflection
if (mFieldData.mFlags.HasFlag(FieldFlags.Const)) if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
{ {
// Unhandled // Unhandled
return .Err; return .Err(.InvalidTargetType);
} }
if (!mFieldData.mFlags.HasFlag(FieldFlags.Static)) if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
return .Err; return .Err(.InvalidTargetType);
targetDataAddr = null; targetDataAddr = null;
} }
@ -195,7 +279,7 @@ namespace System.Reflection
targetDataAddr = GetDataPtrAndType(target, out tTarget); targetDataAddr = GetDataPtrAndType(target, out tTarget);
if (!tTarget.IsSubtypeOf(mTypeInstance)) if (!tTarget.IsSubtypeOf(mTypeInstance))
return .Err; //"Invalid type"); return .Err(.InvalidTargetType); //"Invalid type");
} }
Type tMember = typeof(TMember); Type tMember = typeof(TMember);
@ -214,18 +298,18 @@ namespace System.Reflection
} }
else else
{ {
return .Err; return .Err(.InvalidValueType);
} }
return .Ok; return .Ok;
} }
public Result<Variant> GetValue(Object target) Result<Variant> GetValue(void* startTargetDataAddr, Type tTarget)
{ {
Variant value = Variant(); Variant value = Variant();
void* targetDataAddr; void* targetDataAddr = startTargetDataAddr;
if (target == null) if (targetDataAddr == null)
{ {
if (mFieldData.mFlags.HasFlag(FieldFlags.Const)) if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
{ {
@ -234,14 +318,9 @@ namespace System.Reflection
if (!mFieldData.mFlags.HasFlag(FieldFlags.Static)) if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
return .Err; return .Err;
targetDataAddr = null;
} }
else else
{ {
Type tTarget;
targetDataAddr = GetDataPtrAndType(target, out tTarget);
if (!tTarget.IsSubtypeOf(mTypeInstance)) if (!tTarget.IsSubtypeOf(mTypeInstance))
return .Err; //Invalid type; return .Err; //Invalid type;
} }
@ -267,12 +346,12 @@ namespace System.Reflection
return value; return value;
} }
public Result<Variant> GetValueReference(Object target) public Result<Variant> GetValueReference(void* startTargetDataAddr, Type tTarget)
{ {
Variant value = Variant(); Variant value = Variant();
void* targetDataAddr; void* targetDataAddr = startTargetDataAddr;
if (target == null) if (targetDataAddr == null)
{ {
if (mFieldData.mFlags.HasFlag(FieldFlags.Const)) if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
{ {
@ -286,9 +365,6 @@ namespace System.Reflection
} }
else else
{ {
Type tTarget;
targetDataAddr = GetDataPtrAndType(target, out tTarget);
if (!tTarget.IsSubtypeOf(mTypeInstance)) if (!tTarget.IsSubtypeOf(mTypeInstance))
return .Err; //Invalid type; return .Err; //Invalid type;
} }
@ -306,6 +382,94 @@ namespace System.Reflection
return value; return value;
} }
public Result<Variant> 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<Variant> 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<Variant> 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<Variant> 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<FieldInfo> public struct Enumerator : IEnumerator<FieldInfo>
{ {
BindingFlags mBindingFlags; BindingFlags mBindingFlags;

View file

@ -494,6 +494,9 @@ namespace Tests
sb.mB = "Struct B"; sb.mB = "Struct B";
sb.mC = .() { mA = 1.2f, mB = 2.3f }; sb.mC = .() { mA = 1.2f, mB = 2.3f };
Variant sbVariant = .Create(sb);
defer sbVariant.Dispose();
let type = sb.GetType() as TypeInstance; let type = sb.GetType() as TypeInstance;
let fields = type.GetFields(); let fields = type.GetFields();
int fieldIdx = 0; int fieldIdx = 0;
@ -501,8 +504,13 @@ namespace Tests
{ {
var fieldVal = field.GetValue(sb).Value; var fieldVal = field.GetValue(sb).Value;
defer fieldVal.Dispose(); defer fieldVal.Dispose();
var fieldVal2 = field.GetValue(&sb).Value; var fieldVal2 = field.GetValue(&sb).Value;
defer fieldVal2.Dispose(); defer fieldVal2.Dispose();
var fieldVal3 = field.GetValue(sbVariant).Value;
defer fieldVal3.Dispose();
switch (fieldIdx) switch (fieldIdx)
{ {
case 0: case 0:
@ -514,6 +522,26 @@ namespace Tests
Test.Assert(fieldVal2.Get<int>() == 25); Test.Assert(fieldVal2.Get<int>() == 25);
field.SetValue(&sb, newVal); field.SetValue(&sb, newVal);
Test.Assert(sb.mA == 32); Test.Assert(sb.mA == 32);
Test.Assert(fieldVal3.Get<int>() == 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<int>() == 34);
Variant varInt = .Create(45);
field.SetValue(sbVariant, varInt);
fieldVal3.Dispose();
fieldVal3 = field.GetValue(sbVariant).Value;
Test.Assert(fieldVal3.Get<int>() == 45);
field.SetValue(&sb, varInt);
fieldVal2.Dispose();
fieldVal2 = field.GetValue(&sb).Value;
Test.Assert(fieldVal2.Get<int>() == 45);
case 1: case 1:
Test.Assert(fieldVal.Get<String>() === "Struct B"); Test.Assert(fieldVal.Get<String>() === "Struct B");
field.SetValue(&sb, "Struct C"); field.SetValue(&sb, "Struct C");