From e1b6ff37d8a658ba7949eb540d142e0ffaafbe19 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Wed, 18 Mar 2026 14:14:01 -0400 Subject: [PATCH] INI is a text type --- README.MD | 5 +++- SabreTools.IO.sln | 14 +++++++++ SabreTools.IO/SabreTools.IO.Readers/Enums.cs | 12 -------- SabreTools.IO/SabreTools.IO/PathTool.cs | 2 +- SabreTools.IO/System.Text.INI/Enums.cs | 14 +++++++++ .../IniFile.cs | 18 +++++------- .../Reader.cs} | 22 +++++++------- .../Writer.cs} | 10 +++---- .../IniFileTests.cs | 2 +- .../ReaderWriterTests.cs | 10 +++---- .../SabreTools.Text.INI.Test.csproj | 29 +++++++++++++++++++ 11 files changed, 91 insertions(+), 47 deletions(-) create mode 100644 SabreTools.IO/System.Text.INI/Enums.cs rename SabreTools.IO/{SabreTools.IO => System.Text.INI}/IniFile.cs (94%) rename SabreTools.IO/{SabreTools.IO.Readers/IniReader.cs => System.Text.INI/Reader.cs} (89%) rename SabreTools.IO/{SabreTools.IO.Writers/IniWriter.cs => System.Text.INI/Writer.cs} (93%) rename {SabreTools.IO.Test => SabreTools.Text.INI.Test}/IniFileTests.cs (98%) rename SabreTools.IO.Test/ReadersWriters/IniTests.cs => SabreTools.Text.INI.Test/ReaderWriterTests.cs (83%) create mode 100644 SabreTools.Text.INI.Test/SabreTools.Text.INI.Test.csproj diff --git a/README.MD b/README.MD index 090ab0a..5326753 100644 --- a/README.MD +++ b/README.MD @@ -19,7 +19,6 @@ Generic helper classes that involve custom functionality and utility. | Class | Notes | | --- | --- | | `BufferedStream` | Not a true stream implementation used for buffered, single-byte reads | -| `IniFile` | Key-value pair INI file, implementing `Dictionary` | | `ParentablePath` | Class that represents a path that is rooted by a parent directory | | `PathTool` | Utility class for common Path-related functions | | `ReadOnlyBitStream` | Read-only stream implementation allowing bitwise reading | @@ -138,6 +137,10 @@ Various encryption implementations that are used across multiple projects. Most Classes focused on string comparison by natural sorting. For example, "5" would be sorted before "100". +### `SabreTools.Text.INI` + +Key-value pair INI file, implementing `Dictionary`. Includes reader and writer classes for easier access. + ## Releases For the most recent stable build, download the latest release here: [Releases Page](https://github.com/SabreTools/SabreTools.IO/releases) diff --git a/SabreTools.IO.sln b/SabreTools.IO.sln index ccaf51b..34f42f5 100644 --- a/SabreTools.IO.sln +++ b/SabreTools.IO.sln @@ -15,6 +15,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SabreTools.Matching.Test", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SabreTools.Text.Compare.Test", "SabreTools.Text.Compare.Test\SabreTools.Text.Compare.Test.csproj", "{2FEFC7F7-814D-4FDB-84CA-946137373160}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SabreTools.Text.INI.Test", "SabreTools.Text.INI.Test\SabreTools.Text.INI.Test.csproj", "{4054E2C0-AC30-44EA-916E-73DD9FB3F2D0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -97,6 +99,18 @@ Global {2FEFC7F7-814D-4FDB-84CA-946137373160}.Release|x64.Build.0 = Release|Any CPU {2FEFC7F7-814D-4FDB-84CA-946137373160}.Release|x86.ActiveCfg = Release|Any CPU {2FEFC7F7-814D-4FDB-84CA-946137373160}.Release|x86.Build.0 = Release|Any CPU + {4054E2C0-AC30-44EA-916E-73DD9FB3F2D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4054E2C0-AC30-44EA-916E-73DD9FB3F2D0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4054E2C0-AC30-44EA-916E-73DD9FB3F2D0}.Debug|x64.ActiveCfg = Debug|Any CPU + {4054E2C0-AC30-44EA-916E-73DD9FB3F2D0}.Debug|x64.Build.0 = Debug|Any CPU + {4054E2C0-AC30-44EA-916E-73DD9FB3F2D0}.Debug|x86.ActiveCfg = Debug|Any CPU + {4054E2C0-AC30-44EA-916E-73DD9FB3F2D0}.Debug|x86.Build.0 = Debug|Any CPU + {4054E2C0-AC30-44EA-916E-73DD9FB3F2D0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4054E2C0-AC30-44EA-916E-73DD9FB3F2D0}.Release|Any CPU.Build.0 = Release|Any CPU + {4054E2C0-AC30-44EA-916E-73DD9FB3F2D0}.Release|x64.ActiveCfg = Release|Any CPU + {4054E2C0-AC30-44EA-916E-73DD9FB3F2D0}.Release|x64.Build.0 = Release|Any CPU + {4054E2C0-AC30-44EA-916E-73DD9FB3F2D0}.Release|x86.ActiveCfg = Release|Any CPU + {4054E2C0-AC30-44EA-916E-73DD9FB3F2D0}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/SabreTools.IO/SabreTools.IO.Readers/Enums.cs b/SabreTools.IO/SabreTools.IO.Readers/Enums.cs index 877f09f..6a75968 100644 --- a/SabreTools.IO/SabreTools.IO.Readers/Enums.cs +++ b/SabreTools.IO/SabreTools.IO.Readers/Enums.cs @@ -12,16 +12,4 @@ Comment, EndTopLevel, } - - /// - /// Different types of INI rows being parsed - /// - public enum IniRowType - { - None, - SectionHeader, - KeyValue, - Comment, - Invalid, - } } diff --git a/SabreTools.IO/SabreTools.IO/PathTool.cs b/SabreTools.IO/SabreTools.IO/PathTool.cs index 5728bf6..2b67d6f 100644 --- a/SabreTools.IO/SabreTools.IO/PathTool.cs +++ b/SabreTools.IO/SabreTools.IO/PathTool.cs @@ -25,7 +25,7 @@ namespace SabreTools.IO public static string GetRuntimeDirectory() { #if NET20 || NET35 || NET40 || NET452 - return Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); + return System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); #else return AppContext.BaseDirectory; #endif diff --git a/SabreTools.IO/System.Text.INI/Enums.cs b/SabreTools.IO/System.Text.INI/Enums.cs new file mode 100644 index 0000000..5be73de --- /dev/null +++ b/SabreTools.IO/System.Text.INI/Enums.cs @@ -0,0 +1,14 @@ +namespace SabreTools.Text.INI +{ + /// + /// Different types of INI rows being parsed + /// + public enum RowType + { + None, + SectionHeader, + KeyValue, + Comment, + Invalid, + } +} diff --git a/SabreTools.IO/SabreTools.IO/IniFile.cs b/SabreTools.IO/System.Text.INI/IniFile.cs similarity index 94% rename from SabreTools.IO/SabreTools.IO/IniFile.cs rename to SabreTools.IO/System.Text.INI/IniFile.cs index 15ae753..23879d2 100644 --- a/SabreTools.IO/SabreTools.IO/IniFile.cs +++ b/SabreTools.IO/System.Text.INI/IniFile.cs @@ -3,10 +3,8 @@ using System.Collections; using System.Collections.Generic; using System.IO; using System.Text; -using SabreTools.IO.Readers; -using SabreTools.IO.Writers; -namespace SabreTools.IO +namespace SabreTools.Text.INI { /// /// Key-value pair INI file @@ -111,7 +109,7 @@ namespace SabreTools.IO try { - using IniWriter writer = new(stream, Encoding.UTF8); + using Writer writer = new(stream, Encoding.UTF8); // Order the keys to link sections together var orderedKeys = new string[_keyValuePairs.Keys.Count]; @@ -171,7 +169,7 @@ namespace SabreTools.IO try { // TODO: Can we use the section header in the reader? - using var reader = new IniReader(stream, Encoding.UTF8); + using var reader = new Reader(stream, Encoding.UTF8); string? section = string.Empty; while (!reader.EndOfStream) @@ -183,11 +181,11 @@ namespace SabreTools.IO // Process the row according to type switch (reader.RowType) { - case IniRowType.SectionHeader: + case RowType.SectionHeader: section = reader.Section; break; - case IniRowType.KeyValue: + case RowType.KeyValue: string? key = reader.KeyValuePair?.Key; // Section names are prepended to the key with a '.' separating @@ -198,9 +196,9 @@ namespace SabreTools.IO this[key] = reader.KeyValuePair?.Value; break; - case IniRowType.None: - case IniRowType.Comment: - case IniRowType.Invalid: + case RowType.None: + case RowType.Comment: + case RowType.Invalid: default: // No-op break; diff --git a/SabreTools.IO/SabreTools.IO.Readers/IniReader.cs b/SabreTools.IO/System.Text.INI/Reader.cs similarity index 89% rename from SabreTools.IO/SabreTools.IO.Readers/IniReader.cs rename to SabreTools.IO/System.Text.INI/Reader.cs index 1df026e..7cfb8fc 100644 --- a/SabreTools.IO/SabreTools.IO.Readers/IniReader.cs +++ b/SabreTools.IO/System.Text.INI/Reader.cs @@ -3,9 +3,9 @@ using System.Collections.Generic; using System.IO; using System.Text; -namespace SabreTools.IO.Readers +namespace SabreTools.Text.INI { - public class IniReader : IDisposable + public class Reader : IDisposable { #region Fields @@ -32,7 +32,7 @@ namespace SabreTools.IO.Readers /// /// Current row type /// - public IniRowType RowType { get; private set; } = IniRowType.None; + public RowType RowType { get; private set; } = RowType.None; /// /// Current section being read @@ -60,7 +60,7 @@ namespace SabreTools.IO.Readers /// /// Constructor for reading from a file /// - public IniReader(string filename) + public Reader(string filename) { _reader = new StreamReader(filename); } @@ -68,7 +68,7 @@ namespace SabreTools.IO.Readers /// /// Constructor for reading from a stream /// - public IniReader(Stream stream, Encoding encoding) + public Reader(Stream stream, Encoding encoding) { _reader = new StreamReader(stream, encoding); } @@ -76,7 +76,7 @@ namespace SabreTools.IO.Readers /// /// Constructor for reading from a stream reader /// - public IniReader(StreamReader streamReader) + public Reader(StreamReader streamReader) { _reader = streamReader; } @@ -116,14 +116,14 @@ namespace SabreTools.IO.Readers if (CurrentLine.StartsWith(";")) { KeyValuePair = null; - RowType = IniRowType.Comment; + RowType = RowType.Comment; } // Section else if (CurrentLine.StartsWith("[") && CurrentLine.EndsWith("]")) { KeyValuePair = null; - RowType = IniRowType.SectionHeader; + RowType = RowType.SectionHeader; Section = CurrentLine.TrimStart('[').TrimEnd(']'); } @@ -140,7 +140,7 @@ namespace SabreTools.IO.Readers string value = string.Join("=", valueArr).Trim(); KeyValuePair = new KeyValuePair(key, value); - RowType = IniRowType.KeyValue; + RowType = RowType.KeyValue; } // Empty @@ -148,14 +148,14 @@ namespace SabreTools.IO.Readers { KeyValuePair = null; CurrentLine = string.Empty; - RowType = IniRowType.None; + RowType = RowType.None; } // Invalid else { KeyValuePair = null; - RowType = IniRowType.Invalid; + RowType = RowType.Invalid; if (ValidateRows) throw new InvalidDataException($"Invalid INI row found, cannot continue: {CurrentLine}"); diff --git a/SabreTools.IO/SabreTools.IO.Writers/IniWriter.cs b/SabreTools.IO/System.Text.INI/Writer.cs similarity index 93% rename from SabreTools.IO/SabreTools.IO.Writers/IniWriter.cs rename to SabreTools.IO/System.Text.INI/Writer.cs index b6b6fc5..6dc4294 100644 --- a/SabreTools.IO/SabreTools.IO.Writers/IniWriter.cs +++ b/SabreTools.IO/System.Text.INI/Writer.cs @@ -2,9 +2,9 @@ using System.IO; using System.Text; -namespace SabreTools.IO.Writers +namespace SabreTools.Text.INI { - public class IniWriter : IDisposable + public class Writer : IDisposable { #region Private Properties @@ -20,7 +20,7 @@ namespace SabreTools.IO.Writers /// /// Constructor for writing to a file /// - public IniWriter(string filename) + public Writer(string filename) { _writer = new StreamWriter(filename); } @@ -28,7 +28,7 @@ namespace SabreTools.IO.Writers /// /// Consturctor for writing to a stream /// - public IniWriter(Stream stream, Encoding encoding) + public Writer(Stream stream, Encoding encoding) { #if NET20 || NET35 || NET40 _writer = new StreamWriter(stream, encoding); @@ -40,7 +40,7 @@ namespace SabreTools.IO.Writers /// /// Constructor for writing to a stream writer /// - public IniWriter(StreamWriter streamWriter) + public Writer(StreamWriter streamWriter) { _writer = streamWriter; } diff --git a/SabreTools.IO.Test/IniFileTests.cs b/SabreTools.Text.INI.Test/IniFileTests.cs similarity index 98% rename from SabreTools.IO.Test/IniFileTests.cs rename to SabreTools.Text.INI.Test/IniFileTests.cs index e1441a1..7397440 100644 --- a/SabreTools.IO.Test/IniFileTests.cs +++ b/SabreTools.Text.INI.Test/IniFileTests.cs @@ -2,7 +2,7 @@ using System.IO; using System.Text; using Xunit; -namespace SabreTools.IO.Test +namespace SabreTools.Text.INI.Test { public class IniFileTests { diff --git a/SabreTools.IO.Test/ReadersWriters/IniTests.cs b/SabreTools.Text.INI.Test/ReaderWriterTests.cs similarity index 83% rename from SabreTools.IO.Test/ReadersWriters/IniTests.cs rename to SabreTools.Text.INI.Test/ReaderWriterTests.cs index ee9184b..fb91f46 100644 --- a/SabreTools.IO.Test/ReadersWriters/IniTests.cs +++ b/SabreTools.Text.INI.Test/ReaderWriterTests.cs @@ -1,12 +1,10 @@ using System.IO; using System.Text; -using SabreTools.IO.Readers; -using SabreTools.IO.Writers; using Xunit; -namespace SabreTools.IO.Test.ReadersWriters +namespace SabreTools.Text.INI.Test { - public class IniTests + public class ReaderWriterTests { [Fact] public void EndToEndTest() @@ -15,7 +13,7 @@ namespace SabreTools.IO.Test.ReadersWriters // Build and write the INI var stream = new MemoryStream(); - var writer = new IniWriter(stream, Encoding.UTF8); + var writer = new Writer(stream, Encoding.UTF8); writer.WriteSection("section1"); writer.WriteKeyValuePair("key1", "value1"); @@ -34,7 +32,7 @@ namespace SabreTools.IO.Test.ReadersWriters // Parse the INI stream.Seek(0, SeekOrigin.Begin); - var reader = new IniReader(stream, Encoding.UTF8); + var reader = new Reader(stream, Encoding.UTF8); while (!reader.EndOfStream) { diff --git a/SabreTools.Text.INI.Test/SabreTools.Text.INI.Test.csproj b/SabreTools.Text.INI.Test/SabreTools.Text.INI.Test.csproj new file mode 100644 index 0000000..45347d9 --- /dev/null +++ b/SabreTools.Text.INI.Test/SabreTools.Text.INI.Test.csproj @@ -0,0 +1,29 @@ + + + + net8.0;net9.0;net10.0 + false + latest + enable + true + CS0618 + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + \ No newline at end of file