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