Exemple #1
0
        static bool GetNextValue(string charset, Encoder encoder, HexEncoder hex, char[] chars, ref int index,
                                 ref byte[] bytes, ref byte[] encoded, int maxLength, out string value)
        {
            int length = chars.Length - index;

            if (length < maxLength)
            {
                switch (GetEncodeMethod(chars, index, length))
                {
                case EncodeMethod.Quote:
                    value  = MimeUtils.Quote(new string (chars, index, length));
                    index += length;
                    return(false);

                case EncodeMethod.None:
                    value  = new string (chars, index, length);
                    index += length;
                    return(false);
                }
            }

            length = Math.Min(maxLength, length);
            int ratio, count, n;

            do
            {
                count = encoder.GetByteCount(chars, index, length, true);
                if (count > maxLength && length > 1)
                {
                    ratio   = (int)Math.Round((double)count / (double)length);
                    length -= Math.Max((count - maxLength) / ratio, 1);
                    continue;
                }

                if (bytes.Length < count)
                {
                    Array.Resize <byte> (ref bytes, count);
                }

                count = encoder.GetBytes(chars, index, length, bytes, 0, true);

                // Note: the first chunk needs to be encoded in order to declare the charset
                if (index > 0 || charset == "us-ascii")
                {
                    var method = GetEncodeMethod(bytes, count);

                    if (method == EncodeMethod.Quote)
                    {
                        value  = MimeUtils.Quote(Encoding.ASCII.GetString(bytes, 0, count));
                        index += length;
                        return(false);
                    }

                    if (method == EncodeMethod.None)
                    {
                        value  = Encoding.ASCII.GetString(bytes, 0, count);
                        index += length;
                        return(false);
                    }
                }

                n = hex.EstimateOutputLength(count);
                if (encoded.Length < n)
                {
                    Array.Resize <byte> (ref encoded, n);
                }

                // only the first value gets a charset declaration
                int charsetLength = index == 0 ? charset.Length + 2 : 0;

                n = hex.Encode(bytes, 0, count, encoded);
                if (n > 3 && (charsetLength + n) > maxLength)
                {
                    int x = 0;

                    for (int i = n - 1; i >= 0 && charsetLength + i >= maxLength; i--)
                    {
                        if (encoded[i] == (byte)'%')
                        {
                            x--;
                        }
                        else
                        {
                            x++;
                        }
                    }

                    ratio   = (int)Math.Round((double)count / (double)length);
                    length -= Math.Max(x / ratio, 1);
                    continue;
                }

                if (index == 0)
                {
                    value = charset + "''" + Encoding.ASCII.GetString(encoded, 0, n);
                }
                else
                {
                    value = Encoding.ASCII.GetString(encoded, 0, n);
                }
                index += length;
                return(true);
            } while (true);
        }