11// Licensed to the .NET Foundation under one or more agreements.
22// The .NET Foundation licenses this file to you under the MIT license.
33
4- using System . Diagnostics ;
54using System . Globalization ;
65using Microsoft . AspNetCore . Components . Rendering ;
76
@@ -121,7 +120,9 @@ protected virtual bool ShouldMatch(string currentUriAbsolute)
121120 return false ;
122121 }
123122
124- if ( EqualsHrefExactlyOrIfTrailingSlashAdded ( currentUriAbsolute ) )
123+ var currentUriAbsoluteSpan = currentUriAbsolute . AsSpan ( ) ;
124+ var hrefAbsoluteSpan = _hrefAbsolute . AsSpan ( ) ;
125+ if ( EqualsHrefExactlyOrIfTrailingSlashAdded ( currentUriAbsoluteSpan , hrefAbsoluteSpan ) )
125126 {
126127 return true ;
127128 }
@@ -137,20 +138,20 @@ protected virtual bool ShouldMatch(string currentUriAbsolute)
137138 return false ;
138139 }
139140
140- string uriWithoutQueryAndFragment = GetUriIgnoreQueryAndFragment ( currentUriAbsolute ) ;
141- if ( EqualsHrefExactlyOrIfTrailingSlashAdded ( uriWithoutQueryAndFragment ) )
141+ var uriWithoutQueryAndFragment = GetUriIgnoreQueryAndFragment ( currentUriAbsoluteSpan ) ;
142+ if ( EqualsHrefExactlyOrIfTrailingSlashAdded ( uriWithoutQueryAndFragment , hrefAbsoluteSpan ) )
142143 {
143144 return true ;
144145 }
145- _hrefAbsolute = GetUriIgnoreQueryAndFragment ( _hrefAbsolute ) ;
146- return EqualsHrefExactlyOrIfTrailingSlashAdded ( uriWithoutQueryAndFragment ) ;
146+ hrefAbsoluteSpan = GetUriIgnoreQueryAndFragment ( hrefAbsoluteSpan ) ;
147+ return EqualsHrefExactlyOrIfTrailingSlashAdded ( uriWithoutQueryAndFragment , hrefAbsoluteSpan ) ;
147148 }
148149
149- private static string GetUriIgnoreQueryAndFragment ( string uri )
150+ private static ReadOnlySpan < char > GetUriIgnoreQueryAndFragment ( ReadOnlySpan < char > uri )
150151 {
151- if ( string . IsNullOrEmpty ( uri ) )
152+ if ( uri . IsEmpty )
152153 {
153- return string . Empty ;
154+ return ReadOnlySpan < char > . Empty ;
154155 }
155156
156157 var queryStartPos = uri . IndexOf ( '?' ) ;
@@ -174,18 +175,20 @@ private static string GetUriIgnoreQueryAndFragment(string uri)
174175 {
175176 minPos = Math . Min ( queryStartPos , fragmentStartPos ) ;
176177 }
177- return uri . AsMemory ( 0 ..minPos ) . ToString ( ) ;
178+
179+ return uri . Slice ( 0 , minPos ) ;
178180 }
179- private bool EqualsHrefExactlyOrIfTrailingSlashAdded ( string currentUriAbsolute )
180- {
181- Debug . Assert ( _hrefAbsolute != null ) ;
182181
183- if ( string . Equals ( currentUriAbsolute , _hrefAbsolute , StringComparison . OrdinalIgnoreCase ) )
182+ private static readonly CaseInsensitiveCharComparer CaseInsensitiveComparer = new CaseInsensitiveCharComparer ( ) ;
183+
184+ private static bool EqualsHrefExactlyOrIfTrailingSlashAdded ( ReadOnlySpan < char > currentUriAbsolute , ReadOnlySpan < char > hrefAbsolute )
185+ {
186+ if ( currentUriAbsolute . SequenceEqual ( hrefAbsolute , CaseInsensitiveComparer ) )
184187 {
185188 return true ;
186189 }
187190
188- if ( currentUriAbsolute . Length == _hrefAbsolute . Length - 1 )
191+ if ( currentUriAbsolute . Length == hrefAbsolute . Length - 1 )
189192 {
190193 // Special case: highlight links to http://host/path/ even if you're
191194 // at http://host/path (with no trailing slash)
@@ -195,8 +198,8 @@ private bool EqualsHrefExactlyOrIfTrailingSlashAdded(string currentUriAbsolute)
195198 // which in turn is because it's common for servers to return the same page
196199 // for http://host/vdir as they do for host://host/vdir/ as it's no
197200 // good to display a blank page in that case.
198- if ( _hrefAbsolute [ _hrefAbsolute . Length - 1 ] == '/'
199- && _hrefAbsolute . StartsWith ( currentUriAbsolute , StringComparison . OrdinalIgnoreCase ) )
201+ if ( hrefAbsolute [ hrefAbsolute . Length - 1 ] == '/' &&
202+ currentUriAbsolute . SequenceEqual ( hrefAbsolute . Slice ( 0 , hrefAbsolute . Length - 1 ) , CaseInsensitiveComparer ) )
200203 {
201204 return true ;
202205 }
@@ -258,4 +261,17 @@ private static bool IsUnreservedCharacter(char c)
258261 c == '_' ||
259262 c == '~' ;
260263 }
264+
265+ private class CaseInsensitiveCharComparer : IEqualityComparer < char >
266+ {
267+ public bool Equals ( char x , char y )
268+ {
269+ return char . ToLowerInvariant ( x ) == char . ToLowerInvariant ( y ) ;
270+ }
271+
272+ public int GetHashCode ( char obj )
273+ {
274+ return char . ToLowerInvariant ( obj ) . GetHashCode ( ) ;
275+ }
276+ }
261277}
0 commit comments