class PieceReader extends SeekReader {


    private PieceTable table;
    private SeekInputStream doc;
    
    private boolean unicode;
    private int charPos;
    private int limit;


    public PieceReader(PieceTable table, SeekInputStream doc)
    throws IOException {
        this.table = table;
        this.doc = doc;
        charPos = 0;
        limit = -1;
    }


    private void seekIfNecessary() throws IOException {
        if (doc == null) {
            throw new IOException("Stream closed.");
        }
        if (charPos >= table.getMaxCharPos()) {
            return;
        }
        if (charPos < limit) {
            return;
        }
        Piece piece = table.next();
        unicode = piece.isUnicode();
        limit = piece.getCharPosLimit();
        doc.position(piece.getFilePos());
    }


    public int read() throws IOException {
        seekIfNecessary();
        if (doc == null) {
            throw new IOException("Stream closed.");
        }
        if (charPos >= table.getMaxCharPos()) {
            return -1;
        }

        int ch;
        if (unicode) {
            ch = Endian.littleChar(doc);
        } else {
            ch = Cp1252.decode(doc.read());
        }
        charPos++;
        return ch;
    }


    public int read(char[] buf, int ofs, int len) throws IOException {<FILL_FUNCTION_BODY>}
    
    
    public void close() throws IOException {
        doc.close();
        table = null;
    }
    
    
    public long position() throws IOException {
        return charPos;
    }
    
    
    public void position(long p) throws IOException {
        if (p > Integer.MAX_VALUE) {
            throw new IOException("File too large.");
        }
        int charPos = (int)p;
        Piece piece = table.pieceFor(charPos);
        if (piece == null) {
            throw new IOException("Illegal position: " + p);
        }
        unicode = piece.isUnicode();
        limit = piece.getCharPosLimit();
        
        int ofs = charPos - piece.getCharPosStart();
        this.charPos = charPos;
        doc.position(piece.getFilePos() + ofs);
    }
}

        // FIXME: Think of a faster implementation that will work with
        // both unicode and non-unicode.
        seekIfNecessary();
        if (doc == null) {
            throw new IOException("Stream closed.");
        }
        if (charPos >= table.getMaxCharPos()) {
            return 0;
        }
        for (int i = 0; i < len; i++) {
            int ch = read();
            if (ch < 0) {
                return i;
            }
            buf[ofs + i] = (char)ch;
        }
        return len;
    
<no_super_class>