rt/emul/mini/src/main/java/java/io/PushbackInputStream.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 26 Feb 2013 16:54:16 +0100
changeset 772 d382dacfd73f
parent 560 emul/mini/src/main/java/java/io/PushbackInputStream.java@53fafe384803
permissions -rw-r--r--
Moving modules around so the runtime is under one master pom and can be built without building other modules that are in the repository
     1 /*
     2  * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 
    26 package java.io;
    27 
    28 import org.apidesign.bck2brwsr.emul.lang.System;
    29 
    30 /**
    31  * A <code>PushbackInputStream</code> adds
    32  * functionality to another input stream, namely
    33  * the  ability to "push back" or "unread"
    34  * one byte. This is useful in situations where
    35  * it is  convenient for a fragment of code
    36  * to read an indefinite number of data bytes
    37  * that  are delimited by a particular byte
    38  * value; after reading the terminating byte,
    39  * the  code fragment can "unread" it, so that
    40  * the next read operation on the input stream
    41  * will reread the byte that was pushed back.
    42  * For example, bytes representing the  characters
    43  * constituting an identifier might be terminated
    44  * by a byte representing an  operator character;
    45  * a method whose job is to read just an identifier
    46  * can read until it  sees the operator and
    47  * then push the operator back to be re-read.
    48  *
    49  * @author  David Connelly
    50  * @author  Jonathan Payne
    51  * @since   JDK1.0
    52  */
    53 public
    54 class PushbackInputStream extends FilterInputStream {
    55     /**
    56      * The pushback buffer.
    57      * @since   JDK1.1
    58      */
    59     protected byte[] buf;
    60 
    61     /**
    62      * The position within the pushback buffer from which the next byte will
    63      * be read.  When the buffer is empty, <code>pos</code> is equal to
    64      * <code>buf.length</code>; when the buffer is full, <code>pos</code> is
    65      * equal to zero.
    66      *
    67      * @since   JDK1.1
    68      */
    69     protected int pos;
    70 
    71     /**
    72      * Check to make sure that this stream has not been closed
    73      */
    74     private void ensureOpen() throws IOException {
    75         if (in == null)
    76             throw new IOException("Stream closed");
    77     }
    78 
    79     /**
    80      * Creates a <code>PushbackInputStream</code>
    81      * with a pushback buffer of the specified <code>size</code>,
    82      * and saves its  argument, the input stream
    83      * <code>in</code>, for later use. Initially,
    84      * there is no pushed-back byte  (the field
    85      * <code>pushBack</code> is initialized to
    86      * <code>-1</code>).
    87      *
    88      * @param  in    the input stream from which bytes will be read.
    89      * @param  size  the size of the pushback buffer.
    90      * @exception IllegalArgumentException if size is <= 0
    91      * @since  JDK1.1
    92      */
    93     public PushbackInputStream(InputStream in, int size) {
    94         super(in);
    95         if (size <= 0) {
    96             throw new IllegalArgumentException("size <= 0");
    97         }
    98         this.buf = new byte[size];
    99         this.pos = size;
   100     }
   101 
   102     /**
   103      * Creates a <code>PushbackInputStream</code>
   104      * and saves its  argument, the input stream
   105      * <code>in</code>, for later use. Initially,
   106      * there is no pushed-back byte  (the field
   107      * <code>pushBack</code> is initialized to
   108      * <code>-1</code>).
   109      *
   110      * @param   in   the input stream from which bytes will be read.
   111      */
   112     public PushbackInputStream(InputStream in) {
   113         this(in, 1);
   114     }
   115 
   116     /**
   117      * Reads the next byte of data from this input stream. The value
   118      * byte is returned as an <code>int</code> in the range
   119      * <code>0</code> to <code>255</code>. If no byte is available
   120      * because the end of the stream has been reached, the value
   121      * <code>-1</code> is returned. This method blocks until input data
   122      * is available, the end of the stream is detected, or an exception
   123      * is thrown.
   124      *
   125      * <p> This method returns the most recently pushed-back byte, if there is
   126      * one, and otherwise calls the <code>read</code> method of its underlying
   127      * input stream and returns whatever value that method returns.
   128      *
   129      * @return     the next byte of data, or <code>-1</code> if the end of the
   130      *             stream has been reached.
   131      * @exception  IOException  if this input stream has been closed by
   132      *             invoking its {@link #close()} method,
   133      *             or an I/O error occurs.
   134      * @see        java.io.InputStream#read()
   135      */
   136     public int read() throws IOException {
   137         ensureOpen();
   138         if (pos < buf.length) {
   139             return buf[pos++] & 0xff;
   140         }
   141         return super.read();
   142     }
   143 
   144     /**
   145      * Reads up to <code>len</code> bytes of data from this input stream into
   146      * an array of bytes.  This method first reads any pushed-back bytes; after
   147      * that, if fewer than <code>len</code> bytes have been read then it
   148      * reads from the underlying input stream. If <code>len</code> is not zero, the method
   149      * blocks until at least 1 byte of input is available; otherwise, no
   150      * bytes are read and <code>0</code> is returned.
   151      *
   152      * @param      b     the buffer into which the data is read.
   153      * @param      off   the start offset in the destination array <code>b</code>
   154      * @param      len   the maximum number of bytes read.
   155      * @return     the total number of bytes read into the buffer, or
   156      *             <code>-1</code> if there is no more data because the end of
   157      *             the stream has been reached.
   158      * @exception  NullPointerException If <code>b</code> is <code>null</code>.
   159      * @exception  IndexOutOfBoundsException If <code>off</code> is negative,
   160      * <code>len</code> is negative, or <code>len</code> is greater than
   161      * <code>b.length - off</code>
   162      * @exception  IOException  if this input stream has been closed by
   163      *             invoking its {@link #close()} method,
   164      *             or an I/O error occurs.
   165      * @see        java.io.InputStream#read(byte[], int, int)
   166      */
   167     public int read(byte[] b, int off, int len) throws IOException {
   168         ensureOpen();
   169         if (b == null) {
   170             throw new NullPointerException();
   171         } else if (off < 0 || len < 0 || len > b.length - off) {
   172             throw new IndexOutOfBoundsException();
   173         } else if (len == 0) {
   174             return 0;
   175         }
   176 
   177         int avail = buf.length - pos;
   178         if (avail > 0) {
   179             if (len < avail) {
   180                 avail = len;
   181             }
   182             System.arraycopy(buf, pos, b, off, avail);
   183             pos += avail;
   184             off += avail;
   185             len -= avail;
   186         }
   187         if (len > 0) {
   188             len = super.read(b, off, len);
   189             if (len == -1) {
   190                 return avail == 0 ? -1 : avail;
   191             }
   192             return avail + len;
   193         }
   194         return avail;
   195     }
   196 
   197     /**
   198      * Pushes back a byte by copying it to the front of the pushback buffer.
   199      * After this method returns, the next byte to be read will have the value
   200      * <code>(byte)b</code>.
   201      *
   202      * @param      b   the <code>int</code> value whose low-order
   203      *                  byte is to be pushed back.
   204      * @exception IOException If there is not enough room in the pushback
   205      *            buffer for the byte, or this input stream has been closed by
   206      *            invoking its {@link #close()} method.
   207      */
   208     public void unread(int b) throws IOException {
   209         ensureOpen();
   210         if (pos == 0) {
   211             throw new IOException("Push back buffer is full");
   212         }
   213         buf[--pos] = (byte)b;
   214     }
   215 
   216     /**
   217      * Pushes back a portion of an array of bytes by copying it to the front
   218      * of the pushback buffer.  After this method returns, the next byte to be
   219      * read will have the value <code>b[off]</code>, the byte after that will
   220      * have the value <code>b[off+1]</code>, and so forth.
   221      *
   222      * @param b the byte array to push back.
   223      * @param off the start offset of the data.
   224      * @param len the number of bytes to push back.
   225      * @exception IOException If there is not enough room in the pushback
   226      *            buffer for the specified number of bytes,
   227      *            or this input stream has been closed by
   228      *            invoking its {@link #close()} method.
   229      * @since     JDK1.1
   230      */
   231     public void unread(byte[] b, int off, int len) throws IOException {
   232         ensureOpen();
   233         if (len > pos) {
   234             throw new IOException("Push back buffer is full");
   235         }
   236         pos -= len;
   237         System.arraycopy(b, off, buf, pos, len);
   238     }
   239 
   240     /**
   241      * Pushes back an array of bytes by copying it to the front of the
   242      * pushback buffer.  After this method returns, the next byte to be read
   243      * will have the value <code>b[0]</code>, the byte after that will have the
   244      * value <code>b[1]</code>, and so forth.
   245      *
   246      * @param b the byte array to push back
   247      * @exception IOException If there is not enough room in the pushback
   248      *            buffer for the specified number of bytes,
   249      *            or this input stream has been closed by
   250      *            invoking its {@link #close()} method.
   251      * @since     JDK1.1
   252      */
   253     public void unread(byte[] b) throws IOException {
   254         unread(b, 0, b.length);
   255     }
   256 
   257     /**
   258      * Returns an estimate of the number of bytes that can be read (or
   259      * skipped over) from this input stream without blocking by the next
   260      * invocation of a method for this input stream. The next invocation might be
   261      * the same thread or another thread.  A single read or skip of this
   262      * many bytes will not block, but may read or skip fewer bytes.
   263      *
   264      * <p> The method returns the sum of the number of bytes that have been
   265      * pushed back and the value returned by {@link
   266      * java.io.FilterInputStream#available available}.
   267      *
   268      * @return     the number of bytes that can be read (or skipped over) from
   269      *             the input stream without blocking.
   270      * @exception  IOException  if this input stream has been closed by
   271      *             invoking its {@link #close()} method,
   272      *             or an I/O error occurs.
   273      * @see        java.io.FilterInputStream#in
   274      * @see        java.io.InputStream#available()
   275      */
   276     public int available() throws IOException {
   277         ensureOpen();
   278         int n = buf.length - pos;
   279         int avail = super.available();
   280         return n > (Integer.MAX_VALUE - avail)
   281                     ? Integer.MAX_VALUE
   282                     : n + avail;
   283     }
   284 
   285     /**
   286      * Skips over and discards <code>n</code> bytes of data from this
   287      * input stream. The <code>skip</code> method may, for a variety of
   288      * reasons, end up skipping over some smaller number of bytes,
   289      * possibly zero.  If <code>n</code> is negative, no bytes are skipped.
   290      *
   291      * <p> The <code>skip</code> method of <code>PushbackInputStream</code>
   292      * first skips over the bytes in the pushback buffer, if any.  It then
   293      * calls the <code>skip</code> method of the underlying input stream if
   294      * more bytes need to be skipped.  The actual number of bytes skipped
   295      * is returned.
   296      *
   297      * @param      n  {@inheritDoc}
   298      * @return     {@inheritDoc}
   299      * @exception  IOException  if the stream does not support seek,
   300      *            or the stream has been closed by
   301      *            invoking its {@link #close()} method,
   302      *            or an I/O error occurs.
   303      * @see        java.io.FilterInputStream#in
   304      * @see        java.io.InputStream#skip(long n)
   305      * @since      1.2
   306      */
   307     public long skip(long n) throws IOException {
   308         ensureOpen();
   309         if (n <= 0) {
   310             return 0;
   311         }
   312 
   313         long pskip = buf.length - pos;
   314         if (pskip > 0) {
   315             if (n < pskip) {
   316                 pskip = n;
   317             }
   318             pos += pskip;
   319             n -= pskip;
   320         }
   321         if (n > 0) {
   322             pskip += super.skip(n);
   323         }
   324         return pskip;
   325     }
   326 
   327     /**
   328      * Tests if this input stream supports the <code>mark</code> and
   329      * <code>reset</code> methods, which it does not.
   330      *
   331      * @return   <code>false</code>, since this class does not support the
   332      *           <code>mark</code> and <code>reset</code> methods.
   333      * @see     java.io.InputStream#mark(int)
   334      * @see     java.io.InputStream#reset()
   335      */
   336     public boolean markSupported() {
   337         return false;
   338     }
   339 
   340     /**
   341      * Marks the current position in this input stream.
   342      *
   343      * <p> The <code>mark</code> method of <code>PushbackInputStream</code>
   344      * does nothing.
   345      *
   346      * @param   readlimit   the maximum limit of bytes that can be read before
   347      *                      the mark position becomes invalid.
   348      * @see     java.io.InputStream#reset()
   349      */
   350     public synchronized void mark(int readlimit) {
   351     }
   352 
   353     /**
   354      * Repositions this stream to the position at the time the
   355      * <code>mark</code> method was last called on this input stream.
   356      *
   357      * <p> The method <code>reset</code> for class
   358      * <code>PushbackInputStream</code> does nothing except throw an
   359      * <code>IOException</code>.
   360      *
   361      * @exception  IOException  if this method is invoked.
   362      * @see     java.io.InputStream#mark(int)
   363      * @see     java.io.IOException
   364      */
   365     public synchronized void reset() throws IOException {
   366         throw new IOException("mark/reset not supported");
   367     }
   368 
   369     /**
   370      * Closes this input stream and releases any system resources
   371      * associated with the stream.
   372      * Once the stream has been closed, further read(), unread(),
   373      * available(), reset(), or skip() invocations will throw an IOException.
   374      * Closing a previously closed stream has no effect.
   375      *
   376      * @exception  IOException  if an I/O error occurs.
   377      */
   378     public synchronized void close() throws IOException {
   379         if (in == null)
   380             return;
   381         in.close();
   382         in = null;
   383         buf = null;
   384     }
   385 }