using System; using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; using static Eina.TraitFunctions; using static Eina.AccessorNativeFunctions; namespace Eina { internal class AccessorNativeFunctions { [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool eina_accessor_data_get(IntPtr accessor, uint position, IntPtr data); [DllImport(efl.Libs.Eina)] public static extern void eina_accessor_free(IntPtr accessor); } /// Accessors provide an uniform way of accessing Eina containers, similar to C++ STL's and C# IEnumerable. public class Accessor : IEnumerable, IDisposable { /// Pointer to the native accessor. public IntPtr Handle { get; private set; } = IntPtr.Zero; /// Who is in charge of releasing the resources wrapped by this instance. private Ownership Ownership { get; set; } // FIXME Part of the implicit EFL Container interface. Need to make it explicit. public bool Own { get { return Ownership == Ownership.Managed; } set { Ownership = value ? Ownership.Managed : Ownership.Unmanaged; } } /// Create a new accessor wrapping the given pointer. public Accessor(IntPtr handle, Ownership owner=Ownership.Managed) { Handle = handle; Ownership = owner; } public Accessor(IntPtr handle, bool own, bool ownContent=false) : this(handle, own ? Ownership.Managed : Ownership.Unmanaged) { } /// Release the native resources held by this instance. public void Dispose() { Dispose(true); } protected virtual void Dispose(bool disposing) { if (Ownership == Ownership.Managed && Handle != IntPtr.Zero) { eina_accessor_free(Handle); Handle = IntPtr.Zero; } } ~Accessor() { Dispose(false); } public virtual T Convert(IntPtr data) { return NativeToManaged(data); } /// Returns an enumerator that iterates throught this accessor. public IEnumerator GetEnumerator() { if (Handle == IntPtr.Zero) throw new ObjectDisposedException(base.GetType().Name); IntPtr tmp = MemoryNative.Alloc(Marshal.SizeOf(typeof(IntPtr))); uint position = 0; try { while(eina_accessor_data_get(Handle, position, tmp)) { IntPtr data = (IntPtr)Marshal.PtrToStructure(tmp, typeof(IntPtr)); yield return Convert(data); position += 1; } } finally { MemoryNative.Free(tmp); } } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } } public class AccessorInList : Accessor { public AccessorInList(IntPtr handle, Ownership own): base(handle, own) {} public override T Convert(IntPtr data) { return NativeToManagedInlistNode(data); } } public class AccessorInArray : Accessor { public AccessorInArray(IntPtr handle, Ownership own): base(handle, own) {} public override T Convert(IntPtr data) { return NativeToManagedInplace(data); } } }