// Fast-Path implementation internal static int WriteUtf8(AbstractByteBuffer buffer, int writerIndex, string value, int len) { int oldWriterIndex = writerIndex; // We can use the _set methods as these not need to do any index checks and reference checks. // This is possible as we called ensureWritable(...) before. for (int i = 0; i < len; i++) { char c = value[i]; if (c < 0x80) { buffer._SetByte(writerIndex++, (byte)c); } else if (c < 0x800) { buffer._SetByte(writerIndex++, (byte)(0xc0 | (c >> 6))); buffer._SetByte(writerIndex++, (byte)(0x80 | (c & 0x3f))); } else if (char.IsSurrogate(c)) { if (!char.IsHighSurrogate(c)) { buffer._SetByte(writerIndex++, WriteUtfUnknown); continue; } char c2; try { // Surrogate Pair consumes 2 characters. Optimistically try to get the next character to avoid // duplicate bounds checking with charAt. If an IndexOutOfBoundsException is thrown we will // re-throw a more informative exception describing the problem. c2 = value[++i]; } catch (IndexOutOfRangeException) { buffer._SetByte(writerIndex++, WriteUtfUnknown); break; } if (!char.IsLowSurrogate(c2)) { buffer._SetByte(writerIndex++, WriteUtfUnknown); buffer._SetByte(writerIndex++, char.IsHighSurrogate(c2) ? WriteUtfUnknown : c2); continue; } int codePoint = CharUtil.ToCodePoint(c, c2); // See http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G2630. buffer._SetByte(writerIndex++, (byte)(0xf0 | (codePoint >> 18))); buffer._SetByte(writerIndex++, (byte)(0x80 | ((codePoint >> 12) & 0x3f))); buffer._SetByte(writerIndex++, (byte)(0x80 | ((codePoint >> 6) & 0x3f))); buffer._SetByte(writerIndex++, (byte)(0x80 | (codePoint & 0x3f))); } else { buffer._SetByte(writerIndex++, (byte)(0xe0 | (c >> 12))); buffer._SetByte(writerIndex++, (byte)(0x80 | ((c >> 6) & 0x3f))); buffer._SetByte(writerIndex++, (byte)(0x80 | (c & 0x3f))); } } return(writerIndex - oldWriterIndex); }