From a4d5df3fd6d5f15dffe06bfceab3d29fc0e4d0a6 Mon Sep 17 00:00:00 2001 From: Timerix22 Date: Fri, 31 Dec 2021 00:18:05 +0300 Subject: [PATCH] changed framework to dotnet6 --- ColoredConsole.cs | 123 ++++++------ DTLib.csproj | 96 ++------- DTLib.sln | 22 --- DefaultLogger.cs | 42 ---- EventHandlerAsync.cs | 17 +- Experimental/Tester.cs | 18 ++ Extensions/BaseConverter.cs | 88 +++++---- Extensions/Collections.cs | 65 +++---- Extensions/FrameworkFix.cs | 9 +- Extensions/IfMethod.cs | 31 ++- Extensions/StringConverter.cs | 298 ++++++++++++++-------------- Filesystem/Directory.cs | 284 +++++++++++++-------------- Filesystem/File.cs | 154 +++++++-------- Filesystem/OldFilework.cs | 91 +++++---- Filesystem/Symlink.cs | 26 +-- Hasher.cs | 99 +++++----- Loggers/AsyncLogger.cs | 34 ++++ Loggers/BaseLogger.cs | 16 ++ Loggers/DefaultLogger.cs | 32 +++ Network/FSP.cs | 355 +++++++++++++++++----------------- Network/OldNetwork.cs | 53 +++-- Network/Package.cs | 118 ++++++----- Properties/AssemblyInfo.cs | 35 ---- PublicLog.cs | 27 ++- TImer.cs | 63 +++--- XXHash.cs | 322 +++++++++++++++--------------- 26 files changed, 1194 insertions(+), 1324 deletions(-) delete mode 100644 DTLib.sln delete mode 100644 DefaultLogger.cs create mode 100644 Experimental/Tester.cs create mode 100644 Loggers/AsyncLogger.cs create mode 100644 Loggers/BaseLogger.cs create mode 100644 Loggers/DefaultLogger.cs delete mode 100644 Properties/AssemblyInfo.cs diff --git a/ColoredConsole.cs b/ColoredConsole.cs index 98b684e..9c86dc9 100644 --- a/ColoredConsole.cs +++ b/ColoredConsole.cs @@ -1,75 +1,70 @@ -using System; -using System.Text; +namespace DTLib; -namespace DTLib +// +// вывод и ввод цветного текста в консоли +// работает медленнее чем хотелось бы +// +public static class ColoredConsole { - // - // вывод и ввод цветного текста в консоли - // работает медленнее чем хотелось бы - // - public static class ColoredConsole + // парсит название цвета в ConsoleColor + public static ConsoleColor ParseColor(string color) => color switch { - // парсит название цвета в ConsoleColor - public static ConsoleColor ParseColor(string color) => color switch - { - //case "magneta": - "m" => ConsoleColor.Magenta, - //case "green": - "g" => ConsoleColor.Green, - //case "red": - "r" => ConsoleColor.Red, - //case "yellow": - "y" => ConsoleColor.Yellow, - //case "white": - "w" => ConsoleColor.White, - //case "blue": - "b" => ConsoleColor.Blue, - //case "cyan": - "c" => ConsoleColor.Cyan, - //case "h": - "h" or "gray" => ConsoleColor.Gray, - //case "black": - "black" => ConsoleColor.Black, - _ => throw new Exception($"ColoredConsole.ParseColor({color}) error: incorrect color"), - }; + //case "magneta": + "m" => ConsoleColor.Magenta, + //case "green": + "g" => ConsoleColor.Green, + //case "red": + "r" => ConsoleColor.Red, + //case "yellow": + "y" => ConsoleColor.Yellow, + //case "white": + "w" => ConsoleColor.White, + //case "blue": + "b" => ConsoleColor.Blue, + //case "cyan": + "c" => ConsoleColor.Cyan, + //case "h": + "h" or "gray" => ConsoleColor.Gray, + //case "black": + "black" => ConsoleColor.Black, + _ => throw new Exception($"ColoredConsole.ParseColor({color}) error: incorrect color"), + }; - // вывод цветного текста - public static void Write(params string[] input) + // вывод цветного текста + public static void Write(params string[] input) + { + if (input.Length == 1) { - if (input.Length == 1) + if (Console.ForegroundColor != ConsoleColor.Gray) + Console.ForegroundColor = ConsoleColor.Gray; + Console.Write(input[0]); + } + else if (input.Length % 2 == 0) + { + StringBuilder strB = new(); + for (ushort i = 0; i < input.Length; i++) { - if (Console.ForegroundColor != ConsoleColor.Gray) - Console.ForegroundColor = ConsoleColor.Gray; - Console.Write(input[0]); - } - else if (input.Length % 2 == 0) - { - StringBuilder strB = new(); - for (ushort i = 0; i < input.Length; i++) + ConsoleColor c = ParseColor(input[i]); + if (Console.ForegroundColor != c) { - ConsoleColor c = ParseColor(input[i]); - if (Console.ForegroundColor != c) - { - Console.Write(strB.ToString()); - Console.ForegroundColor = c; - strB.Clear(); - } - strB.Append(input[++i]); - } - if (strB.Length > 0) Console.Write(strB.ToString()); + Console.ForegroundColor = c; + strB.Clear(); + } + strB.Append(input[++i]); } - else - throw new Exception("ColoredConsole.Write() error: every text string must have color string before"); - } - - // ввод цветного текста - public static string Read(string color) - { - ConsoleColor c = ParseColor(color); - if (Console.ForegroundColor != c) - Console.ForegroundColor = c; - return Console.ReadLine(); + if (strB.Length > 0) + Console.Write(strB.ToString()); } + else throw new Exception("ColoredConsole.Write() error: every text string must have color string before"); } -} \ No newline at end of file + + // ввод цветного текста + public static string Read(string color) + { + ConsoleColor c = ParseColor(color); + if (Console.ForegroundColor != c) + Console.ForegroundColor = c; + return Console.ReadLine(); + } +} diff --git a/DTLib.csproj b/DTLib.csproj index 4d736c6..50648ce 100644 --- a/DTLib.csproj +++ b/DTLib.csproj @@ -1,80 +1,16 @@ - - - - - Debug - AnyCPU - {CE793497-2D5C-42D8-B311-E9B32AF9CDFB} - Library - Properties - DTLib - DTLib - v4.8 - 9.0 - 512 - true - - - full - false - bin\ - TRACE - prompt - 4 - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + net6.0 + false + disable + portable + DTLib + True + true + + + + + + + diff --git a/DTLib.sln b/DTLib.sln deleted file mode 100644 index 60172e0..0000000 --- a/DTLib.sln +++ /dev/null @@ -1,22 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31410.357 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DTLib", "DTLib.csproj", "{CE793497-2D5C-42D8-B311-E9B32AF9CDFB}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Build|Any CPU = Build|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {CE793497-2D5C-42D8-B311-E9B32AF9CDFB}.Build|Any CPU.ActiveCfg = Build|Any CPU - {CE793497-2D5C-42D8-B311-E9B32AF9CDFB}.Build|Any CPU.Build.0 = Build|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {64E0B2C4-C103-43B8-AF8C-03C1C2302008} - EndGlobalSection -EndGlobal diff --git a/DefaultLogger.cs b/DefaultLogger.cs deleted file mode 100644 index 71a5f9f..0000000 --- a/DefaultLogger.cs +++ /dev/null @@ -1,42 +0,0 @@ -using DTLib.Filesystem; -using System; -using System.Text; - -namespace DTLib -{ - // вывод лога в консоль и файл - public class DefaultLogger - { - public DefaultLogger(string logfile) => Logfile = logfile; - public DefaultLogger(string dir, string programName) => Logfile = $"{dir}\\{programName}_{DateTime.Now}.log".Replace(':', '-').Replace(' ', '_'); - - public string Logfile { get; set; } - - private bool isEnabled=false; - public void Enable() { lock (Logfile) isEnabled = true; } - public void Disable() { lock (Logfile) isEnabled = false; } - - public void Log(params string[] msg) - { - lock (Logfile) if (!isEnabled) return; - if (msg.Length == 1) msg[0] = "[" + DateTime.Now.ToString() + "]: " + msg[0]; - else msg[1] = "[" + DateTime.Now.ToString() + "]: " + msg[1]; - LogNoTime(msg); - } - - public void LogNoTime(params string[] msg) - { - lock (Logfile) if (!isEnabled) return; - ColoredConsole.Write(msg); - if (msg.Length == 1) - lock (Logfile) File.AppendAllText(Logfile, msg[0]); - else - { - StringBuilder strB = new(); - for (ushort i = 0; i < msg.Length; i++) - strB.Append(msg[++i]); - lock (Logfile) File.AppendAllText(Logfile, strB.ToString()); - } - } - } -} diff --git a/EventHandlerAsync.cs b/EventHandlerAsync.cs index 5af2df5..538f467 100644 --- a/EventHandlerAsync.cs +++ b/EventHandlerAsync.cs @@ -1,11 +1,8 @@ -using System.Threading.Tasks; +namespace DTLib; -namespace DTLib -{ - // по идее это нужно, чтоб делать так: SomeEvent?.Invoke().Wait() - public delegate Task EventHandlerAsyncDelegate(); - public delegate Task EventHandlerAsyncDelegate(T e); - public delegate Task EventHandlerAsyncDelegate(T0 e0, T1 e1); - public delegate Task EventHandlerAsyncDelegate(T0 e0, T1 e1, T2 e2); - public delegate Task EventHandlerAsyncDelegate(T0 e0, T1 e1, T2 e2, T3 e3); -} +// по идее это нужно, чтоб делать так: SomeEvent?.Invoke().Wait() +public delegate Task EventHandlerAsyncDelegate(); +public delegate Task EventHandlerAsyncDelegate(T e); +public delegate Task EventHandlerAsyncDelegate(T0 e0, T1 e1); +public delegate Task EventHandlerAsyncDelegate(T0 e0, T1 e1, T2 e2); +public delegate Task EventHandlerAsyncDelegate(T0 e0, T1 e1, T2 e2, T3 e3); diff --git a/Experimental/Tester.cs b/Experimental/Tester.cs new file mode 100644 index 0000000..bf20005 --- /dev/null +++ b/Experimental/Tester.cs @@ -0,0 +1,18 @@ +using System; +using System.Diagnostics; + +namespace DTLib.Experimental +{ + public static class Tester + { + public static void LogOperationTime(string op_name, int repeats, Action operation) + { + Stopwatch clock = new(); + clock.Start(); + for (int i = 0; i < repeats; i++) + operation(); + clock.Stop(); + PublicLog.LogNoTime("c",$"operation {op_name} took {clock.ElapsedTicks / repeats} ticks\n"); + } + } +} diff --git a/Extensions/BaseConverter.cs b/Extensions/BaseConverter.cs index 951e64e..3f41947 100644 --- a/Extensions/BaseConverter.cs +++ b/Extensions/BaseConverter.cs @@ -1,44 +1,52 @@ -using System; -using System.Collections.Generic; +global using DTLib.Extensions; +global using DTLib.Filesystem; +global using System; +global using System.Collections; +global using System.Collections.Generic; +global using System.Text; +global using System.Threading.Tasks; +global using static DTLib.PublicLog; -namespace DTLib.Extensions +namespace DTLib.Extensions; + +public static class BaseConverter { - public static class BaseConverter + // сокращение конвертации + public static bool ToBool(this T input) => Convert.ToBoolean(input); + public static char ToChar(this T input) => Convert.ToChar(input); + public static byte ToByte(this T input) => Convert.ToByte(input); + public static sbyte ToSByte(this T input) => Convert.ToSByte(input); + public static short ToShort(this T input) => Convert.ToInt16(input); + public static ushort ToUShort(this T input) => Convert.ToUInt16(input); + public static int ToInt(this T input) => Convert.ToInt32(input); + public static uint ToUInt(this T input) => Convert.ToUInt32(input); + public static long ToLong(this T input) => Convert.ToInt64(input); + public static ulong ToULong(this T input) => Convert.ToUInt64(input); + public static float ToFloat(this string input) => float.Parse(input, System.Globalization.CultureInfo.InvariantCulture); + public static double ToDouble(this T input) => Convert.ToDouble(input, System.Globalization.CultureInfo.InvariantCulture); + public static decimal ToDecimal(this T input) => Convert.ToDecimal(input, System.Globalization.CultureInfo.InvariantCulture); + + public static int ToInt(this byte[] bytes) { - // сокращение конвертации - public static int ToInt(this T input) => Convert.ToInt32(input); - public static uint ToUInt(this T input) => Convert.ToUInt32(input); - public static long ToLong(this T input) => Convert.ToInt64(input); - public static ulong ToULong(this T input) => Convert.ToUInt64(input); - public static short ToShort(this T input) => Convert.ToInt16(input); - public static ushort ToUShort(this T input) => Convert.ToUInt16(input); - public static double ToDouble(this T input) => Convert.ToDouble(input, System.Globalization.CultureInfo.InvariantCulture); - public static byte ToByte(this T input) => Convert.ToByte(input); - public static sbyte ToSByte(this T input) => Convert.ToSByte(input); - public static bool ToBool(this T input) => Convert.ToBoolean(input); - - public static int ToInt(this byte[] bytes) - { - int output = 0; - for (ushort i = 0; i < bytes.Length; i++) - output = output * 256 + bytes[i]; - return output; - } - - public static byte[] ToBytes(this int num) - { - List output = new(); - while (num != 0) - { - output.Add(ToByte(num % 256)); - num = (num / 256).Truncate(); - } - output.Reverse(); - return output.ToArray(); - } - - // Math.Truncate принимает как decimal, так и doublе, - // из-за чего вызов метода так: Math.Truncate(10/3) выдаст ошибку "неоднозначный вызов" - public static int Truncate(this T number) => Math.Truncate(number.ToDouble()).ToInt(); + int output = 0; + for (ushort i = 0; i < bytes.Length; i++) + output = output * 256 + bytes[i]; + return output; } -} \ No newline at end of file + + public static byte[] ToBytes(this int num) + { + List output = new(); + while (num != 0) + { + output.Add(ToByte(num % 256)); + num = (num / 256).Truncate(); + } + output.Reverse(); + return output.ToArray(); + } + + // Math.Truncate принимает как decimal, так и doublе, + // из-за чего вызов метода так: Math.Truncate(10/3) выдаст ошибку "неоднозначный вызов" + public static int Truncate(this T number) => Math.Truncate(number.ToDouble()).ToInt(); +} diff --git a/Extensions/Collections.cs b/Extensions/Collections.cs index d71aad1..c7c0df1 100644 --- a/Extensions/Collections.cs +++ b/Extensions/Collections.cs @@ -1,45 +1,38 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace DTLib.Extensions; -namespace DTLib.Extensions +public static class Collections { - public static class Collections + + public static void ForEach(this IEnumerable en, Action act) { + foreach (T elem in en) + act(elem); + } - public static void ForEach(this IEnumerable en, Action act) - { - foreach (T elem in en) - act(elem); - } + // массив в лист + public static List ToList(this T[] input) + { + var list = new List(); + list.AddRange(input); + return list; + } - // массив в лист - public static List ToList(this T[] input) - { - var list = new List(); - list.AddRange(input); - return list; - } - - // удаление нескольких элементов массива - public static T[] RemoveRange(this T[] input, int startIndex, int count) - { - var list = input.ToList(); - list.RemoveRange(startIndex, count); - return list.ToArray(); - } - public static T[] RemoveRange(this T[] input, int startIndex) => input.RemoveRange(startIndex, input.Length - startIndex); + // удаление нескольких элементов массива + public static T[] RemoveRange(this T[] input, int startIndex, int count) + { + var list = input.ToList(); + list.RemoveRange(startIndex, count); + return list.ToArray(); + } + public static T[] RemoveRange(this T[] input, int startIndex) => input.RemoveRange(startIndex, input.Length - startIndex); - // метод как у листов - public static bool Contains(this T[] array, T value) - { - for (int i = 0; i < array.Length; i++) - if (array[i].Equals(value)) - return true; - return false; - } + // метод как у листов + public static bool Contains(this T[] array, T value) + { + for (int i = 0; i < array.Length; i++) + if (array[i].Equals(value)) + return true; + return false; } } diff --git a/Extensions/FrameworkFix.cs b/Extensions/FrameworkFix.cs index 5c286ad..47671b5 100644 --- a/Extensions/FrameworkFix.cs +++ b/Extensions/FrameworkFix.cs @@ -1,8 +1,7 @@ using System.ComponentModel; // включает init и record из c# 9.0 -namespace System.Runtime.CompilerServices -{ - [EditorBrowsable(EditorBrowsableState.Never)] - public class IsExternalInit { } -} \ No newline at end of file +namespace System.Runtime.CompilerServices; + +[EditorBrowsable(EditorBrowsableState.Never)] +public class IsExternalInit { } diff --git a/Extensions/IfMethod.cs b/Extensions/IfMethod.cs index 92a670d..9289499 100644 --- a/Extensions/IfMethod.cs +++ b/Extensions/IfMethod.cs @@ -1,24 +1,21 @@ -using System; +namespace DTLib.Extensions; -namespace DTLib.Extensions +public static class IfMethod { - public static class IfMethod + public static T If(this T input, bool condition, Func if_true, Func if_false) => + condition ? if_true(input) : if_false(input); + + public static void If(this T input, bool condition, Action if_true, Action if_false) { - public static T If(this T input, bool condition, Func if_true, Func if_false) => - condition ? if_true(input) : if_false(input); + if (condition) if_true(input); + else if_false(input); + } - public static void If(this T input, bool condition, Action if_true, Action if_false) - { - if (condition) if_true(input); - else if_false(input); - } + public static T If(this T input, bool condition, Func if_true) => + condition ? if_true(input) : input; - public static T If(this T input, bool condition, Func if_true) => - condition ? if_true(input) : input; - - public static void If(this T input, bool condition, Action if_true) - { - if (condition) if_true(input); - } + public static void If(this T input, bool condition, Action if_true) + { + if (condition) if_true(input); } } diff --git a/Extensions/StringConverter.cs b/Extensions/StringConverter.cs index 7a29e7d..fceaae0 100644 --- a/Extensions/StringConverter.cs +++ b/Extensions/StringConverter.cs @@ -1,157 +1,153 @@ -using System.Collections.Generic; -using System.Text; +namespace DTLib.Extensions; -namespace DTLib.Extensions +public static class StringConverter { - public static class StringConverter + public static Encoding UTF8 = new UTF8Encoding(false); + public static byte[] ToBytes(this string str) => UTF8.GetBytes(str); + public static string BytesToString(this byte[] bytes) => UTF8.GetString(bytes); + + // хеш в виде массива байт в строку (хеш изначально не в кодировке UTF8, так что метод выше не работает с ним) + public static string HashToString(this byte[] hash) { - public static Encoding UTF8 = new UTF8Encoding(false); - public static byte[] ToBytes(this string str) => UTF8.GetBytes(str); - public static string BytesToString(this byte[] bytes) => UTF8.GetString(bytes); - - // хеш в виде массива байт в строку (хеш изначально не в кодировке UTF8, так что метод выше не работает с ним) - public static string HashToString(this byte[] hash) + var builder = new StringBuilder(); + for (int i = 0; i < hash.Length; i++) { - var builder = new StringBuilder(); - for (int i = 0; i < hash.Length; i++) - { - builder.Append(hash[i].ToString("x2")); - } - return builder.ToString(); - } - - - // эти методы работают как надо, в отличии от стандартных, которые иногда дуркуют - public static bool StartsWith(this byte[] source, byte[] startsWith) - { - for (int i = 0; i < startsWith.Length; i++) - { - if (source[i] != startsWith[i]) - return false; - } - return true; - } - - public static bool EndsWith(this byte[] source, byte[] endsWith) - { - for (int i = 0; i < endsWith.Length; i++) - { - if (source[source.Length - endsWith.Length + i] != endsWith[i]) - return false; - } - return true; - } - - public static bool StartsWith(this string s, char c) => s[0] == c; - public static bool EndsWith(this string s, char c) => s[s.Length - 1] == c; - - public static string MergeToString(params object[] parts) - { - StringBuilder builder = new(); - for (int i = 0; i < parts.Length; i++) - builder.Append(parts[i].ToString()); - return builder.ToString(); - } - public static string MergeToString(this IEnumerable collection, string separator) - { - StringBuilder builder = new(); - foreach (T elem in collection) - { - builder.Append(elem.ToString()); - builder.Append(separator); - } - if (builder.Length == 0) - return ""; - builder.Remove(builder.Length - separator.Length, separator.Length); - return builder.ToString(); - } - public static string MergeToString(this IEnumerable collection) - { - StringBuilder builder = new(); - foreach (T elem in collection) - builder.Append(elem.ToString()); - return builder.ToString(); - } - - public static string Multiply(this string input, int howMany) - { - StringBuilder b = new(); - for (int i = 0; i < howMany; i++) - b.Append(input); - return b.ToString(); - } - public static string Multiply(this char input, int howMany) - { - StringBuilder b = new(); - for (int i = 0; i < howMany; i++) - b.Append(input); - return b.ToString(); - } - - - // делает что надо в отличии от String.Split(), который не убирает char c из начала - public static List SplitToList(this string s, char c) - { - char[] ar = s.ToCharArray(); - StringBuilder b = new(); - List o = new(); - if (ar[0] != c) - b.Append(ar[0]); - for (int i = 1; i < ar.Length; i++) - if (ar[i] == c) - { - if (b.Length > 0) - o.Add(b.ToString()); - b.Clear(); - } - else b.Append(ar[i]); - if (b.Length > 0) o.Add(b.ToString()); - return o; - } - - // правильно реагирует на кавычки - public static List SplitToList(this string s, char c, char quot) - { - List output = new(); - var list = s.SplitToList(c); - bool q_open = false; - for (int i = 0; i < list.Count; i++) - { - var _s = list[i]; - if (q_open) - { - if (_s.EndsWith(quot)) - { - q_open = false; - _s = _s.Remove(_s.Length - 1); - } - output[output.Count - 1] += c + _s; - } - else if (_s.StartsWith(quot)) - { - q_open = true; - _s = _s.Remove(0, 1); - } - output.Add(_s); - } - return output; - } - - // разбивает на части указанной длины - public static List SplitToList(this string s, int length) - { - List parts = new(); - int max = (s.Length / length).Truncate(); - for (int i = 0; i < max; i++) - parts.Add(s.Substring(i * length, length)); - if (max * length != s.Length) parts.Add(s.Substring(max * length, s.Length - max * length)); - return parts; - } - - public static string AddZeroes(this T number, int length) - { - var str = number.ToString(); - return Multiply('0', str.Length - length) + str; + builder.Append(hash[i].ToString("x2")); } + return builder.ToString(); } -} \ No newline at end of file + + + // эти методы работают как надо, в отличии от стандартных, которые иногда дуркуют + public static bool StartsWith(this byte[] source, byte[] startsWith) + { + for (int i = 0; i < startsWith.Length; i++) + { + if (source[i] != startsWith[i]) + return false; + } + return true; + } + + public static bool EndsWith(this byte[] source, byte[] endsWith) + { + for (int i = 0; i < endsWith.Length; i++) + { + if (source[source.Length - endsWith.Length + i] != endsWith[i]) + return false; + } + return true; + } + + public static bool StartsWith(this string s, char c) => s[0] == c; + public static bool EndsWith(this string s, char c) => s[s.Length - 1] == c; + + public static string MergeToString(params object[] parts) + { + StringBuilder builder = new(); + for (int i = 0; i < parts.Length; i++) + builder.Append(parts[i].ToString()); + return builder.ToString(); + } + public static string MergeToString(this IEnumerable collection, string separator) + { + StringBuilder builder = new(); + foreach (T elem in collection) + { + builder.Append(elem.ToString()); + builder.Append(separator); + } + if (builder.Length == 0) + return ""; + builder.Remove(builder.Length - separator.Length, separator.Length); + return builder.ToString(); + } + public static string MergeToString(this IEnumerable collection) + { + StringBuilder builder = new(); + foreach (T elem in collection) + builder.Append(elem.ToString()); + return builder.ToString(); + } + + public static string Multiply(this string input, int howMany) + { + StringBuilder b = new(); + for (int i = 0; i < howMany; i++) + b.Append(input); + return b.ToString(); + } + public static string Multiply(this char input, int howMany) + { + StringBuilder b = new(); + for (int i = 0; i < howMany; i++) + b.Append(input); + return b.ToString(); + } + + + // делает что надо в отличии от String.Split(), который не убирает char c из начала + public static List SplitToList(this string s, char c) + { + char[] ar = s.ToCharArray(); + StringBuilder b = new(); + List o = new(); + if (ar[0] != c) + b.Append(ar[0]); + for (int i = 1; i < ar.Length; i++) + if (ar[i] == c) + { + if (b.Length > 0) + o.Add(b.ToString()); + b.Clear(); + } + else b.Append(ar[i]); + if (b.Length > 0) o.Add(b.ToString()); + return o; + } + + // правильно реагирует на кавычки + public static List SplitToList(this string s, char c, char quot) + { + List output = new(); + var list = s.SplitToList(c); + bool q_open = false; + for (int i = 0; i < list.Count; i++) + { + var _s = list[i]; + if (q_open) + { + if (_s.EndsWith(quot)) + { + q_open = false; + _s = _s.Remove(_s.Length - 1); + } + output[output.Count - 1] += c + _s; + } + else if (_s.StartsWith(quot)) + { + q_open = true; + _s = _s.Remove(0, 1); + } + output.Add(_s); + } + return output; + } + + // разбивает на части указанной длины + public static List SplitToList(this string s, int length) + { + List parts = new(); + int max = (s.Length / length).Truncate(); + for (int i = 0; i < max; i++) + parts.Add(s.Substring(i * length, length)); + if (max * length != s.Length) parts.Add(s.Substring(max * length, s.Length - max * length)); + return parts; + } + + public static string AddZeroes(this T number, int length) + { + var str = number.ToString(); + return new string('0', str.Length - length) + str; + } +} diff --git a/Filesystem/Directory.cs b/Filesystem/Directory.cs index 0465697..a180426 100644 --- a/Filesystem/Directory.cs +++ b/Filesystem/Directory.cs @@ -1,159 +1,139 @@ -using DTLib.Extensions; -using System; -using System.Collections.Generic; +namespace DTLib.Filesystem; -namespace DTLib.Filesystem +public static class Directory { - public static class Directory + public static bool Exists(string dir) => System.IO.Directory.Exists(dir); + + // создает папку, если её не существует + public static void Create(string dir) { - public static bool Exists(string dir) => System.IO.Directory.Exists(dir); - - // создает папку, если её не существует - public static void Create(string dir) + if (!Directory.Exists(dir)) { - if (!Directory.Exists(dir)) - { - // проверяет существование папки, в которой нужно создать dir - if (dir.Contains("\\") && !Directory.Exists(dir.Remove(dir.LastIndexOf('\\')))) - Create(dir.Remove(dir.LastIndexOf('\\'))); - System.IO.Directory.CreateDirectory(dir); - } - } - // копирует все файлы и папки - public static void Copy(string source_dir, string new_dir, bool owerwrite = false) - { - Create(new_dir); - var subdirs = new List(); - List files = GetAllFiles(source_dir, ref subdirs); - for (int i = 0; i < subdirs.Count; i++) - { - Create(subdirs[i].Replace(source_dir, new_dir)); - } - for (int i = 0; i < files.Count; i++) - { - string f = files[i].Replace(source_dir, new_dir); - File.Copy(files[i], f, owerwrite); - //PublicLog.Log(new string[] {"g", $"file <", "c", files[i], "b", "> have copied to <", "c", newfile, "b", ">\n'" }); - } - } - - // копирует все файлы и папки и выдаёт список конфликтующих файлов - public static void Copy(string source_dir, string new_dir, out List conflicts, bool owerwrite = false) - { - conflicts = new List(); - var subdirs = new List(); - List files = GetAllFiles(source_dir, ref subdirs); - Create(new_dir); - for (int i = 0; i < subdirs.Count; i++) - { - Create(subdirs[i].Replace(source_dir, new_dir)); - } - for (int i = 0; i < files.Count; i++) - { - string newfile = files[i].Replace(source_dir, new_dir); - if (File.Exists(newfile)) - conflicts.Add(newfile); - File.Copy(files[i], newfile, owerwrite); - //PublicLog.Log(new string[] {"g", $"file <", "c", files[i], "b", "> have copied to <", "c", newfile, "b", ">\n'" }); - } - } - - // удаляет папку со всеми подпапками и файлами - public static void Delete(string dir) - { - var subdirs = new List(); - List files = GetAllFiles(dir, ref subdirs); - for (int i = 0; i < files.Count; i++) - File.Delete(files[i]); - for (int i = subdirs.Count - 1; i >= 0; i--) - { - PublicLog.Log($"deleting {subdirs[i]}\n"); - if (Directory.Exists(subdirs[i])) - System.IO.Directory.Delete(subdirs[i], true); - } - PublicLog.Log($"deleting {dir}\n"); - if (Directory.Exists(dir)) - System.IO.Directory.Delete(dir, true); - } - - public static string[] GetFiles(string dir) => System.IO.Directory.GetFiles(dir); - public static string[] GetFiles(string dir, string searchPattern) => System.IO.Directory.GetFiles(dir, searchPattern); - public static string[] GetDirectories(string dir) => System.IO.Directory.GetDirectories(dir); - - // выдает список всех файлов - public static List GetAllFiles(string dir) - { - var all_files = new List(); - string[] cur_files = Directory.GetFiles(dir); - for (int i = 0; i < cur_files.Length; i++) - { - all_files.Add(cur_files[i]); - //PublicLog.Log(new string[] { "b", "file found: <", "c", cur_files[i], "b", ">\n" }); - } - string[] cur_subdirs = Directory.GetDirectories(dir); - for (int i = 0; i < cur_subdirs.Length; i++) - { - //PublicLog.Log(new string[] { "b", "subdir found: <", "c", cur_subdirs[i], "b", ">\n" }); - all_files.AddRange(GetAllFiles(cur_subdirs[i])); - } - return all_files; - } - - // выдает список всех файлов и подпапок в папке - public static List GetAllFiles(string dir, ref List all_subdirs) - { - var all_files = new List(); - string[] cur_files = Directory.GetFiles(dir); - for (int i = 0; i < cur_files.Length; i++) - { - all_files.Add(cur_files[i]); - //PublicLog.Log(new string[] { "b", "file found: <", "c", cur_files[i], "b", ">\n" }); - } - string[] cur_subdirs = Directory.GetDirectories(dir); - for (int i = 0; i < cur_subdirs.Length; i++) - { - all_subdirs.Add(cur_subdirs[i]); - //PublicLog.Log(new string[] { "b", "subdir found: <", "c", cur_subdirs[i], "b", ">\n" }); - all_files.AddRange(GetAllFiles(cur_subdirs[i], ref all_subdirs)); - } - return all_files; - } - - public static string GetCurrent() => System.IO.Directory.GetCurrentDirectory(); - - public static void GrantAccess(string fullPath) - { - var dirInfo = new System.IO.DirectoryInfo(fullPath); - System.Security.AccessControl.DirectorySecurity dirSecurity = dirInfo.GetAccessControl(); - dirSecurity.AddAccessRule(new System.Security.AccessControl.FileSystemAccessRule( - new System.Security.Principal.SecurityIdentifier( - System.Security.Principal.WellKnownSidType.WorldSid, null), - System.Security.AccessControl.FileSystemRights.FullControl, - System.Security.AccessControl.InheritanceFlags.ObjectInherit | - System.Security.AccessControl.InheritanceFlags.ContainerInherit, - System.Security.AccessControl.PropagationFlags.NoPropagateInherit, - System.Security.AccessControl.AccessControlType.Allow)); - dirInfo.SetAccessControl(dirSecurity); - } - - public static void CreateSymlink(string sourceName, string symlinkName) - { - if (symlinkName.Contains("\\")) - Directory.Create(symlinkName.Remove(symlinkName.LastIndexOf('\\'))); - if (!Symlink.CreateSymbolicLink(symlinkName, sourceName, Symlink.SymlinkTarget.Directory)) - throw new InvalidOperationException($"some error occured while creating symlink\nDirectory.CreateSymlink({symlinkName}, {sourceName})"); - } - - // copies directory with symlinks instead of files - public static int SymCopy(string srcdir, string newdir) - { - var files = Directory.GetAllFiles(srcdir); - if (!srcdir.EndsWith('\\')) srcdir += '\\'; - if (!newdir.EndsWith('\\')) newdir += '\\'; - int i = 0; - for (; i < files.Count; i++) - File.CreateSymlink(files[i], files[i].Replace(srcdir, newdir)); - return i; + // проверяет существование папки, в которой нужно создать dir + if (dir.Contains("\\") && !Directory.Exists(dir.Remove(dir.LastIndexOf('\\')))) + Create(dir.Remove(dir.LastIndexOf('\\'))); + System.IO.Directory.CreateDirectory(dir); } } + // копирует все файлы и папки + public static void Copy(string source_dir, string new_dir, bool owerwrite = false) + { + Create(new_dir); + var subdirs = new List(); + List files = GetAllFiles(source_dir, ref subdirs); + for (int i = 0; i < subdirs.Count; i++) + { + Create(subdirs[i].Replace(source_dir, new_dir)); + } + for (int i = 0; i < files.Count; i++) + { + string f = files[i].Replace(source_dir, new_dir); + File.Copy(files[i], f, owerwrite); + //PublicLog.Log(new string[] {"g", $"file <", "c", files[i], "b", "> have copied to <", "c", newfile, "b", ">\n'" }); + } + } + + // копирует все файлы и папки и выдаёт список конфликтующих файлов + public static void Copy(string source_dir, string new_dir, out List conflicts, bool owerwrite = false) + { + conflicts = new List(); + var subdirs = new List(); + List files = GetAllFiles(source_dir, ref subdirs); + Create(new_dir); + for (int i = 0; i < subdirs.Count; i++) + { + Create(subdirs[i].Replace(source_dir, new_dir)); + } + for (int i = 0; i < files.Count; i++) + { + string newfile = files[i].Replace(source_dir, new_dir); + if (File.Exists(newfile)) + conflicts.Add(newfile); + File.Copy(files[i], newfile, owerwrite); + //PublicLog.Log(new string[] {"g", $"file <", "c", files[i], "b", "> have copied to <", "c", newfile, "b", ">\n'" }); + } + } + + // удаляет папку со всеми подпапками и файлами + public static void Delete(string dir) + { + var subdirs = new List(); + List files = GetAllFiles(dir, ref subdirs); + for (int i = 0; i < files.Count; i++) + File.Delete(files[i]); + for (int i = subdirs.Count - 1; i >= 0; i--) + { + PublicLog.Log($"deleting {subdirs[i]}\n"); + if (Directory.Exists(subdirs[i])) + System.IO.Directory.Delete(subdirs[i], true); + } + PublicLog.Log($"deleting {dir}\n"); + if (Directory.Exists(dir)) + System.IO.Directory.Delete(dir, true); + } + + public static string[] GetFiles(string dir) => System.IO.Directory.GetFiles(dir); + public static string[] GetFiles(string dir, string searchPattern) => System.IO.Directory.GetFiles(dir, searchPattern); + public static string[] GetDirectories(string dir) => System.IO.Directory.GetDirectories(dir); + + // выдает список всех файлов + public static List GetAllFiles(string dir) + { + var all_files = new List(); + string[] cur_files = Directory.GetFiles(dir); + for (int i = 0; i < cur_files.Length; i++) + { + all_files.Add(cur_files[i]); + //PublicLog.Log(new string[] { "b", "file found: <", "c", cur_files[i], "b", ">\n" }); + } + string[] cur_subdirs = Directory.GetDirectories(dir); + for (int i = 0; i < cur_subdirs.Length; i++) + { + //PublicLog.Log(new string[] { "b", "subdir found: <", "c", cur_subdirs[i], "b", ">\n" }); + all_files.AddRange(GetAllFiles(cur_subdirs[i])); + } + return all_files; + } + + // выдает список всех файлов и подпапок в папке + public static List GetAllFiles(string dir, ref List all_subdirs) + { + var all_files = new List(); + string[] cur_files = Directory.GetFiles(dir); + for (int i = 0; i < cur_files.Length; i++) + { + all_files.Add(cur_files[i]); + //PublicLog.Log(new string[] { "b", "file found: <", "c", cur_files[i], "b", ">\n" }); + } + string[] cur_subdirs = Directory.GetDirectories(dir); + for (int i = 0; i < cur_subdirs.Length; i++) + { + all_subdirs.Add(cur_subdirs[i]); + //PublicLog.Log(new string[] { "b", "subdir found: <", "c", cur_subdirs[i], "b", ">\n" }); + all_files.AddRange(GetAllFiles(cur_subdirs[i], ref all_subdirs)); + } + return all_files; + } + + public static string GetCurrent() => System.IO.Directory.GetCurrentDirectory(); + + public static void CreateSymlink(string sourceName, string symlinkName) + { + if (symlinkName.Contains("\\")) + Directory.Create(symlinkName.Remove(symlinkName.LastIndexOf('\\'))); + if (!Symlink.CreateSymbolicLink(symlinkName, sourceName, Symlink.SymlinkTarget.Directory)) + throw new InvalidOperationException($"some error occured while creating symlink\nDirectory.CreateSymlink({symlinkName}, {sourceName})"); + } + + // copies directory with symlinks instead of files + public static int SymCopy(string srcdir, string newdir) + { + var files = Directory.GetAllFiles(srcdir); + if (!srcdir.EndsWith('\\')) srcdir += '\\'; + if (!newdir.EndsWith('\\')) newdir += '\\'; + int i = 0; + for (; i < files.Count; i++) + File.CreateSymlink(files[i], files[i].Replace(srcdir, newdir)); + return i; + } } diff --git a/Filesystem/File.cs b/Filesystem/File.cs index 9896ceb..976713f 100644 --- a/Filesystem/File.cs +++ b/Filesystem/File.cs @@ -1,87 +1,83 @@ -using DTLib.Extensions; -using System; +namespace DTLib.Filesystem; -namespace DTLib.Filesystem +public static class File { - public static class File + public static int GetSize(string file) => new System.IO.FileInfo(file).Length.ToInt(); + + public static bool Exists(string file) => System.IO.File.Exists(file); + + // если файл не существует, создаёт файл, создаёт папки из его пути + public static void Create(string file, bool delete_old = false) { - public static int GetSize(string file) => new System.IO.FileInfo(file).Length.ToInt(); - - public static bool Exists(string file) => System.IO.File.Exists(file); - - // если файл не существует, создаёт файл, создаёт папки из его пути - public static void Create(string file, bool delete_old = false) + if (delete_old && File.Exists(file)) + File.Delete(file); + if (!File.Exists(file)) { - if (delete_old && File.Exists(file)) - File.Delete(file); - if (!File.Exists(file)) - { - if (file.Contains("\\")) - Directory.Create(file.Remove(file.LastIndexOf('\\'))); - using System.IO.FileStream stream = System.IO.File.Create(file); - stream.Close(); - } - } - - public static void Copy(string srcPath, string newPath, bool replace = false) - { - if (!replace && Exists(newPath)) - throw new Exception($"file <{newPath}> alredy exists"); - Create(newPath); - WriteAllBytes(newPath, ReadAllBytes(srcPath)); - } - - public static void Delete(string file) => System.IO.File.Delete(file); - - public static byte[] ReadAllBytes(string file) - { - using System.IO.FileStream stream = File.OpenRead(file); - int size = GetSize(file); - byte[] output = new byte[size]; - stream.Read(output, 0, size); + if (file.Contains("\\")) + Directory.Create(file.Remove(file.LastIndexOf('\\'))); + using System.IO.FileStream stream = System.IO.File.Create(file); stream.Close(); - return output; - } - - public static string ReadAllText(string file) => ReadAllBytes(file).BytesToString(); - - public static void WriteAllBytes(string file, byte[] content) - { - using System.IO.FileStream stream = File.OpenWrite(file); - stream.Write(content, 0, content.Length); - stream.Close(); - } - - public static void WriteAllText(string file, string content) => WriteAllBytes(file, content.ToBytes()); - - public static void AppendAllBytes(string file, byte[] content) - { - using System.IO.FileStream stream = File.OpenAppend(file); - stream.Write(content, 0, content.Length); - stream.Close(); - } - - public static void AppendAllText(string file, string content) => AppendAllBytes(file, content.ToBytes()); - - public static System.IO.FileStream OpenRead(string file) => - Exists(file) ? System.IO.File.OpenRead(file) : throw new Exception($"file not found: <{file}>"); - public static System.IO.FileStream OpenWrite(string file) - { - File.Create(file, true); - return System.IO.File.Open(file, System.IO.FileMode.OpenOrCreate); - } - public static System.IO.FileStream OpenAppend(string file) - { - File.Create(file); - return System.IO.File.Open(file, System.IO.FileMode.Append); - } - - public static void CreateSymlink(string sourceName, string symlinkName) - { - if (symlinkName.Contains("\\")) - Directory.Create(symlinkName.Remove(symlinkName.LastIndexOf('\\'))); - if (!Symlink.CreateSymbolicLink(symlinkName, sourceName, Symlink.SymlinkTarget.File)) - throw new InvalidOperationException($"some error occured while creating symlink\nFile.CreateSymlink({symlinkName}, {sourceName})"); } } + + public static void Copy(string srcPath, string newPath, bool replace = false) + { + if (!replace && Exists(newPath)) + throw new Exception($"file <{newPath}> alredy exists"); + Create(newPath); + WriteAllBytes(newPath, ReadAllBytes(srcPath)); + } + + public static void Delete(string file) => System.IO.File.Delete(file); + + public static byte[] ReadAllBytes(string file) + { + using System.IO.FileStream stream = File.OpenRead(file); + int size = GetSize(file); + byte[] output = new byte[size]; + stream.Read(output, 0, size); + stream.Close(); + return output; + } + + public static string ReadAllText(string file) => ReadAllBytes(file).BytesToString(); + + public static void WriteAllBytes(string file, byte[] content) + { + using System.IO.FileStream stream = File.OpenWrite(file); + stream.Write(content, 0, content.Length); + stream.Close(); + } + + public static void WriteAllText(string file, string content) => WriteAllBytes(file, content.ToBytes()); + + public static void AppendAllBytes(string file, byte[] content) + { + using System.IO.FileStream stream = File.OpenAppend(file); + stream.Write(content, 0, content.Length); + stream.Close(); + } + + public static void AppendAllText(string file, string content) => AppendAllBytes(file, content.ToBytes()); + + public static System.IO.FileStream OpenRead(string file) => + Exists(file) ? System.IO.File.OpenRead(file) : throw new Exception($"file not found: <{file}>"); + public static System.IO.FileStream OpenWrite(string file) + { + File.Create(file, true); + return System.IO.File.Open(file, System.IO.FileMode.OpenOrCreate); + } + public static System.IO.FileStream OpenAppend(string file) + { + File.Create(file); + return System.IO.File.Open(file, System.IO.FileMode.Append); + } + + public static void CreateSymlink(string sourceName, string symlinkName) + { + if (symlinkName.Contains("\\")) + Directory.Create(symlinkName.Remove(symlinkName.LastIndexOf('\\'))); + if (!Symlink.CreateSymbolicLink(symlinkName, sourceName, Symlink.SymlinkTarget.File)) + throw new InvalidOperationException($"some error occured while creating symlink\nFile.CreateSymlink({symlinkName}, {sourceName})"); + } } diff --git a/Filesystem/OldFilework.cs b/Filesystem/OldFilework.cs index aab83fe..bdc4ffc 100644 --- a/Filesystem/OldFilework.cs +++ b/Filesystem/OldFilework.cs @@ -1,68 +1,65 @@ -using System; +namespace DTLib.Filesystem; -namespace DTLib.Filesystem +// +// некоторые старые методы, которые хорошо бы вырезать +// +public static class OldFilework { - // - // некоторые старые методы, которые хорошо бы вырезать - // - public static class OldFilework + // записывает текст в файл и закрывает файл + /*public static void LogToFile(string logfile, string msg) { - // записывает текст в файл и закрывает файл - /*public static void LogToFile(string logfile, string msg) + lock (new object()) { - lock (new object()) - { - File.AppendAllText(logfile, msg); - } - }*/ + File.AppendAllText(logfile, msg); + } + }*/ - // чтение параметров из конфига - public static string ReadFromConfig(string configfile, string key) + // чтение параметров из конфига + public static string ReadFromConfig(string configfile, string key) + { + lock (new object()) { - lock (new object()) + key += ": "; + using var reader = new System.IO.StreamReader(configfile); + while (!reader.EndOfStream) { - key += ": "; - using var reader = new System.IO.StreamReader(configfile); - while (!reader.EndOfStream) + string st = reader.ReadLine(); + if (st.StartsWith(key)) { - string st = reader.ReadLine(); - if (st.StartsWith(key)) + string value = ""; + for (int i = key.Length; i < st.Length; i++) { - string value = ""; - for (int i = key.Length; i < st.Length; i++) + if (st[i] == '#') + return value; + if (st[i] == '%') { - if (st[i] == '#') - return value; - if (st[i] == '%') + bool stop = false; + string placeholder = ""; + i++; + while (!stop) { - bool stop = false; - string placeholder = ""; - i++; - while (!stop) + if (st[i] == '%') { - if (st[i] == '%') - { - stop = true; - value += ReadFromConfig(configfile, placeholder); - } - else - { - placeholder += st[i]; - i++; - } + stop = true; + value += ReadFromConfig(configfile, placeholder); + } + else + { + placeholder += st[i]; + i++; } } - else - value += st[i]; } - reader.Close(); - //if (value == "") throw new System.Exception($"ReadFromConfig({configfile}, {key}) error: key not found"); - return value; + else + value += st[i]; } + reader.Close(); + //if (value == "") throw new System.Exception($"ReadFromConfig({configfile}, {key}) error: key not found"); + return value; } - reader.Close(); - throw new Exception($"ReadFromConfig({configfile}, {key}) error: key not found"); } + reader.Close(); + throw new Exception($"ReadFromConfig({configfile}, {key}) error: key not found"); } } } diff --git a/Filesystem/Symlink.cs b/Filesystem/Symlink.cs index 66e8a5c..2e2b980 100644 --- a/Filesystem/Symlink.cs +++ b/Filesystem/Symlink.cs @@ -1,21 +1,15 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; +using System.Runtime.InteropServices; -namespace DTLib.Filesystem +namespace DTLib.Filesystem; + +internal class Symlink { - internal class Symlink - { - [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] - static internal extern bool CreateSymbolicLink(string symlinkName, string sourceName, SymlinkTarget type); + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + static internal extern bool CreateSymbolicLink(string symlinkName, string sourceName, SymlinkTarget type); - internal enum SymlinkTarget - { - File, - Directory - } + internal enum SymlinkTarget + { + File, + Directory } } diff --git a/Hasher.cs b/Hasher.cs index d132451..ba622aa 100644 --- a/Hasher.cs +++ b/Hasher.cs @@ -1,60 +1,57 @@ -using System.Collections.Generic; -using System.Security.Cryptography; -using DTLib.Filesystem; +using System.Security.Cryptography; -namespace DTLib +namespace DTLib; + +// +// хеширует массивы байтов алшоритмом SHA256 и файлы алгоримом XXHash32 +// +public class Hasher { - // - // хеширует массивы байтов алшоритмом SHA256 и файлы алгоримом XXHash32 - // - public class Hasher + readonly HashAlgorithm sha256 = SHA256.Create(); + readonly HashAlgorithm xxh32 = XXHash32.Create(); + + public Hasher() { } + + // хеш массива + public byte[] Hash(byte[] input) => sha256.ComputeHash(input); + + // хеш из двух массивов + public byte[] Hash(byte[] input, byte[] salt) { - readonly HashAlgorithm sha256 = SHA256.Create(); - readonly HashAlgorithm xxh32 = XXHash32.Create(); + var rez = new List(); + rez.AddRange(input); + rez.AddRange(salt); + return sha256.ComputeHash(rez.ToArray()); + } - public Hasher() { } - - // хеш массива - public byte[] Hash(byte[] input) => sha256.ComputeHash(input); - - // хеш из двух массивов - public byte[] Hash(byte[] input, byte[] salt) + // хеш двух массивов зацикленный + public byte[] HashCycled(byte[] input, byte[] salt, ushort cycles) + { + for (uint i = 0; i < cycles; i++) { - var rez = new List(); - rez.AddRange(input); - rez.AddRange(salt); - return sha256.ComputeHash(rez.ToArray()); + input = Hash(input, salt); } + return input; + } + // хеш зацикленный + public byte[] HashCycled(byte[] input, ushort cycles) + { + for (uint i = 0; i < cycles; i++) + { + input = Hash(input); + } + return input; + } - // хеш двух массивов зацикленный - public byte[] HashCycled(byte[] input, byte[] salt, ushort cycles) - { - for (uint i = 0; i < cycles; i++) - { - input = Hash(input, salt); - } - return input; - } - // хеш зацикленный - public byte[] HashCycled(byte[] input, ushort cycles) - { - for (uint i = 0; i < cycles; i++) - { - input = Hash(input); - } - return input; - } - - // хеш файла - public byte[] HashFile(string filename) - { - using System.IO.FileStream fileStream = File.OpenRead(filename); - //var then = DateTime.Now.Hour * 3600 + DateTime.Now.Minute * 60 + DateTime.Now.Second; - byte[] hash = xxh32.ComputeHash(fileStream); - //var now = DateTime.Now.Hour * 3600 + DateTime.Now.Minute * 60 + DateTime.Now.Second; - //PublicLog.Log($"xxh32 hash: {hash.HashToString()} time: {now - then}\n"); - fileStream.Close(); - return hash; - } + // хеш файла + public byte[] HashFile(string filename) + { + using System.IO.FileStream fileStream = File.OpenRead(filename); + //var then = DateTime.Now.Hour * 3600 + DateTime.Now.Minute * 60 + DateTime.Now.Second; + byte[] hash = xxh32.ComputeHash(fileStream); + //var now = DateTime.Now.Hour * 3600 + DateTime.Now.Minute * 60 + DateTime.Now.Second; + //PublicLog.Log($"xxh32 hash: {hash.HashToString()} time: {now - then}\n"); + fileStream.Close(); + return hash; } } diff --git a/Loggers/AsyncLogger.cs b/Loggers/AsyncLogger.cs new file mode 100644 index 0000000..c86d837 --- /dev/null +++ b/Loggers/AsyncLogger.cs @@ -0,0 +1,34 @@ +namespace DTLib.Loggers; + +// вывод лога в консоль и файл +public class AsyncLogger : BaseLogger +{ + public AsyncLogger(string logfile) : base(logfile) { } + + public AsyncLogger(string dir, string programName) : base(dir, programName) { } + + readonly object consolelocker = new(); + public override void Log(params string[] msg) + { + lock (statelocker) if (!IsEnabled) return; + // добавление даты + if (msg.Length == 1) msg[0] = "[" + DateTime.Now.ToString() + "]: " + msg[0]; + else msg[1] = "[" + DateTime.Now.ToString() + "]: " + msg[1]; + // перенос строки + msg[msg.Length - 1] += '\n'; + // вывод в консоль + lock (consolelocker) + ColoredConsole.Write(msg); + // вывод в файл + if (msg.Length == 1) + lock (Logfile) File.AppendAllText(Logfile, msg[0]); + else + { + StringBuilder strB = new(); + for (ushort i = 0; i < msg.Length; i++) + strB.Append(msg[++i]); + lock (Logfile) File.AppendAllText(Logfile, strB.ToString()); + } + } + public void LogAsync(params string[] msg) => Task.Run(() => Log(msg)); +} diff --git a/Loggers/BaseLogger.cs b/Loggers/BaseLogger.cs new file mode 100644 index 0000000..cbbe437 --- /dev/null +++ b/Loggers/BaseLogger.cs @@ -0,0 +1,16 @@ +namespace DTLib.Loggers; + +public abstract class BaseLogger +{ + public string Logfile { get; init; } + public BaseLogger(string logfile) => Logfile = logfile; + public BaseLogger(string dir, string programName) => Logfile = $"{dir}\\{programName}_{DateTime.Now}.log".Replace(':', '-').Replace(' ', '_'); + + + public bool IsEnabled { get; private set; } = false; + readonly protected object statelocker = new(); + public void Disable() { lock (statelocker) IsEnabled = false; } + public void Enable() { lock (statelocker) IsEnabled = true; } + + public abstract void Log(params string[] msg); +} diff --git a/Loggers/DefaultLogger.cs b/Loggers/DefaultLogger.cs new file mode 100644 index 0000000..903671c --- /dev/null +++ b/Loggers/DefaultLogger.cs @@ -0,0 +1,32 @@ +namespace DTLib.Loggers; + +// вывод лога в консоль и файл +public class DefaultLogger : BaseLogger +{ + public DefaultLogger(string logfile) : base(logfile) { } + + public DefaultLogger(string dir, string programName) : base(dir, programName) { } + + public override void Log(params string[] msg) + { + lock (Logfile) if (!IsEnabled) return; + if (msg.Length == 1) msg[0] = "[" + DateTime.Now.ToString() + "]: " + msg[0]; + else msg[1] = "[" + DateTime.Now.ToString() + "]: " + msg[1]; + LogNoTime(msg); + } + + public void LogNoTime(params string[] msg) + { + lock (Logfile) if (!IsEnabled) return; + ColoredConsole.Write(msg); + if (msg.Length == 1) + lock (Logfile) File.AppendAllText(Logfile, msg[0]); + else + { + StringBuilder strB = new(); + for (ushort i = 0; i < msg.Length; i++) + strB.Append(msg[++i]); + lock (Logfile) File.AppendAllText(Logfile, strB.ToString()); + } + } +} diff --git a/Network/FSP.cs b/Network/FSP.cs index 1920458..ab16f65 100644 --- a/Network/FSP.cs +++ b/Network/FSP.cs @@ -1,211 +1,206 @@ using DTLib.Dtsod; -using DTLib.Extensions; -using DTLib.Filesystem; using System.Net.Sockets; -using System.Text; -using static DTLib.PublicLog; -namespace DTLib.Network +namespace DTLib.Network; + +// +// передача файлов по сети +// +public class FSP { - // - // передача файлов по сети - // - public class FSP + Socket MainSocket { get; init; } + public static bool debug = false; + public FSP(Socket _mainSocket) => MainSocket = _mainSocket; + + public uint BytesDownloaded = 0; + public uint BytesUploaded = 0; + public uint Filesize = 0; + + // скачивает файл с помощью FSP протокола + public void DownloadFile(string filePath_server, string filePath_client) { - Socket MainSocket { get; init; } - public static bool debug = false; - public FSP(Socket _mainSocket) => MainSocket = _mainSocket; - - public uint BytesDownloaded = 0; - public uint BytesUploaded = 0; - public uint Filesize = 0; - - // скачивает файл с помощью FSP протокола - public void DownloadFile(string filePath_server, string filePath_client) + lock (MainSocket) { - lock (MainSocket) + Debug("b", $"requesting file download: {filePath_server}\n"); + MainSocket.SendPackage("requesting file download".ToBytes()); + MainSocket.SendPackage(filePath_server.ToBytes()); + } + DownloadFile(filePath_client); + } + + public void DownloadFile(string filePath_client) + { + using System.IO.Stream fileStream = File.OpenWrite(filePath_client); + Download_SharedCode(fileStream, true); + fileStream.Close(); + Debug("g", $" downloaded {BytesDownloaded} of {Filesize} bytes\n"); + } + + public byte[] DownloadFileToMemory(string filePath_server) + { + lock (MainSocket) + { + Debug("b", $"requesting file download: {filePath_server}\n"); + MainSocket.SendPackage("requesting file download".ToBytes()); + MainSocket.SendPackage(filePath_server.ToBytes()); + } + return DownloadFileToMemory(); + } + + public byte[] DownloadFileToMemory() + { + using var fileStream = new System.IO.MemoryStream(); + Download_SharedCode(fileStream, false); + byte[] output = fileStream.GetBuffer(); + fileStream.Close(); + Debug("g", $" downloaded {BytesDownloaded} of {Filesize} bytes\n"); + return output; + } + + void Download_SharedCode(System.IO.Stream fileStream, bool requiresFlushing) + { + lock (MainSocket) + { + BytesDownloaded = 0; + Filesize = MainSocket.GetPackage().BytesToString().ToUInt(); + MainSocket.SendPackage("ready".ToBytes()); + int packagesCount = 0; + byte[] buffer = new byte[5120]; + int fullPackagesCount = (Filesize / buffer.Length).Truncate(); + // получение полных пакетов файла + for (byte n = 0; packagesCount < fullPackagesCount; packagesCount++) { - Debug("b", $"requesting file download: {filePath_server}\n"); - MainSocket.SendPackage("requesting file download".ToBytes()); - MainSocket.SendPackage(filePath_server.ToBytes()); - } - DownloadFile(filePath_client); - } - - public void DownloadFile(string filePath_client) - { - using System.IO.Stream fileStream = File.OpenWrite(filePath_client); - Download_SharedCode(fileStream, true); - fileStream.Close(); - Debug("g", $" downloaded {BytesDownloaded} of {Filesize} bytes\n"); - } - - public byte[] DownloadFileToMemory(string filePath_server) - { - lock (MainSocket) - { - Debug("b", $"requesting file download: {filePath_server}\n"); - MainSocket.SendPackage("requesting file download".ToBytes()); - MainSocket.SendPackage(filePath_server.ToBytes()); - } - return DownloadFileToMemory(); - } - - public byte[] DownloadFileToMemory() - { - using var fileStream = new System.IO.MemoryStream(); - Download_SharedCode(fileStream, false); - byte[] output = fileStream.GetBuffer(); - fileStream.Close(); - Debug("g", $" downloaded {BytesDownloaded} of {Filesize} bytes\n"); - return output; - } - - void Download_SharedCode(System.IO.Stream fileStream, bool requiresFlushing) - { - lock (MainSocket) - { - BytesDownloaded = 0; - Filesize = MainSocket.GetPackage().BytesToString().ToUInt(); - MainSocket.SendPackage("ready".ToBytes()); - int packagesCount = 0; - byte[] buffer = new byte[5120]; - int fullPackagesCount = (Filesize / buffer.Length).Truncate(); - // получение полных пакетов файла - for (byte n = 0; packagesCount < fullPackagesCount; packagesCount++) + buffer = MainSocket.GetPackage(); + BytesDownloaded += (uint)buffer.Length; + fileStream.Write(buffer, 0, buffer.Length); + if (requiresFlushing) { - buffer = MainSocket.GetPackage(); - BytesDownloaded += (uint)buffer.Length; - fileStream.Write(buffer, 0, buffer.Length); - if (requiresFlushing) + if (n == 100) { - if (n == 100) - { - fileStream.Flush(); - n = 0; - } - else - n++; + fileStream.Flush(); + n = 0; } - } - // получение остатка - if ((Filesize - fileStream.Position) > 0) - { - MainSocket.SendPackage("remain request".ToBytes()); - buffer = MainSocket.GetPackage(); - BytesDownloaded += (uint)buffer.Length; - fileStream.Write(buffer, 0, buffer.Length); + else + n++; } } - if (requiresFlushing) - fileStream.Flush(); - } - - // отдаёт файл с помощью FSP протокола - public void UploadFile(string filePath) - { - BytesUploaded = 0; - Debug("b", $"uploading file {filePath}\n"); - using System.IO.FileStream fileStream = File.OpenRead(filePath); - Filesize = File.GetSize(filePath).ToUInt(); - lock (MainSocket) + // получение остатка + if ((Filesize - fileStream.Position) > 0) { - MainSocket.SendPackage(Filesize.ToString().ToBytes()); - MainSocket.GetAnswer("ready"); - byte[] buffer = new byte[5120]; - int packagesCount = 0; - int fullPackagesCount = (Filesize / buffer.Length).Truncate(); - // отправка полных пакетов файла - for (; packagesCount < fullPackagesCount; packagesCount++) - { - fileStream.Read(buffer, 0, buffer.Length); - MainSocket.SendPackage(buffer); - BytesUploaded += (uint)buffer.Length; - } - // отправка остатка - if ((Filesize - fileStream.Position) > 0) - { - MainSocket.GetAnswer("remain request"); - buffer = new byte[(Filesize - fileStream.Position).ToInt()]; - fileStream.Read(buffer, 0, buffer.Length); - MainSocket.SendPackage(buffer); - BytesUploaded += (uint)buffer.Length; - } + MainSocket.SendPackage("remain request".ToBytes()); + buffer = MainSocket.GetPackage(); + BytesDownloaded += (uint)buffer.Length; + fileStream.Write(buffer, 0, buffer.Length); } - fileStream.Close(); - Debug("g", $" uploaded {BytesUploaded} of {Filesize} bytes\n"); } + if (requiresFlushing) + fileStream.Flush(); + } - public void DownloadByManifest(string dirOnServer, string dirOnClient, bool overwrite = false, bool delete_excess = false) + // отдаёт файл с помощью FSP протокола + public void UploadFile(string filePath) + { + BytesUploaded = 0; + Debug("b", $"uploading file {filePath}\n"); + using System.IO.FileStream fileStream = File.OpenRead(filePath); + Filesize = File.GetSize(filePath).ToUInt(); + lock (MainSocket) { - if (!dirOnClient.EndsWith("\\")) - dirOnClient += "\\"; - if (!dirOnServer.EndsWith("\\")) - dirOnServer += "\\"; - Debug("b", "downloading manifest <", "c", dirOnServer + "manifest.dtsod", "b", ">\n"); - var manifest = new DtsodV22(DownloadFileToMemory(dirOnServer + "manifest.dtsod").BytesToString()); - Debug("g", $"found {manifest.Values.Count} files in manifest\n"); - var hasher = new Hasher(); - foreach (string fileOnServer in manifest.Keys) + MainSocket.SendPackage(Filesize.ToString().ToBytes()); + MainSocket.GetAnswer("ready"); + byte[] buffer = new byte[5120]; + int packagesCount = 0; + int fullPackagesCount = (Filesize / buffer.Length).Truncate(); + // отправка полных пакетов файла + for (; packagesCount < fullPackagesCount; packagesCount++) { - string fileOnClient = dirOnClient + fileOnServer; - Debug("b", "file <", "c", fileOnClient, "b", ">... "); - if (!File.Exists(fileOnClient)) - { - DebugNoTime("y", "doesn't exist\n"); - DownloadFile(dirOnServer + fileOnServer, fileOnClient); - } - else if (overwrite && hasher.HashFile(fileOnClient).HashToString() != manifest[fileOnServer]) - { - DebugNoTime("y", "outdated\n"); - DownloadFile(dirOnServer + fileOnServer, fileOnClient); - } - else - DebugNoTime("g", "without changes\n"); + fileStream.Read(buffer, 0, buffer.Length); + MainSocket.SendPackage(buffer); + BytesUploaded += (uint)buffer.Length; } - // удаление лишних файлов - if (delete_excess) + // отправка остатка + if ((Filesize - fileStream.Position) > 0) { - foreach (string file in Directory.GetAllFiles(dirOnClient)) - { - if (!manifest.ContainsKey(file.Remove(0, dirOnClient.Length))) - { - Debug("y", $"deleting excess file: {file}\n"); - File.Delete(file); - } - } + MainSocket.GetAnswer("remain request"); + buffer = new byte[(Filesize - fileStream.Position).ToInt()]; + fileStream.Read(buffer, 0, buffer.Length); + MainSocket.SendPackage(buffer); + BytesUploaded += (uint)buffer.Length; } } + fileStream.Close(); + Debug("g", $" uploaded {BytesUploaded} of {Filesize} bytes\n"); + } - public static void CreateManifest(string dir) + public void DownloadByManifest(string dirOnServer, string dirOnClient, bool overwrite = false, bool delete_excess = false) + { + if (!dirOnClient.EndsWith("\\")) + dirOnClient += "\\"; + if (!dirOnServer.EndsWith("\\")) + dirOnServer += "\\"; + Debug("b", "downloading manifest <", "c", dirOnServer + "manifest.dtsod", "b", ">\n"); + var manifest = new DtsodV22(DownloadFileToMemory(dirOnServer + "manifest.dtsod").BytesToString()); + Debug("g", $"found {manifest.Values.Count} files in manifest\n"); + var hasher = new Hasher(); + foreach (string fileOnServer in manifest.Keys) { - if (!dir.EndsWith("\\")) - dir += "\\"; - Log($"b", $"creating manifest of {dir}\n"); - StringBuilder manifestBuilder = new(); - Hasher hasher = new(); - if (Directory.GetFiles(dir).Contains(dir + "manifest.dtsod")) - File.Delete(dir + "manifest.dtsod"); - foreach (string _file in Directory.GetAllFiles(dir)) + string fileOnClient = dirOnClient + fileOnServer; + Debug("b", "file <", "c", fileOnClient, "b", ">... "); + if (!File.Exists(fileOnClient)) { - string file = _file.Remove(0, dir.Length); - manifestBuilder.Append(file); - manifestBuilder.Append(": \""); - byte[] hash = hasher.HashFile(dir + file); - manifestBuilder.Append(hash.HashToString()); - manifestBuilder.Append("\";\n"); + DebugNoTime("y", "doesn't exist\n"); + DownloadFile(dirOnServer + fileOnServer, fileOnClient); } - Debug($"g", $" manifest of {dir} created\n"); - File.WriteAllText(dir + "manifest.dtsod", manifestBuilder.ToString()); + else if (overwrite && hasher.HashFile(fileOnClient).HashToString() != manifest[fileOnServer]) + { + DebugNoTime("y", "outdated\n"); + DownloadFile(dirOnServer + fileOnServer, fileOnClient); + } + else + DebugNoTime("g", "without changes\n"); } - - static void Debug(params string[] msg) + // удаление лишних файлов + if (delete_excess) { - if (debug) Log(msg); - } - static void DebugNoTime(params string[] msg) - { - if (debug) LogNoTime(msg); + foreach (string file in Directory.GetAllFiles(dirOnClient)) + { + if (!manifest.ContainsKey(file.Remove(0, dirOnClient.Length))) + { + Debug("y", $"deleting excess file: {file}\n"); + File.Delete(file); + } + } } } + + public static void CreateManifest(string dir) + { + if (!dir.EndsWith("\\")) + dir += "\\"; + Log($"b", $"creating manifest of {dir}\n"); + StringBuilder manifestBuilder = new(); + Hasher hasher = new(); + if (Directory.GetFiles(dir).Contains(dir + "manifest.dtsod")) + File.Delete(dir + "manifest.dtsod"); + foreach (string _file in Directory.GetAllFiles(dir)) + { + string file = _file.Remove(0, dir.Length); + manifestBuilder.Append(file); + manifestBuilder.Append(": \""); + byte[] hash = hasher.HashFile(dir + file); + manifestBuilder.Append(hash.HashToString()); + manifestBuilder.Append("\";\n"); + } + Debug($"g", $" manifest of {dir} created\n"); + File.WriteAllText(dir + "manifest.dtsod", manifestBuilder.ToString()); + } + + static void Debug(params string[] msg) + { + if (debug) Log(msg); + } + static void DebugNoTime(params string[] msg) + { + if (debug) LogNoTime(msg); + } } diff --git a/Network/OldNetwork.cs b/Network/OldNetwork.cs index 96e2eb5..ba30db9 100644 --- a/Network/OldNetwork.cs +++ b/Network/OldNetwork.cs @@ -1,33 +1,32 @@ using System.Diagnostics; -using System.Net; +using System.Net.Http; -namespace DTLib.Network +namespace DTLib.Network; + +// +// пара почти никогда не используемых методов +// +public static class OldNetwork { - // - // пара почти никогда не используемых методов - // - public static class OldNetwork + + + // получает с сайта публичный ip + public static string GetPublicIP() => new HttpClient().GetStringAsync("https://ifconfig.me/ip").GetAwaiter().GetResult(); + + // пингует айпи с помощью встроенной в винду проги, возвращает задержку + public static string PingIP(string address) { - - - // получает с сайта публичный ip - public static string GetPublicIP() => new WebClient().DownloadString("https://ifconfig.me/ip"); - - // пингует айпи с помощью встроенной в винду проги, возвращает задержку - public static string PingIP(string address) - { - var proc = new Process(); - proc.StartInfo.FileName = "cmd.exe"; - proc.StartInfo.Arguments = "/c @echo off & chcp 65001 >nul & ping -n 5 " + address; - proc.StartInfo.CreateNoWindow = true; - proc.StartInfo.UseShellExecute = false; - proc.StartInfo.RedirectStandardOutput = true; - proc.Start(); - System.IO.StreamReader outStream = proc.StandardOutput; - string rezult = outStream.ReadToEnd(); - rezult = rezult.Remove(0, rezult.LastIndexOf('=') + 2); - return rezult.Remove(rezult.Length - 4); - } - + var proc = new Process(); + proc.StartInfo.FileName = "cmd.exe"; + proc.StartInfo.Arguments = "/c @echo off & chcp 65001 >nul & ping -n 5 " + address; + proc.StartInfo.CreateNoWindow = true; + proc.StartInfo.UseShellExecute = false; + proc.StartInfo.RedirectStandardOutput = true; + proc.Start(); + System.IO.StreamReader outStream = proc.StandardOutput; + string rezult = outStream.ReadToEnd(); + rezult = rezult.Remove(0, rezult.LastIndexOf('=') + 2); + return rezult.Remove(rezult.Length - 4); } + } diff --git a/Network/Package.cs b/Network/Package.cs index 50def44..5af12e1 100644 --- a/Network/Package.cs +++ b/Network/Package.cs @@ -1,71 +1,67 @@ -using DTLib.Extensions; -using System; -using System.Collections.Generic; -using System.Net.Sockets; +using System.Net.Sockets; using System.Threading; -namespace DTLib.Network +namespace DTLib.Network; + +// +// отправка/получение пакетов +// +public static class Package { - // - // отправка/получение пакетов - // - public static class Package + // принимает пакет + public static byte[] GetPackage(this Socket socket) { - // принимает пакет - public static byte[] GetPackage(this Socket socket) + int packageSize = 0; + byte[] data = new byte[2]; + // цикл выполняется пока не пройдёт 2000 мс + for (ushort s = 0; s < 400; s += 1) { - int packageSize = 0; - byte[] data = new byte[2]; - // цикл выполняется пока не пройдёт 2000 мс - for (ushort s = 0; s < 400; s += 1) + if (packageSize == 0 && socket.Available >= 2) { - if (packageSize == 0 && socket.Available >= 2) - { - socket.Receive(data, data.Length, 0); - packageSize = data.ToInt(); - } - if (packageSize != 0 && socket.Available >= packageSize) - { - data = new byte[packageSize]; - socket.Receive(data, data.Length, 0); - return data; - } - else - Thread.Sleep(5); + socket.Receive(data, data.Length, 0); + packageSize = data.ToInt(); } - throw new Exception($"GetPackage() error: timeout. socket.Available={socket.Available}\n"); + if (packageSize != 0 && socket.Available >= packageSize) + { + data = new byte[packageSize]; + socket.Receive(data, data.Length, 0); + return data; + } + else + Thread.Sleep(5); } - - // отправляет пакет - public static void SendPackage(this Socket socket, byte[] data) - { - if (data.Length > 65536) - throw new Exception($"SendPackage() error: package is too big ({data.Length} bytes)"); - if (data.Length == 0) - throw new Exception($"SendPackage() error: package has zero size"); - var list = new List(); - byte[] packageSize = data.Length.ToBytes(); - if (packageSize.Length == 1) - list.Add(0); - list.AddRange(packageSize); - list.AddRange(data); - socket.Send(list.ToArray()); - } - public static void SendPackage(this Socket socket, string data) => SendPackage(socket, data.ToBytes()); - - // получает пакет и выбрасывает исключение, если пакет не соответствует образцу - public static void GetAnswer(this Socket socket, string answer) - { - string rec = socket.GetPackage().BytesToString(); - if (rec != answer) - throw new Exception($"GetAnswer() error: invalid answer: <{rec}>"); - } - - public static byte[] RequestPackage(this Socket socket, byte[] request) - { - socket.SendPackage(request); - return socket.GetPackage(); - } - public static byte[] RequestPackage(this Socket socket, string request) => socket.RequestPackage(request.ToBytes()); + throw new Exception($"GetPackage() error: timeout. socket.Available={socket.Available}\n"); } + + // отправляет пакет + public static void SendPackage(this Socket socket, byte[] data) + { + if (data.Length > 65536) + throw new Exception($"SendPackage() error: package is too big ({data.Length} bytes)"); + if (data.Length == 0) + throw new Exception($"SendPackage() error: package has zero size"); + var list = new List(); + byte[] packageSize = data.Length.ToBytes(); + if (packageSize.Length == 1) + list.Add(0); + list.AddRange(packageSize); + list.AddRange(data); + socket.Send(list.ToArray()); + } + public static void SendPackage(this Socket socket, string data) => SendPackage(socket, data.ToBytes()); + + // получает пакет и выбрасывает исключение, если пакет не соответствует образцу + public static void GetAnswer(this Socket socket, string answer) + { + string rec = socket.GetPackage().BytesToString(); + if (rec != answer) + throw new Exception($"GetAnswer() error: invalid answer: <{rec}>"); + } + + public static byte[] RequestPackage(this Socket socket, byte[] request) + { + socket.SendPackage(request); + return socket.GetPackage(); + } + public static byte[] RequestPackage(this Socket socket, string request) => socket.RequestPackage(request.ToBytes()); } diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs deleted file mode 100644 index c0201c5..0000000 --- a/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// Общие сведения об этой сборке предоставляются следующим набором -// набора атрибутов. Измените значения этих атрибутов для изменения сведений, -// связанные со сборкой. -[assembly: AssemblyTitle("DTLib")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("DTLib")] -[assembly: AssemblyCopyright("Copyright © 2021")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Установка значения False для параметра ComVisible делает типы в этой сборке невидимыми -// для компонентов COM. Если необходимо обратиться к типу в этой сборке через -// COM, задайте атрибуту ComVisible значение TRUE для этого типа. -[assembly: ComVisible(false)] - -// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM -[assembly: Guid("ce793497-2d5c-42d8-b311-e9b32af9cdfb")] - -// Сведения о версии сборки состоят из указанных ниже четырех значений: -// -// Основной номер версии -// Дополнительный номер версии -// Номер сборки -// Редакция -// -// Можно задать все значения или принять номера сборки и редакции по умолчанию -// используя "*", как показано ниже: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/PublicLog.cs b/PublicLog.cs index 4ae26b1..9b99530 100644 --- a/PublicLog.cs +++ b/PublicLog.cs @@ -1,16 +1,15 @@ -namespace DTLib -{ - // - // вывод логов со всех классов в библиотеке - // - public static class PublicLog - { - public delegate void LogDelegate(params string[] msg); - // вот к этому объекту подключайте методы для вывода логов - public static event LogDelegate LogEvent; - public static void Log(params string[] msg) => LogEvent?.Invoke(msg); +namespace DTLib; - public static event LogDelegate LogNoTimeEvent; - public static void LogNoTime(params string[] msg) => LogNoTimeEvent?.Invoke(msg); - } +// +// вывод логов со всех классов в библиотеке +// +public static class PublicLog +{ + public delegate void LogDelegate(params string[] msg); + // вот к этому объекту подключайте методы для вывода логов + public static event LogDelegate LogEvent; + public static void Log(params string[] msg) => LogEvent?.Invoke(msg); + + public static event LogDelegate LogNoTimeEvent; + public static void LogNoTime(params string[] msg) => LogNoTimeEvent?.Invoke(msg); } diff --git a/TImer.cs b/TImer.cs index 821c031..dc02ec1 100644 --- a/TImer.cs +++ b/TImer.cs @@ -1,42 +1,39 @@ -using System; -using System.Threading; -using System.Threading.Tasks; +using System.Threading; -namespace DTLib +namespace DTLib; + +// +// простой и понятный класс для выполнения каких-либо действий в отдельном потоке раз в некоторое время +// +public class Timer { - // - // простой и понятный класс для выполнения каких-либо действий в отдельном потоке раз в некоторое время - // - public class Timer + Task TimerTask; + bool Repeat; + CancellationTokenSource кансель = new(); + + // таймер сразу запускается + public Timer(bool repeat, int delay, Action method) { - Task TimerTask; - bool Repeat; - CancellationTokenSource кансель = new(); - - // таймер сразу запускается - public Timer(bool repeat, int delay, Action method) - { - Repeat = repeat; - TimerTask = new Task(() => + Repeat = repeat; + TimerTask = new Task(() => + { + do { - do - { - if (кансель.Token.IsCancellationRequested) - return; - Task.Delay(delay).Wait(); - method(); - } while (Repeat); - }); - } + if (кансель.Token.IsCancellationRequested) + return; + Task.Delay(delay).Wait(); + method(); + } while (Repeat); + }); + } - public void Start() => TimerTask.Start(); + public void Start() => TimerTask.Start(); - // завершение потока - public void Stop() - { - Repeat = false; - кансель.Cancel(); - } + // завершение потока + public void Stop() + { + Repeat = false; + кансель.Cancel(); } } diff --git a/XXHash.cs b/XXHash.cs index 4f29dab..479a42e 100644 --- a/XXHash.cs +++ b/XXHash.cs @@ -1,175 +1,173 @@ -using System; -using System.Security.Cryptography; -namespace DTLib +using System.Security.Cryptography; +namespace DTLib; + +// честно взятый с гитхаба алгоритм хеширования +// выдаёт хеш в виде массива четырёх байтов +sealed class XXHash32 : HashAlgorithm { - // честно взятый с гитхаба алгоритм хеширования - // выдаёт хеш в виде массива четырёх байтов - sealed class XXHash32 : HashAlgorithm + private const uint PRIME32_1 = 2654435761U; + private const uint PRIME32_2 = 2246822519U; + private const uint PRIME32_3 = 3266489917U; + private const uint PRIME32_4 = 668265263U; + private const uint PRIME32_5 = 374761393U; + private static readonly Func FuncGetLittleEndianUInt32; + private static readonly Func FuncGetFinalHashUInt32; + private uint _Seed32; + private uint _ACC32_1; + private uint _ACC32_2; + private uint _ACC32_3; + private uint _ACC32_4; + private uint _Hash32; + private int _RemainingLength; + private long _TotalLength = 0; + private int _CurrentIndex; + private byte[] _CurrentArray; + + static XXHash32() { - private const uint PRIME32_1 = 2654435761U; - private const uint PRIME32_2 = 2246822519U; - private const uint PRIME32_3 = 3266489917U; - private const uint PRIME32_4 = 668265263U; - private const uint PRIME32_5 = 374761393U; - private static readonly Func FuncGetLittleEndianUInt32; - private static readonly Func FuncGetFinalHashUInt32; - private uint _Seed32; - private uint _ACC32_1; - private uint _ACC32_2; - private uint _ACC32_3; - private uint _ACC32_4; - private uint _Hash32; - private int _RemainingLength; - private long _TotalLength = 0; - private int _CurrentIndex; - private byte[] _CurrentArray; - - static XXHash32() + if (BitConverter.IsLittleEndian) { - if (BitConverter.IsLittleEndian) + FuncGetLittleEndianUInt32 = new Func((x, i) => { - FuncGetLittleEndianUInt32 = new Func((x, i) => + unsafe { - unsafe + fixed (byte* array = x) { - fixed (byte* array = x) - { - return *(uint*)(array + i); - } - } - }); - FuncGetFinalHashUInt32 = new Func(i => (i & 0x000000FFU) << 24 | (i & 0x0000FF00U) << 8 | (i & 0x00FF0000U) >> 8 | (i & 0xFF000000U) >> 24); - } - else - { - FuncGetLittleEndianUInt32 = new Func((x, i) => - { - unsafe - { - fixed (byte* array = x) - { - return (uint)(array[i++] | (array[i++] << 8) | (array[i++] << 16) | (array[i] << 24)); - } - } - }); - FuncGetFinalHashUInt32 = new Func(i => i); - } - } - - /// Creates an instance of class by default seed(0). - /// - public static new XXHash32 Create() => new(); - - /// Initializes a new instance of the class by default seed(0). - public XXHash32() => Initialize(0); - - /// Initializes a new instance of the class, and sets the to the specified value. - /// Represent the seed to be used for xxHash32 computing. - public XXHash32(uint seed) => Initialize(seed); - - /// Gets the value of the computed hash code. - /// Hash computation has not yet completed. - public uint HashUInt32 => State == 0 ? _Hash32 : throw new InvalidOperationException("Hash computation has not yet completed."); - - /// Gets or sets the value of seed used by xxHash32 algorithm. - /// Hash computation has not yet completed. - public uint Seed - { - get => _Seed32; - set - { - if (value != _Seed32) - { - if (State != 0) - throw new InvalidOperationException("Hash computation has not yet completed."); - _Seed32 = value; - Initialize(); - } - } - } - - /// Initializes this instance for new hash computing. - public override void Initialize() - { - _ACC32_1 = _Seed32 + PRIME32_1 + PRIME32_2; - _ACC32_2 = _Seed32 + PRIME32_2; - _ACC32_3 = _Seed32 + 0; - _ACC32_4 = _Seed32 - PRIME32_1; - } - - /// Routes data written to the object into the hash algorithm for computing the hash. - /// The input to compute the hash code for. - /// The offset into the byte array from which to begin using data. - /// The number of bytes in the byte array to use as data. - protected override void HashCore(byte[] array, int ibStart, int cbSize) - { - if (State != 1) - State = 1; - int size = cbSize - ibStart; - _RemainingLength = size & 15; - if (cbSize >= 16) - { - int limit = size - _RemainingLength; - do - { - _ACC32_1 = Round32(_ACC32_1, FuncGetLittleEndianUInt32(array, ibStart)); - ibStart += 4; - _ACC32_2 = Round32(_ACC32_2, FuncGetLittleEndianUInt32(array, ibStart)); - ibStart += 4; - _ACC32_3 = Round32(_ACC32_3, FuncGetLittleEndianUInt32(array, ibStart)); - ibStart += 4; - _ACC32_4 = Round32(_ACC32_4, FuncGetLittleEndianUInt32(array, ibStart)); - ibStart += 4; - } while (ibStart < limit); - } - _TotalLength += cbSize; - if (_RemainingLength != 0) - { - _CurrentArray = array; - _CurrentIndex = ibStart; - } - } - - /// Finalizes the hash computation after the last data is processed by the cryptographic stream object. - /// The computed hash code. - protected override byte[] HashFinal() - { - _Hash32 = _TotalLength >= 16 - ? RotateLeft32(_ACC32_1, 1) + RotateLeft32(_ACC32_2, 7) + RotateLeft32(_ACC32_3, 12) + RotateLeft32(_ACC32_4, 18) - : _Seed32 + PRIME32_5; - _Hash32 += (uint)_TotalLength; - while (_RemainingLength >= 4) - { - _Hash32 = RotateLeft32(_Hash32 + FuncGetLittleEndianUInt32(_CurrentArray, _CurrentIndex) * PRIME32_3, 17) * PRIME32_4; - _CurrentIndex += 4; - _RemainingLength -= 4; - } - unsafe - { - fixed (byte* arrayPtr = _CurrentArray) - { - while (_RemainingLength-- >= 1) - { - _Hash32 = RotateLeft32(_Hash32 + arrayPtr[_CurrentIndex++] * PRIME32_5, 11) * PRIME32_1; + return *(uint*)(array + i); } } - } - _Hash32 = (_Hash32 ^ (_Hash32 >> 15)) * PRIME32_2; - _Hash32 = (_Hash32 ^ (_Hash32 >> 13)) * PRIME32_3; - _Hash32 ^= _Hash32 >> 16; - _TotalLength = State = 0; - return BitConverter.GetBytes(FuncGetFinalHashUInt32(_Hash32)); + }); + FuncGetFinalHashUInt32 = new Func(i => (i & 0x000000FFU) << 24 | (i & 0x0000FF00U) << 8 | (i & 0x00FF0000U) >> 8 | (i & 0xFF000000U) >> 24); } - - private static uint Round32(uint input, uint value) => RotateLeft32(input + (value * PRIME32_2), 13) * PRIME32_1; - - private static uint RotateLeft32(uint value, int count) => (value << count) | (value >> (32 - count)); - - private void Initialize(uint seed) + else { - HashSizeValue = 32; - _Seed32 = seed; - Initialize(); + FuncGetLittleEndianUInt32 = new Func((x, i) => + { + unsafe + { + fixed (byte* array = x) + { + return (uint)(array[i++] | (array[i++] << 8) | (array[i++] << 16) | (array[i] << 24)); + } + } + }); + FuncGetFinalHashUInt32 = new Func(i => i); } } + + /// Creates an instance of class by default seed(0). + /// + public static new XXHash32 Create() => new(); + + /// Initializes a new instance of the class by default seed(0). + public XXHash32() => Initialize(0); + + /// Initializes a new instance of the class, and sets the to the specified value. + /// Represent the seed to be used for xxHash32 computing. + public XXHash32(uint seed) => Initialize(seed); + + /// Gets the value of the computed hash code. + /// Hash computation has not yet completed. + public uint HashUInt32 => State == 0 ? _Hash32 : throw new InvalidOperationException("Hash computation has not yet completed."); + + /// Gets or sets the value of seed used by xxHash32 algorithm. + /// Hash computation has not yet completed. + public uint Seed + { + get => _Seed32; + set + { + if (value != _Seed32) + { + if (State != 0) + throw new InvalidOperationException("Hash computation has not yet completed."); + _Seed32 = value; + Initialize(); + } + } + } + + /// Initializes this instance for new hash computing. + public override void Initialize() + { + _ACC32_1 = _Seed32 + PRIME32_1 + PRIME32_2; + _ACC32_2 = _Seed32 + PRIME32_2; + _ACC32_3 = _Seed32 + 0; + _ACC32_4 = _Seed32 - PRIME32_1; + } + + /// Routes data written to the object into the hash algorithm for computing the hash. + /// The input to compute the hash code for. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the byte array to use as data. + protected override void HashCore(byte[] array, int ibStart, int cbSize) + { + if (State != 1) + State = 1; + int size = cbSize - ibStart; + _RemainingLength = size & 15; + if (cbSize >= 16) + { + int limit = size - _RemainingLength; + do + { + _ACC32_1 = Round32(_ACC32_1, FuncGetLittleEndianUInt32(array, ibStart)); + ibStart += 4; + _ACC32_2 = Round32(_ACC32_2, FuncGetLittleEndianUInt32(array, ibStart)); + ibStart += 4; + _ACC32_3 = Round32(_ACC32_3, FuncGetLittleEndianUInt32(array, ibStart)); + ibStart += 4; + _ACC32_4 = Round32(_ACC32_4, FuncGetLittleEndianUInt32(array, ibStart)); + ibStart += 4; + } while (ibStart < limit); + } + _TotalLength += cbSize; + if (_RemainingLength != 0) + { + _CurrentArray = array; + _CurrentIndex = ibStart; + } + } + + /// Finalizes the hash computation after the last data is processed by the cryptographic stream object. + /// The computed hash code. + protected override byte[] HashFinal() + { + _Hash32 = _TotalLength >= 16 + ? RotateLeft32(_ACC32_1, 1) + RotateLeft32(_ACC32_2, 7) + RotateLeft32(_ACC32_3, 12) + RotateLeft32(_ACC32_4, 18) + : _Seed32 + PRIME32_5; + _Hash32 += (uint)_TotalLength; + while (_RemainingLength >= 4) + { + _Hash32 = RotateLeft32(_Hash32 + FuncGetLittleEndianUInt32(_CurrentArray, _CurrentIndex) * PRIME32_3, 17) * PRIME32_4; + _CurrentIndex += 4; + _RemainingLength -= 4; + } + unsafe + { + fixed (byte* arrayPtr = _CurrentArray) + { + while (_RemainingLength-- >= 1) + { + _Hash32 = RotateLeft32(_Hash32 + arrayPtr[_CurrentIndex++] * PRIME32_5, 11) * PRIME32_1; + } + } + } + _Hash32 = (_Hash32 ^ (_Hash32 >> 15)) * PRIME32_2; + _Hash32 = (_Hash32 ^ (_Hash32 >> 13)) * PRIME32_3; + _Hash32 ^= _Hash32 >> 16; + _TotalLength = State = 0; + return BitConverter.GetBytes(FuncGetFinalHashUInt32(_Hash32)); + } + + private static uint Round32(uint input, uint value) => RotateLeft32(input + (value * PRIME32_2), 13) * PRIME32_1; + + private static uint RotateLeft32(uint value, int count) => (value << count) | (value >> (32 - count)); + + private void Initialize(uint seed) + { + HashSizeValue = 32; + _Seed32 = seed; + Initialize(); + } }