Files
Voile/Voile/Source/Resources/DataReaders/TomlDataReader.cs
2025-06-29 23:27:16 +02:00

238 lines
6.2 KiB
C#

using System.Numerics;
using Tommy;
namespace Voile.Resources.DataReaders;
/// <summary>
/// Reads key/value data from a TOML file.
/// </summary>
public class TomlDataReader : IStreamDataReader, IDataValidator, IStreamKeyValueGetter
{
public TomlDataReader() { }
public void Read(Stream data)
{
using var reader = new StreamReader(data);
_table = TOML.Parse(reader);
_valid = _table != null;
}
public bool Valid() => _valid;
public bool HasKey(string key)
{
return _table != null &&
_table.HasKey(key);
}
public IEnumerable<string> GetSubKeys()
{
if (_table == null)
return Enumerable.Empty<string>();
return _table.Keys
.Where(k => _table[k].IsTable)
.ToList();
}
public IEnumerable<string> GetSubKeysRecursive(string prefix = "")
{
if (_table == null)
yield break;
foreach (var key in _table.Keys)
{
var fullKey = string.IsNullOrEmpty(prefix) ? key : $"{prefix}.{key}";
if (_table[key].IsTable)
{
var subReader = GetSubReader(key);
if (subReader != null)
{
foreach (var subKey in subReader.GetSubKeysRecursive(fullKey))
yield return subKey;
yield return fullKey;
}
}
}
}
public IEnumerable<string> GetSubKeys(string subPath)
{
var subReader = GetSubReader(subPath);
if (subReader?._table == null)
return Enumerable.Empty<string>();
return subReader._table.Keys
.Where(k => subReader._table[k].IsTable)
.ToList();
}
public TomlDataReader? GetSubReader(string path)
{
var current = _table;
foreach (var part in path.Split('.'))
{
if (current == null || !current.HasKey(part) || !current[part].IsTable)
return null;
current = current[part].AsTable;
}
return new TomlDataReader { _table = current, _valid = true };
}
public bool GetBool(string key, bool defaultValue = false)
=> TryGetNode(key, out var node) && node.IsBoolean ? node.AsBoolean : defaultValue;
public int GetInt(string key, int defaultValue = 0)
=> TryGetNode(key, out var node) && node.IsInteger ? node.AsInteger : defaultValue;
public long GetLong(string key, long defaultValue = 0)
=> TryGetNode(key, out var node) && node.IsInteger ? node.AsInteger.Value : defaultValue;
public float GetFloat(string key, float defaultValue = 0)
{
if (!TryGetNode(key, out var node))
return defaultValue;
if (node.IsFloat) return node.AsFloat;
if (node.IsInteger) return node.AsInteger;
return defaultValue;
}
public double GetDouble(string key, double defaultValue = 0)
=> TryGetNode(key, out var node) && node.IsFloat ? node.AsFloat : defaultValue;
public Color GetColor(string key, Color defaultValue)
{
if (!TryGetNode(key, out var node))
return defaultValue;
if (node.IsInteger)
{
return new Color(node.AsInteger);
}
else if (node.IsArray)
{
var colorArray = node.AsArray;
var rNode = colorArray[0];
var gNode = colorArray[1];
var bNode = colorArray[2];
var r = rNode.IsInteger ? rNode.AsInteger : 0;
var g = gNode.IsInteger ? gNode.AsInteger : 0;
var b = bNode.IsInteger ? bNode.AsInteger : 0;
int a = 255;
if (colorArray.RawArray.Count == 4)
{
var aNode = colorArray[3];
a = aNode.IsInteger ? aNode.AsInteger : 0;
}
return new Color((byte)r, (byte)g, (byte)b, (byte)a);
}
else if (node.IsString)
{
var colorHexString = node.AsString.Value;
return Color.FromHexString(colorHexString);
}
else
{
return defaultValue;
}
}
public Vector2 GetVector2(string key, Vector2 defaultValue)
{
if (!TryGetNode(key, out var node) || !node.IsArray || node.AsArray.RawArray.Count != 2)
return defaultValue;
var arr = node.AsArray;
return new Vector2(arr[0], arr[1]);
}
public Size GetSize(string key, Size defaultValue)
{
if (!TryGetNode(key, out var node))
return defaultValue;
if (node.IsInteger)
{
return new Size(node.AsInteger);
}
else if (node.IsFloat)
{
return new Size(node.AsFloat);
}
else if (node.IsArray)
{
var sizeArray = node.AsArray;
var lNode = sizeArray[0];
var rNode = sizeArray[1];
var tNode = sizeArray[2];
var bNode = sizeArray[3];
var l = lNode.IsInteger ? lNode.AsInteger : 0;
var t = tNode.IsInteger ? tNode.AsInteger : 0;
var r = rNode.IsInteger ? rNode.AsInteger : 0;
var b = bNode.IsInteger ? bNode.AsInteger : 0;
return new Size(l, r, t, b);
}
return defaultValue;
}
public T[] GetArray<T>(string key, T[] defaultValue)
{
throw new NotImplementedException("Generic array reading not implemented yet.");
}
private bool TryGetNode(string key, out TomlNode node)
{
node = null!;
if (_table == null)
return false;
var current = _table;
var parts = key.Split('.');
for (int i = 0; i < parts.Length; i++)
{
if (!current.HasKey(parts[i]))
return false;
var child = current[parts[i]];
if (i == parts.Length - 1)
{
node = child;
return true;
}
if (!child.IsTable)
return false;
current = child.AsTable;
}
return false;
}
private TomlTable? _table;
private bool _valid;
// Internal use for subreaders
private TomlDataReader(TomlTable table)
{
_table = table;
_valid = true;
}
}