efl-mono: Add object type support for Eina.Value
Summary: C# `Eina.Value` now has builtin support for `EINA_VALUE_TYPE_OBJECT`. To avoid ambiguity with the `Set` method overloads, explicit casting operators were used for wrapping/unwrapping `Efl.Object` instead of implicit ones like for other value types. Thus, to initialize an `Eina.Value` from an object, you can use the following: `var v = (Eina.Value)myObj;` Reviewers: felipealmeida, vitor.sousa, segfaultxavi, Jaehyun_Cho Reviewed By: Jaehyun_Cho Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D9164
This commit is contained in:
parent
0a0f3d5bfe
commit
907bdad065
|
@ -182,6 +182,10 @@ static internal class UnsafeNativeMethods
|
||||||
[return: MarshalAsAttribute(UnmanagedType.U1)]
|
[return: MarshalAsAttribute(UnmanagedType.U1)]
|
||||||
internal static extern bool eina_value_container_append_wrapper_string(IntPtr handle, string data);
|
internal static extern bool eina_value_container_append_wrapper_string(IntPtr handle, string data);
|
||||||
|
|
||||||
|
[DllImport(efl.Libs.CustomExports)]
|
||||||
|
[return: MarshalAsAttribute(UnmanagedType.U1)]
|
||||||
|
internal static extern bool eina_value_container_append_wrapper_ptr(IntPtr handle, IntPtr data);
|
||||||
|
|
||||||
[DllImport(efl.Libs.CustomExports)]
|
[DllImport(efl.Libs.CustomExports)]
|
||||||
[return: MarshalAsAttribute(UnmanagedType.U1)]
|
[return: MarshalAsAttribute(UnmanagedType.U1)]
|
||||||
internal static extern bool eina_value_container_append_wrapper_char(IntPtr handle, sbyte data);
|
internal static extern bool eina_value_container_append_wrapper_char(IntPtr handle, sbyte data);
|
||||||
|
@ -278,6 +282,10 @@ static internal class UnsafeNativeMethods
|
||||||
[return: MarshalAsAttribute(UnmanagedType.U1)]
|
[return: MarshalAsAttribute(UnmanagedType.U1)]
|
||||||
internal static extern bool eina_value_container_set_wrapper_string(IntPtr handle, int index, string value);
|
internal static extern bool eina_value_container_set_wrapper_string(IntPtr handle, int index, string value);
|
||||||
|
|
||||||
|
[DllImport(efl.Libs.CustomExports)]
|
||||||
|
[return: MarshalAsAttribute(UnmanagedType.U1)]
|
||||||
|
internal static extern bool eina_value_container_set_wrapper_ptr(IntPtr handle, int index, IntPtr value);
|
||||||
|
|
||||||
[DllImport(efl.Libs.CustomExports)]
|
[DllImport(efl.Libs.CustomExports)]
|
||||||
[return: MarshalAsAttribute(UnmanagedType.U1)]
|
[return: MarshalAsAttribute(UnmanagedType.U1)]
|
||||||
internal static extern bool eina_value_container_set_wrapper_uchar(IntPtr handle, int index, byte value);
|
internal static extern bool eina_value_container_set_wrapper_uchar(IntPtr handle, int index, byte value);
|
||||||
|
@ -378,6 +386,10 @@ static internal class UnsafeNativeMethods
|
||||||
[return: MarshalAsAttribute(UnmanagedType.U1)]
|
[return: MarshalAsAttribute(UnmanagedType.U1)]
|
||||||
internal static extern bool eina_value_optional_pset(IntPtr handle, IntPtr subtype, ref string value);
|
internal static extern bool eina_value_optional_pset(IntPtr handle, IntPtr subtype, ref string value);
|
||||||
|
|
||||||
|
[DllImport(efl.Libs.Eina)]
|
||||||
|
[return: MarshalAsAttribute(UnmanagedType.U1)]
|
||||||
|
internal static extern bool eina_value_optional_pset(IntPtr handle, IntPtr subtype, ref IntPtr value);
|
||||||
|
|
||||||
[DllImport(efl.Libs.Eina)]
|
[DllImport(efl.Libs.Eina)]
|
||||||
[return: MarshalAsAttribute(UnmanagedType.U1)]
|
[return: MarshalAsAttribute(UnmanagedType.U1)]
|
||||||
internal static extern bool eina_value_optional_pset(IntPtr handle, IntPtr subtype, IntPtr value);
|
internal static extern bool eina_value_optional_pset(IntPtr handle, IntPtr subtype, IntPtr value);
|
||||||
|
@ -507,6 +519,10 @@ static internal class UnsafeNativeMethods
|
||||||
// Error
|
// Error
|
||||||
[DllImport(efl.Libs.CustomExports)]
|
[DllImport(efl.Libs.CustomExports)]
|
||||||
internal static extern IntPtr type_error();
|
internal static extern IntPtr type_error();
|
||||||
|
|
||||||
|
// Error
|
||||||
|
[DllImport(efl.Libs.CustomExports)]
|
||||||
|
internal static extern IntPtr type_object();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,6 +629,7 @@ public enum ValueType
|
||||||
Optional,
|
Optional,
|
||||||
/// <summary>Error values.</summary>
|
/// <summary>Error values.</summary>
|
||||||
Error,
|
Error,
|
||||||
|
Object,
|
||||||
/// <summary>Empty values.</summary>
|
/// <summary>Empty values.</summary>
|
||||||
Empty,
|
Empty,
|
||||||
}
|
}
|
||||||
|
@ -675,6 +692,11 @@ static class ValueTypeMethods
|
||||||
return val == ValueType.Error;
|
return val == ValueType.Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool IsObject(this ValueType val)
|
||||||
|
{
|
||||||
|
return val == ValueType.Object;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Returns the Marshal.SizeOf for the given ValueType native structure.</summary>
|
/// <summary>Returns the Marshal.SizeOf for the given ValueType native structure.</summary>
|
||||||
public static int MarshalSizeOf(this ValueType val)
|
public static int MarshalSizeOf(this ValueType val)
|
||||||
{
|
{
|
||||||
|
@ -771,6 +793,9 @@ static class ValueTypeBridge
|
||||||
ManagedToNative.Add(ValueType.Error, type_error());
|
ManagedToNative.Add(ValueType.Error, type_error());
|
||||||
NativeToManaged.Add(type_error(), ValueType.Error);
|
NativeToManaged.Add(type_error(), ValueType.Error);
|
||||||
|
|
||||||
|
ManagedToNative.Add(ValueType.Object, type_object());
|
||||||
|
NativeToManaged.Add(type_object(), ValueType.Object);
|
||||||
|
|
||||||
ManagedToNative.Add(ValueType.Empty, IntPtr.Zero);
|
ManagedToNative.Add(ValueType.Empty, IntPtr.Zero);
|
||||||
NativeToManaged.Add(IntPtr.Zero, ValueType.Empty);
|
NativeToManaged.Add(IntPtr.Zero, ValueType.Empty);
|
||||||
|
|
||||||
|
@ -1354,6 +1379,32 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Efl.Object conversions are made explicit to avoid ambiguity between
|
||||||
|
// Set(Efl.Object) and Set(Value) when dealing with classes derived from
|
||||||
|
// Efl.Object.
|
||||||
|
/// <summary>Explicit conversion from EFL objects.</summary>
|
||||||
|
public static explicit operator Value(Efl.Object obj)
|
||||||
|
{
|
||||||
|
var v = new Eina.Value(ValueType.Object);
|
||||||
|
if (!v.Set(obj))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Couldn't set value.");
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Explicit conversion from Value to Efl.Objects.</summary>
|
||||||
|
public static explicit operator Efl.Object(Value v)
|
||||||
|
{
|
||||||
|
Efl.Object obj;
|
||||||
|
if (!v.Get(out obj))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Couldn't get value.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Creates an Value instance from a given array description.</summary>
|
/// <summary>Creates an Value instance from a given array description.</summary>
|
||||||
private static Value FromArrayDesc(Eina.EinaNative.Value_Array arrayDesc)
|
private static Value FromArrayDesc(Eina.EinaNative.Value_Array arrayDesc)
|
||||||
{
|
{
|
||||||
|
@ -1789,6 +1840,22 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
|
||||||
return eina_value_set_wrapper_int(this.Handle, error_code);
|
return eina_value_set_wrapper_int(this.Handle, error_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Stores the given object.</summary>
|
||||||
|
public bool Set(Efl.Object value)
|
||||||
|
{
|
||||||
|
// FIXME Implement me
|
||||||
|
SanityChecks();
|
||||||
|
|
||||||
|
if (this.Optional)
|
||||||
|
{
|
||||||
|
IntPtr ptr = value.NativeHandle;
|
||||||
|
return eina_value_optional_pset(this.Handle,
|
||||||
|
ValueTypeBridge.GetNative(ValueType.Object),
|
||||||
|
ref ptr);
|
||||||
|
}
|
||||||
|
return eina_value_set_wrapper_ptr(this.Handle, value.NativeHandle);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Stores the given value into this value. The target value must be an optional.</summary>
|
/// <summary>Stores the given value into this value. The target value must be an optional.</summary>
|
||||||
public bool Set(Value value)
|
public bool Set(Value value)
|
||||||
{
|
{
|
||||||
|
@ -2017,6 +2084,36 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Gets the currently stored value as an <see cref="Efl.Object"/>.</summary>
|
||||||
|
public bool Get(out Efl.Object obj)
|
||||||
|
{
|
||||||
|
// FIXME Implement me
|
||||||
|
SanityChecks();
|
||||||
|
IntPtr ptr;
|
||||||
|
bool ret;
|
||||||
|
|
||||||
|
if (this.Optional)
|
||||||
|
{
|
||||||
|
ret = eina_value_optional_pget(this.Handle, out ptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = eina_value_get_wrapper(this.Handle, out ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
obj = (Efl.Object) Efl.Eo.Globals.CreateWrapperFor(ptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
obj = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>Gets the currently stored value as an complex (e.g. container) Eina.Value.</summary>
|
/// <summary>Gets the currently stored value as an complex (e.g. container) Eina.Value.</summary>
|
||||||
public bool Get(out Value value)
|
public bool Get(out Value value)
|
||||||
{
|
{
|
||||||
|
@ -2281,6 +2378,11 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
|
||||||
string x = Convert.ToString(o);
|
string x = Convert.ToString(o);
|
||||||
return eina_value_container_append_wrapper_string(this.Handle, x);
|
return eina_value_container_append_wrapper_string(this.Handle, x);
|
||||||
}
|
}
|
||||||
|
case ValueType.Object:
|
||||||
|
{
|
||||||
|
var x = (Efl.Object) o;
|
||||||
|
return eina_value_container_append_wrapper_ptr(this.Handle, x.NativeHandle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -2374,6 +2476,12 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
|
||||||
eina_value_container_get_wrapper(this.Handle, i, out ptr);
|
eina_value_container_get_wrapper(this.Handle, i, out ptr);
|
||||||
return Eina.StringConversion.NativeUtf8ToManagedString(ptr);
|
return Eina.StringConversion.NativeUtf8ToManagedString(ptr);
|
||||||
}
|
}
|
||||||
|
case ValueType.Object:
|
||||||
|
{
|
||||||
|
IntPtr ptr = IntPtr.Zero;
|
||||||
|
eina_value_container_get_wrapper(this.Handle, i, out ptr);
|
||||||
|
return Efl.Eo.Globals.CreateWrapperFor(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new InvalidOperationException("Subtype not supported.");
|
throw new InvalidOperationException("Subtype not supported.");
|
||||||
|
@ -2463,6 +2571,12 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
|
||||||
eina_value_container_set_wrapper_string(this.Handle, i, x);
|
eina_value_container_set_wrapper_string(this.Handle, i, x);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ValueType.Object:
|
||||||
|
{
|
||||||
|
Efl.Object x = (Efl.Object)value;
|
||||||
|
eina_value_container_set_wrapper_ptr(this.Handle, i, x.NativeHandle);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -403,6 +403,9 @@ EAPI const Eina_Value_Type *type_list() {
|
||||||
EAPI const Eina_Value_Type *type_error() {
|
EAPI const Eina_Value_Type *type_error() {
|
||||||
return EINA_VALUE_TYPE_ERROR;
|
return EINA_VALUE_TYPE_ERROR;
|
||||||
}
|
}
|
||||||
|
EAPI const Eina_Value_Type *type_object() {
|
||||||
|
return EINA_VALUE_TYPE_OBJECT;
|
||||||
|
}
|
||||||
|
|
||||||
EAPI const Eina_Value_Type *type_optional() {
|
EAPI const Eina_Value_Type *type_optional() {
|
||||||
return EINA_VALUE_TYPE_OPTIONAL;
|
return EINA_VALUE_TYPE_OPTIONAL;
|
||||||
|
|
|
@ -146,6 +146,31 @@ public static class TestEinaValue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void TestObjectSimple()
|
||||||
|
{
|
||||||
|
using (Eina.Value v = new Eina.Value(Eina.ValueType.Object))
|
||||||
|
{
|
||||||
|
var obj = new Dummy.TestObject();
|
||||||
|
Test.Assert(v.Set(obj));
|
||||||
|
Efl.Object target;
|
||||||
|
Test.Assert(v.Get(out target));
|
||||||
|
Test.AssertEquals(target, obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Efl.Object conversions are made explicit to avoid ambiguity between
|
||||||
|
// Set(Efl.Object) and Set(Value) when dealing with classes derived from
|
||||||
|
// Efl.Object.
|
||||||
|
public static void TestObjectImplicit()
|
||||||
|
{
|
||||||
|
var obj = new Dummy.TestObject();
|
||||||
|
var v = (Eina.Value)obj;
|
||||||
|
Test.AssertEquals(v.GetValueType(), Eina.ValueType.Object);
|
||||||
|
Efl.Object target = (Efl.Object)v;
|
||||||
|
|
||||||
|
Test.AssertEquals(target, obj);
|
||||||
|
}
|
||||||
|
|
||||||
public static void TestSetWrongType()
|
public static void TestSetWrongType()
|
||||||
{
|
{
|
||||||
using (Eina.Value v = new Eina.Value(Eina.ValueType.String)) {
|
using (Eina.Value v = new Eina.Value(Eina.ValueType.String)) {
|
||||||
|
@ -259,6 +284,37 @@ public static class TestEinaValue {
|
||||||
Test.AssertEquals(expected, actual);
|
Test.AssertEquals(expected, actual);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void TestValueOptionalObject()
|
||||||
|
{
|
||||||
|
using (Eina.Value a = new Eina.Value(Eina.ValueType.Object)) {
|
||||||
|
Test.Assert(!a.Optional);
|
||||||
|
BoolRet dummy = () => a.OptionalEmpty;
|
||||||
|
Test.AssertRaises<Eina.InvalidValueTypeException>(() => dummy());
|
||||||
|
}
|
||||||
|
|
||||||
|
using (Eina.Value a = new Eina.Value(Eina.ValueType.Optional)) {
|
||||||
|
Test.Assert(a.Optional);
|
||||||
|
Test.Assert(a.OptionalEmpty); // By default, optional values are empty
|
||||||
|
|
||||||
|
// Sets expectation
|
||||||
|
Efl.Object expected = new Dummy.TestObject();
|
||||||
|
Test.Assert(a.Set(expected));
|
||||||
|
Test.Assert(a.Optional);
|
||||||
|
Test.Assert(!a.OptionalEmpty);
|
||||||
|
|
||||||
|
Test.Assert(a.Reset());
|
||||||
|
Test.Assert(a.OptionalEmpty);
|
||||||
|
|
||||||
|
Test.Assert(a.Set(expected));
|
||||||
|
Test.Assert(!a.OptionalEmpty);
|
||||||
|
|
||||||
|
Efl.Object received = null;
|
||||||
|
Test.Assert(a.Get(out received));
|
||||||
|
Test.AssertEquals(expected, received);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void TestValueOptionalArrays()
|
public static void TestValueOptionalArrays()
|
||||||
{
|
{
|
||||||
using (Eina.Value a = new Eina.Value(Eina.ValueType.Optional))
|
using (Eina.Value a = new Eina.Value(Eina.ValueType.Optional))
|
||||||
|
@ -763,6 +819,30 @@ public static class TestEinaValue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void TestValueArrayOfObjects()
|
||||||
|
{
|
||||||
|
|
||||||
|
using(Eina.Value array = new Eina.Value(Eina.ValueType.Array, Eina.ValueType.Object)) {
|
||||||
|
|
||||||
|
var a = new Dummy.TestObject();
|
||||||
|
var b = new Dummy.TestObject();
|
||||||
|
|
||||||
|
Test.Assert(array.Append(a));
|
||||||
|
Test.Assert(array.Append(b));
|
||||||
|
|
||||||
|
Test.AssertEquals((Efl.Object)array[0], a);
|
||||||
|
Test.AssertEquals((Efl.Object)array[1], b);
|
||||||
|
|
||||||
|
var c = new Dummy.TestObject();
|
||||||
|
array[0] = c;
|
||||||
|
array[1] = b;
|
||||||
|
|
||||||
|
Test.AssertEquals((Efl.Object)array[0], c);
|
||||||
|
Test.AssertEquals((Efl.Object)array[1], b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void TestArrayOutOfBounds() {
|
public static void TestArrayOutOfBounds() {
|
||||||
using(Eina.Value array = new Eina.Value(Eina.ValueType.Array, Eina.ValueType.Int32)) {
|
using(Eina.Value array = new Eina.Value(Eina.ValueType.Array, Eina.ValueType.Int32)) {
|
||||||
object placeholder = null;
|
object placeholder = null;
|
||||||
|
|
Loading…
Reference in New Issue