diff --git a/Nuclex.Support (net-4.0).csproj b/Nuclex.Support (net-4.0).csproj
index 14255fb..efa4c66 100644
--- a/Nuclex.Support (net-4.0).csproj
+++ b/Nuclex.Support (net-4.0).csproj
@@ -197,6 +197,14 @@
WeakCollection.cs
+
+
+ ConfigurationFileStore.cs
+
+
+
+
+
diff --git a/Source/Configuration/ConfigurationFile.cs b/Source/Configuration/ConfigurationFile.cs
deleted file mode 100644
index f953541..0000000
--- a/Source/Configuration/ConfigurationFile.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-
-namespace Nuclex.Support.Configuration {
-
- /// 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.
- ///
- public class ConfigurationFile {
-
- /// Initializes a new, empty configuration file
- public ConfigurationFile() {
- this.lines = new List();
- }
-
- /// Parses a configuration file from the specified text reader
- /// Reader the configuration file will be parsed from
- /// The configuration file parsed from the specified reader
- public static ConfigurationFile Parse(TextReader reader) {
- throw new NotImplementedException();
- }
-
- /// Saves the configuration file into the specified writer
- /// Writer the configuration file will be saved into
- public void Save(TextWriter writer) {
-
- }
-
- /// Lines contained in the configuration file
- private IList lines;
-
- }
-
-} // namespace Nuclex.Support.Configuration
diff --git a/Source/Configuration/ConfigurationFileStore.Parsing.cs b/Source/Configuration/ConfigurationFileStore.Parsing.cs
new file mode 100644
index 0000000..aa633d1
--- /dev/null
+++ b/Source/Configuration/ConfigurationFileStore.Parsing.cs
@@ -0,0 +1,139 @@
+#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.IO;
+
+using Nuclex.Support.Parsing;
+
+namespace Nuclex.Support.Configuration {
+
+ partial class ConfigurationFileStore {
+
+ /// Parses a configuration file from the specified text reader
+ /// Reader the configuration file will be parsed from
+ /// The configuration file parsed from the specified reader
+ public static ConfigurationFileStore Parse(TextReader reader) {
+ var store = new ConfigurationFileStore();
+
+ for(; ; ) {
+ string line = reader.ReadLine();
+ if(line == null) {
+ return store;
+ }
+
+
+ }
+ }
+
+ /// Determines the best matching type for an option value
+ /// Value for which the best matching type will be found
+ /// The best matching type for the specified option value
+ private static Type getBestMatchingType(ref StringSegment value) {
+ if(value.Count == 0) {
+ return typeof(string);
+ }
+
+ // If there are at least two characters, it may be an integer with
+ // a sign in front of it
+ if(value.Count >= 2) {
+ int index = value.Offset;
+ if(ParserHelper.SkipInteger(value.Text, ref index)) {
+ if(index < value.Offset + value.Count) {
+ if(value.Text[index] == '.') {
+ return typeof(float);
+ }
+ }
+
+ return typeof(int);
+ }
+ } else if(value.Count >= 1) { // If it's at least one character, it may be a number
+ int index = value.Offset;
+ ParserHelper.SkipNumericals(value.Text, ref index);
+ if(index > value.Offset) {
+ return typeof(int);
+ }
+ }
+
+ // If it parses as a boolean literal, then it must be a boolean
+ if(parseBooleanLiteral(ref value) != null) {
+ return typeof(bool);
+ }
+
+ return typeof(string);
+ }
+
+ /// Tried to parse a boolean literal
+ /// Value that will be parsed as a boolean literal
+ ///
+ /// True or false if the value was a boolean literal, null if it wasn't
+ ///
+ private static bool? parseBooleanLiteral(ref StringSegment value) {
+ switch(value.Count) {
+
+ // If the string spells 'no', it is considered a boolean
+ case 2: {
+ bool isSpellingNo =
+ ((value.Text[value.Offset + 0] == 'n') || (value.Text[value.Offset + 0] == 'N')) &&
+ ((value.Text[value.Offset + 1] == 'o') || (value.Text[value.Offset + 1] == 'O'));
+ return isSpellingNo ? new Nullable(false) : null;
+ }
+
+ // If the string spells 'yes', it is considered a boolean
+ case 3: {
+ bool isSpellingYes =
+ ((value.Text[value.Offset + 0] == 'y') || (value.Text[value.Offset + 0] == 'Y')) &&
+ ((value.Text[value.Offset + 1] == 'e') || (value.Text[value.Offset + 1] == 'E')) &&
+ ((value.Text[value.Offset + 2] == 's') || (value.Text[value.Offset + 2] == 'S'));
+ return isSpellingYes ? new Nullable(true) : null;
+ }
+
+ // If the string spells 'true', it is considered a boolean
+ case 4: {
+ bool isSpellingTrue =
+ ((value.Text[value.Offset + 0] == 't') || (value.Text[value.Offset + 0] == 'T')) &&
+ ((value.Text[value.Offset + 1] == 'r') || (value.Text[value.Offset + 1] == 'R')) &&
+ ((value.Text[value.Offset + 2] == 'u') || (value.Text[value.Offset + 2] == 'U')) &&
+ ((value.Text[value.Offset + 3] == 'e') || (value.Text[value.Offset + 3] == 'E'));
+ return isSpellingTrue ? new Nullable(true) : null;
+ }
+
+ // If the string spells 'false', it is considered a boolean
+ case 5: {
+ bool isSpellingFalse =
+ ((value.Text[value.Offset + 0] == 'f') || (value.Text[value.Offset + 0] == 'F')) &&
+ ((value.Text[value.Offset + 1] == 'a') || (value.Text[value.Offset + 1] == 'A')) &&
+ ((value.Text[value.Offset + 2] == 'l') || (value.Text[value.Offset + 2] == 'L')) &&
+ ((value.Text[value.Offset + 3] == 's') || (value.Text[value.Offset + 3] == 'S')) &&
+ ((value.Text[value.Offset + 4] == 'e') || (value.Text[value.Offset + 4] == 'E'));
+ return isSpellingFalse ? new Nullable(false) : null;
+ }
+
+ // Anything else is not considered a boolean
+ default: {
+ return null;
+ }
+
+ }
+ }
+
+ }
+
+} // namespace Nuclex.Support.Configuration
diff --git a/Source/Configuration/ConfigurationFileStore.cs b/Source/Configuration/ConfigurationFileStore.cs
new file mode 100644
index 0000000..97f09c5
--- /dev/null
+++ b/Source/Configuration/ConfigurationFileStore.cs
@@ -0,0 +1,167 @@
+#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.IO;
+
+using Nuclex.Support.Parsing;
+
+namespace Nuclex.Support.Configuration {
+
+ /// 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.
+ ///
+ public partial class ConfigurationFileStore : ISettingsStore {
+
+ #region class Category
+
+ /// Stores informations about a category found in the configuration file
+ private class Category {
+
+ /// Index of the line the category is defined in
+ public int LineIndex;
+
+ /// Name of the category as a string
+ public StringSegment CategoryName;
+
+ }
+
+ #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.lines = new List();
+ this.categories = new List();
+ this.options = new List