[Bluetooth][Non-ACR] Fix no data exception issue (#787)
[platform/core/csapi/tizenfx.git] / internals / src / EflSharp / EflSharp / efl / eina_hash.cs
1 #pragma warning disable 1591
2
3 using System;
4 using System.Runtime.InteropServices;
5 using System.Collections.Generic;
6
7 using static Eina.TraitFunctions;
8 using static Eina.IteratorNativeFunctions;
9 using static Eina.HashNativeFunctions;
10 using Eina.Callbacks;
11
12 namespace Eina
13 {
14
15 [StructLayout(LayoutKind.Sequential)]
16 public struct HashTupleNative
17 {
18     public IntPtr key;
19     public IntPtr data;
20     public uint   key_length;
21 }
22
23 public static class HashNativeFunctions
24 {
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);
27
28     [DllImport(efl.Libs.Eina)] public static extern void
29         eina_hash_free_cb_set(IntPtr hash, IntPtr data_free_cb);
30
31     [DllImport(efl.Libs.Eina)] public static extern IntPtr
32         eina_hash_string_djb2_new(IntPtr data_free_cb);
33
34     [DllImport(efl.Libs.Eina)] public static extern IntPtr
35         eina_hash_string_superfast_new(IntPtr data_free_cb);
36
37     [DllImport(efl.Libs.Eina)] public static extern IntPtr
38         eina_hash_string_small_new(IntPtr data_free_cb);
39
40     [DllImport(efl.Libs.Eina)] public static extern IntPtr
41         eina_hash_int32_new(IntPtr data_free_cb);
42
43     [DllImport(efl.Libs.Eina)] public static extern IntPtr
44         eina_hash_int64_new(IntPtr data_free_cb);
45
46     [DllImport(efl.Libs.Eina)] public static extern IntPtr
47         eina_hash_pointer_new(IntPtr data_free_cb);
48
49     [DllImport(efl.Libs.Eina)] public static extern IntPtr
50         eina_hash_stringshared_new(IntPtr data_free_cb);
51
52     [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
53         eina_hash_add(IntPtr hash, IntPtr key, IntPtr data);
54
55     [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
56         eina_hash_direct_add(IntPtr hash, IntPtr key, IntPtr data);
57
58     [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
59         eina_hash_del(IntPtr hash, IntPtr key, IntPtr data);
60
61     [DllImport(efl.Libs.Eina)] public static extern IntPtr
62         eina_hash_find(IntPtr hash, IntPtr key);
63
64     [DllImport(efl.Libs.Eina)] public static extern IntPtr
65         eina_hash_modify(IntPtr hash, IntPtr key, IntPtr data);
66
67     [DllImport(efl.Libs.Eina)] public static extern IntPtr
68         eina_hash_set(IntPtr hash, IntPtr key, IntPtr data);
69
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);
72
73     [DllImport(efl.Libs.Eina)] public static extern void
74         eina_hash_free(IntPtr hash);
75
76     [DllImport(efl.Libs.Eina)] public static extern void
77         eina_hash_free_buckets(IntPtr hash);
78
79     [DllImport(efl.Libs.Eina)] public static extern int
80         eina_hash_population(IntPtr hash);
81
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);
84
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);
87
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);
90
91     [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
92         eina_hash_del_by_key(IntPtr hash, IntPtr key);
93
94     [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
95         eina_hash_del_by_data(IntPtr hash, IntPtr data);
96
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);
99
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);
102
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);
105
106     [DllImport(efl.Libs.Eina)] public static extern IntPtr
107         eina_hash_iterator_key_new(IntPtr hash);
108
109     [DllImport(efl.Libs.Eina)] public static extern IntPtr
110         eina_hash_iterator_data_new(IntPtr hash);
111
112     [DllImport(efl.Libs.Eina)] public static extern IntPtr
113         eina_hash_iterator_tuple_new(IntPtr hash);
114
115     [DllImport(efl.Libs.Eina)] public static extern void
116         eina_hash_foreach(IntPtr hash, IntPtr func, IntPtr fdata);
117
118
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);
125
126     [DllImport(efl.Libs.Eina)] public static extern int
127         eina_hash_superfast(string key, int len);
128
129     [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
130         eina_hash_iterator_ptr_key_wrapper_new_custom_export_mono(IntPtr hash);
131 }
132
133 public class Hash<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>, IDisposable
134 {
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;}
139
140     public int Count
141     {
142         get
143         {
144             return Population();
145         }
146     }
147
148
149     private void InitNew()
150     {
151         Handle = EinaHashNew<TKey>();
152         SetOwn(true);
153         SetOwnKey(true);
154         SetOwnValue(true);
155     }
156
157     public Hash()
158     {
159         InitNew();
160     }
161
162     public Hash(IntPtr handle, bool own)
163     {
164         Handle = handle;
165         SetOwnership(own);
166     }
167
168     public Hash(IntPtr handle, bool own, bool ownKey, bool ownValue)
169     {
170         Handle = handle;
171         SetOwnership(own, ownKey, ownValue);
172     }
173
174     ~Hash()
175     {
176         Dispose(false);
177     }
178
179     protected virtual void Dispose(bool disposing)
180     {
181         IntPtr h = Handle;
182         Handle = IntPtr.Zero;
183         if (h == IntPtr.Zero)
184         {
185             return;
186         }
187
188         if (Own)
189         {
190             eina_hash_free(h);
191         }
192     }
193
194     public void Dispose()
195     {
196         Dispose(true);
197         GC.SuppressFinalize(this);
198     }
199
200     public void Free()
201     {
202         Dispose();
203     }
204
205     public IntPtr Release()
206     {
207         IntPtr h = Handle;
208         Handle = IntPtr.Zero;
209         return h;
210     }
211
212     public void SetOwn(bool own)
213     {
214         Own = own;
215     }
216
217     public void SetOwnKey(bool ownKey)
218     {
219         OwnKey = ownKey;
220     }
221
222     public void SetOwnValue(bool ownValue)
223     {
224         OwnValue = ownValue;
225
226         if (ownValue)
227         {
228             eina_hash_free_cb_set(Handle, EinaFreeCb<TValue>());
229         }
230     }
231
232     public void SetOwnership(bool ownAll)
233     {
234         SetOwn(ownAll);
235         SetOwnKey(ownAll);
236         SetOwnValue(ownAll);
237     }
238
239     public void SetOwnership(bool own, bool ownKey, bool ownValue)
240     {
241         SetOwn(own);
242         SetOwnKey(ownKey);
243         SetOwnValue(ownValue);
244     }
245
246     public void UnSetFreeCb()
247     {
248         eina_hash_free_cb_set(Handle, IntPtr.Zero);
249     }
250
251     public bool AddNew(TKey key, TValue val)
252     {
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);
260         return r;
261     }
262
263     public void Add(TKey key, TValue val)
264     {
265         Set(key, val);
266     }
267
268     public bool DelByKey(TKey key)
269     {
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);
275         return r;
276     }
277
278     public bool DelByValue(TValue val)
279     {
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);
284         return r;
285     }
286
287     public void Remove(TKey key)
288     {
289         DelByKey(key);
290     }
291
292     public TValue Find(TKey key)
293     {
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)
300         {
301             throw new KeyNotFoundException();
302         }
303
304         return NativeToManaged<TValue>(IndirectNative<TValue>(found, false));
305     }
306
307     public bool TryGetValue(TKey key, out TValue val)
308     {
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)
314         {
315             val = default(TValue);
316             return false;
317         }
318
319         val = NativeToManaged<TValue>(IndirectNative<TValue>(found, false));
320         return true;
321     }
322
323     public bool ContainsKey(TKey key)
324     {
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;
332     }
333
334     public bool Modify(TKey key, TValue val)
335     {
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)
344         {
345             NativeFree<TValue>(nv);
346             return false;
347         }
348
349         if (OwnValue)
350         {
351             NativeFree<TValue>(old);
352         }
353
354         return true;
355     }
356
357     private static bool ForceRefKey<T>()
358     {
359         return (!typeof(T).IsValueType) && (typeof(T) != typeof(string));
360     }
361
362     private static IntPtr CopyNativeObject<T>(T value, bool forceRef)
363     {
364         if (!IsEflObject(typeof(T)) && forceRef)
365         {
366             GCHandle gch = GCHandle.Alloc(new byte[Marshal.SizeOf<T>()], GCHandleType.Pinned);
367             IntPtr pin = gch.AddrOfPinnedObject();
368
369             ManagedToNativeCopyTo(value, pin);
370
371             return GCHandle.ToIntPtr(gch);
372         }
373         else if (IsEflObject(typeof(T)) && forceRef)
374         {
375             GCHandle gch = GCHandle.Alloc(new byte[Marshal.SizeOf<IntPtr>()], GCHandleType.Pinned);
376             IntPtr pin = gch.AddrOfPinnedObject();
377
378             ManagedToNativeCopyTo(value, pin);
379
380             return GCHandle.ToIntPtr(gch);
381         }
382         else
383         {
384             return ManagedToNativeAlloc(value);
385         }
386     }
387
388     private static IntPtr GetNativePtr<T>(IntPtr gchptr, bool forceRef)
389     {
390         if (forceRef)
391         {
392             GCHandle gch = GCHandle.FromIntPtr(gchptr);
393             IntPtr pin = gch.AddrOfPinnedObject();
394
395             return pin;
396         }
397         else
398         {
399             return gchptr;
400         }
401     }
402
403     private static void FreeNativeIndirection<T>(IntPtr gchptr, bool forceRef)
404     {
405         if (forceRef)
406         {
407             GCHandle gch = GCHandle.FromIntPtr(gchptr);
408             gch.Free();
409         }
410     }
411
412     private static IntPtr IndirectNative<T>(IntPtr ptr, bool forceRef)
413     {
414         if (forceRef)
415         {
416             IntPtr val = Marshal.ReadIntPtr(ptr);
417             return val;
418         }
419         else
420         {
421             return ptr;
422         }
423     }
424
425     public void Set(TKey key, TValue val)
426     {
427         IntPtr gchnk = CopyNativeObject(key, ForceRefKey<TKey>());
428         IntPtr nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
429
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)
436         {
437             NativeFree<TValue>(old);
438         }
439     }
440
441     public TValue this[TKey key]
442     {
443         get
444         {
445             return Find(key);
446         }
447         set
448         {
449             Set(key, value);
450         }
451     }
452
453     public bool Move(TKey key_old, TKey key_new)
454     {
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);
466         return r;
467     }
468
469     public void FreeBuckets()
470     {
471         eina_hash_free_buckets(Handle);
472     }
473
474     public int Population()
475     {
476         return eina_hash_population(Handle);
477     }
478
479     public Eina.Iterator<TKey> Keys()
480     {
481         return new Eina.Iterator<TKey>(EinaHashIteratorKeyNew<TKey>(Handle), true, false);
482     }
483
484     public Eina.Iterator<TValue> Values()
485     {
486         return new Eina.Iterator<TValue>(eina_hash_iterator_data_new(Handle), true, false);
487     }
488
489     public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
490     {
491         IntPtr itr = eina_hash_iterator_tuple_new(Handle);
492         try
493         {
494             for (IntPtr tuplePtr; eina_iterator_next(itr, out tuplePtr);)
495             {
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);
501             }
502         }
503         finally
504         {
505             eina_iterator_free(itr);
506         }
507     }
508
509     System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
510     {
511         return this.GetEnumerator();
512     }
513 }
514
515 }