Files
SabreTools.Serialization/SabreTools.Data.Models/Metadata/DictionaryBase.cs
Matt Nadareski 7689c6dd07 Libraries
This change looks dramatic, but it's just separating out the already-split namespaces into separate top-level folders. In theory, every single one could be built into their own Nuget package. `SabreTools.Serialization` still builds the normal Nuget package that is used by all other projects and includes all namespaces.
2026-03-21 16:26:56 -04:00

154 lines
4.2 KiB
C#

using System.Collections.Generic;
namespace SabreTools.Data.Models.Metadata
{
/// <summary>
/// Specialized dictionary base for item types
/// </summary>
public abstract class DictionaryBase : Dictionary<string, object?>
{
/// <summary>
/// Read a key as the specified type, returning null on error
/// </summary>
public T? Read<T>(string key)
{
try
{
if (!ValidateKey(key))
return default;
if (this[key] is not T)
return default;
return (T?)this[key];
}
catch
{
return default;
}
}
/// <summary>
/// Read a key as a bool, returning null on error
/// </summary>
public bool? ReadBool(string key)
{
if (!ValidateKey(key))
return null;
bool? asBool = Read<bool?>(key);
if (asBool is not null)
return asBool;
string? asString = Read<string>(key);
return asString?.ToLowerInvariant() switch
{
"true" or "yes" => true,
"false" or "no" => false,
_ => null,
};
}
/// <summary>
/// Read a key as a double, returning null on error
/// </summary>
public double? ReadDouble(string key)
{
if (!ValidateKey(key))
return null;
double? asDouble = Read<double?>(key);
if (asDouble is not null)
return asDouble;
string? asString = Read<string>(key);
if (asString is not null && double.TryParse(asString, out double asStringDouble))
return asStringDouble;
return null;
}
/// <summary>
/// Read a key as a long, returning null on error
/// </summary>
/// <remarks>TODO: Add logic to convert SI suffixes and hex</remarks>
public long? ReadLong(string key)
{
if (!ValidateKey(key))
return null;
long? asLong = Read<long?>(key);
if (asLong is not null)
return asLong;
string? asString = Read<string>(key);
if (asString is not null && long.TryParse(asString, out long asStringLong))
return asStringLong;
return null;
}
/// <summary>
/// Read a key as a string, returning null on error
/// </summary>
public string? ReadString(string key)
{
if (!ValidateKey(key))
return null;
string? asString = Read<string>(key);
if (asString is not null)
return asString;
string[]? asArray = Read<string[]>(key);
if (asArray is not null)
#if NETFRAMEWORK || NETSTANDARD2_0
return string.Join(",", asArray);
#else
return string.Join(',', asArray);
#endif
// TODO: Add byte array conversion here
// TODO: Add byte array read helper
return this[key]!.ToString();
}
/// <summary>
/// Read a key as a string[], returning null on error
/// </summary>
public string[]? ReadStringArray(string key)
{
if (!ValidateKey(key))
return null;
string[]? asArray = Read<string[]>(key);
if (asArray is not null)
return asArray;
string? asString = Read<string>(key);
if (asString is not null)
return [asString];
asString = this[key]!.ToString();
if (asString is not null)
return [asString];
return null;
}
/// <summary>
/// Check if a key is valid
/// </summary>
private bool ValidateKey(string key)
{
if (string.IsNullOrEmpty(key))
return false;
else if (!ContainsKey(key))
return false;
else if (this[key] is null)
return false;
return true;
}
}
}