From d1c589e2c081301a69d5ae0322a33ed0083eb983 Mon Sep 17 00:00:00 2001 From: Tony Bark Date: Tue, 9 Apr 2024 09:26:59 -0400 Subject: [PATCH] Improved normalization algorithm --- CSTNet/CST.cs | 152 ++++++++++++++++++------------------------- CSTNet/CSTNet.csproj | 38 +++++------ CSTNet/UIText.cs | 8 +-- README.md | 33 ++++++---- 4 files changed, 105 insertions(+), 126 deletions(-) diff --git a/CSTNet/CST.cs b/CSTNet/CST.cs index 37da99b..36342a3 100644 --- a/CSTNet/CST.cs +++ b/CSTNet/CST.cs @@ -8,107 +8,79 @@ namespace CSTNet; public static class CST { - const char CARET = '^'; - const string LF = "\u000A"; - const string CR = "\u000D"; - const string CRLF = "\u000D\u000A"; - const string LS = "\u2028"; + const char CARET = '^'; + const string LF = "\u000A"; + const string CR = "\u000D"; + const string CRLF = "\u000D\u000A"; + const string LS = "\u2028"; - /// - /// Gets the value from the digit-based key. - /// - /// Returns the entry - public static string Parse(string content, int key) => Parse(content, key.ToString()); + /// + /// Gets the value from the digit-based key. + /// + /// Returns the entry + public static string Parse(string content, int key) => Parse(content, key.ToString()); - /// - /// Gets the value from the string-based key. - /// - /// Returns the entry - public static string Parse(string content, string key) - { - var entries = NormalizeEntries(content); - return GetEntry(entries, key); - } + /// + /// Gets the value from the string-based key. + /// + /// Returns the entry + public static string Parse(string content, string key) + { + var entries = NormalizeEntries(content); + return GetEntry(entries, key); + } #if (NET8_0 && DEBUG) - [UnmanagedCallersOnly(EntryPoint = "parse")] - public static IntPtr Parse(IntPtr content, IntPtr key) - { - // => Parse(Marshal.PtrToStringAnsi(content), Marshal.PtrToStringAnsi(key)); - var entries = NormalizeEntries(Marshal.PtrToStringAnsi(content)); - return Marshal.StringToHGlobalAnsi(GetEntry(entries, Marshal.PtrToStringAnsi(key))); - } + [UnmanagedCallersOnly(EntryPoint = "parse")] + public static IntPtr Parse(IntPtr content, IntPtr key) + { + // => Parse(Marshal.PtrToStringAnsi(content), Marshal.PtrToStringAnsi(key)); + var entries = NormalizeEntries(Marshal.PtrToStringAnsi(content)); + return Marshal.StringToHGlobalAnsi(GetEntry(entries, Marshal.PtrToStringAnsi(key))); + } #endif + /// + /// Normalizes the content by replacing various newline characters with Environment.NewLine and filters out comments. + /// + /// The content to normalize. + /// An enumerable of normalized lines. + public static IEnumerable NormalizeEntries(string content) + { + var newLines = new[] { LF, CR, CRLF, LS }; - /// - /// Replaces the document's line endings with the native system line endings. - /// - /// This stage ensures there are no crashes during parsing. - /// The content of the document. - /// The document's content with native system line endings. - static IEnumerable NormalizeEntries(string content) - { - // Check if the document already uses native system line endings. - if (!content.Contains(Environment.NewLine)) - { - // If not, check for and replace other line ending types. - if (content.Contains(LF)) - content = content.Replace(LF, - Environment.NewLine); + content = newLines.Aggregate(content, (current, nl) => current.Replace(nl, Environment.NewLine)); - if (content.Contains(CR)) - content = content.Replace(CR, - Environment.NewLine); + return content.Split($"{CARET}{Environment.NewLine}", StringSplitOptions.RemoveEmptyEntries) + .Where(line => !line.StartsWith("//") && !line.StartsWith('#') && !line.StartsWith("/*") && !line.EndsWith("*/")); + } - if (content.Contains(CRLF)) - content = content.Replace(CRLF, - Environment.NewLine); + /// + /// Retrieves the value for the specified key from the given entries. + /// + /// The entries to search through. + /// The key to search for. + /// The value for the specified key, or a default string if not found. + static string GetEntry(IEnumerable entries, string key) + { + // Iterate through the entries. + foreach (var entry in entries) + { + // If the line doesn't start with the key, keep searching. + if (!entry.StartsWith(key)) + continue; - if (content.Contains(LS)) - content = content.Replace(LS, - Environment.NewLine); - } + // Locate the index of the caret character. + var startIndex = entry.IndexOf(CARET); + // Get the line from the caret character to the end of the string. + var line = entry[startIndex..]; - // Split the content by the caret and newline characters. - var lines = content.Split(new[] { $"{CARET}{Environment.NewLine}" }, - StringSplitOptions.RemoveEmptyEntries); + // Return the line with the caret characters trimmed. + return line.TrimStart(CARET).TrimEnd(CARET); + } - // Filter out any lines that start with "//", "#", "/*", or end with "*/". - return lines.Where(line => - !line.StartsWith("//") && - !line.StartsWith("#") && - !line.StartsWith("/*") && - !line.EndsWith("*/")) - .AsEnumerable(); - } - - /// - /// Retrieves the value for the specified key from the given entries. - /// - /// The entries to search through. - /// The key to search for. - /// The value for the specified key, or a default string if not found. - static string GetEntry(IEnumerable entries, string key) - { - // Iterate through the entries. - foreach (var entry in entries) - { - // If the line doesn't start with the key, keep searching. - if (!entry.StartsWith(key)) - continue; - - // Locate the index of the caret character. - var startIndex = entry.IndexOf(CARET); - // Get the line from the caret character to the end of the string. - var line = entry[startIndex..]; - - // Return the line with the caret characters trimmed. - return line.TrimStart(CARET).TrimEnd(CARET); - } - - // If no entry is found, return a default string. - return "***MISSING***"; - } + // If no entry is found, return a default string. + return "***MISSING***"; + } } diff --git a/CSTNet/CSTNet.csproj b/CSTNet/CSTNet.csproj index a9aa843..fdb390e 100644 --- a/CSTNet/CSTNet.csproj +++ b/CSTNet/CSTNet.csproj @@ -1,25 +1,25 @@ - - net6.0;net8.0 - 2.1.100 - enable - latest - enable - Tony Bark - - Caret-Separated Text (or CST) is a key-value pair format represented by digits or words - as keys and the value as text enclosed between carets. ([key] ^[value]^) + + net6.0;net8.0 + 2.1.101-alpha + enable + latest + enable + Tony Bark + + Caret-Separated Text (or CST) is a key-value pair format represented by digits or words + as keys and the value as text enclosed between carets. ([key] ^[value]^) - CSTNet provides you the framework for parsing the CST format. - - https://github.com/tonytins/cstdotnet - BSD-3-Clause - + CSTNet provides you the framework for parsing the CST format. + + https://github.com/tonytins/cstdotnet + BSD-3-Clause + - - - true - + + + true + \ No newline at end of file diff --git a/CSTNet/UIText.cs b/CSTNet/UIText.cs index b60b16c..0d02d1a 100644 --- a/CSTNet/UIText.cs +++ b/CSTNet/UIText.cs @@ -4,10 +4,10 @@ namespace CSTNet; public class UIText : IUIText { - /// - /// The language of the text. - /// - string Language { get; set; } = "english"; + /// + /// The language of the text. + /// + string Language { get; set; } = "english"; /// /// The base directory for the language files. diff --git a/README.md b/README.md index 68f9d37..20f783e 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,10 @@ -# CST.NET +# [CST.NET](http://CST.NET) -

- GitHub license - GitHub Workflow Status - GitHub commit activity -
- Code Climate maintainability - NuGet Downloads

Contributor Covenant
-

+<p align="center"><a href="https://github.com/tonytins/cstdotnet/blob/main/LICENSE"><img src="https://img.shields.io/github/license/tonytins/cstdotnet" alt="GitHub license"></a> <a href="https://github.com/tonytins/cstdotnet/actions?query=workflow%3Abuild.yml"><img src="https://img.shields.io/github/actions/workflow/status/tonytins/cstdotnet/build.yml" alt="GitHub Workflow Status"></a> <img src="https://img.shields.io/github/commit-activity/w/tonytins/cstdotnet" alt="GitHub commit activity"> <a href="code_of_conduct.md"></br> <img src="https://img.shields.io/codeclimate/maintainability-percentage/tonytins/cstdotnet" alt="Code Climate maintainability"> <img src="https://img.shields.io/nuget/dt/CSTNet" alt="NuGet Downloads"> <a href="https://www.nuget.org/packages/tonybark.updatetools"><img src="https://img.shields.io/nuget/v/cstnet.svg" /></a></br><img src="https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg" alt="Contributor Covenant"></a></br> </p> -CST.NET is a library for parsing Maxis' key-value pair format. It can be used in conjunction with your own custom frameworks, or the original ``UIText`` APIs. +CST.NET is a library for parsing Maxis' key-value pair format. It can be used in conjunction with your own custom frameworks, or the original `UIText` APIs. -Caret-Separated Text (or CST) is a key-value pair format represented by digits or words as keys and the value as text enclosed between carets. (e.g. `` ^^``) Any text which is not enclosed with carets is considered a comment and ignored. Neither strings nor comments may use the caret character. +Caret-Separated Text (or CST) is a key-value pair format represented by digits or words as keys and the value as text enclosed between carets. (e.g. ` ^^`) Any text which is not enclosed with carets is considered a comment and ignored. Neither strings nor comments may use the caret character. ## Changelog @@ -23,7 +16,7 @@ See [/docs](./doc/README.md). ## To-do -- [ ] Support for parameters (e.g. ``%1``) +- [ ] Support for parameters (e.g. `%1`) ## Known issues @@ -38,6 +31,20 @@ See [/docs](./doc/README.md). - [.NET Interactive](https://github.com/dotnet/interactive/blob/main/README.md) for notebooks (optional). - [VSCode Extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) or [nteract](https://nteract.io/). + +# Contributing + +You can contribute to CST.NET by testing cutting edge features in the latest releases, filing bugs, and joining in the discussion on our forums! + +* [Getting Started](https://github.com/tonytins/cstdotnet/wiki) +* [Project Structure](https://github.com/tonytins/cstdotnet/wiki/Project-structure) +* [Coding Standards](https://github.com/tonytins/cstdotnet/wiki/Coding-standards) +* [Pull Requests](https://github.com/tonytins/cstdotnet/pulls): [Open](https://github.com/tonytins/cstdotnet/pulls)/[Closed](https://github.com/tonytins/cstdotnet/issues?q=is%3Apr+is%3Aclosed) + +Looking for something to do? Check out the issues tagged as [help wanted](https://github.com/tonytins/cstdotnet/labels/help%20wanted) to get started. + +Regarding translations, full object and UI translations should currently be released on the forums. This is far from perfect and is due to be reworked. Stay tuned! + ## License -I license this project under the BSD-3-Clause license - see [LICENSE](LICENSE) for details. +I license this project under the BSD-3-Clause license - see [LICENSE](LICENSE) for details. \ No newline at end of file