| File: StringWithQualityHeaderValueComparer.cs | Web Access |
| Project: src\aspnetcore\src\Http\Headers\src\Microsoft.Net.Http.Headers.csproj (Microsoft.Net.Http.Headers) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.Extensions.Primitives; namespace Microsoft.Net.Http.Headers; /// <summary> /// Implementation of <see cref="IComparer{T}"/> that can compare content negotiation header fields /// based on their quality values (a.k.a q-values). This applies to values used in accept-charset, /// accept-encoding, accept-language and related header fields with similar syntax rules. See /// <see cref="MediaTypeHeaderValueComparer"/> for a comparer for media type /// q-values. /// </summary> public class StringWithQualityHeaderValueComparer : IComparer<StringWithQualityHeaderValue> { private static readonly StringSegment Any = new("*"); private StringWithQualityHeaderValueComparer() { } /// <summary> /// Gets the default instance of <see cref="StringWithQualityHeaderValueComparer"/>. /// </summary> public static StringWithQualityHeaderValueComparer QualityComparer { get; } = new StringWithQualityHeaderValueComparer(); /// <summary> /// Compares two <see cref="StringWithQualityHeaderValue"/> based on their quality value /// (a.k.a their "q-value"). /// Values with identical q-values are considered equal (i.e the result is 0) with the exception of wild-card /// values (i.e. a value of "*") which are considered less than non-wild-card values. This allows to sort /// a sequence of <see cref="StringWithQualityHeaderValue"/> following their q-values ending up with any /// wild-cards at the end. /// </summary> /// <param name="stringWithQuality1">The first value to compare.</param> /// <param name="stringWithQuality2">The second value to compare</param> /// <returns>The result of the comparison.</returns> public int Compare( StringWithQualityHeaderValue? stringWithQuality1, StringWithQualityHeaderValue? stringWithQuality2) { ArgumentNullException.ThrowIfNull(stringWithQuality1); ArgumentNullException.ThrowIfNull(stringWithQuality2); var quality1 = stringWithQuality1.Quality ?? HeaderQuality.Match; var quality2 = stringWithQuality2.Quality ?? HeaderQuality.Match; var qualityDifference = quality1 - quality2; if (qualityDifference < 0) { return -1; } else if (qualityDifference > 0) { return 1; } if (!StringSegment.Equals(stringWithQuality1.Value, stringWithQuality2.Value, StringComparison.OrdinalIgnoreCase)) { if (StringSegment.Equals(stringWithQuality1.Value, Any, StringComparison.Ordinal)) { return -1; } else if (StringSegment.Equals(stringWithQuality2.Value, Any, StringComparison.Ordinal)) { return 1; } } return 0; } }