| File: System\Net\Http\Headers\ProductHeaderValue.cs | Web Access |
| Project: src\runtime\src\libraries\System.Net.Http\src\System.Net.Http.csproj (System.Net.Http) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using System.Diagnostics.CodeAnalysis; namespace System.Net.Http.Headers { public class ProductHeaderValue : ICloneable { private readonly string _name; private readonly string? _version; public string Name { get { return _name; } } // We can't use the System.Version type, since a version can be e.g. "x11". public string? Version { get { return _version; } } public ProductHeaderValue(string name) : this(name, null) { } public ProductHeaderValue(string name, string? version) { HeaderUtilities.CheckValidToken(name); if (!string.IsNullOrEmpty(version)) { HeaderUtilities.CheckValidToken(version); _version = version; } _name = name; } private ProductHeaderValue(ProductHeaderValue source) { Debug.Assert(source != null); _name = source._name; _version = source._version; } public override string ToString() { if (string.IsNullOrEmpty(_version)) { return _name; } return _name + "/" + _version; } public override bool Equals([NotNullWhen(true)] object? obj) { ProductHeaderValue? other = obj as ProductHeaderValue; if (other == null) { return false; } return string.Equals(_name, other._name, StringComparison.OrdinalIgnoreCase) && string.Equals(_version, other._version, StringComparison.OrdinalIgnoreCase); } public override int GetHashCode() { int result = StringComparer.OrdinalIgnoreCase.GetHashCode(_name); if (!string.IsNullOrEmpty(_version)) { result ^= StringComparer.OrdinalIgnoreCase.GetHashCode(_version); } return result; } public static ProductHeaderValue Parse(string input) { int index = 0; return (ProductHeaderValue)GenericHeaderParser.SingleValueProductParser.ParseValue(input, null, ref index); } public static bool TryParse([NotNullWhen(true)] string? input, [NotNullWhen(true)] out ProductHeaderValue? parsedValue) { int index = 0; parsedValue = null; if (GenericHeaderParser.SingleValueProductParser.TryParseValue(input, null, ref index, out object? output)) { parsedValue = (ProductHeaderValue)output!; return true; } return false; } internal static int GetProductLength(string input, int startIndex, out ProductHeaderValue? parsedValue) { Debug.Assert(startIndex >= 0); parsedValue = null; if (string.IsNullOrEmpty(input) || (startIndex >= input.Length)) { return 0; } // Parse the name string: <name> in '<name>/<version>'. int nameLength = HttpRuleParser.GetTokenLength(input, startIndex); if (nameLength == 0) { return 0; } string name = input.Substring(startIndex, nameLength); int current = startIndex + nameLength; current += HttpRuleParser.GetWhitespaceLength(input, current); if ((current == input.Length) || (input[current] != '/')) { parsedValue = new ProductHeaderValue(name); return current - startIndex; } current++; // Skip '/' delimiter. current += HttpRuleParser.GetWhitespaceLength(input, current); // Parse the name string: <version> in '<name>/<version>'. int versionLength = HttpRuleParser.GetTokenLength(input, current); if (versionLength == 0) { return 0; // If there is a '/' separator it must be followed by a valid token. } string version = input.Substring(current, versionLength); current += versionLength; current += HttpRuleParser.GetWhitespaceLength(input, current); parsedValue = new ProductHeaderValue(name, version); return current - startIndex; } object ICloneable.Clone() { return new ProductHeaderValue(this); } } }