namespace RioJoy.Core.Profiles; /// /// Minimal INI reader (sections, key = value, ;/# comments) /// sufficient to parse the legacy RIO.ini. Keys are case-insensitive. /// public sealed class IniFile { private readonly Dictionary> _sections = new(StringComparer.OrdinalIgnoreCase); public static IniFile Parse(string text) { if (text is null) throw new ArgumentNullException(nameof(text)); var ini = new IniFile(); var current = new Dictionary(StringComparer.OrdinalIgnoreCase); ini._sections[string.Empty] = current; foreach (string rawLine in text.Split('\n')) { string line = rawLine.Trim(); if (line.Length == 0 || line[0] is ';' or '#') continue; if (line[0] == '[' && line[^1] == ']') { string section = line[1..^1].Trim(); if (!ini._sections.TryGetValue(section, out current!)) ini._sections[section] = current = new Dictionary(StringComparer.OrdinalIgnoreCase); continue; } int eq = line.IndexOf('='); if (eq < 0) continue; string key = line[..eq].Trim(); string value = line[(eq + 1)..].Trim(); if (key.Length > 0) current[key] = value; } return ini; } /// All key/value pairs in a section (empty if the section is absent). public IDictionary Section(string name) => _sections.TryGetValue(name, out Dictionary? s) ? s : new Dictionary(); public string? GetString(string section, string key) => Section(section).TryGetValue(key, out string? v) ? v : null; public bool GetBool(string section, string key, bool fallback) { string? v = GetString(section, key); if (v is null) return fallback; return v.Trim().ToLowerInvariant() switch { "1" or "true" or "yes" or "on" => true, "0" or "false" or "no" or "off" => false, _ => fallback, }; } /// Parse an integer value that may be hex (0x…) or decimal. public static int ParseInt(string value) { if (value is null) throw new ArgumentNullException(nameof(value)); string v = value.Trim(); bool neg = v.StartsWith("-", StringComparison.Ordinal); if (neg) v = v[1..]; int magnitude = v.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt32(v[2..], 16) : int.Parse(v); return neg ? -magnitude : magnitude; } }