emul/mini/src/main/java/java/io/PushbackInputStream.java
branchemul
changeset 554 05224402145d
parent 149 32653a09f0db
child 560 53fafe384803
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/emul/mini/src/main/java/java/io/PushbackInputStream.java	Wed Jan 23 20:39:23 2013 +0100
     1.3 @@ -0,0 +1,388 @@
     1.4 +/*
     1.5 + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.  Oracle designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Oracle in the LICENSE file that accompanied this code.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 + * version 2 for more details (a copy is included in the LICENSE file that
    1.18 + * accompanied this code).
    1.19 + *
    1.20 + * You should have received a copy of the GNU General Public License version
    1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 + *
    1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 + * or visit www.oracle.com if you need additional information or have any
    1.26 + * questions.
    1.27 + */
    1.28 +
    1.29 +package java.io;
    1.30 +
    1.31 +/**
    1.32 + * A <code>PushbackInputStream</code> adds
    1.33 + * functionality to another input stream, namely
    1.34 + * the  ability to "push back" or "unread"
    1.35 + * one byte. This is useful in situations where
    1.36 + * it is  convenient for a fragment of code
    1.37 + * to read an indefinite number of data bytes
    1.38 + * that  are delimited by a particular byte
    1.39 + * value; after reading the terminating byte,
    1.40 + * the  code fragment can "unread" it, so that
    1.41 + * the next read operation on the input stream
    1.42 + * will reread the byte that was pushed back.
    1.43 + * For example, bytes representing the  characters
    1.44 + * constituting an identifier might be terminated
    1.45 + * by a byte representing an  operator character;
    1.46 + * a method whose job is to read just an identifier
    1.47 + * can read until it  sees the operator and
    1.48 + * then push the operator back to be re-read.
    1.49 + *
    1.50 + * @author  David Connelly
    1.51 + * @author  Jonathan Payne
    1.52 + * @since   JDK1.0
    1.53 + */
    1.54 +public
    1.55 +class PushbackInputStream extends FilterInputStream {
    1.56 +    /**
    1.57 +     * The pushback buffer.
    1.58 +     * @since   JDK1.1
    1.59 +     */
    1.60 +    protected byte[] buf;
    1.61 +
    1.62 +    /**
    1.63 +     * The position within the pushback buffer from which the next byte will
    1.64 +     * be read.  When the buffer is empty, <code>pos</code> is equal to
    1.65 +     * <code>buf.length</code>; when the buffer is full, <code>pos</code> is
    1.66 +     * equal to zero.
    1.67 +     *
    1.68 +     * @since   JDK1.1
    1.69 +     */
    1.70 +    protected int pos;
    1.71 +
    1.72 +    /**
    1.73 +     * Check to make sure that this stream has not been closed
    1.74 +     */
    1.75 +    private void ensureOpen() throws IOException {
    1.76 +        if (in == null)
    1.77 +            throw new IOException("Stream closed");
    1.78 +    }
    1.79 +
    1.80 +    /**
    1.81 +     * Creates a <code>PushbackInputStream</code>
    1.82 +     * with a pushback buffer of the specified <code>size</code>,
    1.83 +     * and saves its  argument, the input stream
    1.84 +     * <code>in</code>, for later use. Initially,
    1.85 +     * there is no pushed-back byte  (the field
    1.86 +     * <code>pushBack</code> is initialized to
    1.87 +     * <code>-1</code>).
    1.88 +     *
    1.89 +     * @param  in    the input stream from which bytes will be read.
    1.90 +     * @param  size  the size of the pushback buffer.
    1.91 +     * @exception IllegalArgumentException if size is <= 0
    1.92 +     * @since  JDK1.1
    1.93 +     */
    1.94 +    public PushbackInputStream(InputStream in, int size) {
    1.95 +        super(in);
    1.96 +        if (size <= 0) {
    1.97 +            throw new IllegalArgumentException("size <= 0");
    1.98 +        }
    1.99 +        this.buf = new byte[size];
   1.100 +        this.pos = size;
   1.101 +    }
   1.102 +
   1.103 +    /**
   1.104 +     * Creates a <code>PushbackInputStream</code>
   1.105 +     * and saves its  argument, the input stream
   1.106 +     * <code>in</code>, for later use. Initially,
   1.107 +     * there is no pushed-back byte  (the field
   1.108 +     * <code>pushBack</code> is initialized to
   1.109 +     * <code>-1</code>).
   1.110 +     *
   1.111 +     * @param   in   the input stream from which bytes will be read.
   1.112 +     */
   1.113 +    public PushbackInputStream(InputStream in) {
   1.114 +        this(in, 1);
   1.115 +    }
   1.116 +
   1.117 +    /**
   1.118 +     * Reads the next byte of data from this input stream. The value
   1.119 +     * byte is returned as an <code>int</code> in the range
   1.120 +     * <code>0</code> to <code>255</code>. If no byte is available
   1.121 +     * because the end of the stream has been reached, the value
   1.122 +     * <code>-1</code> is returned. This method blocks until input data
   1.123 +     * is available, the end of the stream is detected, or an exception
   1.124 +     * is thrown.
   1.125 +     *
   1.126 +     * <p> This method returns the most recently pushed-back byte, if there is
   1.127 +     * one, and otherwise calls the <code>read</code> method of its underlying
   1.128 +     * input stream and returns whatever value that method returns.
   1.129 +     *
   1.130 +     * @return     the next byte of data, or <code>-1</code> if the end of the
   1.131 +     *             stream has been reached.
   1.132 +     * @exception  IOException  if this input stream has been closed by
   1.133 +     *             invoking its {@link #close()} method,
   1.134 +     *             or an I/O error occurs.
   1.135 +     * @see        java.io.InputStream#read()
   1.136 +     */
   1.137 +    public int read() throws IOException {
   1.138 +        ensureOpen();
   1.139 +        if (pos < buf.length) {
   1.140 +            return buf[pos++] & 0xff;
   1.141 +        }
   1.142 +        return super.read();
   1.143 +    }
   1.144 +
   1.145 +    /**
   1.146 +     * Reads up to <code>len</code> bytes of data from this input stream into
   1.147 +     * an array of bytes.  This method first reads any pushed-back bytes; after
   1.148 +     * that, if fewer than <code>len</code> bytes have been read then it
   1.149 +     * reads from the underlying input stream. If <code>len</code> is not zero, the method
   1.150 +     * blocks until at least 1 byte of input is available; otherwise, no
   1.151 +     * bytes are read and <code>0</code> is returned.
   1.152 +     *
   1.153 +     * @param      b     the buffer into which the data is read.
   1.154 +     * @param      off   the start offset in the destination array <code>b</code>
   1.155 +     * @param      len   the maximum number of bytes read.
   1.156 +     * @return     the total number of bytes read into the buffer, or
   1.157 +     *             <code>-1</code> if there is no more data because the end of
   1.158 +     *             the stream has been reached.
   1.159 +     * @exception  NullPointerException If <code>b</code> is <code>null</code>.
   1.160 +     * @exception  IndexOutOfBoundsException If <code>off</code> is negative,
   1.161 +     * <code>len</code> is negative, or <code>len</code> is greater than
   1.162 +     * <code>b.length - off</code>
   1.163 +     * @exception  IOException  if this input stream has been closed by
   1.164 +     *             invoking its {@link #close()} method,
   1.165 +     *             or an I/O error occurs.
   1.166 +     * @see        java.io.InputStream#read(byte[], int, int)
   1.167 +     */
   1.168 +    public int read(byte[] b, int off, int len) throws IOException {
   1.169 +        ensureOpen();
   1.170 +        if (b == null) {
   1.171 +            throw new NullPointerException();
   1.172 +        } else if (off < 0 || len < 0 || len > b.length - off) {
   1.173 +            throw new IndexOutOfBoundsException();
   1.174 +        } else if (len == 0) {
   1.175 +            return 0;
   1.176 +        }
   1.177 +
   1.178 +        int avail = buf.length - pos;
   1.179 +        if (avail > 0) {
   1.180 +            if (len < avail) {
   1.181 +                avail = len;
   1.182 +            }
   1.183 +            arraycopy(buf, pos, b, off, avail);
   1.184 +            pos += avail;
   1.185 +            off += avail;
   1.186 +            len -= avail;
   1.187 +        }
   1.188 +        if (len > 0) {
   1.189 +            len = super.read(b, off, len);
   1.190 +            if (len == -1) {
   1.191 +                return avail == 0 ? -1 : avail;
   1.192 +            }
   1.193 +            return avail + len;
   1.194 +        }
   1.195 +        return avail;
   1.196 +    }
   1.197 +
   1.198 +    /**
   1.199 +     * Pushes back a byte by copying it to the front of the pushback buffer.
   1.200 +     * After this method returns, the next byte to be read will have the value
   1.201 +     * <code>(byte)b</code>.
   1.202 +     *
   1.203 +     * @param      b   the <code>int</code> value whose low-order
   1.204 +     *                  byte is to be pushed back.
   1.205 +     * @exception IOException If there is not enough room in the pushback
   1.206 +     *            buffer for the byte, or this input stream has been closed by
   1.207 +     *            invoking its {@link #close()} method.
   1.208 +     */
   1.209 +    public void unread(int b) throws IOException {
   1.210 +        ensureOpen();
   1.211 +        if (pos == 0) {
   1.212 +            throw new IOException("Push back buffer is full");
   1.213 +        }
   1.214 +        buf[--pos] = (byte)b;
   1.215 +    }
   1.216 +
   1.217 +    /**
   1.218 +     * Pushes back a portion of an array of bytes by copying it to the front
   1.219 +     * of the pushback buffer.  After this method returns, the next byte to be
   1.220 +     * read will have the value <code>b[off]</code>, the byte after that will
   1.221 +     * have the value <code>b[off+1]</code>, and so forth.
   1.222 +     *
   1.223 +     * @param b the byte array to push back.
   1.224 +     * @param off the start offset of the data.
   1.225 +     * @param len the number of bytes to push back.
   1.226 +     * @exception IOException If there is not enough room in the pushback
   1.227 +     *            buffer for the specified number of bytes,
   1.228 +     *            or this input stream has been closed by
   1.229 +     *            invoking its {@link #close()} method.
   1.230 +     * @since     JDK1.1
   1.231 +     */
   1.232 +    public void unread(byte[] b, int off, int len) throws IOException {
   1.233 +        ensureOpen();
   1.234 +        if (len > pos) {
   1.235 +            throw new IOException("Push back buffer is full");
   1.236 +        }
   1.237 +        pos -= len;
   1.238 +        arraycopy(b, off, buf, pos, len);
   1.239 +    }
   1.240 +
   1.241 +    /**
   1.242 +     * Pushes back an array of bytes by copying it to the front of the
   1.243 +     * pushback buffer.  After this method returns, the next byte to be read
   1.244 +     * will have the value <code>b[0]</code>, the byte after that will have the
   1.245 +     * value <code>b[1]</code>, and so forth.
   1.246 +     *
   1.247 +     * @param b the byte array to push back
   1.248 +     * @exception IOException If there is not enough room in the pushback
   1.249 +     *            buffer for the specified number of bytes,
   1.250 +     *            or this input stream has been closed by
   1.251 +     *            invoking its {@link #close()} method.
   1.252 +     * @since     JDK1.1
   1.253 +     */
   1.254 +    public void unread(byte[] b) throws IOException {
   1.255 +        unread(b, 0, b.length);
   1.256 +    }
   1.257 +
   1.258 +    /**
   1.259 +     * Returns an estimate of the number of bytes that can be read (or
   1.260 +     * skipped over) from this input stream without blocking by the next
   1.261 +     * invocation of a method for this input stream. The next invocation might be
   1.262 +     * the same thread or another thread.  A single read or skip of this
   1.263 +     * many bytes will not block, but may read or skip fewer bytes.
   1.264 +     *
   1.265 +     * <p> The method returns the sum of the number of bytes that have been
   1.266 +     * pushed back and the value returned by {@link
   1.267 +     * java.io.FilterInputStream#available available}.
   1.268 +     *
   1.269 +     * @return     the number of bytes that can be read (or skipped over) from
   1.270 +     *             the input stream without blocking.
   1.271 +     * @exception  IOException  if this input stream has been closed by
   1.272 +     *             invoking its {@link #close()} method,
   1.273 +     *             or an I/O error occurs.
   1.274 +     * @see        java.io.FilterInputStream#in
   1.275 +     * @see        java.io.InputStream#available()
   1.276 +     */
   1.277 +    public int available() throws IOException {
   1.278 +        ensureOpen();
   1.279 +        int n = buf.length - pos;
   1.280 +        int avail = super.available();
   1.281 +        return n > (Integer.MAX_VALUE - avail)
   1.282 +                    ? Integer.MAX_VALUE
   1.283 +                    : n + avail;
   1.284 +    }
   1.285 +
   1.286 +    /**
   1.287 +     * Skips over and discards <code>n</code> bytes of data from this
   1.288 +     * input stream. The <code>skip</code> method may, for a variety of
   1.289 +     * reasons, end up skipping over some smaller number of bytes,
   1.290 +     * possibly zero.  If <code>n</code> is negative, no bytes are skipped.
   1.291 +     *
   1.292 +     * <p> The <code>skip</code> method of <code>PushbackInputStream</code>
   1.293 +     * first skips over the bytes in the pushback buffer, if any.  It then
   1.294 +     * calls the <code>skip</code> method of the underlying input stream if
   1.295 +     * more bytes need to be skipped.  The actual number of bytes skipped
   1.296 +     * is returned.
   1.297 +     *
   1.298 +     * @param      n  {@inheritDoc}
   1.299 +     * @return     {@inheritDoc}
   1.300 +     * @exception  IOException  if the stream does not support seek,
   1.301 +     *            or the stream has been closed by
   1.302 +     *            invoking its {@link #close()} method,
   1.303 +     *            or an I/O error occurs.
   1.304 +     * @see        java.io.FilterInputStream#in
   1.305 +     * @see        java.io.InputStream#skip(long n)
   1.306 +     * @since      1.2
   1.307 +     */
   1.308 +    public long skip(long n) throws IOException {
   1.309 +        ensureOpen();
   1.310 +        if (n <= 0) {
   1.311 +            return 0;
   1.312 +        }
   1.313 +
   1.314 +        long pskip = buf.length - pos;
   1.315 +        if (pskip > 0) {
   1.316 +            if (n < pskip) {
   1.317 +                pskip = n;
   1.318 +            }
   1.319 +            pos += pskip;
   1.320 +            n -= pskip;
   1.321 +        }
   1.322 +        if (n > 0) {
   1.323 +            pskip += super.skip(n);
   1.324 +        }
   1.325 +        return pskip;
   1.326 +    }
   1.327 +
   1.328 +    /**
   1.329 +     * Tests if this input stream supports the <code>mark</code> and
   1.330 +     * <code>reset</code> methods, which it does not.
   1.331 +     *
   1.332 +     * @return   <code>false</code>, since this class does not support the
   1.333 +     *           <code>mark</code> and <code>reset</code> methods.
   1.334 +     * @see     java.io.InputStream#mark(int)
   1.335 +     * @see     java.io.InputStream#reset()
   1.336 +     */
   1.337 +    public boolean markSupported() {
   1.338 +        return false;
   1.339 +    }
   1.340 +
   1.341 +    /**
   1.342 +     * Marks the current position in this input stream.
   1.343 +     *
   1.344 +     * <p> The <code>mark</code> method of <code>PushbackInputStream</code>
   1.345 +     * does nothing.
   1.346 +     *
   1.347 +     * @param   readlimit   the maximum limit of bytes that can be read before
   1.348 +     *                      the mark position becomes invalid.
   1.349 +     * @see     java.io.InputStream#reset()
   1.350 +     */
   1.351 +    public synchronized void mark(int readlimit) {
   1.352 +    }
   1.353 +
   1.354 +    /**
   1.355 +     * Repositions this stream to the position at the time the
   1.356 +     * <code>mark</code> method was last called on this input stream.
   1.357 +     *
   1.358 +     * <p> The method <code>reset</code> for class
   1.359 +     * <code>PushbackInputStream</code> does nothing except throw an
   1.360 +     * <code>IOException</code>.
   1.361 +     *
   1.362 +     * @exception  IOException  if this method is invoked.
   1.363 +     * @see     java.io.InputStream#mark(int)
   1.364 +     * @see     java.io.IOException
   1.365 +     */
   1.366 +    public synchronized void reset() throws IOException {
   1.367 +        throw new IOException("mark/reset not supported");
   1.368 +    }
   1.369 +
   1.370 +    /**
   1.371 +     * Closes this input stream and releases any system resources
   1.372 +     * associated with the stream.
   1.373 +     * Once the stream has been closed, further read(), unread(),
   1.374 +     * available(), reset(), or skip() invocations will throw an IOException.
   1.375 +     * Closing a previously closed stream has no effect.
   1.376 +     *
   1.377 +     * @exception  IOException  if an I/O error occurs.
   1.378 +     */
   1.379 +    public synchronized void close() throws IOException {
   1.380 +        if (in == null)
   1.381 +            return;
   1.382 +        in.close();
   1.383 +        in = null;
   1.384 +        buf = null;
   1.385 +    }
   1.386 +    static void arraycopy(byte[] value, int srcBegin, byte[] dst, int dstBegin, int count) {
   1.387 +        while (count-- > 0) {
   1.388 +            dst[dstBegin++] = value[srcBegin++];
   1.389 +        }
   1.390 +    }
   1.391 +}