diff --git a/src/BizHawk.Common/Extensions/StringExtensions.cs b/src/BizHawk.Common/Extensions/StringExtensions.cs index 400ec5dc8e..2d81f34716 100644 --- a/src/BizHawk.Common/Extensions/StringExtensions.cs +++ b/src/BizHawk.Common/Extensions/StringExtensions.cs @@ -183,6 +183,27 @@ public static byte[] ToCharCodepointArray(this string str) return a; } + /// as , but assumes is 7-bit ASCII to allow for an optimisation + /// allocates a new char array only when necessary + public static string ToUpperASCIIFast(this string str) + { + const ushort ASCII_UPCASE_MASK = 0b101111; + for (var i = 0; i < str.Length; i++) + { + if (str[i] is < 'a' or > 'z') continue; + var a = new char[str.Length]; + str.AsSpan(start: 0, length: i).CopyTo(a); + a[i] = unchecked((char) (str[i] & ASCII_UPCASE_MASK)); + while (++i < str.Length) + { + var c = str[i]; + a[i] = c is >= 'a' and <= 'z' ? unchecked((char) (c & ASCII_UPCASE_MASK)) : c; + } + return new(a); + } + return str; + } + /// /// splits a given by , /// applies to each part, then rejoins them diff --git a/src/BizHawk.Emulation.Common/Database/Database.cs b/src/BizHawk.Emulation.Common/Database/Database.cs index 4cf2de773a..4675338e9b 100644 --- a/src/BizHawk.Emulation.Common/Database/Database.cs +++ b/src/BizHawk.Emulation.Common/Database/Database.cs @@ -36,7 +36,10 @@ public static class Database /// The hash to format, this is typically prefixed with a type (e.g. sha1:) /// formatted hash private static string FormatHash(string hash) - => hash.Substring(hash.IndexOf(':') + 1).ToUpperInvariant(); + { + var i = hash.IndexOf(':'); + return (i < 0 ? hash.Substring(startIndex: i + 1) : hash).ToUpperASCIIFast(); + } private static void LoadDatabase_Escape(string line, bool inUser, bool silent) {