/// <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); }