System.Uri.ReCreateParts C# (CSharp) Method

ReCreateParts() private method

private ReCreateParts ( UriComponents parts, ushort nonCanonical, UriFormat formatAs ) : string
parts UriComponents
nonCanonical ushort
formatAs UriFormat
return string
        private string ReCreateParts(UriComponents parts, ushort nonCanonical, UriFormat formatAs)
        {
            EnsureHostString(false);
            string stemp = (parts & UriComponents.Host) == 0 ? string.Empty : _info.Host;
            // we reserve more space than required because a canonical Ipv6 Host
            // may take more characters than in original m_String
            // Also +3 is for :// and +1 is for absent first slash
            // Also we may escape every character, hence multiplying by 12
            // UTF-8 can use up to 4 bytes per char * 3 chars per byte (%A4) = 12 encoded chars
            int count = (_info.Offset.End - _info.Offset.User) * (formatAs == UriFormat.UriEscaped ? 12 : 1);
            char[] chars = new char[stemp.Length + count + _syntax.SchemeName.Length + 3 + 1];
            count = 0;

            //Scheme and slashes
            if ((parts & UriComponents.Scheme) != 0)
            {
                _syntax.SchemeName.CopyTo(0, chars, count, _syntax.SchemeName.Length);
                count += _syntax.SchemeName.Length;
                if (parts != UriComponents.Scheme)
                {
                    chars[count++] = ':';
                    if (InFact(Flags.AuthorityFound))
                    {
                        chars[count++] = '/';
                        chars[count++] = '/';
                    }
                }
            }

            //UserInfo
            if ((parts & UriComponents.UserInfo) != 0 && InFact(Flags.HasUserInfo))
            {
                if ((nonCanonical & (ushort)UriComponents.UserInfo) != 0)
                {
                    switch (formatAs)
                    {
                        case UriFormat.UriEscaped:
                            if (NotAny(Flags.UserEscaped))
                            {
                                chars = UriHelper.EscapeString(_string, _info.Offset.User, _info.Offset.Host, chars,
                                    ref count, true, '?', '#', '%');
                            }
                            else
                            {
                                if (InFact(Flags.E_UserNotCanonical))
                                {
                                    // We should throw here but currently just accept user input known as invalid
                                }
                                _string.CopyTo(_info.Offset.User, chars, count, _info.Offset.Host - _info.Offset.User);
                                count += (_info.Offset.Host - _info.Offset.User);
                            }
                            break;

                        case UriFormat.SafeUnescaped:
                            chars = UriHelper.UnescapeString(_string, _info.Offset.User, _info.Offset.Host - 1,
                                chars, ref count, '@', '/', '\\', InFact(Flags.UserEscaped) ? UnescapeMode.Unescape :
                                UnescapeMode.EscapeUnescape, _syntax, false);
                            chars[count++] = '@';
                            break;

                        case UriFormat.Unescaped:
                            chars = UriHelper.UnescapeString(_string, _info.Offset.User, _info.Offset.Host, chars,
                                ref count, c_DummyChar, c_DummyChar, c_DummyChar,
                                UnescapeMode.Unescape | UnescapeMode.UnescapeAll, _syntax, false);
                            break;

                        default: //V1ToStringUnescape
                            chars = UriHelper.UnescapeString(_string, _info.Offset.User, _info.Offset.Host, chars,
                                ref count, c_DummyChar, c_DummyChar, c_DummyChar, UnescapeMode.CopyOnly, _syntax,
                                false);
                            break;
                    }
                }
                else
                {
                    UriHelper.UnescapeString(_string, _info.Offset.User, _info.Offset.Host, chars, ref count,
                        c_DummyChar, c_DummyChar, c_DummyChar, UnescapeMode.CopyOnly, _syntax, false);
                }
                if (parts == UriComponents.UserInfo)
                {
                    //strip '@' delimiter
                    --count;
                }
            }

            // Host
            if ((parts & UriComponents.Host) != 0 && stemp.Length != 0)
            {
                UnescapeMode mode;
                if (formatAs != UriFormat.UriEscaped && HostType == Flags.BasicHostType
                    && (nonCanonical & (ushort)UriComponents.Host) != 0)
                {
                    // only Basic host could be in the escaped form
                    mode = formatAs == UriFormat.Unescaped
                        ? (UnescapeMode.Unescape | UnescapeMode.UnescapeAll) :
                            (InFact(Flags.UserEscaped) ? UnescapeMode.Unescape : UnescapeMode.EscapeUnescape);
                }
                else
                {
                    mode = UnescapeMode.CopyOnly;
                }
                // NormalizedHost
                if ((parts & UriComponents.NormalizedHost) != 0)
                {
                    unsafe
                    {
                        fixed (char* hostPtr = stemp)
                        {
                            bool allAscii = false;
                            bool atLeastOneValidIdn = false;
                            try
                            {
                                // Upconvert any punycode to unicode, xn--pck -> ?
                                stemp = DomainNameHelper.UnicodeEquivalent(
                                    hostPtr, 0, stemp.Length, ref allAscii, ref atLeastOneValidIdn);
                            }
                            // The host may be invalid punycode (www.xn--?-pck.com), 
                            // but we shouldn't throw after the constructor.
                            catch (UriFormatException) { }
                        }
                    }
                }
                chars = UriHelper.UnescapeString(stemp, 0, stemp.Length, chars, ref count, '/', '?', '#', mode,
                    _syntax, false);

                // A fix up only for SerializationInfo and IpV6 host with a scopeID
                if ((parts & UriComponents.SerializationInfoString) != 0 && HostType == Flags.IPv6HostType &&
                    (object)_info.ScopeId != null)
                {
                    _info.ScopeId.CopyTo(0, chars, count - 1, _info.ScopeId.Length);
                    count += _info.ScopeId.Length;
                    chars[count - 1] = ']';
                }
            }

            //Port (always wants a ':' delimiter if got to this method)
            if ((parts & UriComponents.Port) != 0)
            {
                if ((nonCanonical & (ushort)UriComponents.Port) == 0)
                {
                    //take it from m_String
                    if (InFact(Flags.NotDefaultPort))
                    {
                        ushort start = _info.Offset.Path;
                        while (_string[--start] != ':')
                        {
                            ;
                        }
                        _string.CopyTo(start, chars, count, _info.Offset.Path - start);
                        count += (_info.Offset.Path - start);
                    }
                    else if ((parts & UriComponents.StrongPort) != 0 && _syntax.DefaultPort != UriParser.NoDefaultPort)
                    {
                        chars[count++] = ':';
                        stemp = _info.Offset.PortValue.ToString(CultureInfo.InvariantCulture);
                        stemp.CopyTo(0, chars, count, stemp.Length);
                        count += stemp.Length;
                    }
                }
                else if (InFact(Flags.NotDefaultPort) || ((parts & UriComponents.StrongPort) != 0 &&
                    _syntax.DefaultPort != UriParser.NoDefaultPort))
                {
                    // recreate string from port value
                    chars[count++] = ':';
                    stemp = _info.Offset.PortValue.ToString(CultureInfo.InvariantCulture);
                    stemp.CopyTo(0, chars, count, stemp.Length);
                    count += stemp.Length;
                }
            }

            ushort delimiterAwareIndex;

            //Path
            if ((parts & UriComponents.Path) != 0)
            {
                chars = GetCanonicalPath(chars, ref count, formatAs);

                // (possibly strip the leading '/' delimiter)
                if (parts == UriComponents.Path)
                {
                    if (InFact(Flags.AuthorityFound) && count != 0 && chars[0] == '/')
                    {
                        delimiterAwareIndex = 1; --count;
                    }
                    else
                    {
                        delimiterAwareIndex = 0;
                    }
                    return count == 0 ? string.Empty : new string(chars, delimiterAwareIndex, count);
                }
            }

            //Query (possibly strip the '?' delimiter)
            if ((parts & UriComponents.Query) != 0 && _info.Offset.Query < _info.Offset.Fragment)
            {
                delimiterAwareIndex = (ushort)(_info.Offset.Query + 1);
                if (parts != UriComponents.Query)
                    chars[count++] = '?';   //see Fragment+1 below

                if ((nonCanonical & (ushort)UriComponents.Query) != 0)
                {
                    switch (formatAs)
                    {
                        case UriFormat.UriEscaped:
                            //Can Assert IsImplicitfile == false
                            if (NotAny(Flags.UserEscaped))
                                chars = UriHelper.EscapeString(_string, delimiterAwareIndex, _info.Offset.Fragment, chars,
                                    ref count, true, '#', c_DummyChar, '%');
                            else
                            {
                                UriHelper.UnescapeString(_string, delimiterAwareIndex, _info.Offset.Fragment, chars,
                                    ref count, c_DummyChar, c_DummyChar, c_DummyChar, UnescapeMode.CopyOnly, _syntax,
                                    true);
                            }
                            break;

                        case V1ToStringUnescape:

                            chars = UriHelper.UnescapeString(_string, delimiterAwareIndex, _info.Offset.Fragment, chars,
                                ref count, '#', c_DummyChar, c_DummyChar, (InFact(Flags.UserEscaped) ?
                                UnescapeMode.Unescape : UnescapeMode.EscapeUnescape) | UnescapeMode.V1ToStringFlag,
                                _syntax, true);
                            break;

                        case UriFormat.Unescaped:

                            chars = UriHelper.UnescapeString(_string, delimiterAwareIndex, _info.Offset.Fragment, chars,
                                ref count, '#', c_DummyChar, c_DummyChar,
                                (UnescapeMode.Unescape | UnescapeMode.UnescapeAll), _syntax, true);
                            break;

                        default: // UriFormat.SafeUnescaped

                            chars = UriHelper.UnescapeString(_string, delimiterAwareIndex, _info.Offset.Fragment, chars,
                                ref count, '#', c_DummyChar, c_DummyChar, (InFact(Flags.UserEscaped) ?
                                UnescapeMode.Unescape : UnescapeMode.EscapeUnescape), _syntax, true);
                            break;
                    }
                }
                else
                {
                    UriHelper.UnescapeString(_string, delimiterAwareIndex, _info.Offset.Fragment, chars, ref count,
                        c_DummyChar, c_DummyChar, c_DummyChar, UnescapeMode.CopyOnly, _syntax, true);
                }
            }

            //Fragment (possibly strip the '#' delimiter)
            if ((parts & UriComponents.Fragment) != 0 && _info.Offset.Fragment < _info.Offset.End)
            {
                delimiterAwareIndex = (ushort)(_info.Offset.Fragment + 1);
                if (parts != UriComponents.Fragment)
                    chars[count++] = '#';   //see Fragment+1 below

                if ((nonCanonical & (ushort)UriComponents.Fragment) != 0)
                {
                    switch (formatAs)
                    {
                        case UriFormat.UriEscaped:
                            if (NotAny(Flags.UserEscaped))
                                chars = UriHelper.EscapeString(_string, delimiterAwareIndex, _info.Offset.End, chars,
                                    ref count, true, c_DummyChar, c_DummyChar, '%');
                            else
                            {
                                UriHelper.UnescapeString(_string, delimiterAwareIndex, _info.Offset.End, chars,
                                    ref count, c_DummyChar, c_DummyChar, c_DummyChar, UnescapeMode.CopyOnly, _syntax,
                                    false);
                            }
                            break;

                        case V1ToStringUnescape:

                            chars = UriHelper.UnescapeString(_string, delimiterAwareIndex, _info.Offset.End, chars,
                                ref count, '#', c_DummyChar, c_DummyChar, (InFact(Flags.UserEscaped) ?
                                UnescapeMode.Unescape : UnescapeMode.EscapeUnescape) | UnescapeMode.V1ToStringFlag,
                                _syntax, false);
                            break;
                        case UriFormat.Unescaped:

                            chars = UriHelper.UnescapeString(_string, delimiterAwareIndex, _info.Offset.End, chars,
                                ref count, '#', c_DummyChar, c_DummyChar,
                                UnescapeMode.Unescape | UnescapeMode.UnescapeAll, _syntax, false);
                            break;

                        default: // UriFormat.SafeUnescaped

                            chars = UriHelper.UnescapeString(_string, delimiterAwareIndex, _info.Offset.End, chars,
                                ref count, '#', c_DummyChar, c_DummyChar, (InFact(Flags.UserEscaped) ?
                                UnescapeMode.Unescape : UnescapeMode.EscapeUnescape), _syntax, false);
                            break;
                    }
                }
                else
                {
                    UriHelper.UnescapeString(_string, delimiterAwareIndex, _info.Offset.End, chars, ref count,
                        c_DummyChar, c_DummyChar, c_DummyChar, UnescapeMode.CopyOnly, _syntax, false);
                }
            }

            return new string(chars, 0, count);
        }