FileDocCategorySizeDatePackage
PushbackReader.javaAPI DocAndroid 1.5 API16093Wed May 06 22:41:04 BST 2009java.io

PushbackReader

public class PushbackReader extends FilterReader
Wraps an existing {@link Reader} and adds functionality to "push back" characters that have been read, so that they can be read again. Parsers may find this useful. The number of characters which may be pushed back can be specified during construction. If the buffer of pushed back bytes is empty, characters are read from the underlying reader.
since
Android 1.0

Fields Summary
char[]
buf
The {@code char} array containing the chars to read.
int
pos
The current position within the char array {@code buf}. A value equal to buf.length indicates no chars available. A value of 0 indicates the buffer is full.
Constructors Summary
public PushbackReader(Reader in)
Constructs a new {@code PushbackReader} with the specified reader as source. The size of the pushback buffer is set to the default value of 1 character.

param
in the source reader.
since
Android 1.0

        super(in);
        buf = new char[1];
        pos = 1;
    
public PushbackReader(Reader in, int size)
Constructs a new {@code PushbackReader} with {@code in} as source reader. The size of the pushback buffer is set to {@code size}.

param
in the source reader.
param
size the size of the pushback buffer.
throws
IllegalArgumentException if {@code size} is negative.
since
Android 1.0

        super(in);
        if (size <= 0) {
            throw new IllegalArgumentException(Msg.getString("K0058")); //$NON-NLS-1$
        }
        buf = new char[size];
        pos = size;
    
Methods Summary
public voidclose()
Closes this reader. This implementation closes the source reader and releases the pushback buffer.

throws
IOException if an error occurs while closing this reader.
since
Android 1.0

        synchronized (lock) {
            buf = null;
            in.close();
        }
    
public voidmark(int readAheadLimit)
Marks the current position in this stream. Setting a mark is not supported in this class; this implementation always throws an {@code IOException}.

param
readAheadLimit the number of character that can be read from this reader before the mark is invalidated; this parameter is ignored.
throws
IOException if this method is called.
since
Android 1.0

        throw new IOException(Msg.getString("K007f")); //$NON-NLS-1$
    
public booleanmarkSupported()
Indicates whether this reader supports the {@code mark(int)} and {@code reset()} methods. {@code PushbackReader} does not support them, so it returns {@code false}.

return
always {@code false}.
see
#mark(int)
see
#reset()
since
Android 1.0

        return false;
    
public intread()
Reads a single character from this reader and returns it as an integer with the two higher-order bytes set to 0. Returns -1 if the end of the reader has been reached. If the pushback buffer does not contain any available characters then a character from the source reader is returned. Blocks until one character has been read, the end of the source reader is detected or an exception is thrown.

return
the character read or -1 if the end of the source reader has been reached.
throws
IOException if this reader is closed or an I/O error occurs while reading from this reader.
since
Android 1.0

        synchronized (lock) {
            if (buf == null) {
                throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
            }
            /* Is there a pushback character available? */
            if (pos < buf.length) {
                return buf[pos++];
            }
            /**
             * Assume read() in the InputStream will return 2 lowest-order bytes
             * or -1 if end of stream.
             */
            return in.read();
        }
    
public intread(char[] buffer, int offset, int count)
Reads at most {@code length} bytes from this reader and stores them in byte array {@code buffer} starting at {@code offset}. Characters are read from the pushback buffer first, then from the source reader if more bytes are required. Blocks until {@code count} characters have been read, the end of the source reader is detected or an exception is thrown.

param
buffer the array in which to store the characters read from this reader.
param
offset the initial position in {@code buffer} to store the characters read from this reader.
param
count the maximum number of bytes to store in {@code buffer}.
return
the number of bytes read or -1 if the end of the source reader has been reached.
throws
IndexOutOfBoundsException if {@code offset < 0} or {@code count < 0}, or if {@code offset + count} is greater than the length of {@code buffer}.
throws
IOException if this reader is closed or another I/O error occurs while reading from this reader.
since
Android 1.0

        synchronized (lock) {
            if (null == buf) {
                throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
            }
            // avoid int overflow
            // BEGIN android-changed
            // Exception priorities (in case of multiple errors) differ from
            // RI, but are spec-compliant.
            // made implicit null check explicit, used (offset | count) < 0
            // instead of (offset < 0) || (count < 0) to safe one operation
            if (buffer == null) {
                throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
            }
            if ((offset | count) < 0 || offset > buffer.length - count) {
                throw new IndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
            }
            // END android-changed

            int copiedChars = 0;
            int copyLength = 0;
            int newOffset = offset;
            /* Are there pushback chars available? */
            if (pos < buf.length) {
                copyLength = (buf.length - pos >= count) ? count : buf.length
                        - pos;
                System.arraycopy(buf, pos, buffer, newOffset, copyLength);
                newOffset += copyLength;
                copiedChars += copyLength;
                /* Use up the chars in the local buffer */
                pos += copyLength;
            }
            /* Have we copied enough? */
            if (copyLength == count) {
                return count;
            }
            int inCopied = in.read(buffer, newOffset, count - copiedChars);
            if (inCopied > 0) {
                return inCopied + copiedChars;
            }
            if (copiedChars == 0) {
                return inCopied;
            }
            return copiedChars;
        }
    
public booleanready()
Indicates whether this reader is ready to be read without blocking. Returns {@code true} if this reader will not block when {@code read} is called, {@code false} if unknown or blocking will occur.

return
{@code true} if the receiver will not block when {@code read()} is called, {@code false} if unknown or blocking will occur.
throws
IOException if this reader is closed or some other I/O error occurs.
see
#read()
see
#read(char[], int, int)
since
Android 1.0

        synchronized (lock) {
            if (buf == null) {
                throw new IOException(Msg.getString("K0080")); //$NON-NLS-1$
            }
            return (buf.length - pos > 0 || in.ready());
        }
    
public voidreset()
Resets this reader to the last marked position. Resetting the reader is not supported in this class; this implementation always throws an {@code IOException}.

throws
IOException if this method is called.
since
Android 1.0

        throw new IOException(Msg.getString("K007f")); //$NON-NLS-1$
    
public longskip(long count)
Skips {@code count} characters in this reader. This implementation skips characters in the pushback buffer first and then in the source reader if necessary.

param
count the number of characters to skip.
return
the number of characters actually skipped.
throws
IllegalArgumentException if {@code count < 0}.
throws
IOException if this reader is closed or another I/O error occurs.
since
Android 1.0

        if (count < 0) {
            throw new IllegalArgumentException();
        }
        synchronized (lock) {
            if (buf == null) {
                throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
            }
            if (count == 0) {
                return 0;
            }
            long inSkipped;
            int availableFromBuffer = buf.length - pos;
            if (availableFromBuffer > 0) {
                long requiredFromIn = count - availableFromBuffer;
                if (requiredFromIn <= 0) {
                    pos += count;
                    return count;
                }
                pos += availableFromBuffer;
                inSkipped = in.skip(requiredFromIn);
            } else {
                inSkipped = in.skip(count);
            }
            return inSkipped + availableFromBuffer;
        }
    
public voidunread(char[] buffer)
Pushes all the characters in {@code buffer} back to this reader. The characters are pushed back in such a way that the next character read from this reader is buffer[0], then buffer[1] and so on.

If this reader's internal pushback buffer cannot store the entire contents of {@code buffer}, an {@code IOException} is thrown. Parts of {@code buffer} may have already been copied to the pushback buffer when the exception is thrown.

param
buffer the buffer containing the characters to push back to this reader.
throws
IOException if this reader is closed or the free space in the internal pushback buffer is not sufficient to store the contents of {@code buffer}.
since
Android 1.0

        unread(buffer, 0, buffer.length);
    
public voidunread(char[] buffer, int offset, int count)
Pushes a subset of the characters in {@code buffer} back to this reader. The subset is defined by the start position {@code offset} within {@code buffer} and the number of characters specified by {@code length}. The bytes are pushed back in such a way that the next byte read from this stream is {@code buffer[offset]}, then {@code buffer[1]} and so on.

If this stream's internal pushback buffer cannot store the selected subset of {@code buffer}, an {@code IOException} is thrown. Parts of {@code buffer} may have already been copied to the pushback buffer when the exception is thrown.

param
buffer the buffer containing the characters to push back to this reader.
param
offset the index of the first byte in {@code buffer} to push back.
param
count the number of bytes to push back.
throws
IndexOutOfBoundsException if {@code offset < 0} or {@code count < 0}, or if {@code offset + count} is greater than the length of {@code buffer}.
throws
IOException if this reader is closed or the free space in the internal pushback buffer is not sufficient to store the selected contents of {@code buffer}.
throws
NullPointerException if {@code buffer} is {@code null}.
since
Android 1.0

        synchronized (lock) {
            if (buf == null) {
                throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
            }
            if (count > pos) {
                // Pushback buffer full
                throw new IOException(Msg.getString("K007e")); //$NON-NLS-1$
            }
            // BEGIN android-changed
            if (buffer == null) {
                throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
            }
            // avoid int overflow
            // Exception priorities (in case of multiple errors) differ from
            // RI, but are spec-compliant.
            // used (offset | count) < 0 instead of (offset < 0) || (count < 0)
            // to safe one operation
            if ((offset | count) < 0 || offset > buffer.length - count) {
                throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
            }
            // END android-changed
            for (int i = offset + count - 1; i >= offset; i--) {
                unread(buffer[i]);
            }
        }
    
public voidunread(int oneChar)
Pushes the specified character {@code oneChar} back to this reader. This is done in such a way that the next character read from this reader is {@code (char) oneChar}.

If this reader's internal pushback buffer cannot store the character, an {@code IOException} is thrown.

param
oneChar the character to push back to this stream.
throws
IOException if this reader is closed or the internal pushback buffer is full.
since
Android 1.0

        synchronized (lock) {
            if (buf == null) {
                throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
            }
            if (pos == 0) {
                throw new IOException(Msg.getString("K007e")); //$NON-NLS-1$
            }
            buf[--pos] = (char) oneChar;
        }