private void encodeString()

in serialization/src/main/java/com/twitter/serial/stream/bytebuffer/ByteBufferSerializerOutput.java [256:305]


    private void encodeString(@NotNull String string) {
        final int length = string.length();
        final int headerPosition = mByteBuffer.position();
        writeIntHeader(SerializerDefs.TYPE_STRING_ASCII, length);
        boolean isAscii = true;
        for (int i = 0; i < length; ++i) {
            final int ch = (int) string.charAt(i);
            if (ch < 0x80) {
                ensureCapacity(ByteBufferSerializerDefs.SIZE_BYTE);
                mByteBuffer.put((byte) ch);
            } else {
                isAscii = false;
                if (ch < 0x800) {
                    ensureCapacity(2 * ByteBufferSerializerDefs.SIZE_BYTE);
                    mByteBuffer.put((byte) ((ch >> 6) | 0xc0));
                    mByteBuffer.put((byte) ((ch & 0x3f) | 0x80));
                } else if (isSurrogate(ch)) {
                    // A supplementary character.
                    final int low = i + 1 != length ? string.charAt(i + 1) : 0;
                    if (!isSurrogateLead(ch) || !isSurrogate(low) || !isSurrogateTrail(low)) {
                        ensureCapacity(ByteBufferSerializerDefs.SIZE_BYTE);
                        mByteBuffer.put((byte) '?');
                    } else {
                        // Now we know we have a *valid* surrogate pair, we can consume the low surrogate.
                        //noinspection AssignmentToForLoopParameter
                        ++i;
                        ensureCapacity(4 * ByteBufferSerializerDefs.SIZE_BYTE);
                        final int supplementary = getSupplementary(ch, low);
                        mByteBuffer.put((byte) ((supplementary >> 18) | 0xf0));
                        mByteBuffer.put((byte) (((supplementary >> 12) & 0x3f) | 0x80));
                        mByteBuffer.put((byte) (((supplementary >> 6) & 0x3f) | 0x80));
                        mByteBuffer.put((byte) ((supplementary & 0x3f) | 0x80));
                    }
                } else {
                    ensureCapacity(3 * ByteBufferSerializerDefs.SIZE_BYTE);
                    mByteBuffer.put((byte) ((ch >> 12) | 0xe0));
                    mByteBuffer.put((byte) (((ch >> 6) & 0x3f) | 0x80));
                    mByteBuffer.put((byte) ((ch & 0x3f) | 0x80));
                }
            }
        }

        // If the string is not ASCII, update the header.
        if (!isAscii) {
            final int currentPosition = mByteBuffer.position();
            mByteBuffer.position(headerPosition);
            writeIntHeader(SerializerDefs.TYPE_STRING_UTF8, length);
            mByteBuffer.position(currentPosition);
        }
    }