@@ -16,7 +16,7 @@ internal class GameStringParser
1616
1717 private readonly string _description ;
1818 private readonly StormLocale _gameStringLocale ;
19- private readonly List < TextRange > _textStack = [ ] ;
19+ private readonly List < TextRange > _textStack ;
2020
2121 private readonly HashSet < string > ? _styleTagVariables ;
2222 private readonly HashSet < string > ? _styleConstantTagVariables ;
@@ -29,14 +29,16 @@ internal class GameStringParser
2929 private Dictionary < string , ( string Value , bool Preserve ) > . AlternateLookup < ReadOnlySpan < char > > ? _valueByStyleConstantVarAltLookup ;
3030#endif
3131
32- private bool _isContructed = false ;
32+ private bool _isConstructed = false ;
3333 private int _startingIndex = 0 ;
3434 private int _index = 0 ;
3535
3636 private CultureInfo ? _culture ;
3737
3838 private GameStringParser ( string description , StormLocale gameStringLocale , bool extractFontVars )
3939 {
40+ _textStack = new List < TextRange > ( description . Length / 10 ) ;
41+
4042 _description = description ;
4143 _gameStringLocale = gameStringLocale ;
4244
@@ -198,7 +200,7 @@ private static bool IsDigits(ReadOnlySpan<char> value)
198200
199201 for ( int i = 0 ; i < value . Length ; i ++ )
200202 {
201- if ( char . IsDigit ( value [ i ] ) )
203+ if ( ( uint ) ( value [ i ] - '0' ) <= 9 )
202204 continue ;
203205 else if ( dot is false && value [ i ] == '.' )
204206 dot = true ;
@@ -244,10 +246,10 @@ private static void CopyEndTag(Span<char> buffer, ref int offset, ReadOnlySpan<c
244246
245247 private string Parse ( ReadOnlySpan < char > gameString )
246248 {
247- if ( ! _isContructed )
249+ if ( ! _isConstructed )
248250 {
249251 ConstructTextStack ( gameString ) ;
250- _isContructed = true ;
252+ _isConstructed = true ;
251253 }
252254
253255 return BuildDescription ( gameString , new GameStringFlags ( )
@@ -262,10 +264,10 @@ private string Parse(ReadOnlySpan<char> gameString)
262264
263265 private string ParseToPlainText ( ReadOnlySpan < char > gameString , bool includeNewlineTags , bool includeScaling )
264266 {
265- if ( ! _isContructed )
267+ if ( ! _isConstructed )
266268 {
267269 ConstructTextStack ( gameString ) ;
268- _isContructed = true ;
270+ _isConstructed = true ;
269271 }
270272
271273 return BuildDescription ( gameString , new GameStringFlags ( )
@@ -280,10 +282,10 @@ private string ParseToPlainText(ReadOnlySpan<char> gameString, bool includeNewli
280282
281283 private string ParseToColoredText ( ReadOnlySpan < char > gameString , bool includeScaling )
282284 {
283- if ( ! _isContructed )
285+ if ( ! _isConstructed )
284286 {
285287 ConstructTextStack ( gameString ) ;
286- _isContructed = true ;
288+ _isConstructed = true ;
287289 }
288290
289291 return BuildDescription ( gameString , new GameStringFlags ( )
@@ -305,7 +307,7 @@ private string BuildDescription(ReadOnlySpan<char> gameString, GameStringFlags f
305307
306308 Span < char > buffer = totalSize < 1024 ? stackalloc char [ totalSize ] : new char [ totalSize ] ;
307309
308- ReadOnlySpan < char > startTag = null ;
310+ ReadOnlySpan < char > startTag = [ ] ;
309311 int currentOffset = 0 ;
310312
311313 // loop through and build string
@@ -346,7 +348,7 @@ private string BuildDescription(ReadOnlySpan<char> gameString, GameStringFlags f
346348 else
347349 {
348350 // dont save, empty tag
349- startTag = null ;
351+ startTag = [ ] ;
350352 }
351353 }
352354
@@ -358,7 +360,7 @@ private string BuildDescription(ReadOnlySpan<char> gameString, GameStringFlags f
358360 if ( ! FontValueCopiedInBuffer ( buffer , startTag , ref currentOffset ) )
359361 CopyIntoBuffer ( buffer , ref currentOffset , startTag , true ) ;
360362
361- startTag = null ;
363+ startTag = [ ] ;
362364 }
363365
364366 if ( flags . ScalingTag == TagFlag . Eval && double . TryParse ( itemText . Trim ( '~' ) , CultureInfo . InvariantCulture , out double scaleValue ) )
@@ -385,7 +387,7 @@ private string BuildDescription(ReadOnlySpan<char> gameString, GameStringFlags f
385387 if ( ! FontValueCopiedInBuffer ( buffer , startTag , ref currentOffset ) )
386388 CopyIntoBuffer ( buffer , ref currentOffset , startTag , true ) ;
387389
388- startTag = null ;
390+ startTag = [ ] ;
389391 CopyIntoBuffer ( buffer , ref currentOffset , itemText , false ) ;
390392 }
391393 else if ( item . Type == TextType . ErrorTag )
@@ -402,7 +404,7 @@ private string BuildDescription(ReadOnlySpan<char> gameString, GameStringFlags f
402404 }
403405 }
404406
405- // remove any null chars at the end
407+ // slice, so no null chars the end
406408 return buffer [ ..currentOffset ] . ToString ( ) ;
407409 }
408410
@@ -579,35 +581,18 @@ private void ConstructTextStack(ReadOnlySpan<char> gameString, Range? startTag =
579581 }
580582 }
581583
584+ private void PushNormalText (
582585#if DEBUG
583- private void PushNormalText ( ReadOnlySpan < char > gameString , bool append = false )
586+ ReadOnlySpan < char > gameString ,
587+ #endif
588+ bool append = false )
584589 {
585590 int normalTextLength = _index - _startingIndex ;
586591 if ( normalTextLength > 0 )
587592 {
593+ #if DEBUG
588594 ReadOnlySpan < char > temp = gameString . Slice ( _startingIndex , normalTextLength ) ;
589-
590- if ( append is false )
591- {
592- _textStack . Add ( new TextRange ( new Range ( _startingIndex , _index ) , TextType . Text ) ) ;
593- }
594- else
595- {
596- int lastIndex = _textStack . Count - 1 ;
597-
598- Range existing = _textStack [ lastIndex ] . Range ;
599-
600- _textStack . RemoveAt ( lastIndex ) ;
601- _textStack . Add ( new TextRange ( new Range ( existing . Start , _index ) , TextType . Text ) ) ;
602- }
603- }
604- }
605- #else
606- private void PushNormalText ( bool append = false )
607- {
608- int normalTextLength = _index - _startingIndex ;
609- if ( normalTextLength > 0 )
610- {
595+ #endif
611596 if ( append is false )
612597 {
613598 _textStack . Add ( new TextRange ( new Range ( _startingIndex , _index ) , TextType . Text ) ) ;
@@ -618,12 +603,10 @@ private void PushNormalText(bool append = false)
618603
619604 Range existing = _textStack [ lastIndex ] . Range ;
620605
621- _textStack . RemoveAt ( lastIndex ) ;
622- _textStack . Add ( new TextRange ( new Range ( existing . Start , _index ) , TextType . Text ) ) ;
606+ _textStack [ lastIndex ] = new TextRange ( new Range ( existing . Start , _index ) , TextType . Text ) ;
623607 }
624608 }
625609 }
626- #endif
627610
628611 // try to parse out a tag
629612 private bool TryParseTag ( ReadOnlySpan < char > gameString , [ NotNullWhen ( true ) ] out Range ? tag , out bool isStartTag )
@@ -684,18 +667,9 @@ private bool TryParseScalingTag(ReadOnlySpan<char> gameString, [NotNullWhen(true
684667 int lengthOffset = gameString . Length - currentTextSpan . Length ;
685668
686669 int startScaleIndex = currentTextSpan . IndexOf ( "~~" ) + 1 ; // the second char of the ~~ (first batch)
687- int endScaleIndex = - 1 ; // first char of the ~~ (second batch)
688-
689- for ( int i = startScaleIndex ; i < currentTextSpan . Length ; i ++ )
690- {
691- // find next occurrence of ~~
692- if ( currentTextSpan [ i ] == '~' && i + 1 < currentTextSpan . Length && currentTextSpan [ i + 1 ] == '~' )
693- {
694- endScaleIndex = i ;
695-
696- break ;
697- }
698- }
670+ int endScaleIndex = currentTextSpan [ ( startScaleIndex + 1 ) ..] . IndexOf ( "~~" ) ; // first char of the ~~ (second batch)
671+ if ( endScaleIndex >= 0 )
672+ endScaleIndex += startScaleIndex + 1 ;
699673
700674 if ( startScaleIndex > 0 && endScaleIndex > 0 )
701675 {
@@ -752,8 +726,17 @@ private bool TryGetEndTag(ReadOnlySpan<char> gameString, Range startTag, [NotNul
752726
753727 for ( int i = 0 ; i <= currentTextSpan . Length - searchLength ; i ++ )
754728 {
755- if ( currentTextSpan [ i ] == '<' &&
756- currentTextSpan [ i + 1 ] == '/' &&
729+ int next = currentTextSpan [ i ..] . IndexOf ( '<' ) ;
730+
731+ if ( next < 0 )
732+ break ;
733+
734+ i += next ;
735+
736+ if ( i > currentTextSpan . Length - searchLength )
737+ break ;
738+
739+ if ( currentTextSpan [ i + 1 ] == '/' &&
757740 currentTextSpan [ i + searchLength - 1 ] == '>' &&
758741 currentTextSpan . Slice ( i + 2 , tagTypeSpan . Length ) . Equals ( tagTypeSpan , StringComparison . OrdinalIgnoreCase ) )
759742 {
@@ -1020,7 +1003,7 @@ private void GetScalingLocaleText(Span<char> buffer, ref int offset, double valu
10201003 StormLocale . ZHCN => " (每级+0.##%)" ,
10211004 StormLocale . ZHTW => " (每級+0.##%)" ,
10221005
1023- _ => $ " { value . ToString ( " (+0.##% per level)" , _culture ) } ",
1006+ _ => " (+0.##% per level)",
10241007 } ;
10251008
10261009 value. TryFormat ( buffer [ offset ..] , out int charsWritten , format , _culture ) ;
0 commit comments