new dtsod parser
This commit is contained in:
parent
4957b7a406
commit
17915621f3
@ -35,6 +35,7 @@
|
||||
<Compile Include="CompressedArray.cs" />
|
||||
<Compile Include="Dtsod.cs" />
|
||||
<Compile Include="cs9somefix.cs" />
|
||||
<Compile Include="DtsodParser2.cs" />
|
||||
<Compile Include="Filework.cs" />
|
||||
<Compile Include="ColoredConsole.cs" />
|
||||
<Compile Include="PublicLog.cs" />
|
||||
|
||||
309
DTLib/Dtsod.cs
309
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, dynamic>
|
||||
{
|
||||
string Text;
|
||||
public Dictionary<string, dynamic> Values { get; }
|
||||
static readonly bool debug = false;
|
||||
|
||||
public string Text { get; }
|
||||
//public Dictionary<string, dynamic> Values { get; set; }
|
||||
public Dtsod(string text)
|
||||
{
|
||||
Text = text;
|
||||
Values = Parse(text);
|
||||
foreach (KeyValuePair<string, dynamic> 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<string, dynamic> Parse(string text)
|
||||
Dictionary<string, dynamic> ParseNew(string text)
|
||||
{
|
||||
Dictionary<string, dynamic> 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<dynamic>());
|
||||
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<dynamic> ReadList()
|
||||
{
|
||||
i++;
|
||||
List<dynamic> 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<string, dynamic> 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 <u{stringValue[stringValue.Length - 1]}>")
|
||||
},
|
||||
// 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<string, dynamic> ParseOld(string text)
|
||||
{
|
||||
Dictionary<string, dynamic> output = new();
|
||||
StringBuilder nameStrB = new();
|
||||
@ -59,13 +299,17 @@ 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;
|
||||
switch (str)
|
||||
{
|
||||
// предустановленные значения
|
||||
case "true": return true;
|
||||
case "false": return false;
|
||||
case "null": return null;
|
||||
default:
|
||||
// double
|
||||
else if (str.Contains(".")) return SimpleConverter.ToDouble(str);
|
||||
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
|
||||
@ -83,39 +327,40 @@ namespace DTLib
|
||||
_ => 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
207
DTLib/DtsodParser2.cs
Normal file
207
DTLib/DtsodParser2.cs
Normal file
@ -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<string, dynamic> ParseNew(string text)
|
||||
{
|
||||
Dictionary<string, dynamic> 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<dynamic>());
|
||||
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<string> ReadList()
|
||||
{
|
||||
List<string> 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<string, dynamic> 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 <u{valueString[valueString.Length - 1]}>")
|
||||
},
|
||||
_ => 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
|
||||
@ -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", ">... ");
|
||||
|
||||
@ -95,17 +95,6 @@ namespace DTLib
|
||||
}
|
||||
return b.ToString();
|
||||
}
|
||||
public static string MergeToString<T>(this List<T> 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<T>(this T input) => Convert.ToInt32(input);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user