Files
FSI.BT.IR.Tools/FSI.Lib/WinSettings/IniFile.cs
maier_S a0095a0516 Squashed 'FSI.Lib/' content from commit 6aa4846
git-subtree-dir: FSI.Lib
git-subtree-split: 6aa48465a834a7bfdd9cbeae8d2e4f769d0c0ff8
2022-03-23 10:15:26 +01:00

422 lines
15 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace FSI.Lib.WinSettings
{
/// <summary>
/// Represents one name/value pair in an INI file.
/// </summary>
internal class IniSetting
{
/// <summary>
/// The name of this INI setting.
/// </summary>
public string Name { get; set; }
/// <summary>
/// The value of this INI setting.
/// </summary>
public string Value { get; set; }
}
/// <summary>
/// Class to create and read INI files.
/// </summary>
internal class IniFile
{
/// <summary>
/// Section used for settings not under any section header (within [])
/// </summary>
public const string DefaultSectionName = "General";
/// <summary>
/// Represents an entire INI file section.
/// </summary>
private class IniSection
{
public string Name { get; set; }
public Dictionary<string, IniSetting> Settings { get; private set; }
public IniSection()
{
Name = string.Empty;
Settings = new Dictionary<string, IniSetting>(StringComparer.OrdinalIgnoreCase);
}
}
private readonly Dictionary<string, IniSection> Sections = new Dictionary<string, IniSection>(StringComparer.OrdinalIgnoreCase);
#region File functions
/// <summary>
/// Loads an INI settings file.
/// </summary>
/// <param name="filename">Path of file to load.</param>
public void Load(string filename)
{
Sections.Clear();
// Default section
IniSection section = new IniSection { Name = DefaultSectionName };
Sections.Add(section.Name, section);
string line;
#if NET472
using (StreamReader file = new StreamReader(filename))
{
while ((line = file.ReadLine()) != null)
{
line = line.TrimStart();
if (line.Length > 0)
{
if (line[0] == ';')
{
// Ignore comments
}
else if (line[0] == '[')
{
// Parse section header
int pos = line.IndexOf(']', 1);
if (pos == -1)
pos = line.Length;
string name = line.Substring(1, pos - 1).Trim();
if (name.Length > 0)
{
if (!Sections.TryGetValue(name, out section))
{
section = new IniSection { Name = name };
Sections.Add(section.Name, section);
}
}
}
else
{
// Parse setting name and value
string name, value;
int pos = line.IndexOf('=');
if (pos == -1)
{
name = line.Trim();
value = string.Empty;
}
else
{
name = line.Substring(0, pos).Trim();
value = line.Substring(pos + 1);
}
if (name.Length > 0)
{
if (section.Settings.TryGetValue(name, out IniSetting setting))
{
setting.Value = value;
}
else
{
setting = new IniSetting { Name = name, Value = value };
section.Settings.Add(name, setting);
}
}
}
}
}
}
#elif NET6_0_OR_GREATER
using StreamReader file = new StreamReader(filename);
while ((line = file.ReadLine()) != null)
{
line = line.TrimStart();
if (line.Length > 0)
{
if (line[0] == ';')
{
// Ignore comments
}
else if (line[0] == '[')
{
// Parse section header
int pos = line.IndexOf(']', 1);
if (pos == -1)
pos = line.Length;
string name = line.Substring(1, pos - 1).Trim();
if (name.Length > 0)
{
if (!Sections.TryGetValue(name, out section))
{
section = new IniSection { Name = name };
Sections.Add(section.Name, section);
}
}
}
else
{
// Parse setting name and value
string name, value;
int pos = line.IndexOf('=');
if (pos == -1)
{
name = line.Trim();
value = string.Empty;
}
else
{
name = line.Substring(0, pos).Trim();
value = line.Substring(pos + 1);
}
if (name.Length > 0)
{
if (section.Settings.TryGetValue(name, out IniSetting setting))
{
setting.Value = value;
}
else
{
setting = new IniSetting { Name = name, Value = value };
section.Settings.Add(name, setting);
}
}
}
}
}
#endif
}
/// <summary>
/// Writes the current settings to an INI file. If the file already exists, it is overwritten.
/// </summary>
/// <param name="filename">Path of file to write to.</param>
public void Save(string filename)
{
#if NET472
using (StreamWriter file = new StreamWriter(filename, false))
{
bool firstLine = true;
foreach (IniSection section in Sections.Values)
{
if (firstLine)
firstLine = false;
else
file.WriteLine();
if (section.Settings.Any())
{
file.WriteLine("[{0}]", section.Name);
foreach (IniSetting setting in section.Settings.Values)
file.WriteLine("{0}={1}", setting.Name, setting.Value);
}
}
}
#elif NET6_0_OR_GREATER
using StreamWriter file = new StreamWriter(filename, false);
bool firstLine = true;
foreach (IniSection section in Sections.Values)
{
if (firstLine)
firstLine = false;
else
file.WriteLine();
if (section.Settings.Any())
{
file.WriteLine("[{0}]", section.Name);
foreach (IniSetting setting in section.Settings.Values)
file.WriteLine("{0}={1}", setting.Name, setting.Value);
}
}
#endif
}
#endregion
#region Read values
/// <summary>
/// Returns the value of an INI setting.
/// </summary>
/// <param name="section">The INI file section.</param>
/// <param name="setting">The INI setting name.</param>
/// <param name="defaultValue">The value to return if the setting was not found.</param>
/// <returns>Returns the specified setting value.</returns>
public string GetSetting(string section, string setting, string defaultValue = null)
{
if (Sections.TryGetValue(section, out IniSection iniSection))
{
if (iniSection.Settings.TryGetValue(setting, out IniSetting iniSetting))
return iniSetting.Value;
}
return defaultValue;
}
/// <summary>
/// Returns the value of an INI setting as an integer value.
/// </summary>
/// <param name="section">The INI file section.</param>
/// <param name="setting">The INI setting name.</param>
/// <param name="defaultValue">The value to return if the setting was not found,
/// or if it could not be converted to a integer value.</param>
/// <returns>Returns the specified setting value as an integer value.</returns>
public int GetSetting(string section, string setting, int defaultValue)
{
if (int.TryParse(GetSetting(section, setting), out int value))
return value;
return defaultValue;
}
/// <summary>
/// Returns the value of an INI setting as a double value.
/// </summary>
/// <param name="section">The INI file section.</param>
/// <param name="setting">The INI setting name.</param>
/// <param name="defaultValue">The value to return if the setting was not found,
/// or if it could not be converted to a double value.</param>
/// <returns>Returns the specified setting value as a double value.</returns>
public double GetSetting(string section, string setting, double defaultValue)
{
if (double.TryParse(GetSetting(section, setting), out double value))
return value;
return defaultValue;
}
/// <summary>
/// Returns the value of an INI setting as a Boolean value.
/// </summary>
/// <param name="section">The INI file section.</param>
/// <param name="setting">The INI setting name.</param>
/// <param name="defaultValue">The value to return if the setting was not found,
/// or if it could not be converted to a Boolean value.</param>
/// <returns>Returns the specified setting value as a Boolean.</returns>
public bool GetSetting(string section, string setting, bool defaultValue)
{
if (ConvertToBool(GetSetting(section, setting), out bool value))
return value;
return defaultValue;
}
/// <summary>
/// Returns all settings in the given INI section.
/// </summary>
/// <param name="section">The section that contains the settings to be retrieved.</param>
/// <returns>Returns the settings in the given INI section.</returns>
public IEnumerable<IniSetting> GetSectionSettings(string section)
{
if (Sections.TryGetValue(section, out IniSection iniSection))
{
foreach (var setting in iniSection.Settings)
yield return setting.Value;
}
}
#endregion
#region Write values
/// <summary>
/// Sets an INI file setting. The setting is not written to disk until
/// <see cref="Save"/> is called.
/// </summary>
/// <param name="section">The INI-file section.</param>
/// <param name="setting">The name of the INI-file setting.</param>
/// <param name="value">The value of the INI-file setting</param>
public void SetSetting(string section, string setting, string value)
{
if (!Sections.TryGetValue(section, out IniSection iniSection))
{
iniSection = new IniSection { Name = section };
Sections.Add(iniSection.Name, iniSection);
}
if (!iniSection.Settings.TryGetValue(setting, out IniSetting iniSetting))
{
iniSetting = new IniSetting { Name = setting };
iniSection.Settings.Add(iniSetting.Name, iniSetting);
}
iniSetting.Value = value;
}
/// <summary>
/// Sets an INI file setting with an integer value.
/// </summary>
/// <param name="section">The INI-file section.</param>
/// <param name="setting">The name of the INI-file setting.</param>
/// <param name="value">The value of the INI-file setting</param>
public void SetSetting(string section, string setting, int value)
{
SetSetting(section, setting, value.ToString());
}
/// <summary>
/// Sets an INI file setting with a double value.
/// </summary>
/// <param name="section">The INI-file section.</param>
/// <param name="setting">The name of the INI-file setting.</param>
/// <param name="value">The value of the INI-file setting</param>
public void SetSetting(string section, string setting, double value)
{
SetSetting(section, setting, value.ToString());
}
/// <summary>
/// Sets an INI file setting with a Boolean value.
/// </summary>
/// <param name="section">The INI-file section.</param>
/// <param name="setting">The name of the INI-file setting.</param>
/// <param name="value">The value of the INI-file setting</param>
public void SetSetting(string section, string setting, bool value)
{
SetSetting(section, setting, value.ToString());
}
#endregion
#region Boolean parsing
private readonly string[] TrueStrings = { "true", "yes", "on" };
private readonly string[] FalseStrings = { "false", "no", "off" };
private bool ConvertToBool(string s, out bool value)
{
if (s == null)
value = false;
if (TrueStrings.Any(s2 => string.Compare(s, s2, true) == 0))
value = true;
else if (FalseStrings.Any(s2 => string.Compare(s, s2, true) == 0))
value = false;
else if (int.TryParse(s, out int i))
value = i != 0;
else
{
value = false;
return false;
}
return true;
}
#endregion
//public void Dump()
//{
// foreach (IniSection section in Sections.Values)
// {
// Debug.WriteLine(string.Format("[{0}]", section.Name));
// foreach (IniSetting setting in section.Settings.Values)
// Debug.WriteLine("[{0}]=[{1}]", setting.Name, setting.Value);
// }
//}
}
}