< 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
65%
Covered lines: 70
Uncovered lines: 37
Coverable lines: 107
Total lines: 185
Line coverage: 65.4%
Branch coverage
71%
Covered branches: 30
Total branches: 42
Branch coverage: 71.4%
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%11100%
.ctor(...)100%110%
ToString()100%22100%
Equals(...)0%440%
GetHashCode()100%110%
Parse(...)100%110%
TryParse(...)0%220%
GetStringWithQualityLength(...)83.33%121292%
TryReadQuality(...)90%202093.75%
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
 650421        public StringWithQualityHeaderValue(string value)
 650422        {
 650423            HeaderUtilities.CheckValidToken(value);
 24
 650425            _value = value;
 650426            _quality = NotSetSentinel;
 650427        }
 28
 67929        public StringWithQualityHeaderValue(string value, double quality)
 67930        {
 67931            HeaderUtilities.CheckValidToken(value);
 32
 67933            ArgumentOutOfRangeException.ThrowIfNegative(quality);
 67934            ArgumentOutOfRangeException.ThrowIfGreaterThan(quality, 1.0);
 35
 67936            _value = value;
 67937            _quality = quality;
 67938        }
 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() =>
 1113549            _quality == NotSetSentinel
 1113550                ? _value
 1113551                : 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)
 733186        {
 733187            Debug.Assert(startIndex >= 0);
 88
 733189            parsedValue = null;
 90
 733191            if (string.IsNullOrEmpty(input) || (startIndex >= input.Length))
 092            {
 093                return 0;
 94            }
 95
 96            // Parse the value string: <value> in '<value>; q=<quality>'
 733197            int valueLength = HttpRuleParser.GetTokenLength(input, startIndex);
 98
 733199            if (valueLength == 0)
 14100            {
 14101                return 0;
 102            }
 103
 7317104            string value = input.Substring(startIndex, valueLength);
 7317105            int current = startIndex + valueLength;
 7317106            current += HttpRuleParser.GetWhitespaceLength(input, current);
 107
 7317108            if ((current == input.Length) || (input[current] != ';'))
 6504109            {
 6504110                parsedValue = new StringWithQualityHeaderValue(value);
 6504111                return current - startIndex; // we have a valid token, but no quality.
 112            }
 113
 813114            current++; // skip ';' separator
 813115            current += HttpRuleParser.GetWhitespaceLength(input, current);
 116
 117            // If we found a ';' separator, it must be followed by a quality information
 813118            if (!TryReadQuality(input, out double quality, ref current))
 134119            {
 134120                return 0;
 121            }
 122
 679123            parsedValue = new StringWithQualityHeaderValue(value, quality);
 679124            return current - startIndex;
 7331125        }
 126
 127        private static bool TryReadQuality(string input, out double quality, ref int index)
 813128        {
 813129            int current = index;
 813130            quality = default;
 131
 132            // See if we have a quality value by looking for "q"
 813133            if ((current == input.Length) || ((input[current] != 'q') && (input[current] != 'Q')))
 96134            {
 96135                return false;
 136            }
 137
 717138            current++; // skip 'q' identifier
 717139            current += HttpRuleParser.GetWhitespaceLength(input, current);
 140
 141            // If we found "q" it must be followed by "="
 717142            if ((current == input.Length) || (input[current] != '='))
 4143            {
 4144                return false;
 145            }
 146
 713147            current++; // skip '=' separator
 713148            current += HttpRuleParser.GetWhitespaceLength(input, current);
 149
 713150            if (current == input.Length)
 2151            {
 2152                return false;
 153            }
 154
 711155            int qualityLength = HttpRuleParser.GetNumberLength(input, current, true);
 156
 711157            if (qualityLength == 0)
 2158            {
 2159                return false;
 160            }
 161
 709162            if (!double.TryParse(input.AsSpan(current, qualityLength), NumberStyles.AllowDecimalPoint,
 709163                NumberFormatInfo.InvariantInfo, out quality))
 0164            {
 0165                return false;
 166            }
 167
 709168            if ((quality < 0) || (quality > 1))
 30169            {
 30170                return false;
 171            }
 172
 679173            current += qualityLength;
 679174            current += HttpRuleParser.GetWhitespaceLength(input, current);
 175
 679176            index = current;
 679177            return true;
 813178        }
 179
 180        object ICloneable.Clone()
 0181        {
 0182            return new StringWithQualityHeaderValue(this);
 0183        }
 184    }
 185}