System.Uri.PrivateParseMinimal C# (CSharp) Method

PrivateParseMinimal() private method

private PrivateParseMinimal ( ) : ParsingError
return ParsingError
        private unsafe ParsingError PrivateParseMinimal()
        {
            ushort idx = (ushort)(_flags & Flags.IndexMask);
            ushort length = (ushort)_string.Length;
            string newHost = null;      // stores newly parsed host when original strings are being switched

            // Means a custom UriParser did call "base" InitializeAndValidate()
            _flags &= ~(Flags.IndexMask | Flags.UserDrivenParsing);

            //STEP2: Parse up to the port

            fixed (char* pUriString = ((_iriParsing &&
                                        ((_flags & Flags.HasUnicode) != 0) &&
                                        ((_flags & Flags.HostUnicodeNormalized) == 0)) ? _originalUnicodeString : _string))
            {
                // Cut trailing spaces in m_String
                if (length > idx && UriHelper.IsLWS(pUriString[length - 1]))
                {
                    --length;
                    while (length != idx && UriHelper.IsLWS(pUriString[--length]))
                        ;
                    ++length;
                }

                // Old Uri parser tries to figure out on a DosPath in all cases.
                // Hence http://c:/ is treated as DosPath without the host while it should be a host "c", port 80
                //
                // This block is compatible with Old Uri parser in terms it will look for the DosPath if the scheme
                // syntax allows both empty hostnames and DosPath
                //
                if (_syntax.IsAllSet(UriSyntaxFlags.AllowEmptyHost | UriSyntaxFlags.AllowDOSPath)
                    && NotAny(Flags.ImplicitFile) && (idx + 1 < length))
                {
                    char c;
                    ushort i = (ushort)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 == '/'))
                            break;
                    }

                    if (_syntax.InFact(UriSyntaxFlags.FileLikeUri) || i - idx <= 3)
                    {
                        // if more than one slash after the scheme, the authority is present
                        if (i - idx >= 2)
                        {
                            _flags |= Flags.AuthorityFound;
                        }
                        // DOS-like path?
                        if (i + 1 < (ushort)length && ((c = pUriString[i + 1]) == ':' || c == '|') &&
                            UriHelper.IsAsciiLetter(pUriString[i]))
                        {
                            if (i + 2 >= (ushort)length || ((c = pUriString[i + 2]) != '\\' && c != '/'))
                            {
                                // report an error but only for a file: scheme
                                if (_syntax.InFact(UriSyntaxFlags.FileLikeUri))
                                    return ParsingError.MustRootedPath;
                            }
                            else
                            {
                                // This will set IsDosPath
                                _flags |= Flags.DosPath;

                                if (_syntax.InFact(UriSyntaxFlags.MustHaveAuthority))
                                {
                                    // when DosPath found and Authority is required, set this flag even if Authority is empty
                                    _flags |= Flags.AuthorityFound;
                                }
                                if (i != idx && i - idx != 2)
                                {
                                    //This will remember that DosPath is rooted
                                    idx = (ushort)(i - 1);
                                }
                                else
                                {
                                    idx = i;
                                }
                            }
                        }
                        else if (_syntax.InFact(UriSyntaxFlags.FileLikeUri) && (i - idx >= 2 && i - idx != 3 &&
                            i < length && pUriString[i] != '?' && pUriString[i] != '#'))
                        {
                            // V1.0 did not support file:///, fixing it with minimal behavior change impact
                            // Only FILE scheme may have UNC Path flag set
                            _flags |= Flags.UncPath;
                            idx = i;
                        }
                    }
                }
                //
                //STEP 1.5 decide on the Authority component
                //
                if ((_flags & (Flags.UncPath | Flags.DosPath)) != 0)
                {
                }
                else if ((idx + 2) <= length)
                {
                    char first = pUriString[idx];
                    char second = pUriString[idx + 1];

                    if (_syntax.InFact(UriSyntaxFlags.MustHaveAuthority))
                    {
                        // (V1.0 compatibility) This will allow http:\\ http:\/ http:/\
                        if ((first == '/' || first == '\\') && (second == '/' || second == '\\'))
                        {
                            _flags |= Flags.AuthorityFound;
                            idx += 2;
                        }
                        else
                        {
                            return ParsingError.BadAuthority;
                        }
                    }
                    else if (_syntax.InFact(UriSyntaxFlags.OptionalAuthority) && (InFact(Flags.AuthorityFound) ||
                        (first == '/' && second == '/')))
                    {
                        _flags |= Flags.AuthorityFound;
                        idx += 2;
                    }
                    else if (_syntax.NotAny(UriSyntaxFlags.MailToLikeUri))
                    {
                        // There is no Authority component, save the Path index
                        // Note: mailto is the only guy who is treated specially, should be not.
                        _flags |= ((Flags)idx | Flags.UnknownHostType);
                        return ParsingError.None;
                    }
                }
                else if (_syntax.InFact(UriSyntaxFlags.MustHaveAuthority))
                {
                    return ParsingError.BadAuthority;
                }
                else if (_syntax.NotAny(UriSyntaxFlags.MailToLikeUri))
                {
                    // There is no Authority component, save the Path index
                    // mailto is treated specially.
                    _flags |= ((Flags)idx | Flags.UnknownHostType);
                    return ParsingError.None;
                }

                // vsmacros://c:\path\file
                // Note that two slashes say there must be an Authority but instead the path goes
                // Fro V1 compat the next block allow this case but not for schemes like http
                if (InFact(Flags.DosPath))
                {
                    _flags |= (((_flags & Flags.AuthorityFound) != 0) ? Flags.BasicHostType : Flags.UnknownHostType);
                    _flags |= (Flags)idx;
                    return ParsingError.None;
                }

                //STEP 2: Check the syntax of authority expecting at least one character in it
                //
                // Note here we do know that there is an authority in the string OR it's a DOS path

                // We may find a userInfo and the port when parsing an authority
                // Also we may find a registry based authority.
                // We must ensure that known schemes do use a server-based authority
                {
                    ParsingError err = ParsingError.None;
                    idx = CheckAuthorityHelper(pUriString, idx, (ushort)length, ref err, ref _flags, _syntax, ref newHost);
                    if (err != ParsingError.None)
                        return err;

                    // This will disallow '\' as the host terminator for any scheme that is not implicitFile or cannot have a Dos Path
                    if ((idx < (ushort)length && pUriString[idx] == '\\') && NotAny(Flags.ImplicitFile) &&
                        _syntax.NotAny(UriSyntaxFlags.AllowDOSPath))
                    {
                        return ParsingError.BadAuthorityTerminator;
                    }
                }

                // The Path (or Port) parsing index is reloaded on demand in CreateUriInfo when accessing a Uri property
                _flags |= (Flags)idx;

                // The rest of the string will be parsed on demand
                // The Host/Authority is all checked, the type is known but the host value string
                // is not created/canonicalized at this point.
            }

            if ((s_IdnScope != UriIdnScope.None) || _iriParsing)
                PrivateParseMinimalIri(newHost, idx);

            return ParsingError.None;
        }