vitorsousa pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=cfafd01bbe27bab90117e1a8d97fdace55b47944
commit cfafd01bbe27bab90117e1a8d97fdace55b47944 Author: Lauro Moura <lauromo...@expertisesolutions.com.br> Date: Fri May 18 00:50:37 2018 -0300 efl_mono: Initial support for Accessors. Summary: Plain conversion to IEnumerable, which is the base of LINQ Depends on D6189 Reviewers: felipealmeida, vitor.sousa Reviewed By: vitor.sousa Subscribers: cedric, #committers, zmike Tags: #efl Differential Revision: https://phab.enlightenment.org/D6190 --- src/Makefile_Efl_Mono.am | 1 + src/bindings/mono/eina_mono/eina_accessor.cs | 108 +++++++++++++++++++++++++++ src/bindings/mono/eina_mono/eina_array.cs | 8 ++ src/bindings/mono/eina_mono/eina_inarray.cs | 6 ++ src/bindings/mono/eina_mono/eina_inlist.cs | 6 ++ src/bindings/mono/eina_mono/eina_list.cs | 6 ++ src/tests/efl_mono/Eina.cs | 71 ++++++++++++++++++ 7 files changed, 206 insertions(+) diff --git a/src/Makefile_Efl_Mono.am b/src/Makefile_Efl_Mono.am index a4376c0761..41c9d225c9 100644 --- a/src/Makefile_Efl_Mono.am +++ b/src/Makefile_Efl_Mono.am @@ -23,6 +23,7 @@ efl_eina_mono_files = \ bindings/mono/eina_mono/eina_error.cs \ bindings/mono/eina_mono/eina_value.cs \ bindings/mono/eina_mono/eina_promises.cs \ + bindings/mono/eina_mono/eina_accessor.cs \ bindings/mono/eina_mono/eina_strbuf.cs efl_eldbus_mono_files = \ diff --git a/src/bindings/mono/eina_mono/eina_accessor.cs b/src/bindings/mono/eina_mono/eina_accessor.cs new file mode 100644 index 0000000000..eab0aebc8c --- /dev/null +++ b/src/bindings/mono/eina_mono/eina_accessor.cs @@ -0,0 +1,108 @@ +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); +} + +/// <summary>Accessors provide an uniform way of accessing Eina containers, similar to C++ STL's and C# IEnumerable.</summary> +public class Accessor<T> : IEnumerable<T>, IDisposable +{ + /// <summary>Pointer to the native accessor.</summary> + public IntPtr Handle { get; private set; } = IntPtr.Zero; + + /// <summary>Who is in charge of releasing the resources wrapped by this instance.</summary> + private Ownership Ownership { get; set; } + + /// <summary>Create a new accessor wrapping the given pointer.</summary> + public Accessor(IntPtr handle, Ownership owner=Ownership.Managed) + { + Handle = handle; + Ownership = owner; + } + + /// <summary>Release the native resources held by this instance.</summary> + 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<T>(data); + } + + /// <summary>Returns an enumerator that iterates throught this accessor.</summary> + 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(); + } +} + +public class AccessorInList<T> : Accessor<T> +{ + public AccessorInList(IntPtr handle, Ownership own): base(handle, own) {} + public override T Convert(IntPtr data) + { + return NativeToManagedInlistNode<T>(data); + } +} + +public class AccessorInArray<T> : Accessor<T> +{ + public AccessorInArray(IntPtr handle, Ownership own): base(handle, own) {} + public override T Convert(IntPtr data) + { + return NativeToManagedInplace<T>(data); + } +} + +} diff --git a/src/bindings/mono/eina_mono/eina_array.cs b/src/bindings/mono/eina_mono/eina_array.cs index 6156c0cbb1..86e69fc407 100644 --- a/src/bindings/mono/eina_mono/eina_array.cs +++ b/src/bindings/mono/eina_mono/eina_array.cs @@ -24,6 +24,8 @@ public static class ArrayNativeFunctions [DllImport(efl.Libs.Eina)] public static extern IntPtr eina_array_iterator_new(IntPtr array); + [DllImport(efl.Libs.Eina)] public static extern IntPtr + eina_array_accessor_new(IntPtr array); [DllImport(efl.Libs.CustomExports)] public static extern void eina_array_clean_custom_export_mono(IntPtr array); @@ -288,6 +290,12 @@ public class Array<T> : IEnumerable<T>, IDisposable { return this.GetEnumerator(); } + + /// <summary> Gets an Accessor for this Array.</summary> + public eina.Accessor<T> GetAccessor() + { + return new eina.Accessor<T>(eina_array_accessor_new(Handle), Ownership.Managed); + } } } diff --git a/src/bindings/mono/eina_mono/eina_inarray.cs b/src/bindings/mono/eina_mono/eina_inarray.cs index e246af83f0..a9d3116a34 100644 --- a/src/bindings/mono/eina_mono/eina_inarray.cs +++ b/src/bindings/mono/eina_mono/eina_inarray.cs @@ -321,6 +321,12 @@ public class Inarray<T> : IEnumerable<T>, IDisposable { return this.GetEnumerator(); } + + /// <summary> Gets an Accessor for this Array.</summary> + public eina.Accessor<T> GetAccessor() + { + return new eina.AccessorInArray<T>(eina_inarray_accessor_new(Handle), Ownership.Managed); + } } } diff --git a/src/bindings/mono/eina_mono/eina_inlist.cs b/src/bindings/mono/eina_mono/eina_inlist.cs index 7b69924a9a..c3392a2db8 100644 --- a/src/bindings/mono/eina_mono/eina_inlist.cs +++ b/src/bindings/mono/eina_mono/eina_inlist.cs @@ -313,6 +313,12 @@ public class Inlist<T> : IEnumerable<T>, IDisposable { return this.GetEnumerator(); } + + /// <summary> Gets an Accessor for this List.</summary> + public eina.Accessor<T> GetAccessor() + { + return new eina.AccessorInList<T>(eina_inlist_accessor_new(Handle), Ownership.Managed); + } } } diff --git a/src/bindings/mono/eina_mono/eina_list.cs b/src/bindings/mono/eina_mono/eina_list.cs index cef766f331..e31a8ffed3 100644 --- a/src/bindings/mono/eina_mono/eina_list.cs +++ b/src/bindings/mono/eina_mono/eina_list.cs @@ -349,6 +349,12 @@ public class List<T> : IEnumerable<T>, IDisposable { return this.GetEnumerator(); } + + /// <summary> Gets an Accessor for this List.</summary> + public eina.Accessor<T> GetAccessor() + { + return new eina.Accessor<T>(eina_list_accessor_new(Handle), Ownership.Managed); + } } } diff --git a/src/tests/efl_mono/Eina.cs b/src/tests/efl_mono/Eina.cs index 9a844f5280..f1e1dc49ff 100644 --- a/src/tests/efl_mono/Eina.cs +++ b/src/tests/efl_mono/Eina.cs @@ -4254,4 +4254,75 @@ class TestEinaIterator } } // < TestEinaIterator + +class TestEinaAccessor +{ + public static void basic_accessor_list() + { + var lst = new eina.List<int>(); + lst.Append(1); + lst.Append(2); + lst.Append(3); + lst.Append(4); + + eina.Accessor<int> accessor = lst.GetAccessor(); + + var zipped = accessor.Zip(lst, (first, second) => new Tuple<int, int>(first, second)); + + foreach(Tuple<int, int> pair in zipped) + { + Test.AssertEquals(pair.Item1, pair.Item2); + } + } + + public static void basic_accessor_array() + { + var arr = new eina.Array<string>(); + arr.Append(base_seq_str); + + eina.Accessor<string> accessor = arr.GetAccessor(); + + var zipped = accessor.Zip(arr, (first, second) => new Tuple<string, string>(first, second)); + + foreach(Tuple<string, string> pair in zipped) + { + Test.AssertEquals(pair.Item1, pair.Item2); + } + } + + public static void basic_accessor_inlist() + { + var lst = new eina.Inlist<int>(); + lst.Append(1); + lst.Append(2); + lst.Append(3); + lst.Append(4); + + eina.Accessor<int> accessor = lst.GetAccessor(); + + var zipped = accessor.Zip(lst, (first, second) => new Tuple<int, int>(first, second)); + + foreach(Tuple<int, int> pair in zipped) + { + Test.AssertEquals(pair.Item1, pair.Item2); + } + } + + public static void basic_accessor_inarray() + { + var arr = new eina.Inarray<int>(); + arr.Append(base_seq_int); + + eina.Accessor<int> accessor = arr.GetAccessor(); + + var zipped = accessor.Zip(arr, (first, second) => new Tuple<int, int>(first, second)); + + foreach(Tuple<int, int> pair in zipped) + { + Test.AssertEquals(pair.Item1, pair.Item2); + } + } +} + + } --