Skip to content

Commit 0c7f19a

Browse files
committed
Feedback - avoid allocating a string.
1 parent 17ece19 commit 0c7f19a

File tree

1 file changed

+33
-17
lines changed

1 file changed

+33
-17
lines changed

src/Components/Web/src/Routing/NavLink.cs

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
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;
54
using System.Globalization;
65
using 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

Comments
 (0)