changeset 1:f9444f1786cd

Re #6 - INI parsing library * Add ToString methods * Add types of string and parse to objects instead of parsing to key-value pair * Create method to load INI data from string * Add content of AddSection method
author IBBoard <dev@ibboard.co.uk>
date Sun, 11 Jan 2009 15:37:14 +0000
parents fbde5e1920ba
children 2dde4c1d19d9
files IBBoard.Ini.mdp IIniLine.cs IniBlankLine.cs IniCommentLine.cs IniFile.cs IniFileReader.cs IniKeyValuePairLine.cs IniLineParser.cs IniSection.cs IniSectionParser.cs
diffstat 10 files changed, 325 insertions(+), 82 deletions(-) [+]
line wrap: on
line diff
--- a/IBBoard.Ini.mdp	Thu Jan 08 20:33:56 2009 +0000
+++ b/IBBoard.Ini.mdp	Sun Jan 11 15:37:14 2009 +0000
@@ -24,6 +24,10 @@
     <File name="IniSectionParser.cs" subtype="Code" buildaction="Compile" />
     <File name="IniLineParser.cs" subtype="Code" buildaction="Compile" />
     <File name="InvalidIniSectionException.cs" subtype="Code" buildaction="Compile" />
+    <File name="IniKeyValuePairLine.cs" subtype="Code" buildaction="Compile" />
+    <File name="IIniLine.cs" subtype="Code" buildaction="Compile" />
+    <File name="IniBlankLine.cs" subtype="Code" buildaction="Compile" />
+    <File name="IniCommentLine.cs" subtype="Code" buildaction="Compile" />
   </Contents>
   <References>
     <ProjectReference type="Gac" localcopy="True" refto="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IIniLine.cs	Sun Jan 11 15:37:14 2009 +0000
@@ -0,0 +1,15 @@
+// This file (IIniLine.cs) is a part of the IBBoard.Ini library and is copyright 2009 IBBoard.
+//
+// The file and the library/program it is in are licensed under the GNU LGPL license. Please see COPYING.LGPL for more information and the full license.
+
+using System;
+
+namespace IBBoard.Ini
+{
+	/// <summary>
+	/// Marker interface for IniLine objects
+	/// </summary>
+	public interface IIniLine
+	{
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IniBlankLine.cs	Sun Jan 11 15:37:14 2009 +0000
@@ -0,0 +1,24 @@
+// This file (IniBlankLine.cs) is a part of the IBBoard.Ini library and is copyright 2009 IBBoard.
+//
+// The file and the library/program it is in are licensed under the GNU LGPL license. Please see COPYING.LGPL for more information and the full license.
+
+using System;
+
+namespace IBBoard.Ini
+{
+	/// <summary>
+	/// A blank line in an Ini file
+	/// </summary>
+	public class IniBlankLine : IIniLine
+	{	
+		public IniBlankLine()
+		{
+		}
+
+		public override string ToString()
+		{
+			return "";
+		}
+
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IniCommentLine.cs	Sun Jan 11 15:37:14 2009 +0000
@@ -0,0 +1,38 @@
+// This file (IniCommentLine.cs) is a part of the IBBoard.Ini library and is copyright 2009 IBBoard.
+//
+// The file and the library/program it is in are licensed under the GNU LGPL license. Please see COPYING.LGPL for more information and the full license.
+
+using System;
+
+namespace IBBoard.Ini
+{
+	/// <summary>
+	/// A line in an IniFile that contains a comment
+	/// </summary>
+	public class IniCommentLine : IIniLine
+	{
+		private string comment;
+		
+		public IniCommentLine(string comment)
+		{
+			this.comment = comment.TrimStart(';');
+		}
+
+		//// <value>
+		/// Gets the content of the comment
+		/// </value>
+		public string Comment
+		{
+			get
+			{
+				return comment;
+			}
+		}
+
+		public override string ToString()
+		{
+			return ";" + Comment;
+		}
+
+	}
+}
--- a/IniFile.cs	Thu Jan 08 20:33:56 2009 +0000
+++ b/IniFile.cs	Sun Jan 11 15:37:14 2009 +0000
@@ -3,14 +3,16 @@
 // The file and the library/program it is in are licensed under the GNU LGPL license. Please see COPYING.LGPL for more information and the full license.
 
 using System;
+using System.Collections;
 using System.Collections.Generic;
+using System.Text;
 
 namespace IBBoard.Ini
 {		
 	/// <summary>
 	/// The <code>IniFile</code> provides access to INI formatted data. INI files are no longer used as much as they were, but many older applications including parts of Windows still use them to store data and configuration values in.
 	/// </summary>
-	public class IniFile
+	public class IniFile : IEnumerable<IniSection>
 	{		
 		private Dictionary<string, IniSection> sections;
 		
@@ -21,29 +23,7 @@
 		{
 			sections = new Dictionary<string,IniSection>();
 		}
-		
-		/// <summary>
-		/// Gets a single section by name. If no section exists with that name then a <see cref=" NonExistantIniSection"/> is returned to remove the need for null checks. To check for the existance of a section use the <code>HasSection</code> method.
-		/// </summary>
-		/// <param name="sectionName">
-		/// The name of the section to get
-		/// </param>
-		/// <returns>
-		/// Either the requested <see cref="IniSection"/> or a <see cref=" NonExistantIniSection"/> if it doesn't exist
-		/// </returns>
-		public IniSection GetSection(string sectionName)
-		{
-			IniSection section = null;
-			sections.TryGetValue(sectionName.Trim(), out section);
-			
-			if (section == null)
-			{
-				section = new NonExistantIniSection();
-			}
-			
-			return section;
-		}
-		
+				
 		/// <summary>
 		/// Adds an <see cref="IniSection"/> to the IniFile.
 		/// <p>
@@ -56,12 +36,43 @@
 		{
 			if (!HasSection(section.Name))
 			{
+				sections.Add(section.Name, section);
 			}
 			else
 			{
-				throw new ArgumentException("Ini section already exists");
+				throw new ArgumentException("Ini section already exists with name " + section.Name);
 			}
 		}
+
+		public IEnumerator<IniSection> GetEnumerator()
+		{
+			return sections.Values.GetEnumerator();
+		}
+
+		IEnumerator IEnumerable.GetEnumerator()
+        {
+            return sections.Values.GetEnumerator();
+        }
+
+		//// <value>
+		/// Gets a single section by name. If no section exists with that name then a <see cref=" NonExistantIniSection"/> is returned to remove the need for null checks. To check for the existance of a section use the <code>HasSection</code> method.
+		/// </value>
+		public IniSection this[string sectionName]
+		{
+			get
+			{	
+				IniSection section = null;
+				sections.TryGetValue(sectionName.Trim(), out section);
+				
+				if (section == null)
+				{
+					section = new NonExistantIniSection();
+				}
+				
+				return section;
+			}
+		}
+
 		
 		public bool HasSection(string sectionName)
 		{
@@ -77,5 +88,19 @@
 				return col;
 			}
 		}
+
+		public override string ToString()
+		{
+			StringBuilder stringBuilder = new StringBuilder();
+
+			foreach (IniSection section in this)
+			{
+				stringBuilder.Append(section.ToString());
+				stringBuilder.Append("\n");
+			}
+			
+			return stringBuilder.ToString().Trim();
+		}
+
 	}
 }
--- a/IniFileReader.cs	Thu Jan 08 20:33:56 2009 +0000
+++ b/IniFileReader.cs	Sun Jan 11 15:37:14 2009 +0000
@@ -10,9 +10,10 @@
 {
 	public class IniFileReader
 	{
-		public static IniFile ReadFile(string path)
+		public static IniFile ReadFile(string iniFileContent)
 		{
-			return ReadFile(new FileInfo(path));
+			MemoryStream memoryStream = new MemoryStream(System.Text.ASCIIEncoding.ASCII.GetBytes("test"));
+			return LoadIniFileFromStream(new StreamReader(memoryStream));
 		}
 		
 		public static IniFile ReadFile(FileInfo file)
@@ -22,28 +23,53 @@
 				throw new FileNotFoundException(file.FullName+" did not exist and could not be read");
 			}
 			
-			IniFile iniFile = new IniFile();
-			LoadDataFromFile(file, iniFile);			
-			return iniFile;
+			return LoadIniFileFromFile(file);
 		}
 		
-		private static void LoadDataFromFile(FileInfo file, IniFile iniFile)
+		private static IniFile LoadIniFileFromFile(FileInfo file)
 		{
 			StreamReader stream = file.OpenText();
+			IniFile iniFile = null;
 			
 			try
 			{
-				LoadDataFromStream(iniFile, stream);
+				iniFile = LoadIniFileFromStream(stream);
 			}
 			finally
 			{
 				stream.Close();
 			}
+
+			return iniFile;
 		}
 		
-		private static void LoadDataFromStream(IniFile iniFile, StreamReader stream)
+		private static IniFile LoadIniFileFromStream(StreamReader stream)
+		{
+			string firstHeader = ReadToFirstSectionHeader(stream);
+			return ReadIniFileSectionsToFile(stream, firstHeader);
+		}
+
+		private static string ReadToFirstSectionHeader(StreamReader stream)
 		{
-			StringBuilder sectionStringBuilder = new StringBuilder();
+			string firstSectionHeader = null;
+			
+			while (!stream.EndOfStream && firstSectionHeader == null)
+			{
+				string line = stream.ReadLine().Trim();
+
+				if (IniSectionParser.IsLineStartOfNewSection(line))
+				{
+					firstSectionHeader = line + "\n";
+				}
+			}
+
+			return firstSectionHeader;
+		}
+
+		private static IniFile ReadIniFileSectionsToFile(StreamReader stream, string firstHeader)
+		{
+			IniFile iniFile = new IniFile();			
+			StringBuilder sectionStringBuilder = SetUpStringBuilder(firstHeader);
 			
 			while (!stream.EndOfStream)
 			{
@@ -51,22 +77,39 @@
 				
 				if (IniSectionParser.IsLineStartOfNewSection(line))
 				{
-					String currSection = sectionStringBuilder.ToString();
-					
-					if (IniSectionParser.IsStringAnIniSection(currSection))
-					{
-						IniSection section = IniSectionParser.CreateSection(currSection);
-						iniFile.AddSection(section);
-					}
-					
+					AddSectionFromStringBuilderContents(sectionStringBuilder, iniFile);
 					sectionStringBuilder.Length = 0;
 				}
 				
 				sectionStringBuilder.Append(line);
 				sectionStringBuilder.Append("\n");
 			}
+
+			if (sectionStringBuilder.Length > 0)
+			{
+				AddSectionFromStringBuilderContents(sectionStringBuilder, iniFile);
+			}
+
+			return iniFile;
 		}
-		
-		
+
+		private static StringBuilder SetUpStringBuilder(string firstHeader)
+		{
+			StringBuilder sectionStringBuilder = new StringBuilder();
+
+			if (firstHeader!=null)
+			{
+				sectionStringBuilder.Append(firstHeader);
+				sectionStringBuilder.Append("\n");
+			}
+
+			return sectionStringBuilder;
+		}
+
+		private static void AddSectionFromStringBuilderContents(StringBuilder sectionStringBuilder, IniFile iniFile)
+		{			
+			IniSection section = IniSectionParser.CreateSection(sectionStringBuilder.ToString());
+			iniFile.AddSection(section);
+		}
 	}
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IniKeyValuePairLine.cs	Sun Jan 11 15:37:14 2009 +0000
@@ -0,0 +1,42 @@
+// This file (IniKeyValuePairLine.cs) is a part of the IBBoard.Ini library and is copyright 2009 IBBoard.
+//
+// The file and the library/program it is in are licensed under the GNU LGPL license. Please see COPYING.LGPL for more information and the full license.
+
+using System;
+
+namespace IBBoard.Ini
+{
+	public class IniKeyValuePairLine : IIniLine
+	{
+		private string keyString;
+		private string valueString;
+		
+		public IniKeyValuePairLine(string keyString, string valueString)
+		{
+			this.keyString = keyString;
+			this.valueString = valueString;
+		}
+
+		public string Key
+		{
+			get
+			{
+				return keyString;
+			}
+		}
+
+		public string Value
+		{
+			get
+			{
+				return valueString;
+			}
+		}
+
+		public override string ToString()
+		{
+			return Key + "=" + Value;
+		}
+
+	}
+}
--- a/IniLineParser.cs	Thu Jan 08 20:33:56 2009 +0000
+++ b/IniLineParser.cs	Sun Jan 11 15:37:14 2009 +0000
@@ -9,39 +9,49 @@
 	public class IniLineParser
 	{		
 		/// <summary>
-		/// Gets a key-value pair of strings from a string in the INI settings format. If the line does not contain an equals then a zero-length array is returned.
-		/// If there are multiple equals signs the the key is split from the value on the first one
+		/// Parses a non-section INI line and returns an <see cref="IIniLine"/> object.
 		/// </summary>
 		/// <param name="line">
-		/// A <see cref="System.String"/>
+		/// The line to parse
 		/// </param>
 		/// <returns>
-		/// A <see cref="System.String"/>
+		/// An <see cref="IIniLine"/> containing the data of the line
 		/// </returns>
-		public static string[] GetKeyValuePair(string line)
+		public static IIniLine ParseIniLine(string line)
 		{
 			line = line.Trim();
-			int idx = line.IndexOf('=');
-			string[] keyValuePair;
-			
-			if (idx > 0)
+			IIniLine iniLine = null;
+
+			if (line == "")
 			{
-				keyValuePair = SplitAtIndex(line, idx);
+				iniLine = new IniBlankLine();
+			}
+			else if (line.StartsWith(";"))
+			{
+				iniLine = new IniCommentLine(line);
 			}
 			else
 			{
-				keyValuePair = new string[0];
+				int idx = line.IndexOf('=');
+				
+				if (idx > 0)
+				{
+					iniLine = CreateKeyValuePairLine(line, idx);
+				}
+				else
+				{
+					iniLine = new IniCommentLine(line);
+				}
 			}
 			
-			return keyValuePair;
+			return iniLine;
 		}
 		
-		private static string[] SplitAtIndex(string line, int idx)
+		private static IniKeyValuePairLine CreateKeyValuePairLine(string line, int idx)
 		{
-			string[] keyValuePair = new string[2];
-			keyValuePair[0] = line.Substring(0, idx).Trim();
-			keyValuePair[1] = line.Substring(idx+1).Trim();
-			return keyValuePair;
+			string keyString = line.Substring(0, idx).Trim();
+			string valueString = line.Substring(idx+1).Trim();
+			return new IniKeyValuePairLine(keyString, valueString);
 		}
 	}
 }
--- a/IniSection.cs	Thu Jan 08 20:33:56 2009 +0000
+++ b/IniSection.cs	Sun Jan 11 15:37:14 2009 +0000
@@ -3,20 +3,24 @@
 // The file and the library/program it is in are licensed under the GNU LGPL license. Please see COPYING.LGPL for more information and the full license.
 
 using System;
+using System.Collections;
 using System.Collections.Generic;
+using System.Text;
 
 namespace IBBoard.Ini
 {
-	public class IniSection
+	public class IniSection : IEnumerable<IIniLine>
 	{
 		private string name;
-		private Dictionary<string, string> values;
+		private Dictionary<string, IniKeyValuePairLine> values;
+		private List<IIniLine> iniSectionLines;
 		
 		public IniSection(string sectionName)
 		{			
 			CheckSectionName(sectionName);
 			name = sectionName;
-			values = new Dictionary<string,string>();
+			values = new Dictionary<string,IniKeyValuePairLine>();
+			iniSectionLines = new List<IIniLine>();
 		}
 		
 		private static void CheckSectionName(string sectionName)
@@ -58,23 +62,65 @@
 			}
 		}
 		
-		public void AddKeyValuePair(string key, string pairedValue)
+		//// <value>
+		/// Gets an <see cref=" IniKeyValuePairLine"/> by key, or <code>null</code> if the key doesn't exist
+		/// </value>
+		public IniKeyValuePairLine this[string key]
 		{
-			if (!values.ContainsKey(key))
-			{
-				values.Add(key, pairedValue);
-			}
-			else
-			{
-				throw new ArgumentException("The key '"+key+"' was already defined in ["+Name+"]");
+			get
+			{	
+				IniKeyValuePairLine keyValuePair = null;
+				values.TryGetValue(key.Trim(), out keyValuePair);				
+				return keyValuePair;
 			}
 		}
 		
-		public string GetValueForKey(string key)
+		public void AddIniLine(IIniLine iniLine)
+		{
+			if (iniLine is IniKeyValuePairLine)
+			{
+				IniKeyValuePairLine keyValuePair = (IniKeyValuePairLine)iniLine;
+				string key = keyValuePair.Key;
+				
+				if (!values.ContainsKey(key))
+				{
+					values.Add(key, keyValuePair);
+				}
+				else
+				{
+					throw new ArgumentException("The key '"+key+"' was already defined in ["+Name+"]");
+				}
+			}
+			
+			iniSectionLines.Add(iniLine);
+		}
+
+		public IEnumerator<IIniLine> GetEnumerator()
 		{
-			string pairedValue = null;
-			values.TryGetValue(key, out pairedValue);
-			return pairedValue;
+			return iniSectionLines.GetEnumerator();
 		}
+
+		IEnumerator IEnumerable.GetEnumerator()
+        {
+            return iniSectionLines.GetEnumerator();
+        }
+		
+		public override string ToString()
+		{
+			StringBuilder stringBuilder = new StringBuilder();
+			stringBuilder.Append("[");
+			stringBuilder.Append(Name);
+			stringBuilder.Append("]\n");
+
+			foreach (IIniLine iniLine in this)
+			{
+				stringBuilder.Append(iniLine.ToString());
+				stringBuilder.Append("\n");
+			}
+
+			stringBuilder.Append("\n");			
+			return stringBuilder.ToString().Trim();
+		}
+
 	}
 }
--- a/IniSectionParser.cs	Thu Jan 08 20:33:56 2009 +0000
+++ b/IniSectionParser.cs	Sun Jan 11 15:37:14 2009 +0000
@@ -47,12 +47,8 @@
 			
 			for (int i = 1; i < lineCount; i++)
 			{
-				string[] keyValuePair = IniLineParser.GetKeyValuePair(sectionLines[i]);
-			
-				if (keyValuePair.Length == 2)
-				{
-					section.AddKeyValuePair(keyValuePair[0], keyValuePair[1]);
-				}
+				IIniLine iniLine = IniLineParser.ParseIniLine(sectionLines[i]);
+				section.AddIniLine(iniLine);
 			}
 			
 			return section;