diff --git a/src/libraries/Common/src/System/Net/IPv4AddressHelper.Common.cs b/src/libraries/Common/src/System/Net/IPv4AddressHelper.Common.cs index f4dd4b77772349..c3ad8a7d79d7d3 100644 --- a/src/libraries/Common/src/System/Net/IPv4AddressHelper.Common.cs +++ b/src/libraries/Common/src/System/Net/IPv4AddressHelper.Common.cs @@ -25,7 +25,7 @@ internal static int ParseHostNumber(ReadOnlySpan str, int start, int end) int b = 0; char ch; - for (; (start < end) && (ch = str[start]) != '.' && ch != ':'; ++start) + for (; (start < end) && (ch = str[start]) is not ('.' or ':'); ++start) { b = (b * 10) + ch - '0'; } @@ -118,10 +118,10 @@ internal static unsafe bool IsValidCanonical(char* name, int start, ref int end, if (allowIPv6) { // for ipv4 inside ipv6 the terminator is either ScopeId, prefix or ipv6 terminator - if (ch == ']' || ch == '/' || ch == '%') + if (ch is ']' or '/' or '%') break; } - else if (ch == '/' || ch == '\\' || (notImplicitFile && (ch == ':' || ch == '?' || ch == '#'))) + else if (ch is '/' or '\\' || (notImplicitFile && ch is ':' or '?' or '#')) { break; } @@ -202,7 +202,7 @@ internal static unsafe long ParseNonCanonical(char* name, int start, ref int end if (current < end) { ch = name[current]; - if (ch == 'x' || ch == 'X') + if (ch is 'x' or 'X') { numberBase = Hex; current++; @@ -275,7 +275,7 @@ internal static unsafe long ParseNonCanonical(char* name, int start, ref int end { // end of string, allowed } - else if ((ch = name[current]) == '/' || ch == '\\' || (notImplicitFile && (ch == ':' || ch == '?' || ch == '#'))) + else if ((ch = name[current]) is '/' or '\\' || (notImplicitFile && ch is ':' or '?' or '#')) { end = current; } diff --git a/src/libraries/Common/src/System/Net/IPv6AddressHelper.Common.cs b/src/libraries/Common/src/System/Net/IPv6AddressHelper.Common.cs index 71c655a52efd67..10bb4880bbf67d 100644 --- a/src/libraries/Common/src/System/Net/IPv6AddressHelper.Common.cs +++ b/src/libraries/Common/src/System/Net/IPv6AddressHelper.Common.cs @@ -310,7 +310,7 @@ internal static void Parse(ReadOnlySpan address, Span numbers, int } start = i; - for (++i; i < address.Length && address[i] != ']' && address[i] != '/'; ++i) + for (++i; i < address.Length && address[i] is not (']' or '/'); ++i) { } scopeId = new string(address.Slice(start, i - start)); @@ -339,14 +339,8 @@ internal static void Parse(ReadOnlySpan address, Span numbers, int // check to see if the upcoming number is really an IPv4 // address. If it is, convert it to 2 ushort numbers - for (int j = i; j < address.Length && - (address[j] != ']') && - (address[j] != ':') && - (address[j] != '%') && - (address[j] != '/') && - (j < i + 4); ++j) + for (int j = i; j < address.Length && address[j] is not (']' or ':' or '%' or '/') && (j < i + 4); j++) { - if (address[j] == '.') { // we have an IPv4 address. Find the end of it: @@ -355,7 +349,7 @@ internal static void Parse(ReadOnlySpan address, Span numbers, int // the IPv4 address are the prefix delimiter '/' // or the end-of-string (which we conveniently // delimited with ']') - while (j < address.Length && (address[j] != ']') && (address[j] != '/') && (address[j] != '%')) + while (j < address.Length && address[j] is not (']' or '/' or '%')) { ++j; } diff --git a/src/libraries/System.Private.Uri/src/System/UncNameHelper.cs b/src/libraries/System.Private.Uri/src/System/UncNameHelper.cs index 54cec4103e4077..697b7c37b295d3 100644 --- a/src/libraries/System.Private.Uri/src/System/UncNameHelper.cs +++ b/src/libraries/System.Private.Uri/src/System/UncNameHelper.cs @@ -49,22 +49,24 @@ public static unsafe bool IsValid(char* name, int start, ref int returnedEnd, bo int i = start; for (; i < end; ++i) { - if (name[i] == '/' || name[i] == '\\' || (notImplicitFile && (name[i] == ':' || name[i] == '?' || name[i] == '#'))) + char c = name[i]; + + if (c is '/' or '\\' || (notImplicitFile && c is ':' or '?' or '#')) { end = i; break; } - else if (name[i] == '.') + else if (c == '.') { ++i; break; } - if (char.IsLetter(name[i]) || name[i] == '-' || name[i] == '_') + if (char.IsLetter(c) || c is '-' or '_') { validShortName = true; } - else if (!char.IsAsciiDigit(name[i])) + else if (!char.IsAsciiDigit(c)) { return false; } @@ -79,24 +81,26 @@ public static unsafe bool IsValid(char* name, int start, ref int returnedEnd, bo for (; i < end; ++i) { - if (name[i] == '/' || name[i] == '\\' || (notImplicitFile && (name[i] == ':' || name[i] == '?' || name[i] == '#'))) + char c = name[i]; + + if (c is '/' or '\\' || (notImplicitFile && c is ':' or '?' or '#')) { end = i; break; } - else if (name[i] == '.') + else if (c == '.') { if (!validShortName || ((i - 1) >= start && name[i - 1] == '.')) return false; validShortName = false; } - else if (name[i] == '-' || name[i] == '_') + else if (c is '-' or '_') { if (!validShortName) return false; } - else if (char.IsLetter(name[i]) || char.IsAsciiDigit(name[i])) + else if (char.IsLetter(c) || char.IsAsciiDigit(c)) { if (!validShortName) validShortName = true; diff --git a/src/libraries/System.Private.Uri/src/System/Uri.cs b/src/libraries/System.Private.Uri/src/System/Uri.cs index 770e035d36a085..045717411a7741 100644 --- a/src/libraries/System.Private.Uri/src/System/Uri.cs +++ b/src/libraries/System.Private.Uri/src/System/Uri.cs @@ -293,7 +293,7 @@ private int SecuredPathIndex if (IsDosPath) { char ch = _string[_info.Offset.Path]; - return (ch == '/' || ch == '\\') ? 3 : 2; + return (ch is '/' or '\\') ? 3 : 2; } return 0; } @@ -597,7 +597,7 @@ private static unsafe void GetCombinedString(Uri baseUri, string relativeStr, // for (int i = 0; i < relativeStr.Length; ++i) { - if (relativeStr[i] == '/' || relativeStr[i] == '\\' || relativeStr[i] == '?' || relativeStr[i] == '#') + if (relativeStr[i] is '/' or '\\' or '?' or '#') { break; } @@ -977,7 +977,7 @@ private string GetLocalPath() string str = (IsImplicitFile && _info.Offset.Host == (IsDosPath ? 0 : 2) && _info.Offset.Query == _info.Offset.End) ? _string - : (IsDosPath && (_string[start] == '/' || _string[start] == '\\')) + : (IsDosPath && _string[start] is '/' or '\\') ? _string.Substring(start + 1, _info.Offset.Query - start - 1) : _string.Substring(start, _info.Offset.Query - start); @@ -1014,7 +1014,7 @@ private string GetLocalPath() else { // Dos path - if (_string[start] == '/' || _string[start] == '\\') + if (_string[start] is '/' or '\\') { // Skip leading slash for a DOS path ++start; @@ -2012,14 +2012,13 @@ private unsafe ParsingError PrivateParseMinimal() if (_syntax.IsAllSet(UriSyntaxFlags.AllowEmptyHost | UriSyntaxFlags.AllowDOSPath) && NotAny(Flags.ImplicitFile) && (idx + 1 < length)) { - char c; int i = idx; // V1 Compat: Allow _compression_ of > 3 slashes only for File scheme. // This will skip all slashes and if their number is 2+ it sets the AuthorityFound flag for (; i < length; ++i) { - if (!((c = pUriString[i]) == '\\' || c == '/')) + if (pUriString[i] is not ('\\' or '/')) break; } @@ -2031,10 +2030,9 @@ private unsafe ParsingError PrivateParseMinimal() _flags |= Flags.AuthorityFound; } // DOS-like path? - if (i + 1 < length && ((c = pUriString[i + 1]) == ':' || c == '|') && - char.IsAsciiLetter(pUriString[i])) + if (i + 1 < length && pUriString[i + 1] is ':' or '|' && char.IsAsciiLetter(pUriString[i])) { - if (i + 2 >= length || ((c = pUriString[i + 2]) != '\\' && c != '/')) + if (i + 2 >= length || pUriString[i + 2] is not ('\\' or '/')) { // report an error but only for a file: scheme if (_syntax.InFact(UriSyntaxFlags.FileLikeUri)) @@ -2062,8 +2060,8 @@ private unsafe ParsingError PrivateParseMinimal() } } // UNC share? - else if (_syntax.InFact(UriSyntaxFlags.FileLikeUri) && (i - idx >= 2 && i - idx != 3 && - i < length && pUriString[i] != '?' && pUriString[i] != '#')) + else if (_syntax.InFact(UriSyntaxFlags.FileLikeUri) && i - idx >= 2 && i - idx != 3 && + i < length && pUriString[i] is not ('?' or '#')) { // V1.0 did not support file:///, fixing it with minimal behavior change impact // Only FILE scheme may have UNC Path flag set @@ -2092,7 +2090,7 @@ private unsafe ParsingError PrivateParseMinimal() if (_syntax.InFact(UriSyntaxFlags.MustHaveAuthority)) { // (V1.0 compatibility) This will allow http:\\ http:\/ http:/\ - if ((first == '/' || first == '\\') && (second == '/' || second == '\\')) + if (first is '/' or '\\' && second is '/' or '\\') { _flags |= Flags.AuthorityFound; idx += 2; @@ -2233,7 +2231,7 @@ private unsafe void CreateUriInfo(Flags cF) idx += 2; //skip any other slashes (compatibility with V1.0 parser) int end = (int)(cF & Flags.IndexMask); - while (idx < end && (_string[idx] == '/' || _string[idx] == '\\')) + while (idx < end && _string[idx] is '/' or '\\') { ++idx; } @@ -2260,7 +2258,7 @@ private unsafe void CreateUriInfo(Flags cF) // Skip slashes if it was allowed during ctor time // NB: Today this is only allowed if a Unc or DosPath was found after the scheme int end = (int)(cF & Flags.IndexMask); - while (idx < end && (_string[idx] == '/' || _string[idx] == '\\')) + while (idx < end && _string[idx] is '/' or '\\') { notCanonicalScheme = true; ++idx; @@ -2479,24 +2477,15 @@ private unsafe void CreateHostString() } else if (NotAny(Flags.CanonicalDnsHost)) { - // Check to see if we can take the canonical host string out of _string - if (_info.ScopeId is not null) + // Check to see if we can take the canonical host string out of _string. + // IPv6 ScopeId is included when serializing a Uri. + ref Offset offset = ref _info.Offset; + + if (_info.ScopeId is not null || !_string.AsSpan(offset.Host, offset.End - offset.Host).StartsWith(host, StringComparison.Ordinal)) { // IPv6 ScopeId is included when serializing a Uri flags |= (Flags.HostNotCanonical | Flags.E_HostNotCanonical); } - else - { - for (int i = 0; i < host.Length; ++i) - { - if ((_info.Offset.Host + i) >= _info.Offset.End || - host[i] != _string[_info.Offset.Host + i]) - { - flags |= (Flags.HostNotCanonical | Flags.E_HostNotCanonical); - break; - } - } - } } } @@ -2601,14 +2590,14 @@ private unsafe void GetHostViaCustomSyntax() else { host = CreateHostStringHelper(host, 0, host.Length, ref flags, ref _info.ScopeId); - for (int i = 0; i < host.Length; ++i) + + ref Offset offset = ref _info.Offset; + + if (!_string.AsSpan(offset.Host, offset.End - offset.Host).StartsWith(host, StringComparison.Ordinal)) { - if ((_info.Offset.Host + i) >= _info.Offset.End || host[i] != _string[_info.Offset.Host + i]) - { - _flags |= (Flags.HostNotCanonical | Flags.E_HostNotCanonical); - break; - } + _flags |= (Flags.HostNotCanonical | Flags.E_HostNotCanonical); } + _flags = (_flags & ~Flags.HostTypeMask) | (flags & Flags.HostTypeMask); } } @@ -3405,7 +3394,7 @@ private unsafe void ParseRemaining() // We use special syntax flag to check if the path is rooted, i.e. has a first slash // if (((_flags & Flags.AuthorityFound) != 0) && ((syntaxFlags & UriSyntaxFlags.PathIsRooted) != 0) - && (_info.Offset.Path == length || (str[_info.Offset.Path] != '/' && str[_info.Offset.Path] != '\\'))) + && (_info.Offset.Path == length || str[_info.Offset.Path] is not ('/' or '\\'))) { cF |= Flags.FirstSlashAbsent; } @@ -3803,7 +3792,7 @@ private unsafe int CheckAuthorityHelper(char* pString, int idx, int length, } //Special case is an empty authority - if (idx == length || ((ch = pString[idx]) == '/' || (ch == '\\' && StaticIsFile(syntax)) || ch == '#' || ch == '?')) + if (idx == length || (ch = pString[idx]) == '/' || (ch == '\\' && StaticIsFile(syntax)) || ch is '#' or '?') { if (syntax.InFact(UriSyntaxFlags.AllowEmptyHost)) { @@ -3830,8 +3819,7 @@ private unsafe int CheckAuthorityHelper(char* pString, int idx, int length, { for (; start < end; ++start) { - if (start == end - 1 || pString[start] == '?' || pString[start] == '#' || pString[start] == '\\' || - pString[start] == '/') + if (start == end - 1 || pString[start] is '?' or '#' or '\\' or '/') { start = idx; break; @@ -4013,7 +4001,7 @@ private unsafe int CheckAuthorityHelper(char* pString, int idx, int length, flags |= Flags.BasicHostType; for (end = idx; end < length; ++end) { - if (pString[end] == '/' || (pString[end] == '?' || pString[end] == '#')) + if (pString[end] is '/' or '?' or '#') { break; } @@ -4049,8 +4037,9 @@ private unsafe int CheckAuthorityHelper(char* pString, int idx, int length, int startOtherHost = idx; for (end = idx; end < length; ++end) { - if (dotFound && (pString[end] == '/' || pString[end] == '?' || pString[end] == '#')) + if (dotFound && (pString[end] is '/' or '?' or '#')) break; + else if (end < (idx + 2) && pString[end] == '.') { // allow one or two dots @@ -4226,27 +4215,25 @@ private unsafe Check CheckCanonical(char* str, ref int idx, int end, char delim) foundEscaping = true; } } - else if (c == '/' || c == '\\') + else if (c is '/' or '\\') { if ((res & Check.BackslashInPath) == 0 && c == '\\') { res |= Check.BackslashInPath; } - if ((res & Check.DotSlashAttn) == 0 && i + 1 != end && (str[i + 1] == '/' || str[i + 1] == '\\')) + if ((res & Check.DotSlashAttn) == 0 && i + 1 != end && (str[i + 1] is '/' or '\\')) { res |= Check.DotSlashAttn; } } else if (c == '.') { - if ((res & Check.DotSlashAttn) == 0 && i + 1 == end || str[i + 1] == '.' || str[i + 1] == '/' - || str[i + 1] == '\\' || str[i + 1] == '?' || str[i + 1] == '#') + if ((res & Check.DotSlashAttn) == 0 && i + 1 == end || str[i + 1] is '.' or '/' or '\\' or '?' or '#') { res |= Check.DotSlashAttn; } } - else if (((c <= '"' && c != '!') || (c >= '[' && c <= '^') || c == '>' - || c == '<' || c == '`')) + else if ((c <= '"' && c != '!') || (c >= '[' && c <= '^') || c is '>' or '<' or '`') { if (!needsEscaping) needsEscaping = true; @@ -4269,7 +4256,7 @@ private unsafe Check CheckCanonical(char* str, ref int idx, int end, char delim) //try unescape a byte hex escaping if (i + 2 < end && (c = UriHelper.DecodeHexChars(str[i + 1], str[i + 2])) != c_DummyChar) { - if (c == '.' || c == '/' || c == '\\') + if (c is '.' or '/' or '\\') { res |= Check.DotSlashEscaped; } @@ -4722,8 +4709,8 @@ private static string CombineUri(Uri basePart, string relativePart, UriFormat ur //check a special case for the base as DOS path and a rooted relative string if (basePart.IsDosPath && - (c1 == '/' || c1 == '\\') && - (relativePart.Length == 1 || (relativePart[1] != '/' && relativePart[1] != '\\'))) + c1 is '/' or '\\' && + (relativePart.Length == 1 || relativePart[1] is not ('/' or '\\'))) { // take relative part appended to the base string after the drive letter int idx = basePart.OriginalString.IndexOf(':'); @@ -4740,9 +4727,9 @@ private static string CombineUri(Uri basePart, string relativePart, UriFormat ur // Check special case for Unc or absolute path in relativePart when base is FILE if (StaticIsFile(basePart.Syntax)) { - if (c1 == '\\' || c1 == '/') + if (c1 is '\\' or '/') { - if (relativePart.Length >= 2 && (relativePart[1] == '\\' || relativePart[1] == '/')) + if (relativePart.Length >= 2 && relativePart[1] is '\\' or '/') { //Assuming relative is a Unc path and base is a file uri. return basePart.IsImplicitFile ? relativePart : "file:" + relativePart; @@ -5085,19 +5072,7 @@ protected virtual void CheckSecurity() [Obsolete("Uri.IsReservedCharacter has been deprecated and is not supported.")] protected virtual bool IsReservedCharacter(char character) { - // This method just does not make sense as protected virtual - // It should go public static asap - - return (character == ';') - || (character == '/') - || (character == ':') - || (character == '@') // OK FS char - || (character == '&') - || (character == '=') - || (character == '+') // OK FS char - || (character == '$') // OK FS char - || (character == ',') - ; + return character is ';' or '/' or ':' or '@' or '&' or '=' or '+' or '$' or ','; } // @@ -5113,34 +5088,8 @@ protected virtual bool IsReservedCharacter(char character) [Obsolete("Uri.IsExcludedCharacter has been deprecated and is not supported.")] protected static bool IsExcludedCharacter(char character) { - // This method just does not make sense as protected - // It should go public static asap - - // - // the excluded characters... - // - - return (character <= 0x20) - || (character >= 0x7f) - || (character == '<') - || (character == '>') - || (character == '#') - || (character == '%') - || (character == '"') - - // - // the 'unwise' characters... - // - - || (character == '{') - || (character == '}') - || (character == '|') - || (character == '\\') - || (character == '^') - || (character == '[') - || (character == ']') - || (character == '`') - ; + return !char.IsAscii(character) || + character is <= ' ' or '<' or '>' or '#' or '%' or '"' or '{' or '}' or '|' or '\\' or '^' or '[' or ']' or '`'; } // @@ -5159,31 +5108,7 @@ protected virtual bool IsBadFileSystemCharacter(char character) // This method just does not make sense as protected virtual // It should go public static asap - return (character < 0x20) - || (character == ';') - || (character == '/') - || (character == '?') - || (character == ':') - || (character == '&') - || (character == '=') - || (character == ',') - || (character == '*') - || (character == '<') - || (character == '>') - || (character == '"') - || (character == '|') - || (character == '\\') - || (character == '^') - ; - } - - //Used by UriBuilder - internal bool HasAuthority - { - get - { - return InFact(Flags.AuthorityFound); - } + return character is < ' ' or ';' or '/' or '?' or ':' or '&' or '=' or ',' or '*' or '<' or '>' or '"' or '|' or '\\' or '^'; } } // class Uri } // namespace System diff --git a/src/libraries/System.Private.Uri/src/System/UriExt.cs b/src/libraries/System.Private.Uri/src/System/UriExt.cs index 1aedf02d9299d4..859f59499ea381 100644 --- a/src/libraries/System.Private.Uri/src/System/UriExt.cs +++ b/src/libraries/System.Private.Uri/src/System/UriExt.cs @@ -492,7 +492,7 @@ internal unsafe bool InternalIsWellFormedOriginalString() if (InFact(Flags.UncPath | Flags.DosPath)) { - while (++idx < _info.Offset.User && (_string[idx] == '/' || _string[idx] == '\\')) + if (++idx < _info.Offset.User && _string[idx] is '/' or '\\') return false; } } @@ -726,9 +726,9 @@ private Uri(Flags flags, UriParser? uriParser, string uri) // Check on the DOS path in the relative Uri (a special case) if (relativeStr.Length >= 3 - && (relativeStr[1] == ':' || relativeStr[1] == '|') + && relativeStr[1] is ':' or '|' && char.IsAsciiLetter(relativeStr[0]) - && (relativeStr[2] == '\\' || relativeStr[2] == '/')) + && relativeStr[2] is '\\' or '/') { if (baseUri.IsImplicitFile) { diff --git a/src/libraries/System.Private.Uri/src/System/UriHelper.cs b/src/libraries/System.Private.Uri/src/System/UriHelper.cs index 0ca2f9ad5e7d94..e99bcd94b2fe3a 100644 --- a/src/libraries/System.Private.Uri/src/System/UriHelper.cs +++ b/src/libraries/System.Private.Uri/src/System/UriHelper.cs @@ -55,7 +55,7 @@ internal static unsafe bool TestForSubPath(char* selfPtr, int selfLength, char* chSelf = *(selfPtr + i); chOther = *(otherPtr + i); - if (chSelf == '?' || chSelf == '#') + if (chSelf is '?' or '#') { // survived so far and selfPtr does not have any more path segments return true; @@ -81,7 +81,7 @@ internal static unsafe bool TestForSubPath(char* selfPtr, int selfLength, char* } // if otherPtr terminates then selfPtr must not have any more path segments - if (chOther == '?' || chOther == '#') + if (chOther is '?' or '#') { break; } @@ -105,7 +105,7 @@ internal static unsafe bool TestForSubPath(char* selfPtr, int selfLength, char* // If self is longer then it must not have any more path segments for (; i < selfLength; ++i) { - if ((chSelf = *(selfPtr + i)) == '?' || chSelf == '#') + if ((chSelf = *(selfPtr + i)) is '?' or '#') { return true; } @@ -514,14 +514,14 @@ internal static bool IsNotSafeForUnescape(char ch) // internal static bool IsGenDelim(char ch) { - return (ch == ':' || ch == '/' || ch == '?' || ch == '#' || ch == '[' || ch == ']' || ch == '@'); + return ch is ':' or '/' or '?' or '#' or '[' or ']' or '@'; } internal static readonly char[] s_WSchars = new char[] { ' ', '\n', '\r', '\t' }; internal static bool IsLWS(char ch) { - return (ch <= ' ') && (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'); + return ch is <= ' ' and (' ' or '\n' or '\r' or '\t'); } // Is this a Bidirectional control char.. These get stripped