diff --git a/DTLib/DTLib.csproj b/DTLib/DTLib.csproj
index 21cd6b5..03492d5 100644
--- a/DTLib/DTLib.csproj
+++ b/DTLib/DTLib.csproj
@@ -35,6 +35,7 @@
+
diff --git a/DTLib/Dtsod.cs b/DTLib/Dtsod.cs
index 1539fec..02c4f0a 100644
--- a/DTLib/Dtsod.cs
+++ b/DTLib/Dtsod.cs
@@ -1,23 +1,28 @@
using System;
using System.Collections.Generic;
using System.Text;
+using System.Linq;
+using static DTLib.PublicLog;
namespace DTLib
{
//
// это как json но не совсем
//
- public class Dtsod
+ public class Dtsod : Dictionary
{
- string Text;
- public Dictionary Values { get; }
+ static readonly bool debug = false;
+
+ public string Text { get; }
+ //public Dictionary Values { get; set; }
public Dtsod(string text)
{
Text = text;
- Values = Parse(text);
+ foreach (KeyValuePair pair in ParseNew(text))
+ Add(pair.Key, pair.Value);
}
- // выдаёт Exception
+ /*// выдаёт Exception
public dynamic this[string key]
{
get
@@ -25,6 +30,11 @@ namespace DTLib
if (TryGet(key, out dynamic value)) return value;
else throw new Exception($"Dtsod[{key}] key not found");
}
+ set
+ {
+ if (TrySet(key, value)) return;
+ else throw new Exception($"Dtsod[{key}] key not found");
+ }
}
// не выдаёт KeyNotFoundException
@@ -37,16 +47,246 @@ namespace DTLib
}
catch (KeyNotFoundException)
{
- //PublicLog.Log("y", $"key {key} not found\n");
value = null;
return false;
}
}
+ public bool TrySet(string key, dynamic value)
+ {
+ try
+ {
+ Values[key] = value;
+ return true;
+ }
+ catch (KeyNotFoundException)
+ {
+ return false;
+ }
+ }*/
public override string ToString() => Text;
+ enum ValueType
+ {
+ List,
+ Complex,
+ String,
+ /*Double,
+ Long,
+ Ulong,
+ Short,
+ Ushort,
+ Int,
+ Uint,
+ Null,
+ Boolean,*/
+ Default
+ }
- Dictionary Parse(string text)
+ Dictionary ParseNew(string text)
+ {
+ Dictionary parsed = new();
+ int i = 0;
+ for (; i < text.Length; i++) ReadName();
+ return parsed;
+
+ void ReadName()
+ {
+ void ReadCommentLine()
+ {
+ for (; i < text.Length && text[i] != '\n'; i++) ;
+ }
+
+ bool isListElem = false;
+ dynamic value = null;
+ StringBuilder defaultNameBuilder = new();
+
+ if (debug) LogNoTime("m", "ReadName");
+ for (; i < text.Length; i++)
+ {
+ if (debug) LogNoTime("w", text[i].ToString());
+ switch (text[i])
+ {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ break;
+ case ':':
+ i++;
+ value = ReadValue();
+ string name = defaultNameBuilder.ToString();
+ if (debug) LogNoTime("c", $"parsed.Add({name}, {value})\n");
+ if (isListElem)
+ {
+ if (!parsed.ContainsKey(name)) parsed.Add(name, new List());
+ parsed[name].Add(value);
+ }
+ else parsed.Add(name, value);
+ if (debug) LogNoTime("g", "ReadName return\n");
+ return;
+ // строка, начинающаяся с # будет считаться комментом
+ case '#':
+ ReadCommentLine();
+ break;
+ case '}':
+ throw new Exception("Parse.ReadName() error: unexpected '}' at " + i + "char");
+ // если $ перед названием параметра поставить, значение value добавится в лист с названием name
+ case '$':
+ if (defaultNameBuilder.ToString().Length != 0) throw new Exception("unexpected usage of '$' at char " + i.ToString());
+ isListElem = true;
+ break;
+ case ';':
+ throw new Exception("Parse.ReadName() error: unexpected ';' at " + i + "char");
+ default:
+ defaultNameBuilder.Append(text[i]);
+ break;
+ }
+ }
+ }
+
+ dynamic ReadValue()
+ {
+ ValueType type = ValueType.Default;
+
+ string ReadString()
+ {
+ i++;
+ StringBuilder valueBuilder = new();
+ valueBuilder.Append('"');
+ for (; text[i] != '"' || text[i - 1] == '\\'; i++)
+ {
+ if (debug) LogNoTime("gray", text[i].ToString());
+ valueBuilder.Append(text[i]);
+ }
+ valueBuilder.Append('"');
+ if (debug) LogNoTime("gray", text[i].ToString());
+ type = ValueType.String;
+ return valueBuilder.ToString();
+ }
+
+ List ReadList()
+ {
+ i++;
+ List output = new();
+ StringBuilder valueBuilder = new();
+ for (; text[i] != ']'; i++)
+ {
+ if (debug) LogNoTime("c", text[i].ToString());
+ switch (text[i])
+ {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ break;
+ case ',':
+ output.Add(ParseValueToRightType(valueBuilder.ToString()));
+ valueBuilder.Clear();
+ break;
+ default:
+ valueBuilder.Append(text[i]);
+ break;
+ }
+ }
+ output.Add(ParseValueToRightType(valueBuilder.ToString()));
+ if (debug) LogNoTime("c", text[i].ToString());
+ type = ValueType.List;
+ return output;
+ }
+
+ Dictionary ReadComplex()
+ {
+ i++;
+ StringBuilder valueBuilder = new();
+ for (; text[i] != '}'; i++)
+ {
+ if (debug) LogNoTime("y", text[i].ToString());
+ if (text[i] == '"')
+ {
+ valueBuilder.Append(ReadString());
+ }
+ else valueBuilder.Append(text[i]);
+ }
+ if (debug) LogNoTime("y", text[i].ToString());
+ type = ValueType.Complex;
+ if (debug) LogNoTime("g", valueBuilder.ToString());
+ return ParseNew(valueBuilder.ToString());
+ }
+
+ dynamic ParseValueToRightType(string stringValue)
+ {
+
+ if (debug) LogNoTime("g", $"\nParseValueToRightType({stringValue})");
+ return stringValue switch
+ {
+ _ when stringValue.Contains('"') => stringValue.Remove(stringValue.Length - 1).Remove(0, 1),
+ // bool
+ "true" or "false" => stringValue.ToBool(),
+ // null
+ "null" => null,
+ // double
+ _ when stringValue.Contains('.') => stringValue.ToDouble(),
+ // ushort, ulong, uint
+ _ when (stringValue.Length > 2 && stringValue[stringValue.Length - 2] == 'u') => stringValue[stringValue.Length - 1] switch
+ {
+ 's' => stringValue.Remove(stringValue.Length - 2).ToUShort(),
+ 'i' => stringValue.Remove(stringValue.Length - 2).ToUInt(),
+ 'l' => stringValue.Remove(stringValue.Length - 2).ToULong(),
+ _ => throw new Exception($"Dtsod.Parse.ReadValue() error: wrong type ")
+ },
+ // short, long, int
+ _ => stringValue[stringValue.Length - 1] switch
+ {
+ 's' => stringValue.Remove(stringValue.Length - 1).ToShort(),
+ 'l' => stringValue.Remove(stringValue.Length - 1).ToLong(),
+ _ => stringValue.ToInt()
+ }
+ };
+ }
+
+ dynamic value = null;
+ StringBuilder defaultValueBuilder = new();
+ if (debug) LogNoTime("m", "\nReadValue\n");
+ for (; i < text.Length; i++)
+ {
+ if (debug) LogNoTime("b", text[i].ToString());
+ switch (text[i])
+ {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ break;
+ case '"':
+ value = ReadString();
+ break;
+ case ';':
+ if (debug) LogNoTime("g", $"\nReadValue returns type {type} value <{value}>\n");
+ return type switch
+ {
+ ValueType.List or ValueType.Complex => value,
+ ValueType.String => ParseValueToRightType(value),
+ ValueType.Default => ParseValueToRightType(defaultValueBuilder.ToString()),
+ _ => throw new Exception($"Dtlib.Parse.ReadValue() error: can't convert value to type <{type}>")
+ };
+ case '[':
+ value = ReadList();
+ break;
+ case '{':
+ value = ReadComplex();
+ break;
+ default:
+ defaultValueBuilder.Append(text[i]);
+ break;
+ }
+ }
+ throw new Exception("Dtsod.Parse.ReadValue error: end of text");
+ }
+ }
+
+
+ Dictionary ParseOld(string text)
{
Dictionary output = new();
StringBuilder nameStrB = new();
@@ -59,63 +299,68 @@ namespace DTLib
dynamic StringToElse(string str)
{
- //PublicLog.Log("m", $"StringToElse({str})\n");
if (readString) return str;
// bool
- if (str == "true") return true;
- else if (str == "false") return false;
- // double
- else if (str.Contains(".")) return SimpleConverter.ToDouble(str);
- // ushort, uint, ulong
- else if (str.Length > 2 && str[str.Length - 2] == 'u')
- return str[str.Length - 1] switch
- {
- 's' => SimpleConverter.ToUShort(str.Remove(str.Length - 2)),
- 'i' => SimpleConverter.ToUInt(str.Remove(str.Length - 2)),
- 'l' => SimpleConverter.ToULong(str.Remove(str.Length - 2)),
- _ => throw new Exception($"ParseConfig() error: unknown data type "),
- };
- // short, int, long
- else return str[str.Length - 1] switch
+ switch (str)
{
- 's' => SimpleConverter.ToShort(str.Remove(str.Length - 1)),
- 'l' => SimpleConverter.ToLong(str.Remove(str.Length - 1)),
- _ => SimpleConverter.ToInt(str),
- };
+ // предустановленные значения
+ case "true": return true;
+ case "false": return false;
+ case "null": return null;
+ default:
+ // double
+ if (str.Contains(".")) return SimpleConverter.ToDouble(str);
+ // ushort, uint, ulong
+ else if (str.Length > 2 && str[str.Length - 2] == 'u')
+ return str[str.Length - 1] switch
+ {
+ 's' => SimpleConverter.ToUShort(str.Remove(str.Length - 2)),
+ 'i' => SimpleConverter.ToUInt(str.Remove(str.Length - 2)),
+ 'l' => SimpleConverter.ToULong(str.Remove(str.Length - 2)),
+ _ => throw new Exception($"ParseConfig() error: unknown data type "),
+ };
+ // short, int, long
+ else return str[str.Length - 1] switch
+ {
+ 's' => SimpleConverter.ToShort(str.Remove(str.Length - 1)),
+ 'l' => SimpleConverter.ToLong(str.Remove(str.Length - 1)),
+ _ => SimpleConverter.ToInt(str),
+ };
+ }
}
for (int i = 0; i < text.Length; i++)
{
+ if (debug) LogNoTime(text[i].ToString());
+
+ void ReadString()
+ {
+ i++;
+ while (text[i] != '"' || text[i - 1] == '\\')
+ {
+ if (debug) LogNoTime(text[i].ToString());
+ valStrB.Append(text[i]);
+ i++;
+ }
+ }
+
switch (text[i])
{
case '{':
i++;
- for (; text[i] != '}'; i++) valStrB.Append(text[i]);
- value = Parse(valStrB.ToString());
+ for (; text[i] != '}'; i++)
+ {
+ if (text[i] == '"') ReadString();
+ else valStrB.Append(text[i]);
+ }
+ value = ParseOld(valStrB.ToString());
valStrB.Clear();
break;
case '}':
throw new Exception("ParseConfig() error: unexpected '}' at " + i + "char");
- case '<':
- readString = true;
- short balance = 1;
- while (balance != 0)
- {
- i++;
- if (text[i] == '>') balance--;
- else if (text[i] == '<') balance++;
- valStrB.Append(text[i]);
- }
- valStrB.Remove(valStrB.Length - 1, 1);
- break;
case '"':
readString = true;
- i++;
- while (text[i] != '"' || text[i - 1] == '\\')
- {
- valStrB.Append(text[i]);
- i++;
- }
+ ReadString();
break;
case ':':
readValue = true;
@@ -169,7 +414,5 @@ namespace DTLib
}
return output;
}
-
-
}
}
diff --git a/DTLib/DtsodParser2.cs b/DTLib/DtsodParser2.cs
new file mode 100644
index 0000000..b2ade7e
--- /dev/null
+++ b/DTLib/DtsodParser2.cs
@@ -0,0 +1,207 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DTLib
+{
+ class DtsodParser2
+ {
+
+ enum ValueType
+ {
+ List,
+ Complex,
+ String,
+ Double,
+ Long,
+ Ulong,
+ Short,
+ Ushort,
+ Int,
+ Uint,
+ Null,
+ Boolean,
+ Default
+ }
+
+ Dictionary ParseNew(string text)
+ {
+ Dictionary parsed = new();
+ int i = 0;
+ for (; i < text.Length; i++) ReadName();
+ return parsed;
+
+ void ReadName()
+ {
+ bool isListElem = false;
+
+ void ReadCommentLine()
+ {
+ for (; i < text.Length && text[i] != '\n'; i++) ;
+ }
+
+ dynamic value = null;
+ StringBuilder defaultNameBuilder = new();
+
+ for (; i < text.Length; i++)
+ {
+ switch (text[i])
+ {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ break;
+ case ':':
+ value = ReadValue();
+ break;
+ // строка, начинающаяся с # будет считаться комментом
+ case '#':
+ ReadCommentLine();
+ break;
+ case '}':
+ throw new Exception("ParseConfig() error: unexpected '}' at " + i + "char");
+ // если $ перед названием параметра поставить, значение value добавится в лист с названием name
+ case '$':
+ if (defaultNameBuilder.ToString().Length != 0) throw new Exception("unexpected usage of '$' at char " + i.ToString());
+ isListElem = true;
+ break;
+ case ';':
+ string name = defaultNameBuilder.ToString();
+ if (isListElem)
+ {
+ if (!parsed.ContainsKey(name)) parsed.Add(name, new List());
+ parsed[name].Add(value);
+ }
+ else parsed.Add(name, value);
+ return;
+ default:
+ defaultNameBuilder.Append(text[i]);
+ break;
+ }
+ }
+ }
+
+ dynamic ReadValue()
+ {
+ ValueType type = ValueType.Default;
+
+ string ReadString()
+ {
+ i++;
+ StringBuilder valueBuilder = new();
+ for (; text[i] != '"' || text[i - 1] == '\\'; i++)
+ valueBuilder.Append(text[i]);
+ type = ValueType.String;
+ return valueBuilder.ToString();
+ }
+
+ List ReadList()
+ {
+ List output = new();
+ StringBuilder valueBuilder = new();
+ for (; text[i] != ']'; i++)
+ {
+ switch (text[i])
+ {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ break;
+ case ',':
+ output.Add(valueBuilder.ToString());
+ break;
+ default:
+ valueBuilder.Append(text[i]);
+ break;
+ }
+ }
+ type = ValueType.List;
+ return output;
+ }
+
+ Dictionary ReadComplex()
+ {
+ i++;
+ StringBuilder valueBuilder = new();
+ for (; text[i] != '}'; i++)
+ {
+ if (text[i] == '"') valueBuilder.Append(ReadString());
+ else valueBuilder.Append(text[i]);
+ }
+ type = ValueType.Complex;
+ return ParseNew(valueBuilder.ToString());
+ }
+
+ dynamic value = null;
+ StringBuilder defaultValueBuilder = new();
+ for (; i < text.Length; i++)
+ {
+ switch (text[i])
+ {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ break;
+ case '"':
+ value = ReadString();
+ break;
+ case ';':
+ if (type == ValueType.Default)
+ {
+ string valueString = defaultValueBuilder.ToString();
+ type = valueString switch
+ {
+ "true" or "false" => ValueType.Boolean,
+ "null" => ValueType.Null,
+ _ when valueString.Contains('.') => ValueType.Null,
+ _ when (valueString.Length > 2 && valueString[valueString.Length - 2] == 'u') => valueString[valueString.Length - 1] switch
+ {
+ 's' => ValueType.Ushort,
+ 'i' => ValueType.Uint,
+ 'l' => ValueType.Ulong,
+ _ => throw new Exception($"Dtsod.Parse.ReadValue() error: wrong type ")
+ },
+ _ => valueString[valueString.Length - 1] switch
+ {
+ 's' => ValueType.Short,
+ 'l' => ValueType.Long,
+ _ => ValueType.Int
+ }
+ };
+ }
+
+ return type switch
+ {
+ ValueType.String or ValueType.List or ValueType.Complex => value,
+ ValueType.Double => SimpleConverter.ToDouble(value),
+ ValueType.Long => SimpleConverter.ToLong(value.Remove(value.Length - 1)),
+ ValueType.Ulong => SimpleConverter.ToULong(value.Remove(value.Length - 2)),
+ ValueType.Short => SimpleConverter.ToShort(value.Remove(value.Length - 1)),
+ ValueType.Ushort => SimpleConverter.ToUShort(value.Remove(value.Length - 2)),
+ ValueType.Int => SimpleConverter.ToInt(value),
+ ValueType.Uint => SimpleConverter.ToUInt(value),
+ ValueType.Boolean => SimpleConverter.ToBool(value),
+ ValueType.Null => null,
+ _ => throw new Exception($"Dtlib.Parse.ReadValue() error: can't convert value to type <{type}>")
+ };
+ case '[':
+ value = ReadList();
+ break;
+ case '{':
+ value = ReadComplex();
+ break;
+ default:
+ defaultValueBuilder.Append(text[i]);
+ break;
+ }
+ }
+ throw new Exception("Dtsod.Parse.ReadValue error: end of text");
+ }
+ }
+ }
+}
diff --git a/DTLib/Filework.cs b/DTLib/Filework.cs
index 1978c9a..36bbb05 100644
--- a/DTLib/Filework.cs
+++ b/DTLib/Filework.cs
@@ -192,7 +192,7 @@ namespace DTLib
}
}
- public static void Copy(string srcPath, string newPath, bool replace = false)
+ public static void Copy(string srcPath, string newPath, bool replace = false)
{
if (!replace && Exists(newPath)) throw new Exception($"file <{newPath}> alredy exists");
Create(newPath);
@@ -224,7 +224,6 @@ namespace DTLib
public static void AppendAllBytes(string file, byte[] content)
{
- File.Create(file);
using var stream = File.OpenAppend(file);
stream.Write(content, 0, content.Length);
stream.Close();
diff --git a/DTLib/Network.cs b/DTLib/Network.cs
index 5d7e75a..31b7c37 100644
--- a/DTLib/Network.cs
+++ b/DTLib/Network.cs
@@ -4,8 +4,8 @@ using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Threading;
-using static DTLib.PublicLog;
using static DTLib.Filework;
+using static DTLib.PublicLog;
namespace DTLib
{
@@ -248,7 +248,7 @@ namespace DTLib
var manifest = new Dtsod(File.ReadAllText("TEMP\\manifest.dtsod"));
Log("g", $"found {manifest.Values.Count} files in manifest\n");
var hasher = new Hasher();
- foreach (string fileOnServer in manifest.Values.Keys)
+ foreach (string fileOnServer in manifest.Keys)
{
string fileOnClient = $"{dirOnClient}\\{fileOnServer}";
Log("b", "file <", "c", fileOnClient, "b", ">... ");
diff --git a/DTLib/SimpleConverter.cs b/DTLib/SimpleConverter.cs
index 4aacf9c..22bb7a5 100644
--- a/DTLib/SimpleConverter.cs
+++ b/DTLib/SimpleConverter.cs
@@ -95,17 +95,6 @@ namespace DTLib
}
return b.ToString();
}
- public static string MergeToString(this List list, string separator)
- {
- var b = new StringBuilder();
- b.Append(list[0].ToString());
- for (int i = 1; i < list.Count; i++)
- {
- b.Append(separator);
- b.Append(list[i].ToString());
- }
- return b.ToString();
- }
// сокращение конвертации
public static int ToInt(this T input) => Convert.ToInt32(input);