From 16b9d577424b2e3fe823f197b40f2a15ed0ffed3 Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Mon, 16 Sep 2024 17:01:38 +0300 Subject: [PATCH 1/2] Reuse StringBuilder in token reader --- .../Deserialization/KeyValues1/KV1TokenReader.cs | 13 +++++++------ ValveKeyValue/ValveKeyValue/KVObject.cs | 13 +------------ 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/ValveKeyValue/ValveKeyValue/Deserialization/KeyValues1/KV1TokenReader.cs b/ValveKeyValue/ValveKeyValue/Deserialization/KeyValues1/KV1TokenReader.cs index 7fae6f52..f90d863c 100644 --- a/ValveKeyValue/ValveKeyValue/Deserialization/KeyValues1/KV1TokenReader.cs +++ b/ValveKeyValue/ValveKeyValue/Deserialization/KeyValues1/KV1TokenReader.cs @@ -20,6 +20,7 @@ public KV1TokenReader(TextReader textReader, KVSerializerOptions options) : base this.options = options; } + readonly StringBuilder sb = new(); readonly KVSerializerOptions options; public KVToken ReadNextToken() @@ -69,8 +70,6 @@ KVToken ReadComment() { ReadChar(CommentBegin); - var sb = new StringBuilder(); - // Some keyvalues implementations have a bug where only a single slash is needed for a comment // If the file ends with a single slash then we have an empty comment, bail out if (!TryGetNext(out var next)) @@ -102,6 +101,7 @@ KVToken ReadComment() } var text = sb.ToString(); + sb.Clear(); return new KVToken(KVTokenType.Comment, text); } @@ -135,7 +135,6 @@ KVToken ReadInclusion() string ReadUntil(params char[] terminators) { - var sb = new StringBuilder(); var escapeNext = false; var integerTerminators = new HashSet(terminators.Select(t => (int)t)); @@ -178,6 +177,7 @@ string ReadUntil(params char[] terminators) } var result = sb.ToString(); + sb.Clear(); // Valve bug-for-bug compatibility with tier1 KeyValues/CUtlBuffer: an invalid escape sequence is a null byte which // causes the text to be trimmed to the point of that null byte. @@ -190,8 +190,6 @@ string ReadUntil(params char[] terminators) string ReadUntilWhitespaceOrQuote() { - var sb = new StringBuilder(); - while (true) { var next = Peek(); @@ -203,7 +201,10 @@ string ReadUntilWhitespaceOrQuote() sb.Append(Next()); } - return sb.ToString(); + var result = sb.ToString(); + sb.Clear(); + + return result; } string ReadStringRaw() diff --git a/ValveKeyValue/ValveKeyValue/KVObject.cs b/ValveKeyValue/ValveKeyValue/KVObject.cs index c7e26eb9..1e907cba 100644 --- a/ValveKeyValue/ValveKeyValue/KVObject.cs +++ b/ValveKeyValue/ValveKeyValue/KVObject.cs @@ -100,17 +100,6 @@ KVCollectionValue GetCollectionValue() return collection; } - string DebuggerDescription - { - get - { - var description = new StringBuilder(); - description.Append(Name); - description.Append(": "); - description.Append(Value.ToString()); - - return description.ToString(); - } - } + string DebuggerDescription => $"{Name}: {Value}"; } } From 0f99eae126e73eb02b9b4d4abfbfff59e62fff7f Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Mon, 16 Sep 2024 17:07:39 +0300 Subject: [PATCH 2/2] Remove hashset allocation in token read --- .../Deserialization/KeyValues1/KV1TokenReader.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/ValveKeyValue/ValveKeyValue/Deserialization/KeyValues1/KV1TokenReader.cs b/ValveKeyValue/ValveKeyValue/Deserialization/KeyValues1/KV1TokenReader.cs index f90d863c..6897b7ac 100644 --- a/ValveKeyValue/ValveKeyValue/Deserialization/KeyValues1/KV1TokenReader.cs +++ b/ValveKeyValue/ValveKeyValue/Deserialization/KeyValues1/KV1TokenReader.cs @@ -1,4 +1,3 @@ -using System.Linq; using System.Text; namespace ValveKeyValue.Deserialization.KeyValues1 @@ -109,7 +108,7 @@ KVToken ReadComment() KVToken ReadCondition() { ReadChar(ConditionBegin); - var text = ReadUntil(ConditionEnd); + var text = ReadUntil(static (c) => c == ConditionEnd); ReadChar(ConditionEnd); return new KVToken(KVTokenType.Condition, text); @@ -118,7 +117,7 @@ KVToken ReadCondition() KVToken ReadInclusion() { ReadChar(InclusionMark); - var term = ReadUntil(new[] { ' ', '\t' }); + var term = ReadUntil(static c => c is ' ' or '\t'); var value = ReadStringRaw(); if (string.Equals(term, "include", StringComparison.Ordinal)) @@ -133,12 +132,11 @@ KVToken ReadInclusion() throw new InvalidDataException($"Unrecognized term after '#' symbol (line {Line}, column {Column})"); } - string ReadUntil(params char[] terminators) + string ReadUntil(Func isTerminator) { var escapeNext = false; - var integerTerminators = new HashSet(terminators.Select(t => (int)t)); - while (!integerTerminators.Contains(Peek()) || escapeNext) + while (escapeNext || !isTerminator(Peek())) { var next = Next(); @@ -223,7 +221,7 @@ string ReadStringRaw() string ReadQuotedStringRaw() { ReadChar(QuotationMark); - var text = ReadUntil(QuotationMark); + var text = ReadUntil(static (c) => c == QuotationMark); ReadChar(QuotationMark); return text; }