[EflSharp] Update Circle and efl cs files (#945)
[platform/core/csapi/tizenfx.git] / internals / src / EflSharp / EflSharp / efl / eina_container_common.cs
1 #pragma warning disable 1591
2
3 using System;
4 using System.Linq;
5 using System.Runtime.InteropServices;
6 using System.Collections.Generic;
7 using System.Reflection;
8
9 using Eina.Callbacks;
10 using static Eina.HashNativeFunctions;
11 using static Eina.InarrayNativeFunctions;
12 using static Eina.InlistNativeFunctions;
13 using static Eina.NativeCustomExportFunctions;
14
15 namespace Eina
16 {
17
18 public enum ElementType
19 {
20     NumericType,
21     StringType,
22     StringshareType,
23     ObjectType
24 };
25
26 [StructLayout(LayoutKind.Sequential)]
27 public struct InlistMem
28 {
29     public IntPtr next {get;set;}
30     public IntPtr prev {get;set;}
31     public IntPtr last {get;set;}
32 }
33
34 [StructLayout(LayoutKind.Sequential)]
35 public struct InlistNode<T>
36 {
37     public InlistMem __in_list {get;set;}
38     public T Val {get;set;}
39 }
40
41 public interface IBaseElementTraits<T>
42 {
43     IntPtr ManagedToNativeAlloc(T man);
44     IntPtr ManagedToNativeAllocInlistNode(T man);
45     void ManagedToNativeCopyTo(T man, IntPtr mem);
46     void NativeFree(IntPtr nat);
47     void NativeFreeInlistNodeElement(IntPtr nat);
48     void NativeFreeInlistNode(IntPtr nat, bool freeElement);
49     void NativeFreeInplace(IntPtr nat);
50     void ResidueFreeInplace(IntPtr nat);
51     T NativeToManaged(IntPtr nat);
52     T NativeToManagedInlistNode(IntPtr nat);
53     T NativeToManagedInplace(IntPtr nat);
54     IntPtr EinaCompareCb();
55     IntPtr EinaFreeCb();
56     IntPtr EinaHashNew();
57     IntPtr EinaInarrayNew(uint step);
58     IntPtr EinaHashIteratorKeyNew(IntPtr hash);
59 }
60
61 public class StringElementTraits : IBaseElementTraits<string>
62 {
63     public StringElementTraits()
64     {
65     }
66
67     public IntPtr ManagedToNativeAlloc(string man)
68     {
69         IntPtr newstring = MemoryNative.StrDup(man);
70         return newstring;
71     }
72
73     public IntPtr ManagedToNativeAllocInlistNode(string man)
74     {
75         var node = new InlistNode<IntPtr>();
76         node.Val = ManagedToNativeAlloc(man);
77         GCHandle pinnedData = GCHandle.Alloc(node, GCHandleType.Pinned);
78         IntPtr ptr = pinnedData.AddrOfPinnedObject();
79         IntPtr nat = MemoryNative.AllocCopy(ptr, Marshal.SizeOf<InlistMem>() + Marshal.SizeOf<IntPtr>());
80         pinnedData.Free();
81         return nat;
82     }
83
84     public void ManagedToNativeCopyTo(string man, IntPtr mem)
85     {
86         IntPtr stringptr = ManagedToNativeAlloc(man);
87         Marshal.WriteIntPtr(mem, stringptr);
88     }
89
90     public void NativeFree(IntPtr nat)
91     {
92         if (nat != IntPtr.Zero)
93         {
94             MemoryNative.Free(nat);
95         }
96     }
97
98     public void NativeFreeInlistNodeElement(IntPtr nat)
99     {
100         if (nat == IntPtr.Zero)
101         {
102             return;
103         }
104
105         var val = Marshal.PtrToStructure<IntPtr>
106             (nat + Marshal.SizeOf<InlistMem>());
107         NativeFree(val);
108     }
109
110     public void NativeFreeInlistNode(IntPtr nat, bool freeElement)
111     {
112         if (nat == IntPtr.Zero)
113         {
114             return;
115         }
116
117         if (freeElement)
118         {
119             NativeFreeInlistNodeElement(nat);
120         }
121
122         MemoryNative.Free(nat);
123     }
124
125     public void NativeFreeInplace(IntPtr nat)
126     {
127         MemoryNative.FreeRef(nat);
128     }
129
130     public void ResidueFreeInplace(IntPtr nat)
131     {
132     }
133
134     public string NativeToManaged(IntPtr nat)
135     {
136         if (nat == IntPtr.Zero)
137         {
138             return default(string);
139         }
140
141         return StringConversion.NativeUtf8ToManagedString(nat);
142     }
143
144     public string NativeToManagedInlistNode(IntPtr nat)
145     {
146         if (nat == IntPtr.Zero)
147         {
148             Eina.Log.Error("Null pointer for Inlist node.");
149             return default(string);
150         }
151
152         IntPtr ptr_location = nat + Marshal.SizeOf<InlistMem>();
153         return NativeToManaged(Marshal.ReadIntPtr(ptr_location));
154     }
155
156     // Strings inplaced are always a pointer, because they are variable-sized
157     public string NativeToManagedInplace(IntPtr nat)
158     {
159         if (nat == IntPtr.Zero)
160         {
161             return default(string);
162         }
163
164         nat = Marshal.ReadIntPtr(nat);
165         if (nat == IntPtr.Zero)
166         {
167             return default(string);
168         }
169
170         return NativeToManaged(nat);
171     }
172
173     public IntPtr EinaCompareCb()
174     {
175         return MemoryNative.StrCompareFuncPtrGet();
176     }
177
178     public IntPtr EinaFreeCb()
179     {
180         return MemoryNative.FreeFuncPtrGet();
181     }
182
183     public IntPtr EinaHashNew()
184     {
185         return eina_hash_string_superfast_new(IntPtr.Zero);
186     }
187
188     public IntPtr EinaInarrayNew(uint step)
189     {
190         return eina_inarray_new((uint)Marshal.SizeOf<IntPtr>(), step);
191     }
192
193     public IntPtr EinaHashIteratorKeyNew(IntPtr hash)
194     {
195         return eina_hash_iterator_key_new(hash);
196     }
197 }
198
199 public class StringshareElementTraits : IBaseElementTraits<Eina.Stringshare>
200 {
201     public StringshareElementTraits()
202     {
203     }
204
205     public IntPtr ManagedToNativeAlloc(Eina.Stringshare man)
206     {
207         var strShare = MemoryNative.AddStringshare(man);
208         return strShare;
209     }
210
211     public IntPtr ManagedToNativeAllocInlistNode(Eina.Stringshare man)
212     {
213         var node = new InlistNode<IntPtr>();
214         node.Val = ManagedToNativeAlloc(man);
215         GCHandle pinnedData = GCHandle.Alloc(node, GCHandleType.Pinned);
216         IntPtr ptr = pinnedData.AddrOfPinnedObject();
217         IntPtr nat = MemoryNative.AllocCopy
218             (ptr, Marshal.SizeOf<InlistMem>() + Marshal.SizeOf<IntPtr>());
219         pinnedData.Free();
220         return nat;
221     }
222
223     public void ManagedToNativeCopyTo(Eina.Stringshare man, IntPtr mem)
224     {
225         IntPtr stringptr = ManagedToNativeAlloc(man);
226         Marshal.WriteIntPtr(mem, stringptr);
227     }
228
229     public void NativeFree(IntPtr nat)
230     {
231         if (nat != IntPtr.Zero)
232         {
233             MemoryNative.DelStringshare(nat);
234         }
235     }
236
237     public void NativeFreeInlistNodeElement(IntPtr nat)
238     {
239         if (nat == IntPtr.Zero)
240         {
241             return;
242         }
243
244         var val = Marshal.PtrToStructure<IntPtr>
245             (nat + Marshal.SizeOf<InlistMem>());
246         NativeFree(val);
247     }
248
249     public void NativeFreeInlistNode(IntPtr nat, bool freeElement)
250     {
251         if (nat == IntPtr.Zero)
252         {
253             return;
254         }
255
256         if (freeElement)
257         {
258             NativeFreeInlistNodeElement(nat);
259         }
260
261         MemoryNative.Free(nat);
262     }
263
264     public void NativeFreeInplace(IntPtr nat)
265     {
266         MemoryNative.DelStringshareRef(nat);
267     }
268
269     public void ResidueFreeInplace(IntPtr nat)
270     {
271     }
272
273     public Eina.Stringshare NativeToManaged(IntPtr nat)
274     {
275         if (nat == IntPtr.Zero)
276         {
277             return default(Eina.Stringshare);
278         }
279
280         return StringConversion.NativeUtf8ToManagedString(nat);
281     }
282
283     public Eina.Stringshare NativeToManagedInlistNode(IntPtr nat)
284     {
285         if (nat == IntPtr.Zero)
286         {
287             Eina.Log.Error("Null pointer for Inlist node.");
288             return default(Eina.Stringshare);
289         }
290
291         IntPtr ptr_location = nat + Marshal.SizeOf<InlistMem>();
292         return NativeToManaged(Marshal.ReadIntPtr(ptr_location));
293     }
294
295     // Strings inplaced are always a pointer, because they are variable-sized
296     public Eina.Stringshare NativeToManagedInplace(IntPtr nat)
297     {
298         if (nat == IntPtr.Zero)
299         {
300             return default(Eina.Stringshare);
301         }
302
303         nat = Marshal.ReadIntPtr(nat);
304         if (nat == IntPtr.Zero)
305         {
306             return default(Eina.Stringshare);
307         }
308
309         return NativeToManaged(nat);
310     }
311
312     public IntPtr EinaCompareCb()
313     {
314         return MemoryNative.StrCompareFuncPtrGet();
315     }
316
317     public IntPtr EinaFreeCb()
318     {
319         return MemoryNative.StringshareDelFuncPtrGet();
320     }
321
322     public IntPtr EinaHashNew()
323     {
324         return eina_hash_stringshared_new(MemoryNative.StringshareDelFuncPtrGet());
325     }
326
327     public IntPtr EinaInarrayNew(uint step)
328     {
329         return eina_inarray_new((uint)Marshal.SizeOf<IntPtr>(), step);
330     }
331
332     public IntPtr EinaHashIteratorKeyNew(IntPtr hash)
333     {
334         return eina_hash_iterator_key_new(hash);
335     }
336 }
337
338 public class EflObjectElementTraits<T> : IBaseElementTraits<T>
339 {
340     public IntPtr ManagedToNativeAlloc(T man)
341     {
342         IntPtr h = ((Efl.Eo.IWrapper)man).NativeHandle;
343         if (h == IntPtr.Zero)
344         {
345             return h;
346         }
347
348         return Efl.Eo.Globals.efl_ref(h);
349     }
350
351     public IntPtr ManagedToNativeAllocInlistNode(T man)
352     {
353         var node = new InlistNode<IntPtr>();
354         node.Val = ManagedToNativeAlloc(man);
355         GCHandle pinnedData = GCHandle.Alloc(node, GCHandleType.Pinned);
356         IntPtr ptr = pinnedData.AddrOfPinnedObject();
357         IntPtr nat = MemoryNative.AllocCopy(ptr, Marshal.SizeOf<InlistMem>() + Marshal.SizeOf<IntPtr>());
358         pinnedData.Free();
359         return nat;
360     }
361
362     public void ManagedToNativeCopyTo(T man, IntPtr mem)
363     {
364         IntPtr v = ManagedToNativeAlloc(man);
365         Marshal.WriteIntPtr(mem, v);
366     }
367
368     public void NativeFree(IntPtr nat)
369     {
370         if (nat != IntPtr.Zero)
371         {
372             Efl.Eo.Globals.efl_mono_thread_safe_efl_unref(nat);
373         }
374     }
375
376     public void NativeFreeRef(IntPtr nat, bool unrefs)
377     {
378         if (unrefs)
379         {
380             NativeFree(nat);
381         }
382     }
383
384     public void NativeFreeInlistNodeElement(IntPtr nat)
385     {
386         if (nat == IntPtr.Zero)
387         {
388             return;
389         }
390
391         var val = Marshal.PtrToStructure<IntPtr>
392             (nat + Marshal.SizeOf<InlistMem>());
393         NativeFree(val);
394     }
395
396     public void NativeFreeInlistNode(IntPtr nat, bool freeElement)
397     {
398         if (nat == IntPtr.Zero)
399         {
400             return;
401         }
402
403         if (freeElement)
404         {
405             NativeFreeInlistNodeElement(nat);
406         }
407
408         MemoryNative.Free(nat);
409     }
410
411     public void NativeFreeInplace(IntPtr nat)
412     {
413         NativeFree(nat);
414     }
415
416     public void ResidueFreeInplace(IntPtr nat)
417     {
418     }
419
420     public T NativeToManaged(IntPtr nat)
421     {
422         if (nat == IntPtr.Zero)
423         {
424             return default(T);
425         }
426
427         return (T) Efl.Eo.Globals.CreateWrapperFor(nat, shouldIncRef: true);
428     }
429
430     public T NativeToManagedRef(IntPtr nat)
431     {
432         if (nat == IntPtr.Zero)
433         {
434             return default(T);
435         }
436
437         return NativeToManaged(nat);
438     }
439
440     public T NativeToManagedInlistNode(IntPtr nat)
441     {
442         if (nat == IntPtr.Zero)
443         {
444             Eina.Log.Error("Null pointer for Inlist node.");
445             return default(T);
446         }
447
448         IntPtr ptr_location = nat + Marshal.SizeOf<InlistMem>();
449         return NativeToManaged(Marshal.ReadIntPtr(ptr_location));
450     }
451
452     // EFL objects inplaced are always a pointer, because they are variable-sized
453     public T NativeToManagedInplace(IntPtr nat)
454     {
455         if (nat == IntPtr.Zero)
456         {
457             return default(T);
458         }
459
460         nat = Marshal.ReadIntPtr(nat);
461         if (nat == IntPtr.Zero)
462         {
463             return default(T);
464         }
465
466         return NativeToManaged(nat);
467     }
468
469     public IntPtr EinaCompareCb()
470     {
471         return MemoryNative.PtrCompareFuncPtrGet();
472     }
473
474     public IntPtr EinaFreeCb()
475     {
476         return MemoryNative.EflUnrefFuncPtrGet();
477     }
478
479     public IntPtr EinaHashNew()
480     {
481         return eina_hash_pointer_new(IntPtr.Zero);
482     }
483
484     public IntPtr EinaInarrayNew(uint step)
485     {
486         return eina_inarray_new((uint)Marshal.SizeOf<IntPtr>(), step);
487     }
488
489     public IntPtr EinaHashIteratorKeyNew(IntPtr hash)
490     {
491         return eina_hash_iterator_ptr_key_wrapper_new_custom_export_mono(hash);
492     }
493 }
494
495 public abstract class PrimitiveElementTraits<T>
496 {
497     private Eina_Compare_Cb dlgt = null;
498
499     public IntPtr ManagedToNativeAlloc(T man)
500     {
501         return PrimitiveConversion.ManagedToPointerAlloc(man);
502     }
503
504     public IntPtr ManagedToNativeAllocInlistNode(T man)
505     {
506         var node = new InlistNode<T>();
507         node.Val = man;
508         GCHandle pinnedData = GCHandle.Alloc(node, GCHandleType.Pinned);
509         IntPtr ptr = pinnedData.AddrOfPinnedObject();
510         int Tsize = Marshal.SizeOf<T>() < Marshal.SizeOf<IntPtr>() ? Marshal.SizeOf<IntPtr>() : Marshal.SizeOf<T>();
511         IntPtr nat = MemoryNative.AllocCopy(ptr, Marshal.SizeOf<InlistMem>() + Tsize);
512         pinnedData.Free();
513         return nat;
514     }
515
516     public void NativeFree(IntPtr nat)
517     {
518         MemoryNative.Free(nat);
519     }
520
521     public void NativeFreeInlistNodeElement(IntPtr nat)
522     {
523         // Do nothing
524     }
525
526     public void NativeFreeInlistNode(IntPtr nat, bool freeElement)
527     {
528         MemoryNative.Free(nat);
529     }
530
531     public void NativeFreeInplace(IntPtr nat)
532     {
533         // Do nothing
534     }
535
536     public void ResidueFreeInplace(IntPtr nat)
537     {
538         NativeFree(nat);
539     }
540
541     public T NativeToManaged(IntPtr nat)
542     {
543         if (nat == IntPtr.Zero)
544         {
545             Eina.Log.Error("Null pointer on primitive/struct container.");
546             return default(T);
547         }
548
549         return PrimitiveConversion.PointerToManaged<T>(nat);
550     }
551
552     public T NativeToManagedRef(IntPtr nat)
553     {
554         return NativeToManaged(nat);
555     }
556
557
558     public T NativeToManagedInplace(IntPtr nat)
559     {
560         return NativeToManaged(nat);
561     }
562
563     private int PrimitiveCompareCb(IntPtr ptr1, IntPtr ptr2)
564     {
565         var m1 = (IComparable)NativeToManaged(ptr1);
566         var m2 = NativeToManaged(ptr2);
567         return m1.CompareTo(m2);
568     }
569
570     public IntPtr EinaCompareCb()
571     {
572         if (dlgt == null)
573         {
574             dlgt = new Eina_Compare_Cb(PrimitiveCompareCb);
575         }
576
577         return Marshal.GetFunctionPointerForDelegate(dlgt);
578     }
579
580     public IntPtr EinaFreeCb()
581     {
582         return MemoryNative.FreeFuncPtrGet();
583     }
584
585     public IntPtr EinaInarrayNew(uint step)
586     {
587         return eina_inarray_new((uint)Marshal.SizeOf<T>(), step);
588     }
589
590     public IntPtr EinaHashIteratorKeyNew(IntPtr hash)
591     {
592         return eina_hash_iterator_key_new(hash);
593     }
594 }
595
596 abstract public class Primitive32ElementTraits<T> : PrimitiveElementTraits<T>, IBaseElementTraits<T>
597 {
598     private static IBaseElementTraits<Int32> int32Traits = null;
599
600     public Primitive32ElementTraits()
601     {
602         if (int32Traits == null)
603         {
604             if (typeof(T) == typeof(Int32)) // avoid infinite recursion
605             {
606                 int32Traits = (IBaseElementTraits<Int32>)this;
607             }
608             else
609             {
610                 int32Traits = TraitFunctions.GetTypeTraits<Int32>();
611             }
612         }
613     }
614
615     public abstract void ManagedToNativeCopyTo(T man, IntPtr mem);
616     public abstract T NativeToManagedInlistNode(IntPtr nat);
617
618     public IntPtr ManagedToNativeAllocRef(T man, bool refs)
619     {
620         return int32Traits.ManagedToNativeAlloc(Convert.ToInt32((object)man));
621     }
622
623     public void NativeFreeRef(IntPtr nat, bool unrefs)
624     {
625         int32Traits.NativeFree(nat);
626     }
627
628     public IntPtr EinaHashNew()
629     {
630         return eina_hash_int32_new(IntPtr.Zero);
631     }
632 }
633
634 abstract public class Primitive64ElementTraits<T> : PrimitiveElementTraits<T>, IBaseElementTraits<T>
635 {
636     private static IBaseElementTraits<Int64> int64Traits = null;
637
638     public Primitive64ElementTraits()
639     {
640         if (int64Traits == null)
641         {
642             if (typeof(T) == typeof(Int64)) // avoid infinite recursion
643             {
644                 int64Traits = (IBaseElementTraits<Int64>)this;
645             }
646             else
647             {
648                 int64Traits = TraitFunctions.GetTypeTraits<Int64>();
649             }
650         }
651     }
652
653     public abstract void ManagedToNativeCopyTo(T man, IntPtr mem);
654     public abstract T NativeToManagedInlistNode(IntPtr nat);
655
656     public IntPtr ManagedToNativeAllocRef(T man, bool refs)
657     {
658         return int64Traits.ManagedToNativeAlloc(Convert.ToInt64((object)man));
659     }
660
661     public void NativeFreeRef(IntPtr nat, bool unrefs)
662     {
663         int64Traits.NativeFree(nat);
664     }
665
666     public IntPtr EinaHashNew()
667     {
668         return eina_hash_int64_new(IntPtr.Zero);
669     }
670 }
671
672 public class IntElementTraits : Primitive32ElementTraits<int>, IBaseElementTraits<int>
673 {
674     override public void ManagedToNativeCopyTo(int man, IntPtr mem)
675     {
676         var arr = new int[1];
677         arr[0] = man;
678         Marshal.Copy(arr, 0, mem, 1);
679     }
680
681     override public int NativeToManagedInlistNode(IntPtr nat)
682     {
683         if (nat == IntPtr.Zero)
684         {
685             Eina.Log.Error("Null pointer for Inlist node.");
686             return default(int);
687         }
688
689         IntPtr loc = nat + Marshal.SizeOf<InlistMem>();
690         var v = new int[1];
691         Marshal.Copy(loc, v, 0, 1);
692         return v[0];
693     }
694 }
695
696 public class CharElementTraits : Primitive32ElementTraits<char>, IBaseElementTraits<char>
697 {
698     override public void ManagedToNativeCopyTo(char man, IntPtr mem)
699     {
700         var arr = new char[1];
701         arr[0] = man;
702         Marshal.Copy(arr, 0, mem, 1);
703     }
704
705     override public char NativeToManagedInlistNode(IntPtr nat)
706     {
707         if (nat == IntPtr.Zero)
708         {
709             Eina.Log.Error("Null pointer for Inlist node.");
710             return default(char);
711         }
712
713         IntPtr loc = nat + Marshal.SizeOf<InlistMem>();
714         var v = new char[1];
715         Marshal.Copy(loc, v, 0, 1);
716         return v[0];
717     }
718 }
719
720 public class LongElementTraits : Primitive64ElementTraits<long>, IBaseElementTraits<long>
721 {
722     override public void ManagedToNativeCopyTo(long man, IntPtr mem)
723     {
724         var arr = new long[1];
725         arr[0] = man;
726         Marshal.Copy(arr, 0, mem, 1);
727     }
728
729     override public long NativeToManagedInlistNode(IntPtr nat)
730     {
731         if (nat == IntPtr.Zero)
732         {
733             Eina.Log.Error("Null pointer for Inlist node.");
734             return default(long);
735         }
736
737         IntPtr loc = nat + Marshal.SizeOf<InlistMem>();
738         var v = new long[1];
739         Marshal.Copy(loc, v, 0, 1);
740         return v[0];
741     }
742 }
743
744 public class ShortElementTraits : Primitive32ElementTraits<short>, IBaseElementTraits<short>
745 {
746     override public void ManagedToNativeCopyTo(short man, IntPtr mem)
747     {
748         var arr = new short[1];
749         arr[0] = man;
750         Marshal.Copy(arr, 0, mem, 1);
751     }
752
753     override public short NativeToManagedInlistNode(IntPtr nat)
754     {
755         if (nat == IntPtr.Zero)
756         {
757             Eina.Log.Error("Null pointer for Inlist node.");
758             return default(short);
759         }
760
761         IntPtr loc = nat + Marshal.SizeOf<InlistMem>();
762         var v = new short[1];
763         Marshal.Copy(loc, v, 0, 1);
764         return v[0];
765     }
766 }
767
768 public class FloatElementTraits : Primitive32ElementTraits<float>, IBaseElementTraits<float>
769 {
770     override public void ManagedToNativeCopyTo(float man, IntPtr mem)
771     {
772         var arr = new float[1];
773         arr[0] = man;
774         Marshal.Copy(arr, 0, mem, 1);
775     }
776
777     override public float NativeToManagedInlistNode(IntPtr nat)
778     {
779         if (nat == IntPtr.Zero)
780         {
781             Eina.Log.Error("Null pointer for Inlist node.");
782             return default(float);
783         }
784
785         IntPtr loc = nat + Marshal.SizeOf<InlistMem>();
786         var v = new float[1];
787         Marshal.Copy(loc, v, 0, 1);
788         return v[0];
789     }
790 }
791
792 public class DoubleElementTraits : Primitive64ElementTraits<double>, IBaseElementTraits<double>
793 {
794     override public void ManagedToNativeCopyTo(double man, IntPtr mem)
795     {
796         var arr = new double[1];
797         arr[0] = man;
798         Marshal.Copy(arr, 0, mem, 1);
799     }
800
801     override public double NativeToManagedInlistNode(IntPtr nat)
802     {
803         if (nat == IntPtr.Zero)
804         {
805             Eina.Log.Error("Null pointer for Inlist node.");
806             return default(double);
807         }
808
809         IntPtr loc = nat + Marshal.SizeOf<InlistMem>();
810         var v = new double[1];
811         Marshal.Copy(loc, v, 0, 1);
812         return v[0];
813     }
814 }
815
816 public class ByteElementTraits : Primitive32ElementTraits<byte>, IBaseElementTraits<byte>
817 {
818     override public void ManagedToNativeCopyTo(byte man, IntPtr mem)
819     {
820         var arr = new byte[1];
821         arr[0] = man;
822         Marshal.Copy(arr, 0, mem, 1);
823     }
824
825     override public byte NativeToManagedInlistNode(IntPtr nat)
826     {
827         if (nat == IntPtr.Zero)
828         {
829             Eina.Log.Error("Null pointer for Inlist node.");
830             return default(byte);
831         }
832
833         IntPtr loc = nat + Marshal.SizeOf<InlistMem>();
834         var v = new byte[1];
835         Marshal.Copy(loc, v, 0, 1);
836         return v[0];
837     }
838 }
839
840 public static class TraitFunctions
841 {
842     public static bool IsEflObject(System.Type type)
843     {
844         return typeof(Efl.Eo.IWrapper).IsAssignableFrom(type);
845     }
846
847     public static bool IsString(System.Type type)
848     {
849         return type == typeof(string);
850     }
851
852     public static bool IsStringshare(System.Type type)
853     {
854         return type == typeof(Eina.Stringshare);
855     }
856
857     public static Eina.ElementType GetElementTypeCode(System.Type type)
858     {
859         if (IsEflObject(type))
860         {
861             return ElementType.ObjectType;
862         }
863         else if (IsString(type))
864         {
865             return ElementType.StringType;
866         }
867         else if (IsStringshare(type))
868         {
869             return ElementType.StringshareType;
870         }
871         else
872         {
873             return ElementType.NumericType;
874         }
875     }
876
877     private static IDictionary<System.Type, object> register = new Dictionary<System.Type, object>();
878
879     private static System.Type AsEflInstantiableType(System.Type type)
880     {
881         if (!IsEflObject(type))
882         {
883             return null;
884         }
885
886         if (type.IsInterface)
887         {
888             string fullName = type.FullName + "Concrete";
889             return type.Assembly.GetType(fullName); // That was our best guess...
890         }
891
892         return type; // Not interface, so it should be a concrete.
893     }
894
895     public static object RegisterTypeTraits<T>()
896     {
897         Eina.Log.Debug($"Finding TypeTraits for {typeof(T).Name}");
898         object traits;
899         var type = typeof(T);
900         if (IsEflObject(type))
901         {
902             System.Type concrete = AsEflInstantiableType(type);
903             if (concrete == null || !type.IsAssignableFrom(concrete))
904             {
905                 throw new Exception("Failed to get a suitable concrete class for this type.");
906             }
907
908             // No need to pass concrete as the traits class will use reflection to get the actually most
909             // derived type returned.
910             traits = new EflObjectElementTraits<T>();
911         }
912         else if (IsString(type))
913         {
914             traits = new StringElementTraits();
915         }
916         else if (IsStringshare(type))
917         {
918             traits = new StringshareElementTraits();
919         }
920         else if (type.IsValueType)
921         {
922             if (type == typeof(int))
923             {
924                 traits = new IntElementTraits();
925             }
926             else if (type == typeof(char))
927             {
928                 traits = new CharElementTraits();
929             }
930             else if (type == typeof(long))
931             {
932                 traits = new LongElementTraits();
933             }
934             else if (type == typeof(short))
935             {
936                 traits = new ShortElementTraits();
937             }
938             else if (type == typeof(float))
939             {
940                 traits = new FloatElementTraits();
941             }
942             else if (type == typeof(double))
943             {
944                 traits = new DoubleElementTraits();
945             }
946             else if (type == typeof(byte))
947             {
948                 traits = new ByteElementTraits();
949             }
950             else
951             {
952                 throw new Exception("No traits registered for this type");
953             }
954         }
955         else
956         {
957             throw new Exception("No traits registered for this type");
958         }
959
960         register[type] = traits;
961         return traits;
962     }
963
964     public static object RegisterTypeTraits<T>(IBaseElementTraits<T> traits)
965     {
966         register[typeof(T)] = traits;
967         return traits;
968     }
969
970     public static IBaseElementTraits<T> GetTypeTraits<T>()
971     {
972         object traits;
973         if (!register.TryGetValue(typeof(T), out traits))
974         {
975             traits = RegisterTypeTraits<T>();
976         }
977
978         return (IBaseElementTraits<T>)traits;
979     }
980
981     //                  //
982     // Traits functions //
983     //                  //
984
985     // Convertion functions //
986
987     public static IntPtr ManagedToNativeAlloc<T>(T man)
988     {
989         return GetTypeTraits<T>().ManagedToNativeAlloc(man);
990     }
991
992     public static void ManagedToNativeCopyTo<T>(T man, IntPtr mem)
993     {
994         GetTypeTraits<T>().ManagedToNativeCopyTo(man, mem);
995     }
996
997     public static IntPtr ManagedToNativeAllocInlistNode<T>(T man)
998     {
999         return GetTypeTraits<T>().ManagedToNativeAllocInlistNode(man);
1000     }
1001
1002     public static void NativeFree<T>(IntPtr nat)
1003     {
1004         GetTypeTraits<T>().NativeFree(nat);
1005     }
1006
1007     public static void NativeFreeInlistNodeElement<T>(IntPtr nat)
1008     {
1009         GetTypeTraits<T>().NativeFreeInlistNodeElement(nat);
1010     }
1011
1012     public static void NativeFreeInlistNode<T>(IntPtr nat, bool freeElement = true)
1013     {
1014         GetTypeTraits<T>().NativeFreeInlistNode(nat, freeElement);
1015     }
1016
1017     public static void NativeFreeInplace<T>(IntPtr nat)
1018     {
1019         GetTypeTraits<T>().NativeFreeInplace(nat);
1020     }
1021
1022     public static void ResidueFreeInplace<T>(IntPtr nat)
1023     {
1024         GetTypeTraits<T>().ResidueFreeInplace(nat);
1025     }
1026
1027     public static T NativeToManaged<T>(IntPtr nat)
1028     {
1029         return GetTypeTraits<T>().NativeToManaged(nat);
1030     }
1031
1032     public static T NativeToManagedInlistNode<T>(IntPtr nat)
1033     {
1034         return GetTypeTraits<T>().NativeToManagedInlistNode(nat);
1035     }
1036
1037     public static T NativeToManagedInplace<T>(IntPtr nat)
1038     {
1039         return GetTypeTraits<T>().NativeToManagedInplace(nat);
1040     }
1041
1042     // Misc //
1043
1044     public static IntPtr EinaCompareCb<T>()
1045     {
1046         return GetTypeTraits<T>().EinaCompareCb();
1047     }
1048
1049     public static IntPtr EinaFreeCb<T>()
1050     {
1051         return GetTypeTraits<T>().EinaFreeCb();
1052     }
1053
1054     public static IntPtr EinaHashNew<TKey>()
1055     {
1056         return GetTypeTraits<TKey>().EinaHashNew();
1057     }
1058
1059     public static IntPtr EinaInarrayNew<T>(uint step)
1060     {
1061         return GetTypeTraits<T>().EinaInarrayNew(step);
1062     }
1063
1064     public static IntPtr EinaHashIteratorKeyNew<T>(IntPtr hash)
1065     {
1066         return GetTypeTraits<T>().EinaHashIteratorKeyNew(hash);
1067     }
1068 }
1069
1070 }