Skip to content

Instantly share code, notes, and snippets.

@adamveld12
Created December 27, 2014 18:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adamveld12/8fab8c35b89cbb7f5693 to your computer and use it in GitHub Desktop.
Save adamveld12/8fab8c35b89cbb7f5693 to your computer and use it in GitHub Desktop.
INI File DOM - Loads, creates and modifies INI files. Useful for games
/// <summary>
/// An Ini file implementation/DOM
/// </summary>
public class IniFile
{
private readonly IDictionary<string, Section> _sections = new Dictionary<string, Section>();
/// <summary>
/// The key for a section of the INI file that isn't in a section block
/// </summary>
public const string MAIN_SECTION = "";
private readonly Section _mainSection;
/// <summary>
/// Initializes a new instance of <see cref="IniFile"/>
/// </summary>
public IniFile()
{ _mainSection = new Section { Name = MAIN_SECTION }; }
/// <summary>
/// Removes a section
/// </summary>
/// <param name="key"></param>
public void Remove(string key)
{ _sections.Remove(key); }
/// <summary>
/// Adds a section
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public Section Add(string key)
{
var section = new Section { Name = key };
_sections.Add(section.Name, section);
return section;
}
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <exception cref="KeyNotFoundException"></exception>
public Section this[string key]
{
get
{
Section value;
if (key == MAIN_SECTION)
value = _mainSection;
else if (!_sections.TryGetValue(key, out value))
throw new KeyNotFoundException();
return value;
}
set { _sections.Add(key, value); }
}
/// <summary>
/// Gets the name of this configuration file
/// </summary>
public string Name { get; set; }
public override string ToString()
{
var fileContents = new StringBuilder(_mainSection.ToString());
if (_sections.Count > 0)
{
var otherSectionContents = _sections.Select(x => x.Value.ToString()).Aggregate((acc, item) => acc + "\n\n" + item);
fileContents.Append(otherSectionContents.Trim());
}
return fileContents.ToString();
}
/// <summary>
/// A section in an Ini file
/// </summary>
public sealed class Section : IEnumerable<KeyValuePair<string, string>>
{
private readonly IDictionary<string, string> _values = new Dictionary<string, string>();
/// <summary>
/// Adds a key to the section
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void Add(string key, string value)
{
_values.Add(key, value);
}
/// <summary>
/// Removes a key from the section
/// </summary>
/// <param name="key"></param>
public void Remove(string key)
{
_values.Remove(key);
}
/// <summary>
/// Sets a key/value in the section
/// </summary>
/// <param name="key"></param>
/// <exception cref="KeyNotFoundException"></exception>
public string this[string key]
{
get
{
string value;
if(!_values.TryGetValue(key, out value))
throw new KeyNotFoundException();
return value;
}
set { _values.Add(key, value); }
}
/// <summary>
/// Gets or sets the name of this section
/// </summary>
public string Name { get; set; }
/// <summary>
/// Returns a string that represents the current object.
/// </summary>
/// <returns>
/// A string that represents the current object.
/// </returns>
public override string ToString()
{
string result = "";
if (_values.Count > 0)
{
var keyValuePairString = _values.Select(x => string.Format("{0}={1}", x.Key, x.Value))
.Aggregate((acc, item) => acc + "\n" + item);
result = Name == MAIN_SECTION ? keyValuePairString : string.Format("[{0}]\n{1}", Name, keyValuePairString);
}
return result;
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
/// </returns>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
/// </returns>
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
{
return _values.GetEnumerator();
}
}
/// <summary>
/// Parses an ini file and returns a new instance of <see cref="IniFile"/>
/// </summary>
/// <param name="name"></param>
/// <param name="fileContents"></param>
/// <returns></returns>
public static IniFile Parse(string name, string fileContents)
{
var iniFile = new IniFile
{
Name = name
};
var lines = fileContents.Split('\n');
var currentSection = MAIN_SECTION;
return lines.Aggregate(iniFile, (acc, item) =>
{
if (item != string.Empty)
{
var trimmedItem = item.Trim('\r', ' ', '\n');
// we're in a section
if (trimmedItem.StartsWith("[") && trimmedItem.EndsWith("]"))
{
var sectionName = trimmedItem.Trim('[', ']');
acc[sectionName] = new Section
{
Name = sectionName
};
currentSection = sectionName;
}
// stuff the kvp into the current section
else if(!trimmedItem.StartsWith(";"))
{
var section = acc[currentSection];
var kvp = trimmedItem.Split('=');
section[kvp[0]] = kvp[1];
}
}
return acc;
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment