CVR Manager 1.0.0
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
using System.Text;
|
||||
|
||||
namespace CVRManager.Services;
|
||||
|
||||
public static class Vdf
|
||||
{
|
||||
public static Dictionary<string, object> Parse(string text, int start = 0)
|
||||
{
|
||||
var pos = start;
|
||||
var root = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||
var key = ReadToken(text, ref pos);
|
||||
if (key == null) return root;
|
||||
var next = Peek(text, pos);
|
||||
if (next == '{')
|
||||
{
|
||||
pos = text.IndexOf('{', pos) + 1;
|
||||
root[key] = ParseBlock(text, ref pos);
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
public static Dictionary<string, object> ParseDocument(string text)
|
||||
{
|
||||
var pos = 0;
|
||||
return ParseBlock(text, ref pos, true);
|
||||
}
|
||||
|
||||
static Dictionary<string, object> ParseBlock(string text, ref int pos, bool toEnd = false)
|
||||
{
|
||||
var dict = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||
while (true)
|
||||
{
|
||||
SkipSpace(text, ref pos);
|
||||
if (pos >= text.Length) return dict;
|
||||
if (text[pos] == '}')
|
||||
{
|
||||
pos++;
|
||||
return dict;
|
||||
}
|
||||
var key = ReadToken(text, ref pos);
|
||||
if (key == null) return dict;
|
||||
SkipSpace(text, ref pos);
|
||||
if (pos < text.Length && text[pos] == '{')
|
||||
{
|
||||
pos++;
|
||||
dict[key] = ParseBlock(text, ref pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
var val = ReadToken(text, ref pos);
|
||||
if (val == null) return dict;
|
||||
dict[key] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char Peek(string text, int pos)
|
||||
{
|
||||
SkipSpace(text, ref pos);
|
||||
return pos < text.Length ? text[pos] : '\0';
|
||||
}
|
||||
|
||||
static void SkipSpace(string text, ref int pos)
|
||||
{
|
||||
while (pos < text.Length)
|
||||
{
|
||||
if (char.IsWhiteSpace(text[pos])) pos++;
|
||||
else if (text[pos] == '/' && pos + 1 < text.Length && text[pos + 1] == '/')
|
||||
while (pos < text.Length && text[pos] != '\n') pos++;
|
||||
else break;
|
||||
}
|
||||
}
|
||||
|
||||
static string? ReadToken(string text, ref int pos)
|
||||
{
|
||||
SkipSpace(text, ref pos);
|
||||
if (pos >= text.Length || text[pos] != '"') return null;
|
||||
pos++;
|
||||
var sb = new StringBuilder();
|
||||
while (pos < text.Length && text[pos] != '"')
|
||||
{
|
||||
if (text[pos] == '\\' && pos + 1 < text.Length)
|
||||
{
|
||||
pos++;
|
||||
sb.Append(text[pos] switch { 'n' => '\n', 't' => '\t', var c => c });
|
||||
}
|
||||
else sb.Append(text[pos]);
|
||||
pos++;
|
||||
}
|
||||
pos++;
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static Dictionary<string, object>? Dict(this Dictionary<string, object> d, string key) =>
|
||||
d.TryGetValue(key, out var v) ? v as Dictionary<string, object> : null;
|
||||
|
||||
public static string Str(this Dictionary<string, object> d, string key) =>
|
||||
d.TryGetValue(key, out var v) && v is string s ? s : "";
|
||||
}
|
||||
Reference in New Issue
Block a user