lauromoura pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=e973b87bf845bc6375b7608be40ba9a0851cd4e6
commit e973b87bf845bc6375b7608be40ba9a0851cd4e6 Author: Lauro Moura <[email protected]> Date: Fri Sep 13 19:22:39 2019 -0300 csharp: Fix Hash.DelByValue Summary: The C function `eina_hash_del_by_data` requires the same value that was passed to the `add` function. As C# hashes store stuff through pointers due to marshalling, this makes it hard to pass the same pointer for it. So this functionality is implemented at C# level instead of relying on the native function directly. Fixes T8198 Thanks to @brunobelo and @singh.amitesh for the test case. Reviewers: singh.amitesh, felipealmeida, brunobelo Reviewed By: brunobelo Subscribers: cedric, #reviewers, #committers, singh.amitesh, brunobelo Tags: #efl Maniphest Tasks: T8198 Differential Revision: https://phab.enlightenment.org/D9853 --- src/bindings/mono/eina_mono/eina_hash.cs | 26 +++++++++++---- src/tests/efl_mono/Hash.cs | 55 ++++++++++++++++++++++++++++++++ src/tests/efl_mono/meson.build | 1 + 3 files changed, 76 insertions(+), 6 deletions(-) diff --git a/src/bindings/mono/eina_mono/eina_hash.cs b/src/bindings/mono/eina_mono/eina_hash.cs index 38522dc0e3..dc5c0fd294 100644 --- a/src/bindings/mono/eina_mono/eina_hash.cs +++ b/src/bindings/mono/eina_mono/eina_hash.cs @@ -278,17 +278,31 @@ public class Hash<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>, IDi IntPtr nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>()); var r = eina_hash_del_by_key(Handle, nk); FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>()); - // NativeFreeRef<TKey>(nk, OwnKey && r); return r; } + /// <summary>Searches this hash for <c>val</c> and deletes it from the hash, also deleting it.</summary> + /// <returns><c>true</c> if the value was found and deleted, false if it was <c>null</c> or not found.</returns> public bool DelByValue(TValue val) { - IntPtr gchnv = CopyNativeObject(val, false); - IntPtr nv = GetNativePtr<TValue>(gchnv, false); - var r = eina_hash_del_by_data(Handle, nv); - FreeNativeIndirection<TValue>(gchnv, false); - return r; + // We don't use the C version of `eina_hash_del_by_data` because it requires the exact pointer + // we passed to add(). As our hashes store the data by pointer, this makes it harder to pass the + // same value. + if (val == null) + { + return false; + } + + foreach (var pair in this) + { + if (pair.Value != null && val.Equals(pair.Value)) + { + return this.DelByKey(pair.Key); + } + } + + return false; + } public void Remove(TKey key) diff --git a/src/tests/efl_mono/Hash.cs b/src/tests/efl_mono/Hash.cs new file mode 100644 index 0000000000..e064e47a13 --- /dev/null +++ b/src/tests/efl_mono/Hash.cs @@ -0,0 +1,55 @@ +using System; + +namespace TestSuite { + +class TestHash +{ + + public static void test_del_value() + { + var hash = new Eina.Hash<int, int>(); + Test.AssertEquals(hash.Count, 0); + hash.Add(0, 1); + Test.Assert(hash.DelByValue(1)); + Test.AssertEquals(hash.Count, 0); + + hash.Add(0, 1); + hash.Add(1, 100); + hash.Add(2, 101); + + Test.Assert(hash.DelByValue(100)); + Test.AssertEquals(hash.Count, 2); + + Test.Assert(!hash.DelByValue(200)); + } + + public static void test_del_value_string() + { + var hash = new Eina.Hash<int, string>(); + Test.AssertEquals(hash.Count, 0); + hash.Add(0, "E F L"); + Test.Assert(hash.DelByValue("E F L")); + Test.AssertEquals(hash.Count, 0); + + hash.Add(0, "Eina"); + hash.Add(1, "Eo"); + hash.Add(2, "Ecore"); + + Test.Assert(hash.DelByValue("Ecore")); + Test.AssertEquals(hash.Count, 2); + + Test.Assert(!hash.DelByValue("Elementary")); + } + + public static void test_del_key() + { + var hash = new Eina.Hash<int, int>(); + hash.Add(0, 1); + hash.Add(1, 100); + hash.Add(2, 101); + + hash.DelByKey(1); + Test.AssertEquals(hash.Count, 2); + } +} +} // namespace TestSuite diff --git a/src/tests/efl_mono/meson.build b/src/tests/efl_mono/meson.build index 445c823caa..8dedc3e543 100644 --- a/src/tests/efl_mono/meson.build +++ b/src/tests/efl_mono/meson.build @@ -81,6 +81,7 @@ efl_mono_src = [ 'Value.cs', 'ValueEolian.cs', 'Inheritance.cs', + 'Hash.cs' ] efl_mono_suite = executable('efl-mono-suite', --
