#region CPL License /* Nuclex Framework Copyright (C) 2002-2014 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #endregion using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text; namespace Nuclex.Support.Settings { /// Represents an ini- or cfg-like configuration file /// /// /// This class tries its best to preserve the formatting of configuration files. /// Changing a value will keep the line it appears in intact. The parser also takes /// as much data from a line as it can - anything to the left of an equals sign /// becomes the name, anything to the right (excluding comments) becomes the value. /// /// /// To access the contents of a configuration file, simply parse it and use it like /// you would any other settings store: /// /// /// /// // # Settings.ini /// // message = hello world ; the usual... /// // show message = true /// ISettingsStore settings; /// using(var reader = new StreamReader("settings.ini")) { /// settings = ConfigurationFile.Parse(reader); /// } /// /// if(settings.Get<bool>(null, "show message")) { /// Console.WriteLine(settings.Get<string>(null, "message")); /// } /// /// /// /// It's usually a good idea to keep an application and all of its required files /// together, whether it's code or data, but platforms often have their own conventions: /// /// /// /// Operating System /// Convention /// /// /// Linux /// /// System-wide configuration goes into /etc/<appname>/, user-specific /// configuration goes into ~/.<appname>/ while static configuration that is /// known at build time resides with the application in /opt/<appname>/ /// /// /// /// Windows /// /// System-wide configuration goes into %ProgramData%, user-specific configuration /// has no real place (try %AppData%/<appname>/ if you want to hide it from /// the user, %UserProfile%/Documents/<appname> if the user should see it) /// and static configuration resides with your application /// in %ProgramFiles%/<appname>/. /// /// /// /// MacOS /// /// System-wide configuration goes into /etc/<appname>/, user-specific /// configuration goes into /Users/<username>/.<appname>/ while static /// configuration resides with the application in /Applications/<appname>/ /// /// /// /// public partial class ConfigurationFileStore : ISettingsStore { #region class Category /// Stores informations about a category found in the configuration file private class Category { /// Name of the category as a string public StringSegment CategoryName; /// Lookup table for the options in this category public IDictionary OptionLookup; /// Lines this category and its options consist of public IList Lines; } #endregion // class Category #region class Option /// Stores informations about an option found in the configuration file private class Option { /// Index of the line the option is defined in public int LineIndex; /// Name of the option as a string public StringSegment OptionName; /// Value of the option as a string public StringSegment OptionValue; } #endregion // class Option /// Initializes a new, empty configuration file public ConfigurationFileStore() { this.options = new List