1 #pragma warning disable 1591
5 using System.Runtime.InteropServices;
6 using System.Collections.Generic;
9 using static Eina.HashNativeFunctions;
10 using static Eina.InarrayNativeFunctions;
11 using static Eina.InlistNativeFunctions;
12 using static Eina.NativeCustomExportFunctions;
16 public enum ElementType { NumericType, StringType, ObjectType };
18 [StructLayout(LayoutKind.Sequential)]
19 public struct InlistMem
21 public IntPtr next {get;set;}
22 public IntPtr prev {get;set;}
23 public IntPtr last {get;set;}
26 [StructLayout(LayoutKind.Sequential)]
27 public struct InlistNode<T>
29 public InlistMem __in_list {get;set;}
30 public T Val {get;set;}
33 public interface IBaseElementTraits<T>
35 IntPtr ManagedToNativeAlloc(T man);
36 IntPtr ManagedToNativeAllocInlistNode(T man);
37 void ManagedToNativeCopyTo(T man, IntPtr mem);
38 void NativeFree(IntPtr nat);
39 void NativeFreeInlistNodeElement(IntPtr nat);
40 void NativeFreeInlistNode(IntPtr nat, bool freeElement);
41 void NativeFreeInplace(IntPtr nat);
42 void ResidueFreeInplace(IntPtr nat);
43 T NativeToManaged(IntPtr nat);
44 T NativeToManagedInlistNode(IntPtr nat);
45 T NativeToManagedInplace(IntPtr nat);
46 IntPtr EinaCompareCb();
49 IntPtr EinaInarrayNew(uint step);
50 IntPtr EinaHashIteratorKeyNew(IntPtr hash);
53 public class StringElementTraits : IBaseElementTraits<string>
55 public StringElementTraits()
59 public IntPtr ManagedToNativeAlloc(string man)
61 IntPtr newstring = MemoryNative.StrDup(man);
65 public IntPtr ManagedToNativeAllocInlistNode(string man)
67 var node = new InlistNode<IntPtr>();
68 node.Val = ManagedToNativeAlloc(man);
69 GCHandle pinnedData = GCHandle.Alloc(node, GCHandleType.Pinned);
70 IntPtr ptr = pinnedData.AddrOfPinnedObject();
71 IntPtr nat = MemoryNative.AllocCopy(ptr, Marshal.SizeOf<InlistMem>() + Marshal.SizeOf<IntPtr>());
76 public void ManagedToNativeCopyTo(string man, IntPtr mem)
78 IntPtr stringptr = ManagedToNativeAlloc(man);
79 Marshal.WriteIntPtr(mem, stringptr);
82 public void NativeFree(IntPtr nat)
84 if (nat != IntPtr.Zero)
85 MemoryNative.Free(nat);
88 public void NativeFreeInlistNodeElement(IntPtr nat)
90 if (nat == IntPtr.Zero)
92 var val = Marshal.PtrToStructure<IntPtr>
93 (nat + Marshal.SizeOf<InlistMem>());
97 public void NativeFreeInlistNode(IntPtr nat, bool freeElement)
99 if (nat == IntPtr.Zero)
102 NativeFreeInlistNodeElement(nat);
103 MemoryNative.Free(nat);
106 public void NativeFreeInplace(IntPtr nat)
108 MemoryNative.FreeRef(nat);
111 public void ResidueFreeInplace(IntPtr nat)
115 public string NativeToManaged(IntPtr nat)
117 if (nat == IntPtr.Zero)
118 return default(string);
119 return StringConversion.NativeUtf8ToManagedString(nat);
122 public string NativeToManagedInlistNode(IntPtr nat)
124 if (nat == IntPtr.Zero)
126 Eina.Log.Error("Null pointer for Inlist node.");
127 return default(string);
129 IntPtr ptr_location = nat + Marshal.SizeOf<InlistMem>();
130 return NativeToManaged(Marshal.ReadIntPtr(ptr_location));
133 // Strings inplaced are always a pointer, because they are variable-sized
134 public string NativeToManagedInplace(IntPtr nat)
136 if (nat == IntPtr.Zero)
137 return default(string);
138 nat = Marshal.ReadIntPtr(nat);
139 if (nat == IntPtr.Zero)
140 return default(string);
141 return NativeToManaged(nat);
144 public IntPtr EinaCompareCb()
146 return MemoryNative.StrCompareFuncPtrGet();
149 public IntPtr EinaFreeCb()
151 return MemoryNative.FreeFuncPtrGet();
154 public IntPtr EinaHashNew()
156 return eina_hash_string_superfast_new(IntPtr.Zero);
159 public IntPtr EinaInarrayNew(uint step)
161 return eina_inarray_new((uint)Marshal.SizeOf<IntPtr>(), step);
164 public IntPtr EinaHashIteratorKeyNew(IntPtr hash)
166 return eina_hash_iterator_key_new(hash);
170 public class EflObjectElementTraits<T> : IBaseElementTraits<T>
172 private System.Type concreteType = null;
174 public EflObjectElementTraits(System.Type concrete)
176 concreteType = concrete;
179 public IntPtr ManagedToNativeAlloc(T man)
181 IntPtr h = ((Efl.Eo.IWrapper)man).NativeHandle;
182 if (h == IntPtr.Zero)
184 return Efl.Eo.Globals.efl_ref(h);
187 public IntPtr ManagedToNativeAllocInlistNode(T man)
189 var node = new InlistNode<IntPtr>();
190 node.Val = ManagedToNativeAlloc(man);
191 GCHandle pinnedData = GCHandle.Alloc(node, GCHandleType.Pinned);
192 IntPtr ptr = pinnedData.AddrOfPinnedObject();
193 IntPtr nat = MemoryNative.AllocCopy(ptr, Marshal.SizeOf<InlistMem>() + Marshal.SizeOf<IntPtr>());
198 public void ManagedToNativeCopyTo(T man, IntPtr mem)
200 IntPtr v = ManagedToNativeAlloc(man);
201 Marshal.WriteIntPtr(mem, v);
204 public void NativeFree(IntPtr nat)
206 if (nat != IntPtr.Zero)
207 Efl.Eo.Globals.efl_unref(nat);
210 public void NativeFreeRef(IntPtr nat, bool unrefs)
216 public void NativeFreeInlistNodeElement(IntPtr nat)
218 if (nat == IntPtr.Zero)
220 var val = Marshal.PtrToStructure<IntPtr>
221 (nat + Marshal.SizeOf<InlistMem>());
225 public void NativeFreeInlistNode(IntPtr nat, bool freeElement)
227 if (nat == IntPtr.Zero)
230 NativeFreeInlistNodeElement(nat);
231 MemoryNative.Free(nat);
234 public void NativeFreeInplace(IntPtr nat)
239 public void ResidueFreeInplace(IntPtr nat)
243 public T NativeToManaged(IntPtr nat)
245 if (nat == IntPtr.Zero)
247 return (T) Activator.CreateInstance(concreteType, Efl.Eo.Globals.efl_ref(nat));
250 public T NativeToManagedRef(IntPtr nat)
252 if (nat == IntPtr.Zero)
254 return NativeToManaged(nat);
257 public T NativeToManagedInlistNode(IntPtr nat)
259 if (nat == IntPtr.Zero)
261 Eina.Log.Error("Null pointer for Inlist node.");
264 IntPtr ptr_location = nat + Marshal.SizeOf<InlistMem>();
265 return NativeToManaged(Marshal.ReadIntPtr(ptr_location));
268 // EFL objects inplaced are always a pointer, because they are variable-sized
269 public T NativeToManagedInplace(IntPtr nat)
271 if (nat == IntPtr.Zero)
273 nat = Marshal.ReadIntPtr(nat);
274 if (nat == IntPtr.Zero)
276 return NativeToManaged(nat);
279 public IntPtr EinaCompareCb()
281 return MemoryNative.PtrCompareFuncPtrGet();
284 public IntPtr EinaFreeCb()
286 return MemoryNative.EflUnrefFuncPtrGet();
289 public IntPtr EinaHashNew()
291 return eina_hash_pointer_new(IntPtr.Zero);
294 public IntPtr EinaInarrayNew(uint step)
296 return eina_inarray_new((uint)Marshal.SizeOf<IntPtr>(), step);
299 public IntPtr EinaHashIteratorKeyNew(IntPtr hash)
301 return eina_hash_iterator_ptr_key_wrapper_new_custom_export_mono(hash);
305 public abstract class PrimitiveElementTraits<T>
307 private Eina_Compare_Cb dlgt = null;
309 public IntPtr ManagedToNativeAlloc(T man)
311 return PrimitiveConversion.ManagedToPointerAlloc(man);
314 public IntPtr ManagedToNativeAllocInlistNode(T man)
316 var node = new InlistNode<T>();
318 GCHandle pinnedData = GCHandle.Alloc(node, GCHandleType.Pinned);
319 IntPtr ptr = pinnedData.AddrOfPinnedObject();
320 int Tsize = Marshal.SizeOf<T>() < Marshal.SizeOf<IntPtr>() ? Marshal.SizeOf<IntPtr>() : Marshal.SizeOf<T>();
321 IntPtr nat = MemoryNative.AllocCopy(ptr, Marshal.SizeOf<InlistMem>() + Tsize);
326 public void NativeFree(IntPtr nat)
328 MemoryNative.Free(nat);
331 public void NativeFreeInlistNodeElement(IntPtr nat)
336 public void NativeFreeInlistNode(IntPtr nat, bool freeElement)
338 MemoryNative.Free(nat);
341 public void NativeFreeInplace(IntPtr nat)
346 public void ResidueFreeInplace(IntPtr nat)
351 public T NativeToManaged(IntPtr nat)
353 if (nat == IntPtr.Zero)
355 Eina.Log.Error("Null pointer on primitive/struct container.");
358 return PrimitiveConversion.PointerToManaged<T>(nat);
361 public T NativeToManagedRef(IntPtr nat)
363 return NativeToManaged(nat);
367 public T NativeToManagedInplace(IntPtr nat)
369 return NativeToManaged(nat);
372 private int PrimitiveCompareCb(IntPtr ptr1, IntPtr ptr2)
374 var m1 = (IComparable) NativeToManaged(ptr1);
375 var m2 = NativeToManaged(ptr2);
376 return m1.CompareTo(m2);
379 public IntPtr EinaCompareCb()
382 dlgt = new Eina_Compare_Cb(PrimitiveCompareCb);
383 return Marshal.GetFunctionPointerForDelegate(dlgt);
386 public IntPtr EinaFreeCb()
388 return MemoryNative.FreeFuncPtrGet();
391 public IntPtr EinaInarrayNew(uint step)
393 return eina_inarray_new((uint)Marshal.SizeOf<T>(), step);
396 public IntPtr EinaHashIteratorKeyNew(IntPtr hash)
398 return eina_hash_iterator_key_new(hash);
402 abstract public class Primitive32ElementTraits<T> : PrimitiveElementTraits<T>, IBaseElementTraits<T>
404 private static IBaseElementTraits<Int32> int32Traits = null;
406 public Primitive32ElementTraits()
408 if (int32Traits == null)
409 if (typeof(T) == typeof(Int32)) // avoid infinite recursion
410 int32Traits = (IBaseElementTraits<Int32>)this;
412 int32Traits = TraitFunctions.GetTypeTraits<Int32>();
415 public abstract void ManagedToNativeCopyTo(T man, IntPtr mem);
416 public abstract T NativeToManagedInlistNode(IntPtr nat);
418 public IntPtr ManagedToNativeAllocRef(T man, bool refs)
420 return int32Traits.ManagedToNativeAlloc(Convert.ToInt32((object)man));
423 public void NativeFreeRef(IntPtr nat, bool unrefs)
425 int32Traits.NativeFree(nat);
428 public IntPtr EinaHashNew()
430 return eina_hash_int32_new(IntPtr.Zero);
434 abstract public class Primitive64ElementTraits<T> : PrimitiveElementTraits<T>, IBaseElementTraits<T>
436 private static IBaseElementTraits<Int64> int64Traits = null;
438 public Primitive64ElementTraits()
440 if (int64Traits == null)
441 if (typeof(T) == typeof(Int64)) // avoid infinite recursion
442 int64Traits = (IBaseElementTraits<Int64>)this;
444 int64Traits = TraitFunctions.GetTypeTraits<Int64>();
447 public abstract void ManagedToNativeCopyTo(T man, IntPtr mem);
448 public abstract T NativeToManagedInlistNode(IntPtr nat);
450 public IntPtr ManagedToNativeAllocRef(T man, bool refs)
452 return int64Traits.ManagedToNativeAlloc(Convert.ToInt64((object)man));
455 public void NativeFreeRef(IntPtr nat, bool unrefs)
457 int64Traits.NativeFree(nat);
460 public IntPtr EinaHashNew()
462 return eina_hash_int64_new(IntPtr.Zero);
466 public class IntElementTraits : Primitive32ElementTraits<int>, IBaseElementTraits<int>
468 override public void ManagedToNativeCopyTo(int man, IntPtr mem)
470 var arr = new int[1];
472 Marshal.Copy(arr, 0, mem, 1);
474 override public int NativeToManagedInlistNode(IntPtr nat)
476 if (nat == IntPtr.Zero)
478 Eina.Log.Error("Null pointer for Inlist node.");
481 IntPtr loc = nat + Marshal.SizeOf<InlistMem>();
483 Marshal.Copy(loc, v, 0, 1);
488 public class CharElementTraits : Primitive32ElementTraits<char>, IBaseElementTraits<char>
490 override public void ManagedToNativeCopyTo(char man, IntPtr mem)
492 var arr = new char[1];
494 Marshal.Copy(arr, 0, mem, 1);
496 override public char NativeToManagedInlistNode(IntPtr nat)
498 if (nat == IntPtr.Zero)
500 Eina.Log.Error("Null pointer for Inlist node.");
501 return default(char);
503 IntPtr loc = nat + Marshal.SizeOf<InlistMem>();
505 Marshal.Copy(loc, v, 0, 1);
509 public class LongElementTraits : Primitive64ElementTraits<long>, IBaseElementTraits<long>
511 override public void ManagedToNativeCopyTo(long man, IntPtr mem)
513 var arr = new long[1];
515 Marshal.Copy(arr, 0, mem, 1);
517 override public long NativeToManagedInlistNode(IntPtr nat)
519 if (nat == IntPtr.Zero)
521 Eina.Log.Error("Null pointer for Inlist node.");
522 return default(long);
524 IntPtr loc = nat + Marshal.SizeOf<InlistMem>();
526 Marshal.Copy(loc, v, 0, 1);
531 public class ShortElementTraits : Primitive32ElementTraits<short>, IBaseElementTraits<short>
533 override public void ManagedToNativeCopyTo(short man, IntPtr mem)
535 var arr = new short[1];
537 Marshal.Copy(arr, 0, mem, 1);
539 override public short NativeToManagedInlistNode(IntPtr nat)
541 if (nat == IntPtr.Zero)
543 Eina.Log.Error("Null pointer for Inlist node.");
544 return default(short);
546 IntPtr loc = nat + Marshal.SizeOf<InlistMem>();
547 var v = new short[1];
548 Marshal.Copy(loc, v, 0, 1);
553 public class FloatElementTraits : Primitive32ElementTraits<float>, IBaseElementTraits<float>
555 override public void ManagedToNativeCopyTo(float man, IntPtr mem)
557 var arr = new float[1];
559 Marshal.Copy(arr, 0, mem, 1);
561 override public float NativeToManagedInlistNode(IntPtr nat)
563 if (nat == IntPtr.Zero)
565 Eina.Log.Error("Null pointer for Inlist node.");
566 return default(float);
568 IntPtr loc = nat + Marshal.SizeOf<InlistMem>();
569 var v = new float[1];
570 Marshal.Copy(loc, v, 0, 1);
575 public class DoubleElementTraits : Primitive64ElementTraits<double>, IBaseElementTraits<double>
577 override public void ManagedToNativeCopyTo(double man, IntPtr mem)
579 var arr = new double[1];
581 Marshal.Copy(arr, 0, mem, 1);
583 override public double NativeToManagedInlistNode(IntPtr nat)
585 if (nat == IntPtr.Zero)
587 Eina.Log.Error("Null pointer for Inlist node.");
588 return default(double);
590 IntPtr loc = nat + Marshal.SizeOf<InlistMem>();
591 var v = new double[1];
592 Marshal.Copy(loc, v, 0, 1);
597 public class ByteElementTraits : Primitive32ElementTraits<byte>, IBaseElementTraits<byte>
599 override public void ManagedToNativeCopyTo(byte man, IntPtr mem)
601 var arr = new byte[1];
603 Marshal.Copy(arr, 0, mem, 1);
605 override public byte NativeToManagedInlistNode(IntPtr nat)
607 if (nat == IntPtr.Zero)
609 Eina.Log.Error("Null pointer for Inlist node.");
610 return default(byte);
612 IntPtr loc = nat + Marshal.SizeOf<InlistMem>();
614 Marshal.Copy(loc, v, 0, 1);
619 public static class TraitFunctions
621 public static bool IsEflObject(System.Type type)
623 return typeof(Efl.Eo.IWrapper).IsAssignableFrom(type);
626 public static bool IsString(System.Type type)
628 return type == typeof(string);
631 public static Eina.ElementType GetElementTypeCode(System.Type type)
633 if (IsEflObject(type))
634 return ElementType.ObjectType;
635 else if (IsString(type))
636 return ElementType.StringType;
638 return ElementType.NumericType;
641 private static IDictionary<System.Type, object> register = new Dictionary<System.Type, object>();
643 private static System.Type AsEflInstantiableType(System.Type type)
645 if (!IsEflObject(type))
648 if (type.IsInterface)
650 string fullName = type.FullName + "Concrete";
651 return type.Assembly.GetType(fullName); // That was our best guess...
654 return type; // Not interface, so it should be a concrete.
657 public static object RegisterTypeTraits<T>()
659 Eina.Log.Debug($"Finding TypeTraits for {typeof(T).Name}");
661 var type = typeof(T);
662 if (IsEflObject(type))
664 System.Type concrete = AsEflInstantiableType(type);
665 if (concrete == null || !type.IsAssignableFrom(concrete))
666 throw new Exception("Failed to get a suitable concrete class for this type.");
667 traits = new EflObjectElementTraits<T>(concrete);
669 else if (IsString(type))
670 traits = new StringElementTraits();
671 else if (type.IsValueType)
673 if (type == typeof(int))
674 traits = new IntElementTraits();
675 else if (type == typeof(char))
676 traits = new CharElementTraits();
677 else if (type == typeof(long))
678 traits = new LongElementTraits();
679 else if (type == typeof(short))
680 traits = new ShortElementTraits();
681 else if (type == typeof(float))
682 traits = new FloatElementTraits();
683 else if (type == typeof(double))
684 traits = new DoubleElementTraits();
685 else if (type == typeof(byte))
686 traits = new ByteElementTraits();
688 throw new Exception("No traits registered for this type");
691 throw new Exception("No traits registered for this type");
693 register[type] = traits;
697 public static object RegisterTypeTraits<T>(IBaseElementTraits<T> traits)
699 register[typeof(T)] = traits;
703 public static IBaseElementTraits<T> GetTypeTraits<T>()
706 if (!register.TryGetValue(typeof(T), out traits))
707 traits = RegisterTypeTraits<T>();
708 return (IBaseElementTraits<T>) traits;
712 // Traits functions //
715 // Convertion functions //
717 public static IntPtr ManagedToNativeAlloc<T>(T man)
719 return GetTypeTraits<T>().ManagedToNativeAlloc(man);
722 public static void ManagedToNativeCopyTo<T>(T man, IntPtr mem)
724 GetTypeTraits<T>().ManagedToNativeCopyTo(man, mem);
727 public static IntPtr ManagedToNativeAllocInlistNode<T>(T man)
729 return GetTypeTraits<T>().ManagedToNativeAllocInlistNode(man);
732 public static void NativeFree<T>(IntPtr nat)
734 GetTypeTraits<T>().NativeFree(nat);
737 public static void NativeFreeInlistNodeElement<T>(IntPtr nat)
739 GetTypeTraits<T>().NativeFreeInlistNodeElement(nat);
742 public static void NativeFreeInlistNode<T>(IntPtr nat, bool freeElement = true)
744 GetTypeTraits<T>().NativeFreeInlistNode(nat, freeElement);
747 public static void NativeFreeInplace<T>(IntPtr nat)
749 GetTypeTraits<T>().NativeFreeInplace(nat);
752 public static void ResidueFreeInplace<T>(IntPtr nat)
754 GetTypeTraits<T>().ResidueFreeInplace(nat);
757 public static T NativeToManaged<T>(IntPtr nat)
759 return GetTypeTraits<T>().NativeToManaged(nat);
762 public static T NativeToManagedInlistNode<T>(IntPtr nat)
764 return GetTypeTraits<T>().NativeToManagedInlistNode(nat);
767 public static T NativeToManagedInplace<T>(IntPtr nat)
769 return GetTypeTraits<T>().NativeToManagedInplace(nat);
774 public static IntPtr EinaCompareCb<T>()
776 return GetTypeTraits<T>().EinaCompareCb();
779 public static IntPtr EinaFreeCb<T>()
781 return GetTypeTraits<T>().EinaFreeCb();
784 public static IntPtr EinaHashNew<TKey>()
786 return GetTypeTraits<TKey>().EinaHashNew();
789 public static IntPtr EinaInarrayNew<T>(uint step)
791 return GetTypeTraits<T>().EinaInarrayNew(step);
794 public static IntPtr EinaHashIteratorKeyNew<T>(IntPtr hash)
796 return GetTypeTraits<T>().EinaHashIteratorKeyNew(hash);