238 lines
6.2 KiB
C#
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;
|
|
}
|
|
} |