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)
196 Efl.Eo.Globals.ThreadSafeFreeCbExec(eina_hash_free, h);
201 public void Dispose()
204 GC.SuppressFinalize(this);
212 public IntPtr Release()
215 Handle = IntPtr.Zero;
219 public void SetOwn(bool own)
224 public void SetOwnKey(bool ownKey)
229 public void SetOwnValue(bool ownValue)
235 eina_hash_free_cb_set(Handle, EinaFreeCb<TValue>());
239 public void SetOwnership(bool ownAll)
246 public void SetOwnership(bool own, bool ownKey, bool ownValue)
250 SetOwnValue(ownValue);
253 public void UnSetFreeCb()
255 eina_hash_free_cb_set(Handle, IntPtr.Zero);
258 public bool AddNew(TKey key, TValue val)
260 IntPtr gchnk = CopyNativeObject(key, ForceRefKey<TKey>());
261 IntPtr nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
262 IntPtr gchnv = CopyNativeObject(val, false);
263 IntPtr nv = GetNativePtr<TValue>(gchnv, false);
264 var r = eina_hash_add(Handle, nk, nv);
265 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
266 FreeNativeIndirection<TValue>(gchnv, false);
270 public void Add(TKey key, TValue val)
275 public bool DelByKey(TKey key)
277 IntPtr gchnk = CopyNativeObject(key, ForceRefKey<TKey>());
278 IntPtr nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
279 var r = eina_hash_del_by_key(Handle, nk);
280 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
281 // NativeFreeRef<TKey>(nk, OwnKey && r);
285 public bool DelByValue(TValue val)
287 IntPtr gchnv = CopyNativeObject(val, false);
288 IntPtr nv = GetNativePtr<TValue>(gchnv, false);
289 var r = eina_hash_del_by_data(Handle, nv);
290 FreeNativeIndirection<TValue>(gchnv, false);
294 public void Remove(TKey key)
299 public TValue Find(TKey key)
301 var gchnk = CopyNativeObject<TKey>(key, ForceRefKey<TKey>());
302 var nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
303 var found = eina_hash_find(Handle, nk);
304 //NativeFreeRef<TKey>(nk);
305 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
306 if (found == IntPtr.Zero)
308 throw new KeyNotFoundException();
311 return NativeToManaged<TValue>(IndirectNative<TValue>(found, false));
314 public bool TryGetValue(TKey key, out TValue val)
316 var gchnk = CopyNativeObject<TKey>(key, ForceRefKey<TKey>());
317 var nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
318 var found = eina_hash_find(Handle, nk);
319 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
320 if (found == IntPtr.Zero)
322 val = default(TValue);
326 val = NativeToManaged<TValue>(IndirectNative<TValue>(found, false));
330 public bool ContainsKey(TKey key)
332 var gchnk = CopyNativeObject<TKey>(key, ForceRefKey<TKey>());
333 var nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
334 // var nk = ManagedToNativeAllocRef(key);
335 var found = eina_hash_find(Handle, nk);
336 // NativeFreeRef<TKey>(nk);
337 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
338 return found != IntPtr.Zero;
341 public bool Modify(TKey key, TValue val)
343 var gchnk = CopyNativeObject<TKey>(key, ForceRefKey<TKey>());
344 var nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
345 var gchnv = CopyNativeObject<TValue>(val, false);
346 var nv = GetNativePtr<TValue>(gchnv, false);
347 var old = eina_hash_modify(Handle, nk, nv);
348 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
349 // NativeFreeRef<TKey>(nk);
350 if (old == IntPtr.Zero)
352 NativeFree<TValue>(nv);
358 NativeFree<TValue>(old);
364 private static bool ForceRefKey<T>()
366 return (!typeof(T).IsValueType) && (typeof(T) != typeof(string));
369 private static IntPtr CopyNativeObject<T>(T value, bool forceRef)
371 if (!IsEflObject(typeof(T)) && forceRef)
373 GCHandle gch = GCHandle.Alloc(new byte[Marshal.SizeOf<T>()], GCHandleType.Pinned);
374 IntPtr pin = gch.AddrOfPinnedObject();
376 ManagedToNativeCopyTo(value, pin);
378 return GCHandle.ToIntPtr(gch);
380 else if (IsEflObject(typeof(T)) && forceRef)
382 GCHandle gch = GCHandle.Alloc(new byte[Marshal.SizeOf<IntPtr>()], GCHandleType.Pinned);
383 IntPtr pin = gch.AddrOfPinnedObject();
385 ManagedToNativeCopyTo(value, pin);
387 return GCHandle.ToIntPtr(gch);
391 return ManagedToNativeAlloc(value);
395 private static IntPtr GetNativePtr<T>(IntPtr gchptr, bool forceRef)
399 GCHandle gch = GCHandle.FromIntPtr(gchptr);
400 IntPtr pin = gch.AddrOfPinnedObject();
410 private static void FreeNativeIndirection<T>(IntPtr gchptr, bool forceRef)
414 GCHandle gch = GCHandle.FromIntPtr(gchptr);
419 private static IntPtr IndirectNative<T>(IntPtr ptr, bool forceRef)
423 IntPtr val = Marshal.ReadIntPtr(ptr);
432 public void Set(TKey key, TValue val)
434 IntPtr gchnk = CopyNativeObject(key, ForceRefKey<TKey>());
435 IntPtr nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
437 IntPtr gchnv = CopyNativeObject(val, false);
438 IntPtr nv = GetNativePtr<TValue>(gchnv, false);
439 IntPtr old = eina_hash_set(Handle, nk, nv);
440 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
441 FreeNativeIndirection<TValue>(gchnv, false);
442 if (OwnValue || old != IntPtr.Zero)
444 NativeFree<TValue>(old);
448 public TValue this[TKey key]
460 public bool Move(TKey key_old, TKey key_new)
462 IntPtr gchnko = CopyNativeObject(key_old, ForceRefKey<TKey>());
463 IntPtr nko = GetNativePtr<TKey>(gchnko, ForceRefKey<TKey>());
464 IntPtr gchnk = CopyNativeObject(key_new, ForceRefKey<TKey>());
465 IntPtr nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
466 // var nk_old = ManagedToNativeAllocRef(key_old);
467 // var nk_new = ManagedToNativeAllocRef(key_new, true);
468 var r = eina_hash_move(Handle, nko, nk);
469 FreeNativeIndirection<TKey>(gchnko, ForceRefKey<TKey>());
470 FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
471 // NativeFreeRef<TKey>(nk_old, OwnKey && r);
472 // NativeFreeRef<TKey>(nk_new, !r);
476 public void FreeBuckets()
478 eina_hash_free_buckets(Handle);
481 public int Population()
483 return eina_hash_population(Handle);
486 public Eina.Iterator<TKey> Keys()
488 return new Eina.Iterator<TKey>(EinaHashIteratorKeyNew<TKey>(Handle), true, false);
491 public Eina.Iterator<TValue> Values()
493 return new Eina.Iterator<TValue>(eina_hash_iterator_data_new(Handle), true, false);
496 public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
498 IntPtr itr = eina_hash_iterator_tuple_new(Handle);
501 for (IntPtr tuplePtr; eina_iterator_next(itr, out tuplePtr);)
503 var tuple = Marshal.PtrToStructure<Eina.HashTupleNative>(tuplePtr);
504 IntPtr ikey = IndirectNative<TKey>(tuple.key, ForceRefKey<TKey>());
505 var key = NativeToManaged<TKey>(ikey);
506 var val = NativeToManaged<TValue>(tuple.data);
507 yield return new KeyValuePair<TKey, TValue>(key, val);
512 eina_iterator_free(itr);
516 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
518 return this.GetEnumerator();