1- using System . Linq ;
21using System . Text ;
32
43namespace ValveKeyValue . Deserialization . KeyValues1
@@ -20,6 +19,7 @@ public KV1TokenReader(TextReader textReader, KVSerializerOptions options) : base
2019 this . options = options ;
2120 }
2221
22+ readonly StringBuilder sb = new ( ) ;
2323 readonly KVSerializerOptions options ;
2424
2525 public KVToken ReadNextToken ( )
@@ -69,8 +69,6 @@ KVToken ReadComment()
6969 {
7070 ReadChar ( CommentBegin ) ;
7171
72- var sb = new StringBuilder ( ) ;
73-
7472 // Some keyvalues implementations have a bug where only a single slash is needed for a comment
7573 // If the file ends with a single slash then we have an empty comment, bail out
7674 if ( ! TryGetNext ( out var next ) )
@@ -102,14 +100,15 @@ KVToken ReadComment()
102100 }
103101
104102 var text = sb . ToString ( ) ;
103+ sb . Clear ( ) ;
105104
106105 return new KVToken ( KVTokenType . Comment , text ) ;
107106 }
108107
109108 KVToken ReadCondition ( )
110109 {
111110 ReadChar ( ConditionBegin ) ;
112- var text = ReadUntil ( ConditionEnd ) ;
111+ var text = ReadUntil ( static ( c ) => c == ConditionEnd ) ;
113112 ReadChar ( ConditionEnd ) ;
114113
115114 return new KVToken ( KVTokenType . Condition , text ) ;
@@ -118,7 +117,7 @@ KVToken ReadCondition()
118117 KVToken ReadInclusion ( )
119118 {
120119 ReadChar ( InclusionMark ) ;
121- var term = ReadUntil ( new [ ] { ' ' , '\t ' } ) ;
120+ var term = ReadUntil ( static c => c is ' ' or '\t ' ) ;
122121 var value = ReadStringRaw ( ) ;
123122
124123 if ( string . Equals ( term , "include" , StringComparison . Ordinal ) )
@@ -133,13 +132,11 @@ KVToken ReadInclusion()
133132 throw new InvalidDataException ( $ "Unrecognized term after '#' symbol (line { Line } , column { Column } )") ;
134133 }
135134
136- string ReadUntil ( params char [ ] terminators )
135+ string ReadUntil ( Func < int , bool > isTerminator )
137136 {
138- var sb = new StringBuilder ( ) ;
139137 var escapeNext = false ;
140138
141- var integerTerminators = new HashSet < int > ( terminators . Select ( t => ( int ) t ) ) ;
142- while ( ! integerTerminators . Contains ( Peek ( ) ) || escapeNext )
139+ while ( escapeNext || ! isTerminator ( Peek ( ) ) )
143140 {
144141 var next = Next ( ) ;
145142
@@ -178,6 +175,7 @@ string ReadUntil(params char[] terminators)
178175 }
179176
180177 var result = sb . ToString ( ) ;
178+ sb . Clear ( ) ;
181179
182180 // Valve bug-for-bug compatibility with tier1 KeyValues/CUtlBuffer: an invalid escape sequence is a null byte which
183181 // causes the text to be trimmed to the point of that null byte.
@@ -190,8 +188,6 @@ string ReadUntil(params char[] terminators)
190188
191189 string ReadUntilWhitespaceOrQuote ( )
192190 {
193- var sb = new StringBuilder ( ) ;
194-
195191 while ( true )
196192 {
197193 var next = Peek ( ) ;
@@ -203,7 +199,10 @@ string ReadUntilWhitespaceOrQuote()
203199 sb . Append ( Next ( ) ) ;
204200 }
205201
206- return sb . ToString ( ) ;
202+ var result = sb . ToString ( ) ;
203+ sb . Clear ( ) ;
204+
205+ return result ;
207206 }
208207
209208 string ReadStringRaw ( )
@@ -222,7 +221,7 @@ string ReadStringRaw()
222221 string ReadQuotedStringRaw ( )
223222 {
224223 ReadChar ( QuotationMark ) ;
225- var text = ReadUntil ( QuotationMark ) ;
224+ var text = ReadUntil ( static ( c ) => c == QuotationMark ) ;
226225 ReadChar ( QuotationMark ) ;
227226 return text ;
228227 }
0 commit comments