bundles/org.apache.jasper.glassfish/src/org/apache/jasper/xmlparser/UTF8Reader.java
public int read(char ch[], int offset, int length) throws IOException {

        // handle surrogate
        int out = offset;
        if (fSurrogate != -1) {
            ch[offset + 1] = (char)fSurrogate;
            fSurrogate = -1;
            length--;
            out++;
        }

        // read bytes
        int count = 0;
        if (fOffset == 0) {
            // adjust length to read
            if (length > fBuffer.length) {
                length = fBuffer.length;
            }

            // perform read operation
            count = fInputStream.read(fBuffer, 0, length);
            if (count == -1) {
                return -1;
            }
            count += out - offset;
        }

        // skip read; last character was in error
        // NOTE: Having an offset value other than zero means that there was
        //       an error in the last character read. In this case, we have
        //       skipped the read so we don't consume any bytes past the 
        //       error. By signalling the error on the next block read we
        //       allow the method to return the most valid characters that
        //       it can on the previous block read. -Ac
        else {
            count = fOffset;
            fOffset = 0;
        }

        // convert bytes to characters
        final int total = count;
        for (int in = 0; in < total; in++) {
            int b0 = fBuffer[in] & 0x00FF;

            // UTF-8:   [0xxx xxxx]
            // Unicode: [0000 0000] [0xxx xxxx]
            if (b0 < 0x80) {
                ch[out++] = (char)b0;
                continue;
            }

            // UTF-8:   [110y yyyy] [10xx xxxx]
            // Unicode: [0000 0yyy] [yyxx xxxx]
            if ((b0 & 0xE0) == 0xC0) {
                int b1 = -1;
                if (++in < total) { 
                    b1 = fBuffer[in] & 0x00FF; 
                }
                else {
                    b1 = fInputStream.read();
                    if (b1 == -1) {
                        if (out > offset) {
                            fBuffer[0] = (byte)b0;
                            fOffset = 1;
                            return out - offset;
                        }
                        expectedByte(2, 2);
                    }
                    count++;
                }
                if ((b1 & 0xC0) != 0x80) {
                    if (out > offset) {
                        fBuffer[0] = (byte)b0;
                        fBuffer[1] = (byte)b1;
                        fOffset = 2;
                        return out - offset;
                    }
                    invalidByte(2, 2, b1);
                }
                int c = ((b0 << 6) & 0x07C0) | (b1 & 0x003F);
                ch[out++] = (char)c;
                count -= 1;
                continue;
            }

            // UTF-8:   [1110 zzzz] [10yy yyyy] [10xx xxxx]
            // Unicode: [zzzz yyyy] [yyxx xxxx]
            if ((b0 & 0xF0) == 0xE0) {
                int b1 = -1;
                if (++in < total) { 
                    b1 = fBuffer[in] & 0x00FF; 
                }
                else {
                    b1 = fInputStream.read();
                    if (b1 == -1) {
                        if (out > offset) {
                            fBuffer[0] = (byte)b0;
                            fOffset = 1;
                            return out - offset;
                        }
                        expectedByte(2, 3);
                    }
                    count++;
                }
                if ((b1 & 0xC0) != 0x80) {
                    if (out > offset) {
                        fBuffer[0] = (byte)b0;
                        fBuffer[1] = (byte)b1;
                        fOffset = 2;
                        return out - offset;
                    }
                    invalidByte(2, 3, b1);
                }
                int b2 = -1;
                if (++in < total) { 
                    b2 = fBuffer[in] & 0x00FF; 
                }
                else {
                    b2 = fInputStream.read();
                    if (b2 == -1) {
                        if (out > offset) {
                            fBuffer[0] = (byte)b0;
                            fBuffer[1] = (byte)b1;
                            fOffset = 2;
                            return out - offset;
                        }
                        expectedByte(3, 3);
                    }
                    count++;
                }
                if ((b2 & 0xC0) != 0x80) {
                    if (out > offset) {
                        fBuffer[0] = (byte)b0;
                        fBuffer[1] = (byte)b1;
                        fBuffer[2] = (byte)b2;
                        fOffset = 3;
                        return out - offset;
                    }
                    invalidByte(3, 3, b2);
                }
                int c = ((b0 << 12) & 0xF000) | ((b1 << 6) & 0x0FC0) |
                        (b2 & 0x003F);
                ch[out++] = (char)c;
                count -= 2;
                continue;
            }

            // UTF-8:   [1111 0uuu] [10uu zzzz] [10yy yyyy] [10xx xxxx]*
            // Unicode: [1101 10ww] [wwzz zzyy] (high surrogate)
            //          [1101 11yy] [yyxx xxxx] (low surrogate)
            //          * uuuuu = wwww + 1
            if ((b0 & 0xF8) == 0xF0) {
                int b1 = -1;
                if (++in < total) { 
                    b1 = fBuffer[in] & 0x00FF; 
                }
                else {
                    b1 = fInputStream.read();
                    if (b1 == -1) {
                        if (out > offset) {
                            fBuffer[0] = (byte)b0;
                            fOffset = 1;
                            return out - offset;
                        }
                        expectedByte(2, 4);
                    }
                    count++;
                }
                if ((b1 & 0xC0) != 0x80) {
                    if (out > offset) {
                        fBuffer[0] = (byte)b0;
                        fBuffer[1] = (byte)b1;
                        fOffset = 2;
                        return out - offset;
                    }
                    invalidByte(2, 4, b1);
                }
                int b2 = -1;
                if (++in < total) { 
                    b2 = fBuffer[in] & 0x00FF; 
                }
                else {
                    b2 = fInputStream.read();
                    if (b2 == -1) {
                        if (out > offset) {
                            fBuffer[0] = (byte)b0;
                            fBuffer[1] = (byte)b1;
                            fOffset = 2;
                            return out - offset;
                        }
                        expectedByte(3, 4);
                    }
                    count++;
                }
                if ((b2 & 0xC0) != 0x80) {
                    if (out > offset) {
                        fBuffer[0] = (byte)b0;
                        fBuffer[1] = (byte)b1;
                        fBuffer[2] = (byte)b2;
                        fOffset = 3;
                        return out - offset;
                    }
                    invalidByte(3, 4, b2);
                }
                int b3 = -1;
                if (++in < total) { 
                    b3 = fBuffer[in] & 0x00FF; 
                }
                else {
                    b3 = fInputStream.read();
                    if (b3 == -1) {
                        if (out > offset) {
                            fBuffer[0] = (byte)b0;
                            fBuffer[1] = (byte)b1;
                            fBuffer[2] = (byte)b2;
                            fOffset = 3;
                            return out - offset;
                        }
                        expectedByte(4, 4);
                    }
                    count++;
                }
                if ((b3 & 0xC0) != 0x80) {
                    if (out > offset) {
                        fBuffer[0] = (byte)b0;
                        fBuffer[1] = (byte)b1;
                        fBuffer[2] = (byte)b2;
                        fBuffer[3] = (byte)b3;
                        fOffset = 4;
                        return out - offset;
                    }
                    invalidByte(4, 4, b2);
                }

                // decode bytes into surrogate characters
                int uuuuu = ((b0 << 2) & 0x001C) | ((b1 >> 4) & 0x0003);
                if (uuuuu > 0x10) {
                    invalidSurrogate(uuuuu);
                }
                int wwww = uuuuu - 1;
                int zzzz = b1 & 0x000F;
                int yyyyyy = b2 & 0x003F;
                int xxxxxx = b3 & 0x003F;
                int hs = 0xD800 | ((wwww << 6) & 0x03C0) | (zzzz << 2) | (yyyyyy >> 4);
                int ls = 0xDC00 | ((yyyyyy << 6) & 0x03C0) | xxxxxx;

                // set characters
                ch[out++] = (char)hs;
                ch[out++] = (char)ls;
                count -= 2;
                continue;
            }

            // error
            if (out > offset) {
                fBuffer[0] = (byte)b0;
                fOffset = 1;
                return out - offset;
            }
            invalidByte(1, 1, b0);
        }

        // return number of characters converted
        return count;

    }
public int read(char ch[], int offset, int length) throws IOException {

        // handle surrogate
        int out = offset;
        if (fSurrogate != -1) {
            ch[offset + 1] = (char)fSurrogate;
            fSurrogate = -1;
            length--;
            out++;
        }

        // read bytes
        int count = 0;
        if (fOffset == 0) {
            // adjust length to read
            if (length > fBuffer.length) {
                length = fBuffer.length;
            }

            // perform read operation
            count = fInputStream.read(fBuffer, 0, length);
            if (count == -1) {
                return -1;
            }
            count += out - offset;
        }

        // skip read; last character was in error
        // NOTE: Having an offset value other than zero means that there was
        //       an error in the last character read. In this case, we have
        //       skipped the read so we don't consume any bytes past the 
        //       error. By signalling the error on the next block read we
        //       allow the method to return the most valid characters that
        //       it can on the previous block read. -Ac
        else {
            count = fOffset;
            fOffset = 0;
        }

        // convert bytes to characters
        final int total = count;
        for (int in = 0; in < total; in++) {
            int b0 = fBuffer[in] & 0x00FF;

            // UTF-8:   [0xxx xxxx]
            // Unicode: [0000 0000] [0xxx xxxx]
            if (b0 < 0x80) {
                ch[out++] = (char)b0;
                continue;
            }

            // UTF-8:   [110y yyyy] [10xx xxxx]
            // Unicode: [0000 0yyy] [yyxx xxxx]
            if ((b0 & 0xE0) == 0xC0) {
                int b1 = -1;
                if (++in < total) { 
                    b1 = fBuffer[in] & 0x00FF; 
                }
                else {
                    b1 = fInputStream.read();
                    if (b1 == -1) {
                        if (out > offset) {
                            fBuffer[0] = (byte)b0;
                            fOffset = 1;
                            return out - offset;
                        }
                        expectedByte(2, 2);
                    }
                    count++;
                }
                if ((b1 & 0xC0) != 0x80) {
                    if (out > offset) {
                        fBuffer[0] = (byte)b0;
                        fBuffer[1] = (byte)b1;
                        fOffset = 2;
                        return out - offset;
                    }
                    invalidByte(2, 2, b1);
                }
                int c = ((b0 << 6) & 0x07C0) | (b1 & 0x003F);
                ch[out++] = (char)c;
                count -= 1;
                continue;
            }

            // UTF-8:   [1110 zzzz] [10yy yyyy] [10xx xxxx]
            // Unicode: [zzzz yyyy] [yyxx xxxx]
            if ((b0 & 0xF0) == 0xE0) {
                int b1 = -1;
                if (++in < total) { 
                    b1 = fBuffer[in] & 0x00FF; 
                }
                else {
                    b1 = fInputStream.read();
                    if (b1 == -1) {
                        if (out > offset) {
                            fBuffer[0] = (byte)b0;
                            fOffset = 1;
                            return out - offset;
                        }
                        expectedByte(2, 3);
                    }
                    count++;
                }
                if ((b1 & 0xC0) != 0x80) {
                    if (out > offset) {
                        fBuffer[0] = (byte)b0;
                        fBuffer[1] = (byte)b1;
                        fOffset = 2;
                        return out - offset;
                    }
                    invalidByte(2, 3, b1);
                }
                int b2 = -1;
                if (++in < total) { 
                    b2 = fBuffer[in] & 0x00FF; 
                }
                else {
                    b2 = fInputStream.read();
                    if (b2 == -1) {
                        if (out > offset) {
                            fBuffer[0] = (byte)b0;
                            fBuffer[1] = (byte)b1;
                            fOffset = 2;
                            return out - offset;
                        }
                        expectedByte(3, 3);
                    }
                    count++;
                }
                if ((b2 & 0xC0) != 0x80) {
                    if (out > offset) {
                        fBuffer[0] = (byte)b0;
                        fBuffer[1] = (byte)b1;
                        fBuffer[2] = (byte)b2;
                        fOffset = 3;
                        return out - offset;
                    }
                    invalidByte(3, 3, b2);
                }
                int c = ((b0 << 12) & 0xF000) | ((b1 << 6) & 0x0FC0) |
                        (b2 & 0x003F);
                ch[out++] = (char)c;
                count -= 2;
                continue;
            }

            // UTF-8:   [1111 0uuu] [10uu zzzz] [10yy yyyy] [10xx xxxx]*
            // Unicode: [1101 10ww] [wwzz zzyy] (high surrogate)
            //          [1101 11yy] [yyxx xxxx] (low surrogate)
            //          * uuuuu = wwww + 1
            if ((b0 & 0xF8) == 0xF0) {
                int b1 = -1;
                if (++in < total) { 
                    b1 = fBuffer[in] & 0x00FF; 
                }
                else {
                    b1 = fInputStream.read();
                    if (b1 == -1) {
                        if (out > offset) {
                            fBuffer[0] = (byte)b0;
                            fOffset = 1;
                            return out - offset;
                        }
                        expectedByte(2, 4);
                    }
                    count++;
                }
                if ((b1 & 0xC0) != 0x80) {
                    if (out > offset) {
                        fBuffer[0] = (byte)b0;
                        fBuffer[1] = (byte)b1;
                        fOffset = 2;
                        return out - offset;
                    }
                    invalidByte(2, 4, b1);
                }
                int b2 = -1;
                if (++in < total) { 
                    b2 = fBuffer[in] & 0x00FF; 
                }
                else {
                    b2 = fInputStream.read();
                    if (b2 == -1) {
                        if (out > offset) {
                            fBuffer[0] = (byte)b0;
                            fBuffer[1] = (byte)b1;
                            fOffset = 2;
                            return out - offset;
                        }
                        expectedByte(3, 4);
                    }
                    count++;
                }
                if ((b2 & 0xC0) != 0x80) {
                    if (out > offset) {
                        fBuffer[0] = (byte)b0;
                        fBuffer[1] = (byte)b1;
                        fBuffer[2] = (byte)b2;
                        fOffset = 3;
                        return out - offset;
                    }
                    invalidByte(3, 4, b2);
                }
                int b3 = -1;
                if (++in < total) { 
                    b3 = fBuffer[in] & 0x00FF; 
                }
                else {
                    b3 = fInputStream.read();
                    if (b3 == -1) {
                        if (out > offset) {
                            fBuffer[0] = (byte)b0;
                            fBuffer[1] = (byte)b1;
                            fBuffer[2] = (byte)b2;
                            fOffset = 3;
                            return out - offset;
                        }
                        expectedByte(4, 4);
                    }
                    count++;
                }
                if ((b3 & 0xC0) != 0x80) {
                    if (out > offset) {
                        fBuffer[0] = (byte)b0;
                        fBuffer[1] = (byte)b1;
                        fBuffer[2] = (byte)b2;
                        fBuffer[3] = (byte)b3;
                        fOffset = 4;
                        return out - offset;
                    }
                    invalidByte(4, 4, b2);
                }

                // decode bytes into surrogate characters
                int uuuuu = ((b0 << 2) & 0x001C) | ((b1 >> 4) & 0x0003);
                if (uuuuu > 0x10) {
                    invalidSurrogate(uuuuu);
                }
                int wwww = uuuuu - 1;
                int zzzz = b1 & 0x000F;
                int yyyyyy = b2 & 0x003F;
                int xxxxxx = b3 & 0x003F;
                int hs = 0xD800 | ((wwww << 6) & 0x03C0) | (zzzz << 2) | (yyyyyy >> 4);
                int ls = 0xDC00 | ((yyyyyy << 6) & 0x03C0) | xxxxxx;

                // set characters
                ch[out++] = (char)hs;
                ch[out++] = (char)ls;
                count -= 2;
                continue;
            }

            // error
            if (out > offset) {
                fBuffer[0] = (byte)b0;
                fOffset = 1;
                return out - offset;
            }
            invalidByte(1, 1, b0);
        }

        // return number of characters converted
        return count;

    }
public int read ( char ch [ ] , int offset , int length ) throws IOException { // handle surrogate int out = offset ; if ( fSurrogate != - 1 ) { ch [ offset + 1 ] = ( char ) fSurrogate ; fSurrogate = - 1 ; length -- ; out ++ ; } // read bytes int count = 0 ; if ( fOffset == 0 ) { // adjust length to read if ( length > fBuffer . length ) { length = fBuffer . length ; } // perform read operation count = fInputStream . read ( fBuffer , 0 , length ) ; if ( count == - 1 ) { return - 1 ; } count += out - offset ; } // skip read; last character was in error // NOTE: Having an offset value other than zero means that there was //       an error in the last character read. In this case, we have //       skipped the read so we don't consume any bytes past the  //       error. By signalling the error on the next block read we //       allow the method to return the most valid characters that //       it can on the previous block read. -Ac else { count = fOffset ; fOffset = 0 ; } // convert bytes to characters final int total = count ; for ( int in = 0 ; in < total ; in ++ ) { int b0 = fBuffer [ in ] & 0x00FF ; // UTF-8:   [0xxx xxxx] // Unicode: [0000 0000] [0xxx xxxx] if ( b0 < 0x80 ) { ch [ out ++ ] = ( char ) b0 ; continue ; } // UTF-8:   [110y yyyy] [10xx xxxx] // Unicode: [0000 0yyy] [yyxx xxxx] if ( ( b0 & 0xE0 ) == 0xC0 ) { int b1 = - 1 ; if ( ++ in < total ) { b1 = fBuffer [ in ] & 0x00FF ; } else { b1 = fInputStream . read ( ) ; if ( b1 == - 1 ) { if ( out > offset ) { fBuffer [ 0 ] = ( byte ) b0 ; fOffset = 1 ; return out - offset ; } expectedByte ( 2 , 2 ) ; } count ++ ; } if ( ( b1 & 0xC0 ) != 0x80 ) { if ( out > offset ) { fBuffer [ 0 ] = ( byte ) b0 ; fBuffer [ 1 ] = ( byte ) b1 ; fOffset = 2 ; return out - offset ; } invalidByte ( 2 , 2 , b1 ) ; } int c = ( ( b0 << 6 ) & 0x07C0 ) | ( b1 & 0x003F ) ; ch [ out ++ ] = ( char ) c ; count -= 1 ; continue ; } // UTF-8:   [1110 zzzz] [10yy yyyy] [10xx xxxx] // Unicode: [zzzz yyyy] [yyxx xxxx] if ( ( b0 & 0xF0 ) == 0xE0 ) { int b1 = - 1 ; if ( ++ in < total ) { b1 = fBuffer [ in ] & 0x00FF ; } else { b1 = fInputStream . read ( ) ; if ( b1 == - 1 ) { if ( out > offset ) { fBuffer [ 0 ] = ( byte ) b0 ; fOffset = 1 ; return out - offset ; } expectedByte ( 2 , 3 ) ; } count ++ ; } if ( ( b1 & 0xC0 ) != 0x80 ) { if ( out > offset ) { fBuffer [ 0 ] = ( byte ) b0 ; fBuffer [ 1 ] = ( byte ) b1 ; fOffset = 2 ; return out - offset ; } invalidByte ( 2 , 3 , b1 ) ; } int b2 = - 1 ; if ( ++ in < total ) { b2 = fBuffer [ in ] & 0x00FF ; } else { b2 = fInputStream . read ( ) ; if ( b2 == - 1 ) { if ( out > offset ) { fBuffer [ 0 ] = ( byte ) b0 ; fBuffer [ 1 ] = ( byte ) b1 ; fOffset = 2 ; return out - offset ; } expectedByte ( 3 , 3 ) ; } count ++ ; } if ( ( b2 & 0xC0 ) != 0x80 ) { if ( out > offset ) { fBuffer [ 0 ] = ( byte ) b0 ; fBuffer [ 1 ] = ( byte ) b1 ; fBuffer [ 2 ] = ( byte ) b2 ; fOffset = 3 ; return out - offset ; } invalidByte ( 3 , 3 , b2 ) ; } int c = ( ( b0 << 12 ) & 0xF000 ) | ( ( b1 << 6 ) & 0x0FC0 ) | ( b2 & 0x003F ) ; ch [ out ++ ] = ( char ) c ; count -= 2 ; continue ; } // UTF-8:   [1111 0uuu] [10uu zzzz] [10yy yyyy] [10xx xxxx]* // Unicode: [1101 10ww] [wwzz zzyy] (high surrogate) //          [1101 11yy] [yyxx xxxx] (low surrogate) //          * uuuuu = wwww + 1 if ( ( b0 & 0xF8 ) == 0xF0 ) { int b1 = - 1 ; if ( ++ in < total ) { b1 = fBuffer [ in ] & 0x00FF ; } else { b1 = fInputStream . read ( ) ; if ( b1 == - 1 ) { if ( out > offset ) { fBuffer [ 0 ] = ( byte ) b0 ; fOffset = 1 ; return out - offset ; } expectedByte ( 2 , 4 ) ; } count ++ ; } if ( ( b1 & 0xC0 ) != 0x80 ) { if ( out > offset ) { fBuffer [ 0 ] = ( byte ) b0 ; fBuffer [ 1 ] = ( byte ) b1 ; fOffset = 2 ; return out - offset ; } invalidByte ( 2 , 4 , b1 ) ; } int b2 = - 1 ; if ( ++ in < total ) { b2 = fBuffer [ in ] & 0x00FF ; } else { b2 = fInputStream . read ( ) ; if ( b2 == - 1 ) { if ( out > offset ) { fBuffer [ 0 ] = ( byte ) b0 ; fBuffer [ 1 ] = ( byte ) b1 ; fOffset = 2 ; return out - offset ; } expectedByte ( 3 , 4 ) ; } count ++ ; } if ( ( b2 & 0xC0 ) != 0x80 ) { if ( out > offset ) { fBuffer [ 0 ] = ( byte ) b0 ; fBuffer [ 1 ] = ( byte ) b1 ; fBuffer [ 2 ] = ( byte ) b2 ; fOffset = 3 ; return out - offset ; } invalidByte ( 3 , 4 , b2 ) ; } int b3 = - 1 ; if ( ++ in < total ) { b3 = fBuffer [ in ] & 0x00FF ; } else { b3 = fInputStream . read ( ) ; if ( b3 == - 1 ) { if ( out > offset ) { fBuffer [ 0 ] = ( byte ) b0 ; fBuffer [ 1 ] = ( byte ) b1 ; fBuffer [ 2 ] = ( byte ) b2 ; fOffset = 3 ; return out - offset ; } expectedByte ( 4 , 4 ) ; } count ++ ; } if ( ( b3 & 0xC0 ) != 0x80 ) { if ( out > offset ) { fBuffer [ 0 ] = ( byte ) b0 ; fBuffer [ 1 ] = ( byte ) b1 ; fBuffer [ 2 ] = ( byte ) b2 ; fBuffer [ 3 ] = ( byte ) b3 ; fOffset = 4 ; return out - offset ; } invalidByte ( 4 , 4 , b2 ) ; } // decode bytes into surrogate characters int uuuuu = ( ( b0 << 2 ) & 0x001C ) | ( ( b1 >> 4 ) & 0x0003 ) ; if ( uuuuu > 0x10 ) { invalidSurrogate ( uuuuu ) ; } int wwww = uuuuu - 1 ; int zzzz = b1 & 0x000F ; int yyyyyy = b2 & 0x003F ; int xxxxxx = b3 & 0x003F ; int hs = 0xD800 | ( ( wwww << 6 ) & 0x03C0 ) | ( zzzz << 2 ) | ( yyyyyy >> 4 ) ; int ls = 0xDC00 | ( ( yyyyyy << 6 ) & 0x03C0 ) | xxxxxx ; // set characters ch [ out ++ ] = ( char ) hs ; ch [ out ++ ] = ( char ) ls ; count -= 2 ; continue ; } // error if ( out > offset ) { fBuffer [ 0 ] = ( byte ) b0 ; fOffset = 1 ; return out - offset ; } invalidByte ( 1 , 1 , b0 ) ; } // return number of characters converted return count ; }
Read characters into a portion of an array.  This method will block
until some input is available, an I/O error occurs, or the end of the
stream is reached.

@param      ch     Destination buffer
@param      offset Offset at which to start storing characters
@param      length Maximum number of characters to read

@return     The number of characters read, or -1 if the end of the
stream has been reached

@exception  IOException  If an I/O error occurs
Read characters into a portion of an array . This method will block until some input is available an I / O error occurs or the end of the stream is reached .