efl/src/bindings/mono/eina_mono/eina_accessor.cs

227 lines
7.5 KiB
C#

/*
* 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 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);
}
/// <summary>Accessors provide an uniform way of accessing Eina containers,
/// similar to C++ STL's and C# IEnumerable.
/// <para>Since EFL 1.23.</para>
/// </summary>
public class Accessor<T> : IEnumerable<T>, IDisposable
{
/// <summary>Pointer to the native accessor.</summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public IntPtr Handle { get; private set; } = IntPtr.Zero;
/// <summary>Who is in charge of releasing the resources wrapped by this instance.
/// <para>Since EFL 1.23.</para>
/// </summary>
private Ownership Ownership { get; set; }
// FIXME Part of the implicit EFL Container interface. Need to make it explicit.
/// <summary>Whether this wrapper owns the native accessor.
/// <para>Since EFL 1.23.</para>
/// </summary>
public bool Own
{
get
{
return Ownership == Ownership.Managed;
}
set
{
Ownership = value ? Ownership.Managed : Ownership.Unmanaged;
}
}
/// <summary>Create a new accessor wrapping the given pointer.
/// <para>Since EFL 1.23.</para>
/// </summary>
/// <param name="handle">The native handle to be wrapped.</param>
/// <param name="owner">Whether this wrapper owns the native accessor.</param>
[EditorBrowsable(EditorBrowsableState.Never)]
public Accessor(IntPtr handle, Ownership owner = Ownership.Managed)
{
Handle = handle;
Ownership = owner;
}
/// <summary>Create a new accessor wrapping the given pointer.
/// <para>Since EFL 1.23.</para>
/// </summary>
/// <param name="handle">The native handle to be wrapped.</param>
/// <param name="own">Whether this wrapper owns the native accessor.</param>
/// <param name="ownContent">For compatibility with other EFL# containers. Ignored in acessors.</param>
[EditorBrowsable(EditorBrowsableState.Never)]
public Accessor(IntPtr handle, bool own, bool ownContent = false)
: this(handle, own ? Ownership.Managed : Ownership.Unmanaged)
{
}
/// <summary>Release the native resources held by this instance.
/// <para>Since EFL 1.23.</para>
/// </summary>
public void Dispose()
{
Dispose(true);
}
/// <summary>Disposes of this wrapper, releasing the native accessor if
/// owned.
/// <para>Since EFL 1.23.</para>
/// </summary>
/// <param name="disposing">True if this was called from <see cref="Dispose()"/> public method. False if
/// called from the C# finalizer.</param>
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;
}
}
/// <summary>Finalizer to be called from the Garbage Collector.
/// <para>Since EFL 1.23.</para>
/// </summary>
~Accessor()
{
Dispose(false);
}
/// <summary>Convert the native data into managed. This is used when returning the data through a
/// <see cref="System.Collections.Generic.IEnumerator&lt;T&gt;"/>.
/// <para>Since EFL 1.23.</para>
/// </summary>
/// <param name="data">The data to be converted</param>
/// <returns>The managed data representing <c>data</c>.</returns>
internal virtual T Convert(IntPtr data)
{
return NativeToManaged<T>(data);
}
/// <summary>Returns an enumerator that iterates throught this accessor.
/// <para>Since EFL 1.23.</para>
/// </summary>
/// <returns>An enumerator to walk through the acessor items.</returns>
public IEnumerator<T> 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();
}
}
/// <summary>Accessor for Inlists.
/// <para>Since EFL 1.23.</para>
/// </summary>
public class AccessorInList<T> : Accessor<T>
{
/// <summary>Create a new accessor wrapping the given pointer.
/// <para>Since EFL 1.23.</para>
/// </summary>
/// <param name="handle">The native handle to be wrapped.</param>
/// <param name="own">Whether this wrapper owns the native accessor.</param>
[EditorBrowsable(EditorBrowsableState.Never)]
public AccessorInList(IntPtr handle, Ownership own) : base(handle, own)
{
}
/// <summary>Convert the native data into managed. This is used when returning the data through a
/// <see cref="System.Collections.Generic.IEnumerator&lt;T&gt;"/>.</summary>
/// <param name="data">The data to be converted</param>
/// <returns>The managed data representing <c>data</c>.</returns>
internal override T Convert(IntPtr data)
{
return NativeToManagedInlistNode<T>(data);
}
}
/// <summary>Accessor for Inarrays.
/// <para>Since EFL 1.23.</para>
/// </summary>
public class AccessorInArray<T> : Accessor<T>
{
/// <summary>Create a new accessor wrapping the given pointer.
/// <para>Since EFL 1.23.</para>
/// </summary>
/// <param name="handle">The native handle to be wrapped.</param>
/// <param name="own">Whether this wrapper owns the native accessor.</param>
[EditorBrowsable(EditorBrowsableState.Never)]
public AccessorInArray(IntPtr handle, Ownership own) : base(handle, own)
{
}
/// <summary>Convert the native data into managed. This is used when returning the data through a
/// <see cref="System.Collections.Generic.IEnumerator&lt;T&gt;"/>.</summary>
/// <param name="data">The data to be converted</param>
/// <returns>The managed data representing <c>data</c>.</returns>
internal override T Convert(IntPtr data)
{
return NativeToManagedInplace<T>(data);
}
}
}