< Summary

Information
Class: System.Net.Http.Headers.StringWithQualityHeaderValue
Assembly: System.Net.Http
File(s): D:\runner\runtime\src\libraries\System.Net.Http\src\System\Net\Http\Headers\StringWithQualityHeaderValue.cs
Line coverage
34%
Covered lines: 37
Uncovered lines: 70
Coverable lines: 107
Total lines: 185
Line coverage: 34.5%
Branch coverage
33%
Covered branches: 14
Total branches: 42
Branch coverage: 33.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%11100%
.ctor(...)100%110%
.ctor(...)100%110%
ToString()50%22100%
Equals(...)0%440%
GetHashCode()100%110%
Parse(...)100%110%
TryParse(...)0%220%
GetStringWithQualityLength(...)75%121284%
TryReadQuality(...)20%202021.87%
System.ICloneable.Clone()100%110%

File(s)

D:\runner\runtime\src\libraries\System.Net.Http\src\System\Net\Http\Headers\StringWithQualityHeaderValue.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Diagnostics;
 5using System.Diagnostics.CodeAnalysis;
 6using System.Globalization;
 7
 8namespace System.Net.Http.Headers
 9{
 10    public class StringWithQualityHeaderValue : ICloneable
 11    {
 12        private const double NotSetSentinel = double.PositiveInfinity;
 13
 14        private readonly string _value;
 15        private readonly double _quality;
 16
 017        public string Value => _value;
 18
 019        public double? Quality => _quality == NotSetSentinel ? null : _quality;
 20
 364221        public StringWithQualityHeaderValue(string value)
 364222        {
 364223            HeaderUtilities.CheckValidToken(value);
 24
 364225            _value = value;
 364226            _quality = NotSetSentinel;
 364227        }
 28
 029        public StringWithQualityHeaderValue(string value, double quality)
 030        {
 031            HeaderUtilities.CheckValidToken(value);
 32
 033            ArgumentOutOfRangeException.ThrowIfNegative(quality);
 034            ArgumentOutOfRangeException.ThrowIfGreaterThan(quality, 1.0);
 35
 036            _value = value;
 037            _quality = quality;
 038        }
 39
 040        private StringWithQualityHeaderValue(StringWithQualityHeaderValue source)
 041        {
 042            Debug.Assert(source != null);
 43
 044            _value = source._value;
 045            _quality = source._quality;
 046        }
 47
 48        public override string ToString() =>
 342049            _quality == NotSetSentinel
 342050                ? _value
 342051                : string.Create(CultureInfo.InvariantCulture, stackalloc char[128], $"{_value}; q={_quality:0.0##}");
 52
 53        public override bool Equals([NotNullWhen(true)] object? obj) =>
 054            obj is StringWithQualityHeaderValue other &&
 055            string.Equals(_value, other._value, StringComparison.OrdinalIgnoreCase) &&
 056            // Note that we don't consider double.Epsilon here. We really consider two values equal if they're
 057            // actually equal. This makes sure that we also get the same hashcode for two values considered equal
 058            // by Equals().
 059            _quality == other._quality;
 60
 61        public override int GetHashCode() =>
 062            HashCode.Combine(StringComparer.OrdinalIgnoreCase.GetHashCode(_value), _quality);
 63
 64        public static StringWithQualityHeaderValue Parse(string input)
 065        {
 066            int index = 0;
 067            return (StringWithQualityHeaderValue)GenericHeaderParser.SingleValueStringWithQualityParser.ParseValue(
 068                input, null, ref index);
 069        }
 70
 71        public static bool TryParse([NotNullWhen(true)] string? input, [NotNullWhen(true)] out StringWithQualityHeaderVa
 072        {
 073            int index = 0;
 074            parsedValue = null;
 75
 076            if (GenericHeaderParser.SingleValueStringWithQualityParser.TryParseValue(
 077                input, null, ref index, out object? output))
 078            {
 079                parsedValue = (StringWithQualityHeaderValue)output!;
 080                return true;
 81            }
 082            return false;
 083        }
 84
 85        internal static int GetStringWithQualityLength(string? input, int startIndex, out object? parsedValue)
 375686        {
 375687            Debug.Assert(startIndex >= 0);
 88
 375689            parsedValue = null;
 90
 375691            if (string.IsNullOrEmpty(input) || (startIndex >= input.Length))
 092            {
 093                return 0;
 94            }
 95
 96            // Parse the value string: <value> in '<value>; q=<quality>'
 375697            int valueLength = HttpRuleParser.GetTokenLength(input, startIndex);
 98
 375699            if (valueLength == 0)
 88100            {
 88101                return 0;
 102            }
 103
 3668104            string value = input.Substring(startIndex, valueLength);
 3668105            int current = startIndex + valueLength;
 3668106            current += HttpRuleParser.GetWhitespaceLength(input, current);
 107
 3668108            if ((current == input.Length) || (input[current] != ';'))
 3642109            {
 3642110                parsedValue = new StringWithQualityHeaderValue(value);
 3642111                return current - startIndex; // we have a valid token, but no quality.
 112            }
 113
 26114            current++; // skip ';' separator
 26115            current += HttpRuleParser.GetWhitespaceLength(input, current);
 116
 117            // If we found a ';' separator, it must be followed by a quality information
 26118            if (!TryReadQuality(input, out double quality, ref current))
 26119            {
 26120                return 0;
 121            }
 122
 0123            parsedValue = new StringWithQualityHeaderValue(value, quality);
 0124            return current - startIndex;
 3756125        }
 126
 127        private static bool TryReadQuality(string input, out double quality, ref int index)
 26128        {
 26129            int current = index;
 26130            quality = default;
 131
 132            // See if we have a quality value by looking for "q"
 26133            if ((current == input.Length) || ((input[current] != 'q') && (input[current] != 'Q')))
 26134            {
 26135                return false;
 136            }
 137
 0138            current++; // skip 'q' identifier
 0139            current += HttpRuleParser.GetWhitespaceLength(input, current);
 140
 141            // If we found "q" it must be followed by "="
 0142            if ((current == input.Length) || (input[current] != '='))
 0143            {
 0144                return false;
 145            }
 146
 0147            current++; // skip '=' separator
 0148            current += HttpRuleParser.GetWhitespaceLength(input, current);
 149
 0150            if (current == input.Length)
 0151            {
 0152                return false;
 153            }
 154
 0155            int qualityLength = HttpRuleParser.GetNumberLength(input, current, true);
 156
 0157            if (qualityLength == 0)
 0158            {
 0159                return false;
 160            }
 161
 0162            if (!double.TryParse(input.AsSpan(current, qualityLength), NumberStyles.AllowDecimalPoint,
 0163                NumberFormatInfo.InvariantInfo, out quality))
 0164            {
 0165                return false;
 166            }
 167
 0168            if ((quality < 0) || (quality > 1))
 0169            {
 0170                return false;
 171            }
 172
 0173            current += qualityLength;
 0174            current += HttpRuleParser.GetWhitespaceLength(input, current);
 175
 0176            index = current;
 0177            return true;
 26178        }
 179
 180        object ICloneable.Clone()
 0181        {
 0182            return new StringWithQualityHeaderValue(this);
 0183        }
 184    }
 185}