//
        // Parse
        //
        //  Convert this IPv6 address into a sequence of 8 16-bit numbers
        //
        // Inputs:
        //  <member>    Name
        //      The validated IPv6 address
        //
        // Outputs:
        //  <member>    numbers
        //      Array filled in with the numbers in the IPv6 groups
        //
        //  <member>    PrefixLength
        //      Set to the number after the prefix separator (/) if found
        //
        // Assumes:
        //  <Name> has been validated and contains only hex digits in groups of
        //  16-bit numbers, the characters ':' and '/', and a possible IPv4
        //  address
        //
        // Returns:
        //  true if this is a loopback, false otherwise. There is no falure indication as the sting must be a valid one.
        //
        // Throws:
        //  Nothing
        //

        unsafe internal static bool Parse(string address, ushort *numbers, int start, ref string scopeId)
        {
            int  number          = 0;
            int  index           = 0;
            int  compressorIndex = -1;
            bool numberIsValid   = true;

            //This used to be a class instance member but have not been used so far
            int PrefixLength = 0;

            if (address[start] == '[')
            {
                ++start;
            }

            for (int i = start; i < address.Length && address[i] != ']';)
            {
                switch (address[i])
                {
                case '%':
                    if (numberIsValid)
                    {
                        numbers[index++] = (ushort)number;
                        numberIsValid    = false;
                    }

                    start = i;
                    for (++i; address[i] != ']' && address[i] != '/'; ++i)
                    {
                        ;
                    }
                    scopeId = address.Substring(start, i - start);
                    // ignore prefix if any
                    for (; address[i] != ']'; ++i)
                    {
                        ;
                    }
                    break;

                case ':':
                    numbers[index++] = (ushort)number;
                    number           = 0;
                    ++i;
                    if (address[i] == ':')
                    {
                        compressorIndex = index;
                        ++i;
                    }
                    else if ((compressorIndex < 0) && (index < 6))
                    {
                        //
                        // no point checking for IPv4 address if we don't
                        // have a compressor or we haven't seen 6 16-bit
                        // numbers yet
                        //

                        break;
                    }

                    //
                    // 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; (address[j] != ']') &&
                         (address[j] != ':') &&
                         (address[j] != '%') &&
                         (address[j] != '/') &&
                         (j < i + 4); ++j)
                    {
                        if (address[j] == '.')
                        {
                            //
                            // we have an IPv4 address. Find the end of it:
                            // we know that since we have a valid IPv6
                            // address, the only things that will terminate
                            // the IPv4 address are the prefix delimiter '/'
                            // or the end-of-string (which we conveniently
                            // delimited with ']')
                            //

                            while ((address[j] != ']') && (address[j] != '/') && (address[j] != '%'))
                            {
                                ++j;
                            }
                            number           = IPv4AddressHelper.ParseHostNumber(address, i, j);
                            numbers[index++] = (ushort)(number >> 16);
                            numbers[index++] = (ushort)number;
                            i = j;

                            //
                            // set this to avoid adding another number to
                            // the array if there's a prefix
                            //

                            number        = 0;
                            numberIsValid = false;
                            break;
                        }
                    }
                    break;

                case '/':
                    if (numberIsValid)
                    {
                        numbers[index++] = (ushort)number;
                        numberIsValid    = false;
                    }

                    //
                    // since we have a valid IPv6 address string, the prefix
                    // length is the last token in the string
                    //

                    for (++i; address[i] != ']'; ++i)
                    {
                        PrefixLength = PrefixLength * 10 + (address[i] - '0');
                    }
                    break;

                default:
                    number = number * 16 + Uri.FromHex(address[i++]);
                    break;
                }
            }

            //
            // add number to the array if its not the prefix length or part of
            // an IPv4 address that's already been handled
            //

            if (numberIsValid)
            {
                numbers[index++] = (ushort)number;
            }

            //
            // if we had a compressor sequence ("::") then we need to expand the
            // numbers array
            //

            if (compressorIndex > 0)
            {
                int toIndex   = NumberOfLabels - 1;
                int fromIndex = index - 1;

                for (int i = index - compressorIndex; i > 0; --i)
                {
                    numbers[toIndex--]   = numbers[fromIndex];
                    numbers[fromIndex--] = 0;
                }
            }

            //
            // is the address loopback? Loopback is defined as one of:
            //
            //  0:0:0:0:0:0:0:1
            //  0:0:0:0:0:0:127.0.0.1       == 0:0:0:0:0:0:7F00:0001
            //  0:0:0:0:0:FFFF:127.0.0.1    == 0:0:0:0:0:FFFF:7F00:0001
            //

            return(((numbers[0] == 0) &&
                    (numbers[1] == 0) &&
                    (numbers[2] == 0) &&
                    (numbers[3] == 0) &&
                    (numbers[4] == 0)) &&
                   (((numbers[5] == 0) &&
                     (numbers[6] == 0) &&
                     (numbers[7] == 1)) ||
                    (((numbers[6] == 0x7F00) &&
                      (numbers[7] == 0x0001)) &&
                     ((numbers[5] == 0) ||
                      (numbers[5] == 0xFFFF)))));
        }
        internal static unsafe bool Parse(string address, ushort *numbers, int start, ref string scopeId)
        {
            int  num  = 0;
            int  num2 = 0;
            int  num3 = -1;
            bool flag = true;
            int  num4 = 0;

            if (address[start] == '[')
            {
                start++;
            }
            int num5 = start;

            while ((num5 < address.Length) && (address[num5] != ']'))
            {
                switch (address[num5])
                {
                case '%':
                {
                    if (flag)
                    {
                        numbers[num2++] = (ushort)num;
                        flag            = false;
                    }
                    start = num5;
                    num5++;
                    while ((address[num5] != ']') && (address[num5] != '/'))
                    {
                        num5++;
                    }
                    scopeId = address.Substring(start, num5 - start);
                    while (address[num5] != ']')
                    {
                        num5++;
                    }
                    continue;
                }

                case '/':
                {
                    if (flag)
                    {
                        numbers[num2++] = (ushort)num;
                        flag            = false;
                    }
                    num5++;
                    while (address[num5] != ']')
                    {
                        num4 = (num4 * 10) + (address[num5] - '0');
                        num5++;
                    }
                    continue;
                }

                case ':':
                {
                    numbers[num2++] = (ushort)num;
                    num             = 0;
                    num5++;
                    if (address[num5] == ':')
                    {
                        num3 = num2;
                        num5++;
                    }
                    else if ((num3 < 0) && (num2 < 6))
                    {
                        continue;
                    }
                    for (int i = num5; (((address[i] != ']') && (address[i] != ':')) && ((address[i] != '%') && (address[i] != '/'))) && (i < (num5 + 4)); i++)
                    {
                        if (address[i] == '.')
                        {
                            while (((address[i] != ']') && (address[i] != '/')) && (address[i] != '%'))
                            {
                                i++;
                            }
                            num             = IPv4AddressHelper.ParseHostNumber(address, num5, i);
                            numbers[num2++] = (ushort)(num >> 0x10);
                            numbers[num2++] = (ushort)num;
                            num5            = i;
                            num             = 0;
                            flag            = false;
                            break;
                        }
                    }
                    continue;
                }
                }
                num = (num * 0x10) + Uri.FromHex(address[num5++]);
            }
            if (flag)
            {
                numbers[num2++] = (ushort)num;
            }
            if (num3 > 0)
            {
                int num7  = 7;
                int index = num2 - 1;
                for (int j = num2 - num3; j > 0; j--)
                {
                    numbers[num7--]  = numbers[index];
                    numbers[index--] = 0;
                }
            }
            if ((((numbers[0] != 0) || (numbers[1] != 0)) || ((numbers[2] != 0) || (numbers[3] != 0))) || (numbers[4] != 0))
            {
                return(false);
            }
            if (((numbers[5] != 0) || (numbers[6] != 0)) || (numbers[7] != 1))
            {
                if ((numbers[6] != 0x7f00) || (numbers[7] != 1))
                {
                    return(false);
                }
                if (numbers[5] != 0)
                {
                    return(numbers[5] == 0xffff);
                }
            }
            return(true);
        }