private int getCodePoint() throws IOException {
        if (ungetChar != NO_UNGET_CHAR) {
            int c = ungetChar;
            ungetChar = NO_UNGET_CHAR;
            return c;
        }
        int c = r.read();
        if (c == -1) {
            try {
                r.close();
            } catch (IOException e) {
                // nop
            }
            return c;
        }
        if (!Character.isSurrogate((char) c))
            return c;
        if (!Character.isHighSurrogate((char) c))
            throw new IOException("Invalid unicode sequence");
        int d = r.read();
        if (d == -1) {
            try {
                r.close();
            } catch (IOException e) {
                // nop
            }
            throw new IOException("Invalid unicode sequence");
        }
        if (!Character.isLowSurrogate((char) d))
            throw new IOException("Invalid unicode sequence");
        return Character.toCodePoint((char) c, (char) d);
    }