[EflSharp] Introduce EflSharp project (#749)
[platform/core/csapi/tizenfx.git] / internals / src / EflSharp / EflSharp / 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         get {
142             return Population();
143         }
144     }
145
146
147     private void InitNew()
148     {
149         Handle = EinaHashNew<TKey>();
150         SetOwn(true);
151         SetOwnKey(true);
152         SetOwnValue(true);
153     }
154
155     public Hash()
156     {
157         InitNew();
158     }
159
160     public Hash(IntPtr handle, bool own)
161     {
162         Handle = handle;
163         SetOwnership(own);
164     }
165
166     public Hash(IntPtr handle, bool own, bool ownKey, bool ownValue)
167     {
168         Handle = handle;
169         SetOwnership(own, ownKey, ownValue);
170     }
171
172     ~Hash()
173     {
174         Dispose(false);
175     }
176
177     protected virtual void Dispose(bool disposing)
178     {
179         IntPtr h = Handle;
180         Handle = IntPtr.Zero;
181         if (h == IntPtr.Zero)
182             return;
183
184         if (Own)
185             eina_hash_free(h);
186     }
187
188     public void Dispose()
189     {
190         Dispose(true);
191         GC.SuppressFinalize(this);
192     }
193
194     public void Free()
195     {
196         Dispose();
197     }
198
199     public IntPtr Release()
200     {
201         IntPtr h = Handle;
202         Handle = IntPtr.Zero;
203         return h;
204     }
205
206     public void SetOwn(bool own)
207     {
208         Own = own;
209     }
210
211     public void SetOwnKey(bool ownKey)
212     {
213         OwnKey = ownKey;
214     }
215
216     public void SetOwnValue(bool ownValue)
217     {
218         OwnValue = ownValue;
219
220         if (ownValue)
221             eina_hash_free_cb_set(Handle, EinaFreeCb<TValue>());
222     }
223
224     public void SetOwnership(bool ownAll)
225     {
226         SetOwn(ownAll);
227         SetOwnKey(ownAll);
228         SetOwnValue(ownAll);
229     }
230
231     public void SetOwnership(bool own, bool ownKey, bool ownValue)
232     {
233         SetOwn(own);
234         SetOwnKey(ownKey);
235         SetOwnValue(ownValue);
236     }
237
238     public void UnSetFreeCb()
239     {
240         eina_hash_free_cb_set(Handle, IntPtr.Zero);
241     }
242
243     public bool AddNew(TKey key, TValue val)
244     {
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);
252         return r;
253     }
254
255     public void Add(TKey key, TValue val)
256     {
257         Set(key, val);
258     }
259
260     public bool DelByKey(TKey key)
261     {
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);
267         return r;
268     }
269
270     public bool DelByValue(TValue val)
271     {
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);
276         return r;
277     }
278
279     public void Remove(TKey key)
280     {
281         DelByKey(key);
282     }
283
284     public TValue Find(TKey key)
285     {
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();
293
294         return NativeToManaged<TValue>(IndirectNative<TValue>(found, false));
295     }
296
297     public bool TryGetValue(TKey key, out TValue val)
298     {
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)
304         {
305             val = default(TValue);
306             return false;
307         }
308         val = NativeToManaged<TValue>(IndirectNative<TValue>(found, false));
309         return true;
310     }
311
312     public bool ContainsKey(TKey key)
313     {
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;
321     }
322
323     public bool Modify(TKey key, TValue val)
324     {
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)
333         {
334             NativeFree<TValue>(nv);
335             return false;
336         }
337         if (OwnValue)
338             NativeFree<TValue>(old);
339         return true;
340     }
341
342     private static bool ForceRefKey<T>()
343     {
344         return (!typeof(T).IsValueType) && (typeof(T) != typeof(string));
345     }
346
347     private static IntPtr CopyNativeObject<T>(T value, bool forceRef)
348     {
349         if (!IsEflObject(typeof(T)) && forceRef)
350         {
351             GCHandle gch = GCHandle.Alloc(new byte[Marshal.SizeOf<T>()], GCHandleType.Pinned);
352             IntPtr pin = gch.AddrOfPinnedObject();
353
354             ManagedToNativeCopyTo(value, pin);
355
356             return GCHandle.ToIntPtr(gch);
357         }
358         else if(IsEflObject(typeof(T)) && forceRef)
359         {
360             GCHandle gch = GCHandle.Alloc(new byte[Marshal.SizeOf<IntPtr>()], GCHandleType.Pinned);
361             IntPtr pin = gch.AddrOfPinnedObject();
362
363             ManagedToNativeCopyTo(value, pin);
364
365             return GCHandle.ToIntPtr(gch);
366         }
367         else
368         {
369             return ManagedToNativeAlloc(value);
370         }
371     }
372     private static IntPtr GetNativePtr<T>(IntPtr gchptr, bool forceRef)
373     {
374         if (forceRef)
375         {
376             GCHandle gch = GCHandle.FromIntPtr(gchptr);
377             IntPtr pin = gch.AddrOfPinnedObject();
378
379             return pin;
380         }
381         else
382         {
383             return gchptr;
384         }
385     }
386     private static void FreeNativeIndirection<T>(IntPtr gchptr, bool forceRef)
387     {
388         if (forceRef)
389         {
390             GCHandle gch = GCHandle.FromIntPtr(gchptr);
391             gch.Free();
392         }
393     }
394
395     private static IntPtr IndirectNative<T>(IntPtr ptr, bool forceRef)
396     {
397         if (forceRef)
398         {
399             IntPtr val = Marshal.ReadIntPtr(ptr);
400             return val;
401         }
402         else
403         {
404             return ptr;
405         }
406     }
407
408     public void Set(TKey key, TValue val)
409     {
410         IntPtr gchnk = CopyNativeObject(key, ForceRefKey<TKey>());
411         IntPtr nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
412
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);
418     }
419
420     public TValue this[TKey key]
421     {
422         get
423         {
424             return Find(key);
425         }
426         set
427         {
428             Set(key, value);
429         }
430     }
431
432     public bool Move(TKey key_old, TKey key_new)
433     {
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);
445         return r;
446     }
447
448     public void FreeBuckets()
449     {
450         eina_hash_free_buckets(Handle);
451     }
452
453     public int Population()
454     {
455         return eina_hash_population(Handle);
456     }
457
458     public Eina.Iterator<TKey> Keys()
459     {
460         return new Eina.Iterator<TKey>(EinaHashIteratorKeyNew<TKey>(Handle), true, false);
461     }
462
463     public Eina.Iterator<TValue> Values()
464     {
465         return new Eina.Iterator<TValue>(eina_hash_iterator_data_new(Handle), true, false);
466     }
467
468     public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
469     {
470         IntPtr itr = eina_hash_iterator_tuple_new(Handle);
471         try
472         {
473             for (IntPtr tuplePtr; eina_iterator_next(itr, out tuplePtr);)
474             {
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);
480             }
481         }
482         finally
483         {
484             eina_iterator_free(itr);
485         }
486     }
487
488     System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
489     {
490         return this.GetEnumerator();
491     }
492 }
493
494 }
495