diff --git a/src/BizHawk.Common/Extensions/CollectionExtensions.cs b/src/BizHawk.Common/Extensions/CollectionExtensions.cs index 8e89495826..7f49167b62 100644 --- a/src/BizHawk.Common/Extensions/CollectionExtensions.cs +++ b/src/BizHawk.Common/Extensions/CollectionExtensions.cs @@ -292,6 +292,24 @@ namespace BizHawk.Common.CollectionExtensions return true; } + public static ReadOnlySpan Slice(this ReadOnlySpan span, Range range) + { + var (offset, length) = range.GetOffsetAndLength(span.Length); + return span.Slice(start: offset, length: length); + } + + public static Span Slice(this Span span, Range range) + { + var (offset, length) = range.GetOffsetAndLength(span.Length); + return span.Slice(start: offset, length: length); + } + + public static string Substring(this string str, Range range) + { + var (offset, length) = range.GetOffsetAndLength(str.Length); + return str.Substring(startIndex: offset, length: length); + } + /// shallow clone public static Dictionary ToDictionary(this IEnumerable> list) => list.ToDictionary(static kvp => kvp.Key, static kvp => kvp.Value); diff --git a/src/BizHawk.Emulation.Common/Database/Database.cs b/src/BizHawk.Emulation.Common/Database/Database.cs index 257aecea1f..bbd36e1a94 100644 --- a/src/BizHawk.Emulation.Common/Database/Database.cs +++ b/src/BizHawk.Emulation.Common/Database/Database.cs @@ -9,6 +9,7 @@ using System.Text; using System.Threading; using BizHawk.Common; +using BizHawk.Common.CollectionExtensions; using BizHawk.Common.StringExtensions; namespace BizHawk.Emulation.Common @@ -102,21 +103,15 @@ namespace BizHawk.Emulation.Common private static bool initialized = false; - public static CompactGameInfo ParseCGIRecord(string line) + public static CompactGameInfo ParseCGIRecord(string lineStr) { + var line = lineStr.AsSpan(); const char FIELD_SEPARATOR = '\t'; - var iFieldStart = -1; - var iFieldEnd = -1; // offset of the tab char, or line.Length if at end - string AdvanceAndReadField(out bool isLastField) - { - iFieldStart = iFieldEnd + 1; - iFieldEnd = line.IndexOf(FIELD_SEPARATOR, iFieldStart); - isLastField = iFieldEnd < 0; - if (isLastField) iFieldEnd = line.Length; - return line.Substring(startIndex: iFieldStart, length: iFieldEnd - iFieldStart); - } - var hashDigest = FormatHash(AdvanceAndReadField(out _)); - var dumpStatus = AdvanceAndReadField(out _).Trim() switch + var iter = line.Split(FIELD_SEPARATOR); + _ = iter.MoveNext(); + var hashDigest = FormatHash(lineStr.Substring(iter.Current)); + _ = iter.MoveNext(); + var dumpStatus = line.Slice(iter.Current).Trim() switch { "B" => RomStatus.BadDump, // see /Assets/gamedb/gamedb.txt "V" => RomStatus.BadDump, // see /Assets/gamedb/gamedb.txt @@ -128,21 +123,23 @@ namespace BizHawk.Emulation.Common "U" => RomStatus.Unknown, _ => RomStatus.GoodDump }; - var knownName = AdvanceAndReadField(out _); - var sysID = AdvanceAndReadField(out var isLastField); + _ = iter.MoveNext(); + var knownName = lineStr.Substring(iter.Current); + _ = iter.MoveNext(); + var sysID = lineStr.Substring(iter.Current); string/*?*/ metadata = null; string region = string.Empty; string forcedCore = string.Empty; - if (!isLastField) + if (iter.MoveNext()) { - _ = AdvanceAndReadField(out isLastField); // rarely present; possibly genre or just a remark - if (!isLastField) + //_ = line.Slice(iter.Current); // rarely populated; possibly genre or just a remark + if (iter.MoveNext()) { - metadata = AdvanceAndReadField(out isLastField); - if (!isLastField) + metadata = lineStr.Substring(iter.Current); + if (iter.MoveNext()) { - region = AdvanceAndReadField(out isLastField); - if (!isLastField) forcedCore = AdvanceAndReadField(out isLastField); + region = lineStr.Substring(iter.Current); + if (iter.MoveNext()) forcedCore = lineStr.Substring(iter.Current); } } }