diff options
Diffstat (limited to 'src/bindings/mono/eina_mono/eina_value.cs')
-rw-r--r-- | src/bindings/mono/eina_mono/eina_value.cs | 153 |
1 files changed, 124 insertions, 29 deletions
diff --git a/src/bindings/mono/eina_mono/eina_value.cs b/src/bindings/mono/eina_mono/eina_value.cs index d4e8dfbf94..578c660b91 100644 --- a/src/bindings/mono/eina_mono/eina_value.cs +++ b/src/bindings/mono/eina_mono/eina_value.cs @@ -325,6 +325,10 @@ static internal class UnsafeNativeMethods { [return: MarshalAsAttribute(UnmanagedType.U1)] internal static extern bool eina_value_pset_wrapper(IntPtr handle, ref eina.EinaNative.Value_List ptr); + [DllImport(efl.Libs.Eina)] + [return: MarshalAsAttribute(UnmanagedType.U1)] + internal static extern bool eina_value_copy(IntPtr src, IntPtr dest); + // Supported types // 8 bits byte @@ -375,6 +379,10 @@ static internal class UnsafeNativeMethods { // Optional [DllImport(efl.Libs.CustomExports)] internal static extern IntPtr type_optional(); + + // Error + [DllImport(efl.Libs.CustomExports)] + internal static extern IntPtr type_error(); } } @@ -382,8 +390,8 @@ static internal class UnsafeNativeMethods { [StructLayout(LayoutKind.Sequential)] public struct Value_Native { - IntPtr type; - IntPtr value; // Atually an Eina_Value_Union, but it is padded to 8 bytes. + public IntPtr Type; + public IntPtr Value; // Atually an Eina_Value_Union, but it is padded to 8 bytes. } @@ -429,13 +437,6 @@ public class InvalidValueTypeException: Exception protected InvalidValueTypeException(SerializationInfo info, StreamingContext context) : base(info, context) { } } -/// <summary>Internal enum to handle value ownership between managed and unmanaged code.</summary> -public enum ValueOwnership { - /// <summary> The value is owned by the managed code. It'll free the handle on disposal.</summary> - Managed, - /// <summary> The value is owned by the unmanaged code. It won't be freed on disposal.</summary> - Unmanaged -} /// <summary>Managed-side Enum to represent Eina_Value_Type constants</summary> public enum ValueType { @@ -473,6 +474,10 @@ public enum ValueType { Hash, /// <summary>Optional (aka empty) values.</summary> Optional, + /// <summary>Error values.</summary> + Error, + /// <summary>Empty values.</summary> + Empty, } static class ValueTypeMethods { @@ -524,6 +529,11 @@ static class ValueTypeMethods { return val == ValueType.Optional; } + public static bool IsError(this ValueType val) + { + return val == ValueType.Error; + } + /// <summary>Returns the Marshal.SizeOf for the given ValueType native structure.</summary> public static int MarshalSizeOf(this ValueType val) { @@ -611,6 +621,12 @@ static class ValueTypeBridge ManagedToNative.Add(ValueType.Optional, type_optional()); NativeToManaged.Add(type_optional(), ValueType.Optional); + ManagedToNative.Add(ValueType.Error, type_error()); + NativeToManaged.Add(type_error(), ValueType.Error); + + ManagedToNative.Add(ValueType.Empty, IntPtr.Zero); + NativeToManaged.Add(IntPtr.Zero, ValueType.Empty); + TypesLoaded = true; } } @@ -650,10 +666,13 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value> // EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct -- FIXME - public IntPtr Handle { get; protected set;} - public ValueOwnership Ownership { get; protected set;} + internal IntPtr Handle { get; set;} + /// <summary> Whether this wrapper owns (can free) the native value. </summary> + public Ownership Ownership { get; protected set;} private bool Disposed; + /// <summary> Whether this wrapper has already freed the native value. </summary> public bool Flushed { get; protected set;} + /// <summary> Whether this is an Optional value (meaning it can have a value or not). </summary> public bool Optional { get { return GetValueType() == eina.ValueType.Optional; @@ -666,8 +685,17 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value> // } } */ } + /// <summary> Whether this wrapper is actually empty/uninitialized (zeroed). This is different from an empty optional value. </summary> public bool Empty { get { + SanityChecks(); + return GetValueType() == eina.ValueType.Empty; + } + } + + /// <summary> Whether this optional value is empty. </summary> + public bool OptionalEmpty { + get { OptionalSanityChecks(); bool empty; if (!eina_value_optional_empty_is_wrapper(this.Handle, out empty)) @@ -680,10 +708,10 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value> // Constructor to be used by the "FromContainerDesc" methods. private Value() { this.Handle = MemoryNative.Alloc(eina_value_sizeof()); - this.Ownership = ValueOwnership.Managed; + this.Ownership = Ownership.Managed; } - public Value(IntPtr handle, ValueOwnership ownership=ValueOwnership.Managed) { + public Value(IntPtr handle, Ownership ownership=Ownership.Managed) { this.Handle = handle; this.Ownership = ownership; } @@ -693,8 +721,15 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value> { if (type.IsContainer()) throw new ArgumentException("To use container types you must provide a subtype"); + this.Handle = MemoryNative.Alloc(eina_value_sizeof()); - this.Ownership = ValueOwnership.Managed; + if (this.Handle == IntPtr.Zero) + throw new OutOfMemoryException("Failed to allocate memory for eina.Value"); + + // Initialize to EINA_VALUE_EMPTY before performing any other operation on this value. + MemoryNative.Memset(this.Handle, 0, eina_value_sizeof()); + + this.Ownership = Ownership.Managed; Setup(type); } @@ -705,7 +740,7 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value> throw new ArgumentException("First type must be a container type."); this.Handle = MemoryNative.Alloc(eina_value_sizeof()); - this.Ownership = ValueOwnership.Managed; + this.Ownership = Ownership.Managed; Setup(containerType, subtype, step); } @@ -713,14 +748,30 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value> /// <summary>Constructor to build value from Values_Natives passed by value from C.</summary> public Value(Value_Native value) { - this.Handle = MemoryNative.Alloc(Marshal.SizeOf(typeof(Value_Native))); + IntPtr tmp = MemoryNative.Alloc(Marshal.SizeOf(typeof(Value_Native))); try { - Marshal.StructureToPtr(value, this.Handle, false); + Marshal.StructureToPtr(value, tmp, false); // Can't get the address of a struct directly. + if (value.Type == IntPtr.Zero) // Got an EINA_VALUE_EMPTY by value. + { + this.Handle = tmp; + tmp = IntPtr.Zero; + } + else + { + this.Handle = MemoryNative.Alloc(Marshal.SizeOf(typeof(Value_Native))); + + // Copy is used to deep copy the pointed payload (e.g. strings) inside this struct, so we can own this value. + if (!eina_value_copy(tmp, this.Handle)) + throw new System.InvalidOperationException("Failed to copy value to managed memory."); + } } catch { MemoryNative.Free(this.Handle); throw; + } finally { + MemoryNative.Free(tmp); } - this.Ownership = ValueOwnership.Managed; + + this.Ownership = Ownership.Managed; } /// <summary>Implicit conversion from managed value to native struct representation.</summary> @@ -758,13 +809,13 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value> /// <summary>Releases the ownership of the underlying value to C.</summary> public void ReleaseOwnership() { - this.Ownership = ValueOwnership.Unmanaged; + this.Ownership = Ownership.Unmanaged; } /// <summary>Takes the ownership of the underlying value to the Managed runtime.</summary> public void TakeOwnership() { - this.Ownership = ValueOwnership.Managed; + this.Ownership = Ownership.Managed; } /// <summary>Public method to explicitly free the wrapped eina value.</summary> @@ -777,13 +828,13 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value> /// <summary>Actually free the wrapped eina value. Can be called from Dispose() or through the GC.</summary> protected virtual void Dispose(bool disposing) { - if (this.Ownership == ValueOwnership.Unmanaged) { + if (this.Ownership == Ownership.Unmanaged) { Disposed = true; return; } if (!Disposed && (Handle != IntPtr.Zero)) { - if (!Flushed) + if (!Flushed && !Empty) eina_value_flush_wrapper(this.Handle); MemoryNative.Free(this.Handle); @@ -798,11 +849,12 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value> } /// <summary>Returns the native handle wrapped by this object.</summary> - public IntPtr NativeHandle() - { - if (Disposed) - throw new ObjectDisposedException(base.GetType().Name); - return this.Handle; + public IntPtr NativeHandle { + get { + if (Disposed) + throw new ObjectDisposedException(base.GetType().Name); + return this.Handle; + } } /// <summary>Converts this storage to type 'type'</summary> @@ -811,6 +863,18 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value> if (Disposed) throw new ObjectDisposedException(base.GetType().Name); + // Can't call setup with Empty value type (would give an eina error) + if (type == eina.ValueType.Empty) + { + // Need to cleanup as it may point to payload outside the underlying Eina_Value (like arrays and strings). + if (!Empty) + eina_value_flush_wrapper(this.Handle); + + MemoryNative.Memset(this.Handle, 0, eina_value_sizeof()); + + return true; + } + if (type.IsContainer()) throw new ArgumentException("To setup a container you must provide a subtype."); @@ -1072,6 +1136,21 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value> return eina_value_set_wrapper_string(this.Handle, value); } + /// <summary>Stores the given error value.</summary> + public bool Set(eina.Error value) + { + SanityChecks(); + + int error_code = value; + + if (this.Optional) + return eina_value_optional_pset(this.Handle, + ValueTypeBridge.GetNative(ValueType.Error), + ref error_code); + + return eina_value_set_wrapper_int(this.Handle, error_code); + } + /// <summary>Stores the given value into this value. The target value must be an optional.</summary> public bool Set(Value value) { @@ -1225,6 +1304,22 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value> return true; } + /// <summary>Gets the currently stored value as an eina.Error.</summary> + public bool Get(out eina.Error value) + { + SanityChecks(); + bool ret; + int intermediate; // It seems out doesn't play well with implicit operators... + if (this.Optional) + ret = eina_value_optional_pget(this.Handle, out intermediate); + else + ret = eina_value_get_wrapper(this.Handle, out intermediate); + + value = intermediate; + + return ret; + } + /// <summary>Gets the currently stored value as an complex (e.g. container) eina.Value.</summary> public bool Get(out Value value) { @@ -1516,7 +1611,7 @@ public class ValueMarshaler : ICustomMarshaler { /// <summary>Creates a managed value from a C pointer, whitout taking ownership of it.</summary> public object MarshalNativeToManaged(IntPtr pNativeData) { - return new Value(pNativeData, ValueOwnership.Unmanaged); + return new Value(pNativeData, Ownership.Unmanaged); } /// <summary>Retrieves the C pointer from a given managed value, @@ -1554,7 +1649,7 @@ public class ValueMarshaler : ICustomMarshaler { public class ValueMarshalerOwn : ICustomMarshaler { /// <summary>Creates a managed value from a C pointer, taking the ownership.</summary> public object MarshalNativeToManaged(IntPtr pNativeData) { - return new Value(pNativeData, ValueOwnership.Managed); + return new Value(pNativeData, Ownership.Managed); } /// <summary>Retrieves the C pointer from a given managed value, |