/* * Copyright 2019 by its authors. See AUTHORS. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using static Eina.TraitFunctions; using static Eina.AccessorNativeFunctions; namespace Eina { internal class AccessorNativeFunctions { [DllImport(efl.Libs.Eina)] public static extern IntPtr eina_carray_length_accessor_new(IntPtr array, uint step, uint length); [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool eina_accessor_data_get(IntPtr accessor, uint position, out 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. /// Since EFL 1.23. /// [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Justification="This is a generalized container mapping the native one.")] public class Accessor : IEnumerable, IDisposable { /// Pointer to the native accessor. [EditorBrowsable(EditorBrowsableState.Never)] public IntPtr Handle { get; private set; } = IntPtr.Zero; /// Who is in charge of releasing the resources wrapped by this instance. /// Since EFL 1.23. /// private Ownership Ownership { get; set; } // FIXME Part of the implicit EFL Container interface. Need to make it explicit. /// Whether this wrapper owns the native accessor. /// Since EFL 1.23. /// public bool Own { get { return Ownership == Ownership.Managed; } set { Ownership = value ? Ownership.Managed : Ownership.Unmanaged; } } /// Create a new accessor wrapping the given pointer. /// Since EFL 1.23. /// /// The native handle to be wrapped. /// Whether this wrapper owns the native accessor. [EditorBrowsable(EditorBrowsableState.Never)] public Accessor(IntPtr handle, Ownership owner = Ownership.Managed) { Handle = handle; Ownership = owner; } /// Create a new accessor wrapping the given pointer. /// Since EFL 1.23. /// /// The native handle to be wrapped. /// Whether this wrapper owns the native accessor. /// For compatibility with other EFL# containers. Ignored in acessors. [EditorBrowsable(EditorBrowsableState.Never)] public Accessor(IntPtr handle, bool own, bool ownContent = false) : this(handle, own ? Ownership.Managed : Ownership.Unmanaged) { } /// Release the native resources held by this instance. /// Since EFL 1.23. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// Disposes of this wrapper, releasing the native accessor if /// owned. /// Since EFL 1.23. /// /// True if this was called from public method. False if /// called from the C# finalizer. protected virtual void Dispose(bool disposing) { if (Ownership == Ownership.Managed && Handle != IntPtr.Zero) { if (disposing) { eina_accessor_free(Handle); } else { Efl.Eo.Globals.ThreadSafeFreeCbExec(eina_accessor_free, Handle); } Handle = IntPtr.Zero; } } /// Finalizer to be called from the Garbage Collector. /// Since EFL 1.23. /// ~Accessor() { Dispose(false); } /// Convert the native data into managed. This is used when returning the data through a /// . /// Since EFL 1.23. /// /// The data to be converted /// The managed data representing data. internal virtual T Convert(IntPtr data) { return NativeToManaged(data); } /// Returns an enumerator that iterates throught this accessor. /// Since EFL 1.23. /// /// An enumerator to walk through the acessor items. 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); } */ yield break; } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } } /// Accessor for Inlists. /// Since EFL 1.23. /// [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Justification="This is a generalized container mapping the native one.")] public class AccessorInList : Accessor { /// Create a new accessor wrapping the given pointer. /// Since EFL 1.23. /// /// The native handle to be wrapped. /// Whether this wrapper owns the native accessor. [EditorBrowsable(EditorBrowsableState.Never)] public AccessorInList(IntPtr handle, Ownership own) : base(handle, own) { } /// Convert the native data into managed. This is used when returning the data through a /// . /// The data to be converted /// The managed data representing data. internal override T Convert(IntPtr data) { return NativeToManagedInlistNode(data); } } /// Accessor for Inarrays. /// Since EFL 1.23. /// [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Justification="This is a generalized container mapping the native one.")] public class AccessorInArray : Accessor { /// Create a new accessor wrapping the given pointer. /// Since EFL 1.23. /// /// The native handle to be wrapped. /// Whether this wrapper owns the native accessor. [EditorBrowsable(EditorBrowsableState.Never)] public AccessorInArray(IntPtr handle, Ownership own) : base(handle, own) { } /// Convert the native data into managed. This is used when returning the data through a /// . /// The data to be converted /// The managed data representing data. internal override T Convert(IntPtr data) { return NativeToManagedInplace(data); } } }