@Override
  public void write(char[] buffer, int offset, int length) {
    if (!_state.isActive()) throw new IllegalStateException(String.valueOf(_state));

    byte[] wsBuffer = _buffer;
    int wsOffset = _offset;

    for (; length > 0; length--) {
      if (wsBuffer.length <= wsOffset + 2) {
        _offset = wsOffset;
        complete(false);
        wsOffset = _offset;
      }

      char ch = buffer[offset++];

      if (ch < 0x80) wsBuffer[wsOffset++] = (byte) ch;
      else if (ch < 0x800) {
        wsBuffer[wsOffset++] = (byte) (0xc0 + (ch >> 6));
        wsBuffer[wsOffset++] = (byte) (0x80 + (ch & 0x3f));
      } else if (0xd800 <= ch && ch <= 0xdbff) {
        _savedPair = ch;
      } else if (0xdc00 <= ch && ch <= 0xdfff) {
        int cp = ((_savedPair & 0x3ff) << 10) + (ch & 0x3ff);
        _savedPair = 0;

        if (buffer.length <= _offset + 4) {
          complete(false);
        }

        cp += 0x10000;

        wsBuffer[wsOffset++] = (byte) (0xf0 + (cp >> 18));
        wsBuffer[wsOffset++] = (byte) (0x80 + ((cp >> 12) & 0x3f));
        wsBuffer[wsOffset++] = (byte) (0x80 + ((cp >> 6) & 0x3f));
        wsBuffer[wsOffset++] = (byte) (0x80 + (cp & 0x3f));
      } else {
        wsBuffer[wsOffset++] = (byte) (0xe0 + (ch >> 12));
        wsBuffer[wsOffset++] = (byte) (0x80 + ((ch >> 6) & 0x3f));
        wsBuffer[wsOffset++] = (byte) (0x80 + (ch & 0x3f));
      }
    }

    _offset = wsOffset;
  }
  @Override
  public void write(int ch) {
    if (!_state.isActive()) throw new IllegalStateException(String.valueOf(_state));

    byte[] buffer = _buffer;

    if (_offset == buffer.length) {
      complete(false);
    }

    if (ch < 0x80) buffer[_offset++] = (byte) ch;
    else if (ch < 0x800) {
      if (buffer.length <= _offset + 1) {
        complete(false);
      }

      buffer[_offset++] = (byte) (0xc0 + (ch >> 6));
      buffer[_offset++] = (byte) (0x80 + (ch & 0x3f));
    } else if (0xd800 <= ch && ch <= 0xdbff) {
      _savedPair = (char) ch;
    } else if (0xdc00 <= ch && ch <= 0xdfff) {
      int cp = ((_savedPair & 0x3ff) << 10) + (ch & 0x3ff);
      _savedPair = 0;

      if (buffer.length <= _offset + 4) {
        complete(false);
      }

      cp += 0x10000;

      buffer[_offset++] = (byte) (0xf0 + (cp >> 18));
      buffer[_offset++] = (byte) (0x80 + ((cp >> 12) & 0x3f));
      buffer[_offset++] = (byte) (0x80 + ((cp >> 6) & 0x3f));
      buffer[_offset++] = (byte) (0x80 + (cp & 0x3f));
    } else {
      if (buffer.length <= _offset + 2) {
        complete(false);
      }

      buffer[_offset++] = (byte) (0xe0 + (ch >> 12));
      buffer[_offset++] = (byte) (0x80 + ((ch >> 6) & 0x3f));
      buffer[_offset++] = (byte) (0x80 + (ch & 0x3f));
    }
  }