From 8f011387a05587aa1578fbe132cc585122221b30 Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Sun, 11 Oct 2020 01:26:43 -0700 Subject: [PATCH] Improve key parser performance a bit --- src/LibHac/Common/Keys/ExternalKeyReader.cs | 26 ++++++++++++++++----- src/LibHac/Util/StringUtils.cs | 3 +-- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/LibHac/Common/Keys/ExternalKeyReader.cs b/src/LibHac/Common/Keys/ExternalKeyReader.cs index de44f7a8..8c530728 100644 --- a/src/LibHac/Common/Keys/ExternalKeyReader.cs +++ b/src/LibHac/Common/Keys/ExternalKeyReader.cs @@ -177,6 +177,8 @@ namespace LibHac.Common.Keys Span buffer = stackalloc char[1024]; var ctx = new KvPairReaderContext(streamReader, buffer); + // Estimate the number of keys by assuming each line is about 69 bytes. + // Subtract 2 from that so we estimate slightly high. keySet.ExternalKeySet.EnsureCapacity((int)reader.Length / 67); while (true) @@ -310,11 +312,18 @@ namespace LibHac.Common.Keys continue; case ReaderState.Initial when IsValidNameChar(c): state = ReaderState.Key; - ToLower(ref buffer[i]); keyOffset = i; - continue; - case ReaderState.Key when IsValidNameChar(c): - ToLower(ref buffer[i]); + + // Skip the next few rounds through the state machine since we know we should be + // encountering a string of name characters + do + { + ToLower(ref buffer[i]); + i++; + } while (i < buffer.Length && IsValidNameChar(buffer[i])); + + // Decrement so we can process this character the next round through the state machine + i--; continue; case ReaderState.Key when IsWhiteSpace(c): state = ReaderState.WhiteSpace1; @@ -334,6 +343,13 @@ namespace LibHac.Common.Keys case ReaderState.Delimiter when StringUtils.IsHexDigit((byte)c): state = ReaderState.Value; valueOffset = i; + + do + { + i++; + } while (i < buffer.Length && !IsEndOfLine(buffer[i]) && !IsWhiteSpace(buffer[i])); + + i--; continue; case ReaderState.Value when IsEndOfLine(c): state = ReaderState.End; @@ -343,8 +359,6 @@ namespace LibHac.Common.Keys state = ReaderState.WhiteSpace2; valueLength = i - valueOffset; continue; - case ReaderState.Value when StringUtils.IsHexDigit((byte)c): - continue; case ReaderState.WhiteSpace2 when IsWhiteSpace(c): continue; case ReaderState.WhiteSpace2 when IsEndOfLine(c): diff --git a/src/LibHac/Util/StringUtils.cs b/src/LibHac/Util/StringUtils.cs index b20e2b62..aea3333d 100644 --- a/src/LibHac/Util/StringUtils.cs +++ b/src/LibHac/Util/StringUtils.cs @@ -194,8 +194,7 @@ namespace LibHac.Util public static bool IsHexDigit(byte c) { - return (uint)(c - (byte)'0') <= 9 || - (c | 0x20u) - (byte)'a' <= 'f' - 'a'; + return HexConverter.CharToHexLookup[c] != 0xFF; } public static bool TryFromHexString(ReadOnlySpan chars, Span outputBytes)