9bb4f85802
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
100 lines
3.0 KiB
C#
100 lines
3.0 KiB
C#
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 : "";
|
|
}
|