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();
+ }
}