diff --git a/DTLib.Dtsod/DtsodFunctions.cs b/DTLib.Dtsod/DtsodConverter.cs similarity index 90% rename from DTLib.Dtsod/DtsodFunctions.cs rename to DTLib.Dtsod/DtsodConverter.cs index 75deffd..d30aaf1 100644 --- a/DTLib.Dtsod/DtsodFunctions.cs +++ b/DTLib.Dtsod/DtsodConverter.cs @@ -1,6 +1,6 @@ namespace DTLib.Dtsod; -public static class DtsodFunctions +public static class DtsodConverter { public static IDtsod ConvertVersion(IDtsod src, DtsodVersion targetVersion) => targetVersion switch @@ -11,7 +11,7 @@ public static class DtsodFunctions #if DEBUG DtsodVersion.V30 => new DtsodV30(src.ToDictionary()), #endif - _ => throw new Exception($"DtsodFunctions.Convert() error: unknown target version <{targetVersion}>"), + _ => throw new Exception($"DtsodConverter.Convert() error: unknown target version <{targetVersion}>"), }; // заменяет дефолтные значения на пользовательские diff --git a/DTLib.Dtsod/DtsodVersion.cs b/DTLib.Dtsod/DtsodVersion.cs index a2a3b0c..b68f0ff 100644 --- a/DTLib.Dtsod/DtsodVersion.cs +++ b/DTLib.Dtsod/DtsodVersion.cs @@ -4,7 +4,8 @@ public enum DtsodVersion : byte { V21 = 21, V22 = 22, - V23 = 23 + V23 = 23, + V24 = 24 #if DEBUG ,V30 = 30 #endif diff --git a/DTLib.Dtsod/V24/Autoarr/Autoarr.cs b/DTLib.Dtsod/V24/Autoarr/Autoarr.cs new file mode 100644 index 0000000..858aa10 --- /dev/null +++ b/DTLib.Dtsod/V24/Autoarr/Autoarr.cs @@ -0,0 +1,97 @@ +namespace DTLib.Dtsod.V24.Autoarr; + +public class Autoarr : IEnumerable, IDisposable where T : struct +{ + private readonly IntPtr AutoarrHandler; + private readonly AutoarrFunctions Funcs; + public readonly uint MaxLength; + //if true, destructor frees allocated unmanaged memory + public bool AutoDispose; + + public Autoarr(IntPtr ptr, bool autoDispose=true) + { + AutoDispose = autoDispose; + Funcs = AutoarrFunctions.GetFunctions(); + MaxLength = Funcs.MaxLength(AutoarrHandler); + Length = Funcs.Length(AutoarrHandler); + AutoarrHandler = ptr; + } + + public Autoarr(ushort blockCount, ushort blockLength, bool autoDispose=true) : this(IntPtr.Zero,autoDispose) + { + AutoarrHandler = Funcs.Create(blockCount, blockLength); + } + + public uint Length { get; private set; } + + public T this[uint i] + { + get + { + if (i < Length) return Funcs.Get(AutoarrHandler, i); + throw new IndexOutOfRangeException($"index {i} >= Autoarr.Length {Length}"); + } + set + { + if (i < Length) Funcs.Set(AutoarrHandler, i, value); + else throw new IndexOutOfRangeException($"index {i} >= Autoarr.Length {Length}"); + } + } + + public void Dispose() + { + Funcs.Free(AutoarrHandler); + } + + public IEnumerator GetEnumerator() + { + return new AutoarrEnumerator(this); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public void Add(T value) + { + if (Length++ < MaxLength - 1) Funcs.Add(AutoarrHandler, value); + else throw new IndexOutOfRangeException($"Autoarr.Length == MaxLength ({MaxLength})"); + } + + ~Autoarr() + { + if (AutoDispose) Dispose(); + } + + private class AutoarrEnumerator : IEnumerator + { + private readonly Autoarr arr; + private uint index; + + public AutoarrEnumerator(Autoarr ar) + { + arr = ar; + } + + + public T Current { get; private set; } + object IEnumerator.Current => Current; + + public void Dispose() + { + } + + public bool MoveNext() + { + var r = ++index < arr.Length; + if (r) Current = arr[index]; + return r; + } + + public void Reset() + { + index = 0; + } + } +} \ No newline at end of file diff --git a/DTLib.Dtsod/V24/Autoarr/AutoarrFunctions.cs b/DTLib.Dtsod/V24/Autoarr/AutoarrFunctions.cs new file mode 100644 index 0000000..3f64c06 --- /dev/null +++ b/DTLib.Dtsod/V24/Autoarr/AutoarrFunctions.cs @@ -0,0 +1,26 @@ +using System.Dynamic; + +namespace DTLib.Dtsod.V24.Autoarr; +using AutoarrPtr=System.IntPtr; + +public abstract class AutoarrFunctions +{ + internal abstract AutoarrPtr Create(ushort maxBlocksCount, ushort maxBlockLength); + internal abstract void Free(AutoarrPtr ar); + internal abstract T Get(AutoarrPtr ar, uint index); + internal abstract void Add(AutoarrPtr ar, T element); + internal abstract void Set(AutoarrPtr ar, uint index, T element); + internal abstract uint Length(AutoarrPtr ar); + internal abstract uint MaxLength(AutoarrPtr ar); + + private static AutoarrFunctions f_uni = new AutoarrUnitypeFunctions(); + private static AutoarrFunctions f_kvp = new AutoarrKVPairFunctions(); + static internal AutoarrFunctions GetFunctions() + { + if (typeof(T) == typeof(Unitype)) + return (AutoarrFunctions)Convert.ChangeType(f_uni, typeof(AutoarrFunctions)); + else if (typeof(T) == typeof(KVPair)) + return (AutoarrFunctions) Convert.ChangeType(f_kvp, typeof(AutoarrFunctions)); + else throw new Exception($"unsupported type: {typeof(T)}"); + } +} \ No newline at end of file diff --git a/DTLib.Dtsod/V24/Autoarr/AutoarrKVPairFunctions.cs b/DTLib.Dtsod/V24/Autoarr/AutoarrKVPairFunctions.cs new file mode 100644 index 0000000..9e7b238 --- /dev/null +++ b/DTLib.Dtsod/V24/Autoarr/AutoarrKVPairFunctions.cs @@ -0,0 +1,51 @@ +using System.Runtime.InteropServices; + +namespace DTLib.Dtsod.V24.Autoarr; + +internal class AutoarrKVPairFunctions : AutoarrFunctions +{ + [DllImport("kerep.dll", CallingConvention = CallingConvention.Cdecl)] + static extern void kerep_Autoarr_KVPair_create(ushort max_blocks_count, ushort max_block_length, out AutoarrKVPairPtr output); + internal override AutoarrKVPairPtr Create(ushort maxBlocksCount, ushort maxBlockLength) + { + kerep_Autoarr_KVPair_create(maxBlocksCount, maxBlockLength, out var ar); + return ar; + } + + [DllImport("kerep.dll", CallingConvention = CallingConvention.Cdecl)] + internal static extern void kerep_Autoarr_KVPair_free(AutoarrKVPairPtr ar); + internal override void Free(AutoarrKVPairPtr ar) => kerep_Autoarr_KVPair_free(ar); + + [DllImport("kerep.dll", CallingConvention = CallingConvention.Cdecl)] + static extern void kerep_Autoarr_KVPair_get(AutoarrKVPairPtr ar, uint index, out KVPair output); + internal override KVPair Get(AutoarrKVPairPtr ar, uint index) + { + kerep_Autoarr_KVPair_get(ar, index, out var output); + return output; + } + + [DllImport("kerep.dll",CallingConvention = CallingConvention.Cdecl)] + internal static extern void kerep_Autoarr_KVPair_add(AutoarrKVPairPtr ar, KVPair element); + internal override void Add(AutoarrKVPairPtr ar, KVPair element) => kerep_Autoarr_KVPair_add(ar, element); + + [DllImport("kerep.dll", CallingConvention = CallingConvention.Cdecl)] + internal static extern void kerep_Autoarr_KVPair_set(AutoarrKVPairPtr ar, uint index, KVPair element); + internal override void Set(AutoarrKVPairPtr ar, uint index, KVPair element) => + kerep_Autoarr_KVPair_set(ar, index, element); + + [DllImport("kerep.dll", CallingConvention = CallingConvention.Cdecl)] + static extern void kerep_Autoarr_KVPair_length(AutoarrKVPairPtr ar, out uint output); + internal override uint Length(AutoarrKVPairPtr ar) + { + kerep_Autoarr_KVPair_length(ar, out var l); + return l; + } + + [DllImport("kerep.dll", CallingConvention = CallingConvention.Cdecl)] + static extern void kerep_Autoarr_KVPair_max_length(AutoarrKVPairPtr ar, out uint output); + internal override uint MaxLength(AutoarrKVPairPtr ar) + { + kerep_Autoarr_KVPair_max_length(ar, out var l); + return l; + } +} \ No newline at end of file diff --git a/DTLib.Dtsod/V24/Autoarr/AutoarrUnitypeFunctions.cs b/DTLib.Dtsod/V24/Autoarr/AutoarrUnitypeFunctions.cs new file mode 100644 index 0000000..83b4157 --- /dev/null +++ b/DTLib.Dtsod/V24/Autoarr/AutoarrUnitypeFunctions.cs @@ -0,0 +1,51 @@ +using System.Runtime.InteropServices; + +namespace DTLib.Dtsod.V24.Autoarr; + +internal class AutoarrUnitypeFunctions : AutoarrFunctions +{ + [DllImport("kerep.dll", CallingConvention = CallingConvention.Cdecl)] + static extern void kerep_Autoarr_Unitype_create(ushort max_blocks_count, ushort max_block_length, out AutoarrUnitypePtr output); + internal override AutoarrUnitypePtr Create(ushort maxBlocksCount, ushort maxBlockLength) + { + kerep_Autoarr_Unitype_create(maxBlocksCount, maxBlockLength, out var ar); + return ar; + } + + [DllImport("kerep.dll", CallingConvention = CallingConvention.Cdecl)] + internal static extern void kerep_Autoarr_Unitype_free(AutoarrUnitypePtr ar); + internal override void Free(AutoarrUnitypePtr ar) => kerep_Autoarr_Unitype_free(ar); + + [DllImport("kerep.dll", CallingConvention = CallingConvention.Cdecl)] + static extern void kerep_Autoarr_Unitype_get(AutoarrUnitypePtr ar, uint index, out Unitype output); + internal override Unitype Get(AutoarrUnitypePtr ar, uint index) + { + kerep_Autoarr_Unitype_get(ar, index, out var output); + return output; + } + + [DllImport("kerep.dll",CallingConvention = CallingConvention.Cdecl)] + internal static extern void kerep_Autoarr_Unitype_add(AutoarrUnitypePtr ar, Unitype element); + internal override void Add(AutoarrUnitypePtr ar, Unitype element) => kerep_Autoarr_Unitype_add(ar, element); + + [DllImport("kerep.dll", CallingConvention = CallingConvention.Cdecl)] + internal static extern void kerep_Autoarr_Unitype_set(AutoarrUnitypePtr ar, uint index, Unitype element); + internal override void Set(AutoarrUnitypePtr ar, uint index, Unitype element) => + kerep_Autoarr_Unitype_set(ar, index, element); + + [DllImport("kerep.dll", CallingConvention = CallingConvention.Cdecl)] + static extern void kerep_Autoarr_Unitype_length(AutoarrUnitypePtr ar, out uint output); + internal override uint Length(AutoarrUnitypePtr ar) + { + kerep_Autoarr_Unitype_length(ar, out var l); + return l; + } + + [DllImport("kerep.dll", CallingConvention = CallingConvention.Cdecl)] + static extern void kerep_Autoarr_Unitype_max_length(AutoarrUnitypePtr ar, out uint output); + internal override uint MaxLength(AutoarrUnitypePtr ar) + { + kerep_Autoarr_Unitype_max_length(ar, out var l); + return l; + } +} \ No newline at end of file diff --git a/DTLib.Dtsod/V24/DtsodV24.cs b/DTLib.Dtsod/V24/DtsodV24.cs new file mode 100644 index 0000000..2ae404c --- /dev/null +++ b/DTLib.Dtsod/V24/DtsodV24.cs @@ -0,0 +1,92 @@ +using DTLib.Dtsod.V24.Autoarr; +using Funcs=DTLib.Dtsod.V24.DtsodV24Functions; + +namespace DTLib.Dtsod.V24; + +public class DtsodV24 : IDtsod, IEnumerable>, IDisposable +{ + public DtsodVersion Version => DtsodVersion.V24; + private readonly DtsodPtr DtsodHandler; + //if true, destructor frees allocated unmanaged memory + public bool AutoDispose = true; + + public DtsodV24(DtsodPtr ptr) => DtsodHandler = ptr; + + public DtsodV24() => DtsodHandler = Funcs.Deserialize(" "); + + public DtsodV24(string text) => DtsodHandler = Funcs.Deserialize(text); + + public DtsodV24(IDictionary dict) : this() + { + foreach (KeyValuePair pair in dict) + AddOrSet(pair.Key, pair.Value); + } + + public IDictionary ToDictionary() + { + DtsodDict dict = new(); + + return dict; + } + + + public bool TryGet(string key, out dynamic elem) + { + var g = Funcs.Get(DtsodHandler, key); + elem = g.ToDynamic(); + return g.type == my_type.Null; + } + + public void AddOrSet(string key, dynamic value) => + Funcs.AddOrSet(DtsodHandler, key, new Unitype(value)); + + public dynamic this[string key] + { + get + { + if (!TryGet(key, out var v)) throw new KeyNotFoundException($"key <{key}> not found"); + return v; + } + set => AddOrSet(key, value); + } + + public bool TryRemove(string key) => Funcs.Remove(DtsodHandler,key); + + [Obsolete("do you really need to use this? look at TryGet/TryRemove/AddOrSet")] + public bool ContainsKey(string key) => Funcs.Contains(DtsodHandler, key); + + public void Dispose() => Funcs.Free(DtsodHandler); + + ~DtsodV24() + { + if(AutoDispose) Dispose(); + } + + + public IEnumerator> GetEnumerator() => new DtsodV24Enumerator(this); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + class DtsodV24Enumerator: IEnumerator> + { + private readonly DtsodV24 d; + private ushort h; + + public DtsodV24Enumerator(DtsodV24 _d) => d = _d; + + public void Dispose() { } + + public bool MoveNext() + { + bool r = ++h < Funcs.Height(d.DtsodHandler); + if(r) Current = new Autoarr(Funcs.GetRow(d.DtsodHandler,h), false); + return r; + } + + public void Reset() => h = 0; + + public Autoarr Current { get; private set; } + + object IEnumerator.Current => Current; + } +} \ No newline at end of file diff --git a/DTLib.Dtsod/V24/KerepFunctions.cs b/DTLib.Dtsod/V24/DtsodV24Functions.cs similarity index 62% rename from DTLib.Dtsod/V24/KerepFunctions.cs rename to DTLib.Dtsod/V24/DtsodV24Functions.cs index 7d79baf..b67c89f 100644 --- a/DTLib.Dtsod/V24/KerepFunctions.cs +++ b/DTLib.Dtsod/V24/DtsodV24Functions.cs @@ -1,9 +1,12 @@ +global using DtsodPtr=System.IntPtr; +global using AutoarrKVPairPtr=System.IntPtr; +global using AutoarrUnitypePtr=System.IntPtr; using System.Runtime.InteropServices; -using DtsodPtr=System.IntPtr; +using DTLib.Dtsod.V24.Autoarr; namespace DTLib.Dtsod.V24; -public static unsafe class KerepFunctions +public static unsafe class DtsodV24Functions { [DllImport("kerep.dll", CallingConvention = CallingConvention.Cdecl)] static extern void pinvoke_print(string msg); @@ -39,26 +42,21 @@ public static unsafe class KerepFunctions return text; } - //returns value or UniNull if key not found [DllImport("kerep.dll", CallingConvention = CallingConvention.Cdecl)] static extern void kerep_DtsodV24_get(DtsodPtr dtsod, string key, out Unitype output); - + //returns value or UniNull if key not found internal static Unitype Get(DtsodPtr dtsod, string key) { kerep_DtsodV24_get(dtsod, key, out var output); return output; } + [DllImport("kerep.dll",EntryPoint = "kerep_DtsodV24_addOrSet",CallingConvention = CallingConvention.Cdecl)] //adds or sets value - [DllImport("kerep.dll", CallingConvention = CallingConvention.Cdecl)] - static extern void kerep_DtsodV24_addOrSet(DtsodPtr dtsod, string key, Unitype value); - internal static void AddOrSet(DtsodPtr dtsod, string key, Unitype value) - { - kerep_DtsodV24_addOrSet(dtsod, key, value); - } + internal static extern void AddOrSet(DtsodPtr dtsod, string key, Unitype value); - //checks for dtsod contains value or dont [DllImport("kerep.dll", CallingConvention = CallingConvention.Cdecl)] + //checks for dtsod contains value or dont static extern void kerep_DtsodV24_contains(DtsodPtr dtsod, string key, [MarshalAs(UnmanagedType.I1)] out bool output); internal static bool Contains(DtsodPtr dtsod, string key) { @@ -66,12 +64,35 @@ public static unsafe class KerepFunctions return output; } - //replaces value with UniNull if key exists in dtsod [DllImport("kerep.dll", CallingConvention = CallingConvention.Cdecl)] static extern void kerep_DtsodV24_remove(DtsodPtr dtsod, string key, [MarshalAs(UnmanagedType.I1)] out bool output); + //replaces value with UniNull if key exists in dtsod internal static bool Remove(DtsodPtr dtsod, string key) { kerep_DtsodV24_remove(dtsod, key, out var output); return output; } + + [DllImport("kerep.dll",EntryPoint="kerep_DtsodV24_free", CallingConvention = CallingConvention.Cdecl)] + //replaces value with UniNull if key exists in dtsod + internal static extern void Free(DtsodPtr dtsod); + + [DllImport("kerep.dll",EntryPoint="kerep_DtsodV24_free", CallingConvention = CallingConvention.Cdecl)] + static extern void kerep_DtsodV24_height(DtsodPtr dtsod, out ushort heigth); + //returns current amounts of rows (Autoarrs of KVPairs) in hashtable + internal static ushort Height(DtsodPtr ptr) + { + kerep_DtsodV24_height(ptr, out var h); + return h; + } + + [DllImport("kerep.dll",EntryPoint="kerep_DtsodV24_free", CallingConvention = CallingConvention.Cdecl)] + static extern void kerep_DtsodV24_getrow(DtsodPtr dtsod, ushort h, out AutoarrKVPairPtr row); + //Returns row from hashtable. + //check current hashtable height before calling this. + internal static AutoarrKVPairPtr GetRow(DtsodPtr ptr, ushort height) + { + kerep_DtsodV24_getrow(ptr, height, out var rowptr); + return rowptr; + } } \ No newline at end of file diff --git a/DTLib.Dtsod/V24/KerepStructs.cs b/DTLib.Dtsod/V24/KerepStructs.cs index bbefaae..4c0c2ba 100644 --- a/DTLib.Dtsod/V24/KerepStructs.cs +++ b/DTLib.Dtsod/V24/KerepStructs.cs @@ -4,7 +4,7 @@ namespace DTLib.Dtsod.V24; internal enum my_type : byte { - Null, Float, Double, Char, Bool, + Null, Float32, Float64, Char, Bool, UInt8, Int8, UInt16, Int16, UInt32, Int32, UInt64, Int64, UInt8Ptr, Int8Ptr, UInt16Ptr, Int16Ptr, UInt32Ptr, Int32Ptr, UInt64Ptr, Int64Ptr, CharPtr, STNodePtr, HashtablePtr, @@ -19,16 +19,40 @@ internal struct Unitype { [FieldOffset(0)] internal long Int64; [FieldOffset(0)] internal ulong UInt64; - [FieldOffset(0)] internal double Double; - [FieldOffset(0)] internal byte Char; + [FieldOffset(0)] internal double Float64; + [MarshalAs(UnmanagedType.I1)] + [FieldOffset(0)] internal char Char; [MarshalAs(UnmanagedType.I1)] [FieldOffset(0)] internal bool Bool; [FieldOffset(0)] internal IntPtr VoidPtr; [FieldOffset(8)] internal my_type type; + + public Unitype(dynamic something) + { + throw new NotImplementedException(); + } + + public dynamic ToDynamic() + { + switch (type) + { + case my_type.Null: return null; + case my_type.Bool: return Bool; + case my_type.Char: return Char; + case my_type.Int64: return Int64; + case my_type.UInt64: return UInt64; + case my_type.Float64: return Float64; + case my_type.CharPtr: return Marshal.PtrToStringAuto(VoidPtr); + case my_type.AutoarrUnitypePtr: return new Autoarr.Autoarr(VoidPtr); + case my_type.AutoarrKVPairPtr: return new Autoarr.Autoarr(VoidPtr); + case my_type.HashtablePtr: return new DtsodV24(VoidPtr); + default: throw new Exception($"can't unbox value of type {type}"); + } + } } [StructLayout(LayoutKind.Sequential)] -internal struct KVPair +public struct KVPair { internal IntPtr key; internal Unitype value; diff --git a/DTLib.Tests/Program.cs b/DTLib.Tests/Program.cs index 9288652..79714d7 100644 --- a/DTLib.Tests/Program.cs +++ b/DTLib.Tests/Program.cs @@ -34,7 +34,7 @@ public static class Program //DictTest.Test(); for (uint i = 0; i < 10; i++) { - Dtsod.V24.KerepFunctions.TestMarshalling(); + Dtsod.V24.DtsodV24Functions.TestMarshalling(); Info.Log($"{i}"); } } diff --git a/kerep b/kerep index c1d004f..3940eeb 160000 --- a/kerep +++ b/kerep @@ -1 +1 @@ -Subproject commit c1d004f411c5c2963bbbcb6172f08ad55188ed88 +Subproject commit 3940eeb2a7c9147a5b91e1e2519530a3b1e8b9ca