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;}
147 private void InitNew()
149 Handle = EinaHashNew<TKey>();
160 public Hash(IntPtr handle, bool own)
166 public Hash(IntPtr handle, bool own, bool ownKey, bool ownValue)
169 SetOwnership(own, ownKey, ownValue);
177 protected virtual void Dispose(bool disposing)
180 Handle = IntPtr.Zero;
181 if (h == IntPtr.Zero)
188 public void Dispose()
191 GC.SuppressFinalize(this);
199 public IntPtr Release()
202 Handle = IntPtr.Zero;
206 public void SetOwn(bool own)
211 public void SetOwnKey(bool ownKey)
216 public void SetOwnValue(bool ownValue)
221 eina_hash_free_cb_set(Handle, EinaFreeCb<TValue>());
224 public void SetOwnership(bool ownAll)
231 public void SetOwnership(bool own, bool ownKey, bool ownValue)
235 SetOwnValue(ownValue);
238 public void UnSetFreeCb()
240 eina_hash_free_cb_set(Handle, IntPtr.Zero);
243 public bool AddNew(TKey key, TValue val)
245 IntPtr gchnk = CopyNativeObject(key, ForceRefKey<TKey>());
246 IntPtr nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
247 IntPtr gchnv = CopyNativeObject(val, false);
248 IntPtr nv = GetNativePtr<TValue>(gchnv, false);
249 var r = eina_hash_add(Handle, nk, nv);
250 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
251 FreeNativeIndirection<TValue>(gchnv, false);
255 public void Add(TKey key, TValue val)
260 public bool DelByKey(TKey key)
262 IntPtr gchnk = CopyNativeObject(key, ForceRefKey<TKey>());
263 IntPtr nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
264 var r = eina_hash_del_by_key(Handle, nk);
265 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
266 // NativeFreeRef<TKey>(nk, OwnKey && r);
270 public bool DelByValue(TValue val)
272 IntPtr gchnv = CopyNativeObject(val, false);
273 IntPtr nv = GetNativePtr<TValue>(gchnv, false);
274 var r = eina_hash_del_by_data(Handle, nv);
275 FreeNativeIndirection<TValue>(gchnv, false);
279 public void Remove(TKey key)
284 public TValue Find(TKey key)
286 var gchnk = CopyNativeObject<TKey>(key, ForceRefKey<TKey>());
287 var nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
288 var found = eina_hash_find(Handle, nk);
289 //NativeFreeRef<TKey>(nk);
290 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
291 if (found == IntPtr.Zero)
292 throw new KeyNotFoundException();
294 return NativeToManaged<TValue>(IndirectNative<TValue>(found, false));
297 public bool TryGetValue(TKey key, out TValue val)
299 var gchnk = CopyNativeObject<TKey>(key, ForceRefKey<TKey>());
300 var nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
301 var found = eina_hash_find(Handle, nk);
302 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
303 if (found == IntPtr.Zero)
305 val = default(TValue);
308 val = NativeToManaged<TValue>(IndirectNative<TValue>(found, false));
312 public bool ContainsKey(TKey key)
314 var gchnk = CopyNativeObject<TKey>(key, ForceRefKey<TKey>());
315 var nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
316 // var nk = ManagedToNativeAllocRef(key);
317 var found = eina_hash_find(Handle, nk);
318 // NativeFreeRef<TKey>(nk);
319 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
320 return found != IntPtr.Zero;
323 public bool Modify(TKey key, TValue val)
325 var gchnk = CopyNativeObject<TKey>(key, ForceRefKey<TKey>());
326 var nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
327 var gchnv = CopyNativeObject<TValue>(val, false);
328 var nv = GetNativePtr<TValue>(gchnv, false);
329 var old = eina_hash_modify(Handle, nk, nv);
330 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
331 // NativeFreeRef<TKey>(nk);
332 if (old == IntPtr.Zero)
334 NativeFree<TValue>(nv);
338 NativeFree<TValue>(old);
342 private static bool ForceRefKey<T>()
344 return (!typeof(T).IsValueType) && (typeof(T) != typeof(string));
347 private static IntPtr CopyNativeObject<T>(T value, bool forceRef)
349 if (!IsEflObject(typeof(T)) && forceRef)
351 GCHandle gch = GCHandle.Alloc(new byte[Marshal.SizeOf<T>()], GCHandleType.Pinned);
352 IntPtr pin = gch.AddrOfPinnedObject();
354 ManagedToNativeCopyTo(value, pin);
356 return GCHandle.ToIntPtr(gch);
358 else if(IsEflObject(typeof(T)) && forceRef)
360 GCHandle gch = GCHandle.Alloc(new byte[Marshal.SizeOf<IntPtr>()], GCHandleType.Pinned);
361 IntPtr pin = gch.AddrOfPinnedObject();
363 ManagedToNativeCopyTo(value, pin);
365 return GCHandle.ToIntPtr(gch);
369 return ManagedToNativeAlloc(value);
372 private static IntPtr GetNativePtr<T>(IntPtr gchptr, bool forceRef)
376 GCHandle gch = GCHandle.FromIntPtr(gchptr);
377 IntPtr pin = gch.AddrOfPinnedObject();
386 private static void FreeNativeIndirection<T>(IntPtr gchptr, bool forceRef)
390 GCHandle gch = GCHandle.FromIntPtr(gchptr);
395 private static IntPtr IndirectNative<T>(IntPtr ptr, bool forceRef)
399 IntPtr val = Marshal.ReadIntPtr(ptr);
408 public void Set(TKey key, TValue val)
410 IntPtr gchnk = CopyNativeObject(key, ForceRefKey<TKey>());
411 IntPtr nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
413 IntPtr gchnv = CopyNativeObject(val, false);
414 IntPtr nv = GetNativePtr<TValue>(gchnv, false);
415 IntPtr old = eina_hash_set(Handle, nk, nv);
416 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
417 FreeNativeIndirection<TValue>(gchnv, false);
420 public TValue this[TKey key]
432 public bool Move(TKey key_old, TKey key_new)
434 IntPtr gchnko = CopyNativeObject(key_old, ForceRefKey<TKey>());
435 IntPtr nko = GetNativePtr<TKey>(gchnko, ForceRefKey<TKey>());
436 IntPtr gchnk = CopyNativeObject(key_new, ForceRefKey<TKey>());
437 IntPtr nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
438 // var nk_old = ManagedToNativeAllocRef(key_old);
439 // var nk_new = ManagedToNativeAllocRef(key_new, true);
440 var r = eina_hash_move(Handle, nko, nk);
441 FreeNativeIndirection<TKey>(gchnko, ForceRefKey<TKey>());
442 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
443 // NativeFreeRef<TKey>(nk_old, OwnKey && r);
444 // NativeFreeRef<TKey>(nk_new, !r);
448 public void FreeBuckets()
450 eina_hash_free_buckets(Handle);
453 public int Population()
455 return eina_hash_population(Handle);
458 public Eina.Iterator<TKey> Keys()
460 return new Eina.Iterator<TKey>(EinaHashIteratorKeyNew<TKey>(Handle), true, false);
463 public Eina.Iterator<TValue> Values()
465 return new Eina.Iterator<TValue>(eina_hash_iterator_data_new(Handle), true, false);
468 public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
470 IntPtr itr = eina_hash_iterator_tuple_new(Handle);
473 for (IntPtr tuplePtr; eina_iterator_next(itr, out tuplePtr);)
475 var tuple = Marshal.PtrToStructure<Eina.HashTupleNative>(tuplePtr);
476 IntPtr ikey = IndirectNative<TKey>(tuple.key, ForceRefKey<TKey>());
477 var key = NativeToManaged<TKey>(ikey);
478 var val = NativeToManaged<TValue>(tuple.data);
479 yield return new KeyValuePair<TKey, TValue>(key, val);
484 eina_iterator_free(itr);
488 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
490 return this.GetEnumerator();