/* * 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.ListNativeFunctions; using Eina.Callbacks; namespace Eina { [EditorBrowsable(EditorBrowsableState.Never)] public static class ListNativeFunctions { [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_append(IntPtr list, IntPtr data); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_prepend(IntPtr list, IntPtr data); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_append_relative(IntPtr list, IntPtr data, IntPtr relative); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_append_relative_list(IntPtr list, IntPtr data, IntPtr relative); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_prepend_relative(IntPtr list, IntPtr data, IntPtr relative); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_prepend_relative_list(IntPtr list, IntPtr data, IntPtr relative); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_sorted_insert(IntPtr list, IntPtr func, IntPtr data); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_remove(IntPtr list, IntPtr data); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_remove_list(IntPtr list, IntPtr remove_list); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_promote_list(IntPtr list, IntPtr move_list); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_demote_list(IntPtr list, IntPtr move_list); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_data_find(IntPtr list, IntPtr data); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_data_find_list(IntPtr list, IntPtr data); [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] internal static extern bool eina_list_move(ref IntPtr to, ref IntPtr from, IntPtr data); [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] internal static extern bool eina_list_move_list(ref IntPtr to, ref IntPtr from, IntPtr data); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_free(IntPtr list); [DllImport(efl.Libs.CustomExports)] internal static extern void efl_mono_thread_safe_eina_list_free(IntPtr list); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_nth(IntPtr list, uint n); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_nth_list(IntPtr list, uint n); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_reverse(IntPtr list); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_reverse_clone(IntPtr list); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_clone(IntPtr list); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_sort(IntPtr list, uint limit, IntPtr func); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_shuffle(IntPtr list, IntPtr func); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_merge(IntPtr left, IntPtr right); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_sorted_merge(IntPtr left, IntPtr right, IntPtr func); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_split_list(IntPtr list, IntPtr relative, ref IntPtr right); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_search_sorted_near_list(IntPtr list, IntPtr func, IntPtr data, IntPtr result_cmp); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_search_sorted_list(IntPtr list, IntPtr func, IntPtr data); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_search_sorted(IntPtr list, IntPtr func, IntPtr data); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_search_unsorted_list(IntPtr list, IntPtr func, IntPtr data); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_search_unsorted(IntPtr list, IntPtr func, IntPtr data); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_iterator_new(IntPtr list); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_iterator_reversed_new(IntPtr list); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_list_accessor_new(IntPtr list); [DllImport(efl.Libs.Eina)] internal static extern int eina_list_data_idx(IntPtr list, IntPtr data); [DllImport(efl.Libs.CustomExports)] internal static extern IntPtr eina_list_last_custom_export_mono(IntPtr list); [DllImport(efl.Libs.CustomExports)] internal static extern IntPtr eina_list_next_custom_export_mono(IntPtr list); [DllImport(efl.Libs.CustomExports)] internal static extern IntPtr eina_list_prev_custom_export_mono(IntPtr list); [DllImport(efl.Libs.CustomExports)] internal static extern IntPtr eina_list_data_get_custom_export_mono(IntPtr list); [DllImport(efl.Libs.CustomExports)] internal static extern IntPtr eina_list_data_set_custom_export_mono(IntPtr list, IntPtr data); [DllImport(efl.Libs.CustomExports)] internal static extern uint eina_list_count_custom_export_mono(IntPtr list); [DllImport(efl.Libs.CustomExports)] internal static extern IntPtr eina_list_last_data_get_custom_export_mono(IntPtr list); } /// Native wrapper around a linked list of items. /// Since EFL 1.23. /// public class List : IEnumerable, IDisposable { [EditorBrowsable(EditorBrowsableState.Never)] public IntPtr Handle {get;set;} = IntPtr.Zero; /// Whether this managed list owns the native one. /// Since EFL 1.23. /// public bool Own {get;set;} /// Whether the native list wrapped owns the content it points to. /// Since EFL 1.23. /// public bool OwnContent {get;set;} /// Delegate for comparing two elements of this list. /// Since EFL 1.23. /// /// First element. /// Second element. /// -1, 0 or 1 for respectively smaller, equal or larger. public delegate int Compare(T a, T b); /// The number of elements on this list. /// Since EFL 1.23. /// public int Length { get { return Count(); } } private void InitNew() { Handle = IntPtr.Zero; Own = true; OwnContent = true; } private IntPtr InternalLast() { return eina_list_last_custom_export_mono(Handle); } private static IntPtr InternalNext(IntPtr list) { return eina_list_next_custom_export_mono(list); } private static IntPtr InternalPrev(IntPtr list) { return eina_list_prev_custom_export_mono(list); } private static IntPtr InternalDataGet(IntPtr list) { return eina_list_data_get_custom_export_mono(list); } private static IntPtr InternalDataSet(IntPtr list, IntPtr data) { return eina_list_data_set_custom_export_mono(list, data); } /// Creates a new empty list. /// Since EFL 1.23. /// public List() { InitNew(); } /// Creates a new list wrapping the given handle. [EditorBrowsable(EditorBrowsableState.Never)] public List(IntPtr handle, bool own) { Handle = handle; Own = own; OwnContent = own; } /// Creates a new list wrapping the given handle. [EditorBrowsable(EditorBrowsableState.Never)] public List(IntPtr handle, bool own, bool ownContent) { Handle = handle; Own = own; OwnContent = ownContent; } /// Finalizes this list. /// Since EFL 1.23. /// ~List() { Dispose(false); } /// Disposes of this list. /// Since EFL 1.23. /// /// Whether this was called from the finalizer (false) or from the /// method. protected virtual void Dispose(bool disposing) { IntPtr h = Handle; Handle = IntPtr.Zero; if (h == IntPtr.Zero) { return; } if (Own && OwnContent) { for (IntPtr curr = h; curr != IntPtr.Zero; curr = InternalNext(curr)) { NativeFree(InternalDataGet(curr)); } } if (Own) { if (disposing) { eina_list_free(h); } else { efl_mono_thread_safe_eina_list_free(h); } } } /// Disposes of this list. /// Since EFL 1.23. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// Disposes of this list. /// Since EFL 1.23. /// public void Free() { Dispose(); } /// Relinquishes of the native list. /// Since EFL 1.23. /// /// The previously wrapped native list handle. public IntPtr Release() { IntPtr h = Handle; Handle = IntPtr.Zero; return h; } /// Sets whether this wrapper should own the native list or not. /// Since EFL 1.23. /// /// If the hash own for all ownerships. public void SetOwnership(bool ownAll) { Own = ownAll; OwnContent = ownAll; } /// Sets whether this wrapper should own the native list and /// its content or not. /// Since EFL 1.23. /// /// If own the object. /// If own the content's object. public void SetOwnership(bool own, bool ownContent) { Own = own; OwnContent = ownContent; } /// Returns the number of elements in this list. /// Since EFL 1.23. /// /// The number of elements. public int Count() { return (int)eina_list_count_custom_export_mono(Handle); } /// Appends val to the list. /// Since EFL 1.23. /// /// The item to be appended. public void Append(T val) { IntPtr ele = ManagedToNativeAlloc(val); Handle = eina_list_append(Handle, ele); } /// Prepends val to the list. /// Since EFL 1.23. /// /// The item to be prepended. public void Prepend(T val) { IntPtr ele = ManagedToNativeAlloc(val); Handle = eina_list_prepend(Handle, ele); } /// Inserts val in the list in a sorted manner. /// It presumes the list is already sorted. /// Since EFL 1.23. /// /// The item to be inserted. public void SortedInsert(T val) { IntPtr ele = ManagedToNativeAlloc(val); Handle = eina_list_sorted_insert(Handle, EinaCompareCb(), ele); } /// Inserts val in the list in a sorted manner with the /// given compareCb for element comparison. /// It presumes the list is already sorted. /// Since EFL 1.23. /// /// The function to compare two elements of the list. /// The item to be inserted. public void SortedInsert(Compare compareCb, T val) { IntPtr ele = ManagedToNativeAlloc(val); Handle = eina_list_sorted_insert(Handle, Marshal.GetFunctionPointerForDelegate(GetNativeCompareCb(compareCb)), ele); } /// Sorts limit elements in this list inplace. /// Since EFL 1.23. /// /// The max number of elements to be sorted. public void Sort(int limit = 0) { Handle = eina_list_sort(Handle, (uint)limit, EinaCompareCb()); } /// Sorts all elements in this list inplace. /// Since EFL 1.23. /// /// The function to compare two elements of the list. public void Sort(Compare compareCb) { Handle = eina_list_sort(Handle, 0, Marshal.GetFunctionPointerForDelegate(GetNativeCompareCb(compareCb))); } /// Sorts limit elements in this list inplace. /// Since EFL 1.23. /// /// The max number of elements to be sorted. /// The function to compare two elements of the list. public void Sort(int limit, Compare compareCb) { Handle = eina_list_sort(Handle, (uint)limit, Marshal.GetFunctionPointerForDelegate(GetNativeCompareCb(compareCb))); } private Eina.Callbacks.EinaCompareCb GetNativeCompareCb(Compare managedCb) { return (IntPtr a, IntPtr b) => { return managedCb(NativeToManaged(a), NativeToManaged(b)); }; } /// Returns the nth element of this list. Due to marshalling details, the returned element /// may be a different C# object from the one you used to append. /// Since EFL 1.23. /// /// The 0-based index to be retrieved. /// The value in the specified element. public T Nth(int n) { // TODO: check bounds ??? IntPtr ele = eina_list_nth(Handle, (uint)n); return NativeToManaged(ele); } /// Sets the data at the idx position. /// Since EFL 1.23. /// /// The 0-based index to be set. /// The value to be inserted. public void DataSet(int idx, T val) { IntPtr pos = eina_list_nth_list(Handle, (uint)idx); if (pos == IntPtr.Zero) { throw new IndexOutOfRangeException(); } if (OwnContent) { NativeFree(InternalDataGet(pos)); } IntPtr ele = ManagedToNativeAlloc(val); InternalDataSet(pos, ele); } /// Accessor for the data at the idx position. /// Since EFL 1.23. /// /// The 0-based index to be get/set. public T this[int idx] { get { return Nth(idx); } set { DataSet(idx, value); } } /// Returns the data at the last list element. /// Since EFL 1.23. /// /// The value contained in the last list position. public T LastDataGet() { IntPtr ele = eina_list_last_data_get_custom_export_mono(Handle); return NativeToManaged(ele); } /// Reverses this list in place. /// Since EFL 1.23. /// /// A reference to this object. public List Reverse() { Handle = eina_list_reverse(Handle); return this; } /// Randomly shuffles this list in place. /// Since EFL 1.23. /// public void Shuffle() { Handle = eina_list_shuffle(Handle, IntPtr.Zero); } /// Gets a C# array of the elements in this list. /// Since EFL 1.23. /// /// A managed array of the elements. public T[] ToArray() { var managed = new T[Count()]; int i = 0; for (IntPtr curr = Handle; curr != IntPtr.Zero; curr = InternalNext(curr), ++i) { managed[i] = NativeToManaged(InternalDataGet(curr)); } return managed; } /// Appends the given array of elements to this list. /// Since EFL 1.23. /// /// The values to be appended. public void AppendArray(T[] values) { foreach (T v in values) { Append(v); } } /// Gets an iterator that iterates this list in normal order. /// Since EFL 1.23. /// /// The iterator. public Eina.Iterator GetIterator() { return new Eina.Iterator(eina_list_iterator_new(Handle), true); } /// Gets an iterator that iterates this list in reverse order. /// Since EFL 1.23. /// /// The iterator. public Eina.Iterator GetReversedIterator() { return new Eina.Iterator(eina_list_iterator_reversed_new(Handle), true); } /// Gets an enumerator into this list. /// Since EFL 1.23. /// /// The enumerator. public IEnumerator GetEnumerator() { for (IntPtr curr = Handle; curr != IntPtr.Zero; curr = InternalNext(curr)) { yield return NativeToManaged(InternalDataGet(curr)); } } /// Gets an enumerator into this list. /// Since EFL 1.23. /// /// The enumerator. System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.GetEnumerator(); } /// Gets an Accessor for this List. /// Since EFL 1.23. /// /// The accessor. public Eina.Accessor GetAccessor() { return new Eina.Accessor(eina_list_accessor_new(Handle), Ownership.Managed); } } }