1 #pragma warning disable 1591
4 using System.Runtime.InteropServices;
5 using System.Collections.Generic;
7 using static Eina.TraitFunctions;
8 using static Eina.IteratorNativeFunctions;
9 using static Eina.HashNativeFunctions;
15 [StructLayout(LayoutKind.Sequential)]
16 public struct HashTupleNative
20 public uint key_length;
23 public static class HashNativeFunctions
25 [DllImport(efl.Libs.Eina)] public static extern IntPtr
26 eina_hash_new(IntPtr key_length_cb, IntPtr key_cmp_cb, IntPtr key_hash_cb, IntPtr data_free_cb, int buckets_power_size);
28 [DllImport(efl.Libs.Eina)] public static extern void
29 eina_hash_free_cb_set(IntPtr hash, IntPtr data_free_cb);
31 [DllImport(efl.Libs.Eina)] public static extern IntPtr
32 eina_hash_string_djb2_new(IntPtr data_free_cb);
34 [DllImport(efl.Libs.Eina)] public static extern IntPtr
35 eina_hash_string_superfast_new(IntPtr data_free_cb);
37 [DllImport(efl.Libs.Eina)] public static extern IntPtr
38 eina_hash_string_small_new(IntPtr data_free_cb);
40 [DllImport(efl.Libs.Eina)] public static extern IntPtr
41 eina_hash_int32_new(IntPtr data_free_cb);
43 [DllImport(efl.Libs.Eina)] public static extern IntPtr
44 eina_hash_int64_new(IntPtr data_free_cb);
46 [DllImport(efl.Libs.Eina)] public static extern IntPtr
47 eina_hash_pointer_new(IntPtr data_free_cb);
49 [DllImport(efl.Libs.Eina)] public static extern IntPtr
50 eina_hash_stringshared_new(IntPtr data_free_cb);
52 [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
53 eina_hash_add(IntPtr hash, IntPtr key, IntPtr data);
55 [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
56 eina_hash_direct_add(IntPtr hash, IntPtr key, IntPtr data);
58 [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
59 eina_hash_del(IntPtr hash, IntPtr key, IntPtr data);
61 [DllImport(efl.Libs.Eina)] public static extern IntPtr
62 eina_hash_find(IntPtr hash, IntPtr key);
64 [DllImport(efl.Libs.Eina)] public static extern IntPtr
65 eina_hash_modify(IntPtr hash, IntPtr key, IntPtr data);
67 [DllImport(efl.Libs.Eina)] public static extern IntPtr
68 eina_hash_set(IntPtr hash, IntPtr key, IntPtr data);
70 [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
71 eina_hash_move(IntPtr hash, IntPtr old_key, IntPtr new_key);
73 [DllImport(efl.Libs.Eina)] public static extern void
74 eina_hash_free(IntPtr hash);
76 [DllImport(efl.Libs.Eina)] public static extern void
77 eina_hash_free_buckets(IntPtr hash);
79 [DllImport(efl.Libs.Eina)] public static extern int
80 eina_hash_population(IntPtr hash);
82 [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
83 eina_hash_add_by_hash(IntPtr hash, IntPtr key, int key_length, int key_hash, IntPtr data);
85 [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
86 eina_hash_direct_add_by_hash(IntPtr hash, IntPtr key, int key_length, int key_hash, IntPtr data);
88 [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
89 eina_hash_del_by_key_hash(IntPtr hash, IntPtr key, int key_length, int key_hash);
91 [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
92 eina_hash_del_by_key(IntPtr hash, IntPtr key);
94 [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
95 eina_hash_del_by_data(IntPtr hash, IntPtr data);
97 [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
98 eina_hash_del_by_hash(IntPtr hash, IntPtr key, int key_length, int key_hash, IntPtr data);
100 [DllImport(efl.Libs.Eina)] public static extern IntPtr
101 eina_hash_find_by_hash(IntPtr hash, IntPtr key, int key_length, int key_hash);
103 [DllImport(efl.Libs.Eina)] public static extern IntPtr
104 eina_hash_modify_by_hash(IntPtr hash, IntPtr key, int key_length, int key_hash, IntPtr data);
106 [DllImport(efl.Libs.Eina)] public static extern IntPtr
107 eina_hash_iterator_key_new(IntPtr hash);
109 [DllImport(efl.Libs.Eina)] public static extern IntPtr
110 eina_hash_iterator_data_new(IntPtr hash);
112 [DllImport(efl.Libs.Eina)] public static extern IntPtr
113 eina_hash_iterator_tuple_new(IntPtr hash);
115 [DllImport(efl.Libs.Eina)] public static extern void
116 eina_hash_foreach(IntPtr hash, IntPtr func, IntPtr fdata);
119 [DllImport(efl.Libs.Eina)] public static extern void
120 eina_hash_list_append(IntPtr hash, IntPtr key, IntPtr data);
121 [DllImport(efl.Libs.Eina)] public static extern void
122 eina_hash_list_prepend(IntPtr hash, IntPtr key, IntPtr data);
123 [DllImport(efl.Libs.Eina)] public static extern void
124 eina_hash_list_remove(IntPtr hash, IntPtr key, IntPtr data);
126 [DllImport(efl.Libs.Eina)] public static extern int
127 eina_hash_superfast(string key, int len);
129 [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
130 eina_hash_iterator_ptr_key_wrapper_new_custom_export_mono(IntPtr hash);
133 public class Hash<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>, IDisposable
135 public IntPtr Handle {get; set;} = IntPtr.Zero;
136 public bool Own {get; set;}
137 public bool OwnKey {get; set;}
138 public bool OwnValue {get; set;}
149 private void InitNew()
151 Handle = EinaHashNew<TKey>();
162 public Hash(IntPtr handle, bool own)
168 public Hash(IntPtr handle, bool own, bool ownKey, bool ownValue)
171 SetOwnership(own, ownKey, ownValue);
179 protected virtual void Dispose(bool disposing)
182 Handle = IntPtr.Zero;
183 if (h == IntPtr.Zero)
194 public void Dispose()
197 GC.SuppressFinalize(this);
205 public IntPtr Release()
208 Handle = IntPtr.Zero;
212 public void SetOwn(bool own)
217 public void SetOwnKey(bool ownKey)
222 public void SetOwnValue(bool ownValue)
228 eina_hash_free_cb_set(Handle, EinaFreeCb<TValue>());
232 public void SetOwnership(bool ownAll)
239 public void SetOwnership(bool own, bool ownKey, bool ownValue)
243 SetOwnValue(ownValue);
246 public void UnSetFreeCb()
248 eina_hash_free_cb_set(Handle, IntPtr.Zero);
251 public bool AddNew(TKey key, TValue val)
253 IntPtr gchnk = CopyNativeObject(key, ForceRefKey<TKey>());
254 IntPtr nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
255 IntPtr gchnv = CopyNativeObject(val, false);
256 IntPtr nv = GetNativePtr<TValue>(gchnv, false);
257 var r = eina_hash_add(Handle, nk, nv);
258 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
259 FreeNativeIndirection<TValue>(gchnv, false);
263 public void Add(TKey key, TValue val)
268 public bool DelByKey(TKey key)
270 IntPtr gchnk = CopyNativeObject(key, ForceRefKey<TKey>());
271 IntPtr nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
272 var r = eina_hash_del_by_key(Handle, nk);
273 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
274 // NativeFreeRef<TKey>(nk, OwnKey && r);
278 public bool DelByValue(TValue val)
280 IntPtr gchnv = CopyNativeObject(val, false);
281 IntPtr nv = GetNativePtr<TValue>(gchnv, false);
282 var r = eina_hash_del_by_data(Handle, nv);
283 FreeNativeIndirection<TValue>(gchnv, false);
287 public void Remove(TKey key)
292 public TValue Find(TKey key)
294 var gchnk = CopyNativeObject<TKey>(key, ForceRefKey<TKey>());
295 var nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
296 var found = eina_hash_find(Handle, nk);
297 //NativeFreeRef<TKey>(nk);
298 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
299 if (found == IntPtr.Zero)
301 throw new KeyNotFoundException();
304 return NativeToManaged<TValue>(IndirectNative<TValue>(found, false));
307 public bool TryGetValue(TKey key, out TValue val)
309 var gchnk = CopyNativeObject<TKey>(key, ForceRefKey<TKey>());
310 var nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
311 var found = eina_hash_find(Handle, nk);
312 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
313 if (found == IntPtr.Zero)
315 val = default(TValue);
319 val = NativeToManaged<TValue>(IndirectNative<TValue>(found, false));
323 public bool ContainsKey(TKey key)
325 var gchnk = CopyNativeObject<TKey>(key, ForceRefKey<TKey>());
326 var nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
327 // var nk = ManagedToNativeAllocRef(key);
328 var found = eina_hash_find(Handle, nk);
329 // NativeFreeRef<TKey>(nk);
330 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
331 return found != IntPtr.Zero;
334 public bool Modify(TKey key, TValue val)
336 var gchnk = CopyNativeObject<TKey>(key, ForceRefKey<TKey>());
337 var nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
338 var gchnv = CopyNativeObject<TValue>(val, false);
339 var nv = GetNativePtr<TValue>(gchnv, false);
340 var old = eina_hash_modify(Handle, nk, nv);
341 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
342 // NativeFreeRef<TKey>(nk);
343 if (old == IntPtr.Zero)
345 NativeFree<TValue>(nv);
351 NativeFree<TValue>(old);
357 private static bool ForceRefKey<T>()
359 return (!typeof(T).IsValueType) && (typeof(T) != typeof(string));
362 private static IntPtr CopyNativeObject<T>(T value, bool forceRef)
364 if (!IsEflObject(typeof(T)) && forceRef)
366 GCHandle gch = GCHandle.Alloc(new byte[Marshal.SizeOf<T>()], GCHandleType.Pinned);
367 IntPtr pin = gch.AddrOfPinnedObject();
369 ManagedToNativeCopyTo(value, pin);
371 return GCHandle.ToIntPtr(gch);
373 else if (IsEflObject(typeof(T)) && forceRef)
375 GCHandle gch = GCHandle.Alloc(new byte[Marshal.SizeOf<IntPtr>()], GCHandleType.Pinned);
376 IntPtr pin = gch.AddrOfPinnedObject();
378 ManagedToNativeCopyTo(value, pin);
380 return GCHandle.ToIntPtr(gch);
384 return ManagedToNativeAlloc(value);
388 private static IntPtr GetNativePtr<T>(IntPtr gchptr, bool forceRef)
392 GCHandle gch = GCHandle.FromIntPtr(gchptr);
393 IntPtr pin = gch.AddrOfPinnedObject();
403 private static void FreeNativeIndirection<T>(IntPtr gchptr, bool forceRef)
407 GCHandle gch = GCHandle.FromIntPtr(gchptr);
412 private static IntPtr IndirectNative<T>(IntPtr ptr, bool forceRef)
416 IntPtr val = Marshal.ReadIntPtr(ptr);
425 public void Set(TKey key, TValue val)
427 IntPtr gchnk = CopyNativeObject(key, ForceRefKey<TKey>());
428 IntPtr nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
430 IntPtr gchnv = CopyNativeObject(val, false);
431 IntPtr nv = GetNativePtr<TValue>(gchnv, false);
432 IntPtr old = eina_hash_set(Handle, nk, nv);
433 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
434 FreeNativeIndirection<TValue>(gchnv, false);
435 if (OwnValue || old != IntPtr.Zero)
437 NativeFree<TValue>(old);
441 public TValue this[TKey key]
453 public bool Move(TKey key_old, TKey key_new)
455 IntPtr gchnko = CopyNativeObject(key_old, ForceRefKey<TKey>());
456 IntPtr nko = GetNativePtr<TKey>(gchnko, ForceRefKey<TKey>());
457 IntPtr gchnk = CopyNativeObject(key_new, ForceRefKey<TKey>());
458 IntPtr nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
459 // var nk_old = ManagedToNativeAllocRef(key_old);
460 // var nk_new = ManagedToNativeAllocRef(key_new, true);
461 var r = eina_hash_move(Handle, nko, nk);
462 FreeNativeIndirection<TKey>(gchnko, ForceRefKey<TKey>());
463 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
464 // NativeFreeRef<TKey>(nk_old, OwnKey && r);
465 // NativeFreeRef<TKey>(nk_new, !r);
469 public void FreeBuckets()
471 eina_hash_free_buckets(Handle);
474 public int Population()
476 return eina_hash_population(Handle);
479 public Eina.Iterator<TKey> Keys()
481 return new Eina.Iterator<TKey>(EinaHashIteratorKeyNew<TKey>(Handle), true, false);
484 public Eina.Iterator<TValue> Values()
486 return new Eina.Iterator<TValue>(eina_hash_iterator_data_new(Handle), true, false);
489 public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
491 IntPtr itr = eina_hash_iterator_tuple_new(Handle);
494 for (IntPtr tuplePtr; eina_iterator_next(itr, out tuplePtr);)
496 var tuple = Marshal.PtrToStructure<Eina.HashTupleNative>(tuplePtr);
497 IntPtr ikey = IndirectNative<TKey>(tuple.key, ForceRefKey<TKey>());
498 var key = NativeToManaged<TKey>(ikey);
499 var val = NativeToManaged<TValue>(tuple.data);
500 yield return new KeyValuePair<TKey, TValue>(key, val);
505 eina_iterator_free(itr);
509 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
511 return this.GetEnumerator();