/* * 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. */ #pragma warning disable 1591 using System; using System.Runtime.InteropServices; using System.Collections.Generic; using System.ComponentModel; using static Eina.TraitFunctions; using static Eina.ArrayNativeFunctions; namespace Eina { [EditorBrowsable(EditorBrowsableState.Never)] public static class ArrayNativeFunctions { [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_array_new(uint step); [DllImport(efl.Libs.Eina)] internal static extern void eina_array_free(IntPtr array); [DllImport(efl.Libs.Eina)] internal static extern void eina_array_flush(IntPtr array); [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] internal static extern bool eina_array_remove(IntPtr array, IntPtr keep, IntPtr gdata); [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] internal static extern bool eina_array_push(IntPtr array, IntPtr data); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_array_iterator_new(IntPtr array); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_array_accessor_new(IntPtr array); [DllImport(efl.Libs.CustomExports)] internal static extern void eina_array_clean_custom_export_mono(IntPtr array); [DllImport(efl.Libs.CustomExports)] [return: MarshalAs(UnmanagedType.U1)] internal static extern bool eina_array_push_custom_export_mono(IntPtr array, IntPtr data); [DllImport(efl.Libs.CustomExports)] internal static extern IntPtr eina_array_pop_custom_export_mono(IntPtr array); [DllImport(efl.Libs.CustomExports)] internal static extern IntPtr eina_array_data_get_custom_export_mono(IntPtr array, uint idx); [DllImport(efl.Libs.CustomExports)] internal static extern void eina_array_data_set_custom_export_mono(IntPtr array, uint idx, IntPtr data); [DllImport(efl.Libs.CustomExports)] internal static extern uint eina_array_count_custom_export_mono(IntPtr array); [DllImport(efl.Libs.CustomExports)] [return: MarshalAs(UnmanagedType.U1)] internal static extern bool eina_array_foreach_custom_export_mono(IntPtr array, IntPtr cb, IntPtr fdata); } /// A container of contiguous allocated elements. /// Since EFL 1.23. /// public class Array : IEnumerable, IDisposable { public const uint DefaultStep = 32; /// Pointer to the native buffer. [EditorBrowsable(EditorBrowsableState.Never)] public IntPtr Handle {get;set;} = IntPtr.Zero; /// Whether this wrapper owns the native buffer. /// Since EFL 1.23. /// public bool Own {get;set;} /// Who is in charge of releasing the resources wrapped by /// this instance. /// Since EFL 1.23. /// public bool OwnContent {get;set;} /// Length of the array. /// Since EFL 1.23. /// public int Length { get { return Count(); } } private void InitNew(uint step) { Handle = eina_array_new(step); Own = true; OwnContent = true; if (Handle == IntPtr.Zero) { throw new SEHException("Could not alloc array"); } } internal bool InternalPush(IntPtr ele) { return eina_array_push_custom_export_mono(Handle, ele); } internal IntPtr InternalPop() { return eina_array_pop_custom_export_mono(Handle); } internal IntPtr InternalDataGet(int idx) { return eina_array_data_get_custom_export_mono(Handle, (uint)idx); // TODO: Check bounds ??? } internal void InternalDataSet(int idx, IntPtr ele) { eina_array_data_set_custom_export_mono(Handle, (uint)idx, ele); // TODO: Check bounds ??? } /// /// Create a new array. /// Since EFL 1.23. /// public Array() { InitNew(DefaultStep); } /// /// Create a new array. /// Since EFL 1.23. /// /// Step size of the array. public Array(uint step) { InitNew(step); } /// /// Create a new array. /// /// The native handle to be wrapped. /// Whether this wrapper owns the native handle. [EditorBrowsable(EditorBrowsableState.Never)] public Array(IntPtr handle, bool own) { if (handle == IntPtr.Zero) { throw new ArgumentNullException("Handle can't be null"); } Handle = handle; Own = own; OwnContent = own; } /// /// Create a new array. /// /// The native array to be wrapped. /// Whether this wrapper owns the native array. /// For compatibility with other EFL# containers. [EditorBrowsable(EditorBrowsableState.Never)] public Array(IntPtr handle, bool own, bool ownContent) { if (handle == IntPtr.Zero) { throw new ArgumentNullException("Handle can't be null"); } Handle = handle; Own = own; OwnContent = ownContent; } /// /// Finalizer to be called from the Garbage Collector. /// Since EFL 1.23. /// ~Array() { Dispose(false); } /// Disposes of this wrapper, releasing the native array 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) { IntPtr h = Handle; Handle = IntPtr.Zero; if (h == IntPtr.Zero) { return; } if (Own && OwnContent) { int len = (int)eina_array_count_custom_export_mono(h); for (int i = 0; i < len; ++i) { NativeFree(eina_array_data_get_custom_export_mono(h, (uint)i)); } } if (Own) { if (disposing) { eina_array_free(h); } else { Efl.Eo.Globals.ThreadSafeFreeCbExec(eina_array_free, h); } } } /// Releases the native resources held by this instance. /// Since EFL 1.23. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// Releases the native resources held by this instance. /// Since EFL 1.23. /// public void Free() { Dispose(); } /// /// Releases the native array. /// Since EFL 1.23. /// /// The native array. public IntPtr Release() { IntPtr h = Handle; Handle = IntPtr.Zero; return h; } private void FreeElementsIfOwned() { if (OwnContent) { int len = Length; for (int i = 0; i < len; ++i) { NativeFree(InternalDataGet(i)); } } } /// /// Clears an array's elements and deallocates the memory. /// Since EFL 1.23. /// public void Clean() { FreeElementsIfOwned(); eina_array_clean_custom_export_mono(Handle); } /// /// Clears an array's elements and deallocates the memory. /// public void Flush() { FreeElementsIfOwned(); eina_array_flush(Handle); } /// /// Returns the number of elements in an array. /// Since EFL 1.23. /// /// The number of elements. public int Count() { return (int)eina_array_count_custom_export_mono(Handle); } public void SetOwnership(bool ownAll) { Own = ownAll; OwnContent = ownAll; } public void SetOwnership(bool own, bool ownContent) { Own = own; OwnContent = ownContent; } /// /// Inserts the element of the array at the end. /// Since EFL 1.23. /// /// The value of the element to be inserted. public bool Push(T val) { IntPtr ele = ManagedToNativeAlloc(val); var r = InternalPush(ele); if (!r) { NativeFree(ele); } return r; } // TODO ??? // public void Add(T val) // { // if (!Push(val)) // { // throw; // } // } /// /// Returns the element of the array at the end. /// Since EFL 1.23. /// /// The element at the end position. public T Pop() { IntPtr ele = InternalPop(); var r = NativeToManaged(ele); if (OwnContent && ele != IntPtr.Zero) { NativeFree(ele); } return r; } /// /// Returns the element of the array at the specified position. /// Since EFL 1.23. /// /// The position of the desired element. /// The element at the specified position public T DataGet(int idx) { IntPtr ele = InternalDataGet(idx); return NativeToManaged(ele); } /// /// Returns the element of the array at the specified position. /// Since EFL 1.23. /// /// The position of the desired element. /// The element at the specified position public T At(int idx) { return DataGet(idx); } /// /// Replaces the element at the specified position. /// Since EFL 1.23. /// /// The position of the desired element. /// The value of the element to be inserted. public void DataSet(int idx, T val) { IntPtr ele = InternalDataGet(idx); // TODO: check bondaries ?? if (OwnContent && ele != IntPtr.Zero) { NativeFree(ele); } ele = ManagedToNativeAlloc(val); InternalDataSet(idx, ele); } /// /// Accessor by index to the elements of this list. /// Since EFL 1.23. /// public T this[int idx] { get { return DataGet(idx); } set { DataSet(idx, value); } } /// /// Returns a array containing all of the elements in proper sequence. /// Since EFL 1.23. /// /// A array public T[] ToArray() { int len = Length; var managed = new T[len]; for (int i = 0; i < len; ++i) { managed[i] = DataGet(i); } return managed; } /// /// Appends all elements at the end of array. /// Since EFL 1.23. /// public bool Append(T[] values) { foreach (T v in values) { if (!Push(v)) { return false; } } return true; } /// Gets an Iterator for this Array. /// Since EFL 1.23. /// public Eina.Iterator GetIterator() { return new Eina.Iterator(eina_array_iterator_new(Handle), true); } /// Gets an Enumerator for this Array. /// Since EFL 1.23. /// public IEnumerator GetEnumerator() { int len = Length; for (int i = 0; i < len; ++i) { yield return DataGet(i); } } /// Gets an Enumerator for this Array. /// Since EFL 1.23. /// System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.GetEnumerator(); } /// Gets an Accessor for this Array. /// Since EFL 1.23. /// public Eina.Accessor GetAccessor() { return new Eina.Accessor(eina_array_accessor_new(Handle), Ownership.Managed); } } }