dependency resolver changed
This commit is contained in:
parent
ebec0071a2
commit
705874ef9e
@ -25,7 +25,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="Dependencies\*">
|
<None Update="Dependencies\**\*">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
BIN
DTLib.Dtsod/Dependencies/windows/x64/kerep.dll
Normal file
BIN
DTLib.Dtsod/Dependencies/windows/x64/kerep.dll
Normal file
Binary file not shown.
BIN
DTLib.Dtsod/Dependencies/windows/x86/kerep.dll
Normal file
BIN
DTLib.Dtsod/Dependencies/windows/x86/kerep.dll
Normal file
Binary file not shown.
@ -46,18 +46,13 @@ public class Autoarr<T> : IEnumerable<T>, IDisposable where T : struct
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
if(AutoDispose)
|
||||||
Funcs.Free(UnmanagedPtr);
|
Funcs.Free(UnmanagedPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerator<T> GetEnumerator()
|
public IEnumerator<T> GetEnumerator() => new AutoarrEnumerator(this);
|
||||||
{
|
|
||||||
return new AutoarrEnumerator(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
{
|
|
||||||
return GetEnumerator();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Add(T value)
|
public void Add(T value)
|
||||||
{
|
{
|
||||||
@ -79,17 +74,12 @@ public class Autoarr<T> : IEnumerable<T>, IDisposable where T : struct
|
|||||||
private readonly Autoarr<T> arr;
|
private readonly Autoarr<T> arr;
|
||||||
private uint index;
|
private uint index;
|
||||||
|
|
||||||
public AutoarrEnumerator(Autoarr<T> ar)
|
public AutoarrEnumerator(Autoarr<T> ar) => arr = ar;
|
||||||
{
|
|
||||||
arr = ar;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T Current { get; private set; }
|
public T Current { get; private set; }
|
||||||
object IEnumerator.Current => Current;
|
object IEnumerator.Current => Current;
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose() { }
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,20 +0,0 @@
|
|||||||
using DTLib.Filesystem;
|
|
||||||
|
|
||||||
namespace DTLib.Dtsod.V24;
|
|
||||||
|
|
||||||
public static class DependencyResolver
|
|
||||||
{
|
|
||||||
private static bool KerepCopied=false;
|
|
||||||
|
|
||||||
public static void CopyLibs()
|
|
||||||
{
|
|
||||||
if(KerepCopied) return;
|
|
||||||
|
|
||||||
string kereplib = Environment.OSVersion.Platform == PlatformID.Win32NT
|
|
||||||
? "kerep.dll"
|
|
||||||
: "kerep.so";
|
|
||||||
File.Copy($"Dependencies{Путь.Разд}{kereplib}",kereplib, true);
|
|
||||||
KerepCopied = true;
|
|
||||||
Log("g",$"{kereplib} copied");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -4,7 +4,7 @@ using Funcs=DTLib.Dtsod.V24.DtsodV24Functions;
|
|||||||
|
|
||||||
namespace DTLib.Dtsod.V24;
|
namespace DTLib.Dtsod.V24;
|
||||||
|
|
||||||
public class DtsodV24 : IDtsod, IEnumerable<Autoarr<KVPair>>, IDisposable
|
public class DtsodV24 : IDtsod, IEnumerable<KVPair>, IDisposable
|
||||||
{
|
{
|
||||||
public DtsodVersion Version => DtsodVersion.V24;
|
public DtsodVersion Version => DtsodVersion.V24;
|
||||||
public readonly DtsodPtr UnmanagedPtr;
|
public readonly DtsodPtr UnmanagedPtr;
|
||||||
@ -29,7 +29,9 @@ public class DtsodV24 : IDtsod, IEnumerable<Autoarr<KVPair>>, IDisposable
|
|||||||
public IDictionary<string, dynamic> ToDictionary()
|
public IDictionary<string, dynamic> ToDictionary()
|
||||||
{
|
{
|
||||||
DtsodDict<string, dynamic> dict = new();
|
DtsodDict<string, dynamic> dict = new();
|
||||||
throw new NotImplementedException();
|
foreach (var p in this)
|
||||||
|
dict.Add(p.key,p.value.ToDynamic());
|
||||||
|
return dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -68,31 +70,41 @@ public class DtsodV24 : IDtsod, IEnumerable<Autoarr<KVPair>>, IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public IEnumerator<Autoarr<KVPair>> GetEnumerator() => new DtsodV24Enumerator(this);
|
public IEnumerator<KVPair> GetEnumerator() => new DtsodV24Enumerator(this);
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
|
||||||
class DtsodV24Enumerator: IEnumerator<Autoarr<KVPair>>
|
class DtsodV24Enumerator: IEnumerator<KVPair>
|
||||||
{
|
{
|
||||||
private readonly DtsodV24 d;
|
private readonly DtsodV24 d;
|
||||||
private ushort h;
|
private ushort h;
|
||||||
|
private IEnumerator<KVPair> arEnumerator;
|
||||||
|
|
||||||
public DtsodV24Enumerator(DtsodV24 _d) => d = _d;
|
public DtsodV24Enumerator(DtsodV24 _d) => d = _d;
|
||||||
|
|
||||||
public void Dispose() { }
|
bool NextAr()
|
||||||
|
|
||||||
public bool MoveNext()
|
|
||||||
{
|
{
|
||||||
if (h >= Funcs.Height(d.UnmanagedPtr)) return false;
|
if (h >= Funcs.Height(d.UnmanagedPtr)) return false;
|
||||||
Current = new Autoarr<KVPair>(Funcs.GetRow(d.UnmanagedPtr,h), false);
|
var ar = new Autoarr<KVPair>(Funcs.GetRow(d.UnmanagedPtr, h), false);
|
||||||
|
arEnumerator = ar.GetEnumerator();
|
||||||
h++;
|
h++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if(arEnumerator==null)
|
||||||
|
NextAr();
|
||||||
|
while(!arEnumerator.MoveNext())
|
||||||
|
if(!NextAr()) return false;
|
||||||
|
Current = arEnumerator.Current;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public void Reset() => h = 0;
|
public void Reset() => h = 0;
|
||||||
|
public KVPair Current { get; private set; }
|
||||||
public Autoarr<KVPair> Current { get; private set; }
|
|
||||||
|
|
||||||
object IEnumerator.Current => Current;
|
object IEnumerator.Current => Current;
|
||||||
|
|
||||||
|
public void Dispose() { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -9,6 +9,8 @@ namespace DTLib.Dtsod.V24;
|
|||||||
|
|
||||||
internal static class DtsodV24Functions
|
internal static class DtsodV24Functions
|
||||||
{
|
{
|
||||||
|
private const string kereplib = "kerep";
|
||||||
|
|
||||||
static DtsodV24Functions()
|
static DtsodV24Functions()
|
||||||
{
|
{
|
||||||
DependencyResolver.CopyLibs();
|
DependencyResolver.CopyLibs();
|
||||||
@ -24,7 +26,7 @@ internal static class DtsodV24Functions
|
|||||||
|
|
||||||
|
|
||||||
//parses text to binary values
|
//parses text to binary values
|
||||||
[DllImport("kerep", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(kereplib, CallingConvention = CallingConvention.Cdecl)]
|
||||||
static extern void kerep_DtsodV24_deserialize(string text, out DtsodPtr output, out CharPtr errmsg);
|
static extern void kerep_DtsodV24_deserialize(string text, out DtsodPtr output, out CharPtr errmsg);
|
||||||
internal static DtsodPtr Deserialize(string text)
|
internal static DtsodPtr Deserialize(string text)
|
||||||
{
|
{
|
||||||
@ -34,7 +36,7 @@ internal static class DtsodV24Functions
|
|||||||
}
|
}
|
||||||
|
|
||||||
//creates text representation of dtsod
|
//creates text representation of dtsod
|
||||||
[DllImport("kerep", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(kereplib, CallingConvention = CallingConvention.Cdecl)]
|
||||||
static extern void kerep_DtsodV24_serialize(DtsodPtr dtsod, out CharPtr output, out CharPtr errmsg);
|
static extern void kerep_DtsodV24_serialize(DtsodPtr dtsod, out CharPtr output, out CharPtr errmsg);
|
||||||
internal static string Serialize(DtsodPtr dtsod)
|
internal static string Serialize(DtsodPtr dtsod)
|
||||||
{
|
{
|
||||||
@ -43,7 +45,7 @@ internal static class DtsodV24Functions
|
|||||||
return Marshal.PtrToStringUTF8(text);
|
return Marshal.PtrToStringUTF8(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport("kerep", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(kereplib, CallingConvention = CallingConvention.Cdecl)]
|
||||||
static extern void kerep_DtsodV24_get(DtsodPtr dtsod, string key, out Unitype output);
|
static extern void kerep_DtsodV24_get(DtsodPtr dtsod, string key, out Unitype output);
|
||||||
//returns value or UniNull if key not found
|
//returns value or UniNull if key not found
|
||||||
internal static Unitype Get(DtsodPtr dtsod, string key)
|
internal static Unitype Get(DtsodPtr dtsod, string key)
|
||||||
@ -52,7 +54,7 @@ internal static class DtsodV24Functions
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport("kerep",EntryPoint = "kerep_DtsodV24_addOrSet",CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(kereplib,EntryPoint = "kerep_DtsodV24_addOrSet",CallingConvention = CallingConvention.Cdecl)]
|
||||||
//adds or sets value
|
//adds or sets value
|
||||||
static extern void kerep_DtsodV24_addOrSet(DtsodPtr dtsod, IntPtr key, Unitype value);
|
static extern void kerep_DtsodV24_addOrSet(DtsodPtr dtsod, IntPtr key, Unitype value);
|
||||||
|
|
||||||
@ -62,7 +64,7 @@ internal static class DtsodV24Functions
|
|||||||
kerep_DtsodV24_addOrSet(dtsod, keyptr, value);
|
kerep_DtsodV24_addOrSet(dtsod, keyptr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport("kerep", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(kereplib, CallingConvention = CallingConvention.Cdecl)]
|
||||||
//checks for dtsod contains value or dont
|
//checks for dtsod contains value or dont
|
||||||
static extern void kerep_DtsodV24_contains(DtsodPtr dtsod, string key, [MarshalAs(UnmanagedType.I1)] out bool output);
|
static extern void kerep_DtsodV24_contains(DtsodPtr dtsod, string key, [MarshalAs(UnmanagedType.I1)] out bool output);
|
||||||
internal static bool Contains(DtsodPtr dtsod, string key)
|
internal static bool Contains(DtsodPtr dtsod, string key)
|
||||||
@ -71,7 +73,7 @@ internal static class DtsodV24Functions
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport("kerep", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(kereplib, CallingConvention = CallingConvention.Cdecl)]
|
||||||
static extern void kerep_DtsodV24_remove(DtsodPtr dtsod, string key, [MarshalAs(UnmanagedType.I1)] out bool output);
|
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
|
//replaces value with UniNull if key exists in dtsod
|
||||||
internal static bool Remove(DtsodPtr dtsod, string key)
|
internal static bool Remove(DtsodPtr dtsod, string key)
|
||||||
@ -80,11 +82,11 @@ internal static class DtsodV24Functions
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport("kerep",EntryPoint="kerep_DtsodV24_free", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(kereplib,EntryPoint="kerep_DtsodV24_free", CallingConvention = CallingConvention.Cdecl)]
|
||||||
//replaces value with UniNull if key exists in dtsod
|
//replaces value with UniNull if key exists in dtsod
|
||||||
internal static extern void Free(DtsodPtr dtsod);
|
internal static extern void Free(DtsodPtr dtsod);
|
||||||
|
|
||||||
[DllImport("kerep", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(kereplib, CallingConvention = CallingConvention.Cdecl)]
|
||||||
static extern void kerep_DtsodV24_height(DtsodPtr dtsod, out ushort heigth);
|
static extern void kerep_DtsodV24_height(DtsodPtr dtsod, out ushort heigth);
|
||||||
//returns current amounts of rows (Autoarrs of KVPairs) in hashtable
|
//returns current amounts of rows (Autoarrs of KVPairs) in hashtable
|
||||||
internal static ushort Height(DtsodPtr ptr)
|
internal static ushort Height(DtsodPtr ptr)
|
||||||
@ -93,7 +95,7 @@ internal static class DtsodV24Functions
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport("kerep", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(kereplib, CallingConvention = CallingConvention.Cdecl)]
|
||||||
static extern void kerep_DtsodV24_getrow(DtsodPtr dtsod, ushort h, out AutoarrKVPairPtr row);
|
static extern void kerep_DtsodV24_getrow(DtsodPtr dtsod, ushort h, out AutoarrKVPairPtr row);
|
||||||
//Returns row from hashtable.
|
//Returns row from hashtable.
|
||||||
//check current hashtable height before calling this.
|
//check current hashtable height before calling this.
|
||||||
|
|||||||
@ -66,48 +66,6 @@ public struct Unitype
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*public Unitype(bool v) : this()
|
|
||||||
{
|
|
||||||
TypeCode = KerepTypeCode.Bool;
|
|
||||||
Bool = v;
|
|
||||||
}
|
|
||||||
public Unitype(int v) : this()
|
|
||||||
{
|
|
||||||
TypeCode = KerepTypeCode.Int64;
|
|
||||||
Int64 = v;
|
|
||||||
}
|
|
||||||
public Unitype(uint v) : this()
|
|
||||||
{
|
|
||||||
TypeCode = KerepTypeCode.UInt64;
|
|
||||||
UInt64 = v;
|
|
||||||
}
|
|
||||||
public Unitype(double v) : this()
|
|
||||||
{
|
|
||||||
TypeCode = KerepTypeCode.Float64;
|
|
||||||
Float64 = v;
|
|
||||||
}
|
|
||||||
public Unitype(string s) : this()
|
|
||||||
{
|
|
||||||
TypeCode = KerepTypeCode.CharPtr;
|
|
||||||
VoidPtr = s.ToHGlobalUTF8();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Unitype(Autoarr<Unitype> v) : this()
|
|
||||||
{
|
|
||||||
TypeCode = KerepTypeCode.AutoarrUnitypePtr;
|
|
||||||
VoidPtr = v.UnmanagedPtr;
|
|
||||||
}
|
|
||||||
public Unitype(Autoarr<KVPair> v) : this()
|
|
||||||
{
|
|
||||||
TypeCode = KerepTypeCode.AutoarrKVPairPtr;
|
|
||||||
VoidPtr = v.UnmanagedPtr;
|
|
||||||
}
|
|
||||||
public Unitype(DtsodV24 v) : this()
|
|
||||||
{
|
|
||||||
TypeCode = KerepTypeCode.HashtablePtr;
|
|
||||||
VoidPtr = v.UnmanagedPtr;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public dynamic ToDynamic()
|
public dynamic ToDynamic()
|
||||||
{
|
{
|
||||||
switch (TypeCode)
|
switch (TypeCode)
|
||||||
|
|||||||
@ -19,11 +19,8 @@ public static class TestDtsodV24
|
|||||||
{
|
{
|
||||||
Info.Log("c", "-----[TestDtsodV24/TestBaseTypes]-----");
|
Info.Log("c", "-----[TestDtsodV24/TestBaseTypes]-----");
|
||||||
DtsodV24 dtsod = new(File.ReadAllText($"DtsodV24{Путь.Разд}base_types.dtsod"));
|
DtsodV24 dtsod = new(File.ReadAllText($"DtsodV24{Путь.Разд}base_types.dtsod"));
|
||||||
foreach (var autoarr in dtsod)
|
foreach (var pair in dtsod)
|
||||||
{
|
|
||||||
foreach (KVPair pair in autoarr)
|
|
||||||
Info.LogNoTime("b", pair.ToString());
|
Info.LogNoTime("b", pair.ToString());
|
||||||
}
|
|
||||||
Info.Log("g", "test completed");
|
Info.Log("g", "test completed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,14 +36,24 @@ public static class TestDtsodV24
|
|||||||
{
|
{
|
||||||
Info.Log("c", "-------[TestDtsodV24/TestLists]-------");
|
Info.Log("c", "-------[TestDtsodV24/TestLists]-------");
|
||||||
DtsodV24 dtsod = new(File.ReadAllText($"DtsodV24{Путь.Разд}lists.dtsod"));
|
DtsodV24 dtsod = new(File.ReadAllText($"DtsodV24{Путь.Разд}lists.dtsod"));
|
||||||
foreach (var autoarr in dtsod)
|
foreach (KVPair pair in dtsod)
|
||||||
foreach (KVPair pair in autoarr)
|
|
||||||
{
|
{
|
||||||
var list = new Autoarr<Unitype>(pair.value.VoidPtr, false);
|
var list = new Autoarr<Unitype>(pair.value.VoidPtr, false);
|
||||||
Info.LogNoTime("b", pair.key.ToStringUTF8(), "w", $" length: {list.Length}");
|
Info.LogNoTime("b", pair.key.ToStringUTF8(), "w", $" length: {list.Length}");
|
||||||
foreach (var el in list)
|
foreach (var el in list)
|
||||||
|
{
|
||||||
Info.LogNoTime("h", '\t' + el.ToString());
|
Info.LogNoTime("h", '\t' + el.ToString());
|
||||||
|
if (el.TypeCode == KerepTypeCode.AutoarrUnitypePtr)
|
||||||
|
{
|
||||||
|
var ar = new Autoarr<Unitype>(el.VoidPtr, false);
|
||||||
|
foreach (var k in ar)
|
||||||
|
{
|
||||||
|
Info.LogNoTime($"\t\t{k.ToString()}");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Info.Log("y",dtsod.ToString());
|
||||||
Info.Log("g", "test completed");
|
Info.Log("g", "test completed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,3 +13,4 @@ $complex: {
|
|||||||
f:-1f;
|
f:-1f;
|
||||||
};
|
};
|
||||||
list_of_lists: [ [ "sss" ] ];
|
list_of_lists: [ [ "sss" ] ];
|
||||||
|
blank_list: [];
|
||||||
|
|||||||
@ -28,10 +28,11 @@ public static class Program
|
|||||||
Console.Title="tester";
|
Console.Title="tester";
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
TestPInvoke.TestAll();
|
/*TestPInvoke.TestAll();
|
||||||
TestAutoarr.TestAll();
|
TestAutoarr.TestAll();
|
||||||
TestDtsodV23.TestAll();
|
TestDtsodV23.TestAll();
|
||||||
TestDtsodV24.TestAll();
|
TestDtsodV24.TestAll();*/
|
||||||
|
TestDtsodV24.TestLists();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{ Info.Log("r", ex.ToString()); }
|
{ Info.Log("r", ex.ToString()); }
|
||||||
|
|||||||
36
DTLib/DependencyResolver.cs
Normal file
36
DTLib/DependencyResolver.cs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace DTLib;
|
||||||
|
|
||||||
|
public static class DependencyResolver
|
||||||
|
{
|
||||||
|
private static bool DepsCopied=false;
|
||||||
|
|
||||||
|
public static void CopyLibs()
|
||||||
|
{
|
||||||
|
if(DepsCopied) return;
|
||||||
|
string depsdir = "Dependencies" + Путь.Разд;
|
||||||
|
depsdir += Environment.OSVersion.Platform switch
|
||||||
|
{
|
||||||
|
PlatformID.Unix => "linux",
|
||||||
|
PlatformID.Win32NT => "windows",
|
||||||
|
_=> throw new Exception($"unsupported os {Environment.OSVersion.Platform}")
|
||||||
|
};
|
||||||
|
depsdir += Путь.Разд;
|
||||||
|
depsdir += RuntimeInformation.ProcessArchitecture switch
|
||||||
|
{
|
||||||
|
Architecture.X64 => "x64",
|
||||||
|
Architecture.X86 => "x86",
|
||||||
|
Architecture.Arm64 => "arm64",
|
||||||
|
Architecture.Arm => "arm",
|
||||||
|
_=> throw new Exception($"unsupported platform {RuntimeInformation.ProcessArchitecture}")
|
||||||
|
};
|
||||||
|
foreach (var file in Directory.GetAllFiles(depsdir))
|
||||||
|
{
|
||||||
|
var extracted = file.Substring(file.LastIndexOf(Путь.Разд) + 1);
|
||||||
|
File.Copy(file,extracted, true);
|
||||||
|
Log("g",$"{extracted} copied");
|
||||||
|
}
|
||||||
|
DepsCopied = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
1
kerep
Submodule
1
kerep
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 009174ecfc3899fc615fcd2d6e9f64256b0f4e65
|
||||||
Loading…
Reference in New Issue
Block a user