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
This commit is contained in:
Lauro Moura 2019-09-13 19:22:39 -03:00
parent cfae5ba285
commit e973b87bf8
3 changed files with 76 additions and 6 deletions

View File

@ -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)

View File

@ -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

View File

@ -81,6 +81,7 @@ efl_mono_src = [
'Value.cs',
'ValueEolian.cs',
'Inheritance.cs',
'Hash.cs'
]
efl_mono_suite = executable('efl-mono-suite',