Created
December 27, 2014 18:30
-
-
Save adamveld12/8fab8c35b89cbb7f5693 to your computer and use it in GitHub Desktop.
INI File DOM - Loads, creates and modifies INI files. Useful for games
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <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