/// <summary>UTF8文字を作成する。</summary>
        /// <param name="buf">バイトバッファ。</param>
        /// <param name="i">変換開始位置。</param>
        /// <param name="skip">変換バイト数。</param>
        /// <returns>UTF8文字。</returns>
        internal static UTF8 Build(byte[] buf, int i, int skip)
        {
            var res = new UTF8();

            switch (skip)
            {
            case 1:
                res.ch1 = buf[i];
                break;

            case 2:
                res.ch1 = buf[i];
                res.ch2 = buf[i + 1];
                break;

            case 3:
                res.ch1 = buf[i];
                res.ch2 = buf[i + 1];
                res.ch3 = buf[i + 2];
                break;

            case 4:
                res.ch1 = buf[i];
                res.ch2 = buf[i + 1];
                res.ch3 = buf[i + 2];
                res.ch4 = buf[i + 3];
                break;

            case 5:
                res.ch1 = buf[i];
                res.ch2 = buf[i + 1];
                res.ch3 = buf[i + 2];
                res.ch4 = buf[i + 3];
                res.ch5 = buf[i + 4];
                break;

            default:
                res.ch1 = buf[i];
                res.ch2 = buf[i + 1];
                res.ch3 = buf[i + 2];
                res.ch4 = buf[i + 3];
                res.ch5 = buf[i + 4];
                res.ch6 = buf[i + 5];
                break;
            }
            return(res);
        }
        /// <summary>UNICODEエスケープ判定。</summary>
        /// <param name="iter">イテレータ。</param>
        /// <param name="len">読み込む文字数。</param>
        /// <param name="buf">バイトリスト。</param>
        private static void AppendUnicode(TomlInnerBuffer.TomlIter iter, int len, List <byte> buf)
        {
            // 16進数文字を判定し、数値化
            uint val = 0;

            for (int i = 0; i < len; ++i)
            {
                UTF8 c = iter.GetChar(i);
                val <<= 4;

                if (c.ch1 >= '0' && c.ch1 <= '9')
                {
                    val |= (uint)(c.ch1 - '0');
                }
                else if (c.ch1 >= 'a' && c.ch1 <= 'f')
                {
                    val |= (uint)(10 + c.ch1 - 'a');
                }
                else if (c.ch1 >= 'A' && c.ch1 <= 'F')
                {
                    val |= (uint)(10 + c.ch1 - 'A');
                }
                else
                {
                    throw new TomlAnalisysException(Resources.UNICODE_DEFINE_ERR, iter);
                }
            }

            // UTF8へ変換
            if (val < 0x80)
            {
                buf.Add((byte)(val & 0xff));
            }
            else if (val < 0x800)
            {
                buf.Add((byte)(0xc0 | (val >> 6)));
                buf.Add((byte)(0x80 | (val & 0x3f)));
            }
            else if (val < 0x10000)
            {
                buf.Add((byte)(0xe0 | (val >> 12)));
                buf.Add((byte)(0x80 | ((val >> 6) & 0x3f)));
                buf.Add((byte)(0x80 | (val & 0x3f)));
            }
            else if (val < 0x200000)
            {
                buf.Add((byte)(0xf0 | (val >> 18)));
                buf.Add((byte)(0x80 | ((val >> 12) & 0x3f)));
                buf.Add((byte)(0x80 | ((val >> 6) & 0x3f)));
                buf.Add((byte)(0x80 | (val & 0x3f)));
            }
            else if (val < 0x4000000)
            {
                buf.Add((byte)(0xf8 | (val >> 24)));
                buf.Add((byte)(0x80 | ((val >> 18) & 0x3f)));
                buf.Add((byte)(0x80 | ((val >> 12) & 0x3f)));
                buf.Add((byte)(0x80 | ((val >> 6) & 0x3f)));
                buf.Add((byte)(0x80 | (val & 0x3f)));
            }
            else
            {
                buf.Add((byte)(0xfc | (val >> 30)));
                buf.Add((byte)(0x80 | ((val >> 24) & 0x3f)));
                buf.Add((byte)(0x80 | ((val >> 18) & 0x3f)));
                buf.Add((byte)(0x80 | ((val >> 12) & 0x3f)));
                buf.Add((byte)(0x80 | ((val >> 6) & 0x3f)));
                buf.Add((byte)(0x80 | (val & 0x3f)));
            }
            iter.Skip(len);
        }
        /// <summary>'\'エスケープ文字を取得する。</summary>
        /// <param name="iter">イテレータ。</param>
        /// <param name="buf">バイトリスト。</param>
        private static void AppendEscapeChar(TomlInnerBuffer.TomlIter iter, List <byte> buf)
        {
            if (iter.RemnantLength > 2)
            {
                UTF8 c = iter.GetChar(1);

                switch (c.ch1)
                {
                case (byte)'b':
                    buf.Add((byte)'\b');
                    iter.Skip(2);
                    break;

                case (byte)'t':
                    buf.Add((byte)'\t');
                    iter.Skip(2);
                    break;

                case (byte)'n':
                    buf.Add((byte)'\n');
                    iter.Skip(2);
                    break;

                case (byte)'f':
                    buf.Add((byte)'\f');
                    iter.Skip(2);
                    break;

                case (byte)'r':
                    buf.Add((byte)'\r');
                    iter.Skip(2);
                    break;

                case (byte)'"':
                    buf.Add((byte)'"');
                    iter.Skip(2);
                    break;

                case (byte)'/':
                    buf.Add((byte)'/');
                    iter.Skip(2);
                    break;

                case (byte)'\\':
                    buf.Add((byte)'\\');
                    iter.Skip(2);
                    break;

                case (byte)'u':
                    if (iter.RemnantLength >= 6)
                    {
                        iter.Skip(2);
                        AppendUnicode(iter, 4, buf);
                    }
                    break;

                case (byte)'U':
                    if (iter.RemnantLength >= 10)
                    {
                        iter.Skip(2);
                        AppendUnicode(iter, 8, buf);
                    }
                    break;

                default:
                    throw new TomlAnalisysException(Resources.INVALID_ESCAPE_CHAR_ERR, iter);
                }
            }
        }
        /// <summary>改行まで文字を取り込む。</summary>
        /// <param name="sr">読み込みストリーム。</param>
        public bool ReadLine(Stream sr)
        {
            var res = false;

            while (true)
            {
                // バッファに文字を取り込む
                int maxLen = 0;
                if (this.readed > 0)
                {
                    maxLen      = this.readed;
                    this.readed = 0;
                }
                else
                {
                    maxLen = sr.Read(this.restBuffer, 0, this.restBuffer.Length);
                }

                int skip = 0;
                if (maxLen > 0)
                {
                    res = true;
                    for (int i = 0; i < maxLen && this.restBuffer[i] != 0; i += skip)
                    {
                        // 文字のバイト数を取得
                        skip = GetSkipByte(this.restBuffer[i]);

                        // UTF8の文字をバッファに書き込む
                        //
                        // 1. 文字数分取り込んでいるためバッファに書き込む
                        //    1-1. 改行ならば取り込み中止
                        // 2. 文字数取り込めていないため、次を取り込む
                        if (i + skip <= maxLen)
                        {
                            var ch = UTF8.Build(this.restBuffer, i, skip);      // 1
                            this.characters.Add(ch);

                            if (ch.ch1 == '\n')                                 // 1-1
                            {
                                Buffer.BlockCopy(this.restBuffer, i + 1,
                                                 this.restBuffer, 0,
                                                 this.restBuffer.Length - (i + 1));
                                this.readed    = maxLen - (i + 1);
                                this.xPosition = this.characters.Count;
                                this.yPosition++;
                                goto LOOP_END;
                            }
                        }
                        else
                        {
                            var rest = maxLen - i;                              // 2
                            Buffer.BlockCopy(this.restBuffer, i, this.restBuffer, 0, rest);
                            this.readed = rest + sr.Read(this.restBuffer, rest, this.restBuffer.Length - rest);
                        }
                    }
                }
                else
                {
                    break;
                }
            }
LOOP_END:
            this.IsEndStream = !res;
            return(res);
        }