< prev index next >

src/java.desktop/share/classes/javax/imageio/stream/ImageInputStreamImpl.java

Print this page




  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 javax.imageio.stream;
  27 
  28 import java.io.DataInputStream;
  29 import java.io.EOFException;
  30 import java.io.IOException;
  31 import java.nio.ByteOrder;
  32 import java.util.Stack;
  33 import javax.imageio.IIOException;
  34 
  35 /**
  36  * An abstract class implementing the <code>ImageInputStream</code> interface.
  37  * This class is designed to reduce the number of methods that must
  38  * be implemented by subclasses.
  39  *
  40  * <p> In particular, this class handles most or all of the details of
  41  * byte order interpretation, buffering, mark/reset, discarding,
  42  * closing, and disposing.
  43  */
  44 public abstract class ImageInputStreamImpl implements ImageInputStream {
  45 
  46     private Stack<Long> markByteStack = new Stack<>();
  47 
  48     private Stack<Integer> markBitStack = new Stack<>();
  49 
  50     private boolean isClosed = false;
  51 
  52     // Length of the buffer used for readFully(type[], int, int)
  53     private static final int BYTE_BUF_LENGTH = 8192;
  54 
  55     /**
  56      * Byte buffer used for readFully(type[], int, int).  Note that this
  57      * array is also used for bulk reads in readShort(), readInt(), etc, so
  58      * it should be large enough to hold a primitive value (i.e. >= 8 bytes).
  59      * Also note that this array is package protected, so that it can be
  60      * used by ImageOutputStreamImpl in a similar manner.
  61      */
  62     byte[] byteBuf = new byte[BYTE_BUF_LENGTH];
  63 
  64     /**
  65      * The byte order of the stream as an instance of the enumeration
  66      * class <code>java.nio.ByteOrder</code>, where
  67      * <code>ByteOrder.BIG_ENDIAN</code> indicates network byte order
  68      * and <code>ByteOrder.LITTLE_ENDIAN</code> indicates the reverse
  69      * order.  By default, the value is
  70      * <code>ByteOrder.BIG_ENDIAN</code>.
  71      */
  72     protected ByteOrder byteOrder = ByteOrder.BIG_ENDIAN;
  73 
  74     /**
  75      * The current read position within the stream.  Subclasses are
  76      * responsible for keeping this value current from any method they
  77      * override that alters the read position.
  78      */
  79     protected long streamPos;
  80 
  81     /**
  82      * The current bit offset within the stream.  Subclasses are
  83      * responsible for keeping this value current from any method they
  84      * override that alters the bit offset.
  85      */
  86     protected int bitOffset;
  87 
  88     /**
  89      * The position prior to which data may be discarded.  Seeking
  90      * to a smaller position is not allowed.  <code>flushedPos</code>
  91      * will always be {@literal >= 0}.
  92      */
  93     protected long flushedPos = 0;
  94 
  95     /**
  96      * Constructs an <code>ImageInputStreamImpl</code>.
  97      */
  98     public ImageInputStreamImpl() {
  99     }
 100 
 101     /**
 102      * Throws an <code>IOException</code> if the stream has been closed.
 103      * Subclasses may call this method from any of their methods that
 104      * require the stream not to be closed.
 105      *
 106      * @exception IOException if the stream is closed.
 107      */
 108     protected final void checkClosed() throws IOException {
 109         if (isClosed) {
 110             throw new IOException("closed");
 111         }
 112     }
 113 
 114     public void setByteOrder(ByteOrder byteOrder) {
 115         this.byteOrder = byteOrder;
 116     }
 117 
 118     public ByteOrder getByteOrder() {
 119         return byteOrder;
 120     }
 121 
 122     /**
 123      * Reads a single byte from the stream and returns it as an
 124      * <code>int</code> between 0 and 255.  If EOF is reached,
 125      * <code>-1</code> is returned.
 126      *
 127      * <p> Subclasses must provide an implementation for this method.
 128      * The subclass implementation should update the stream position
 129      * before exiting.
 130      *
 131      * <p> The bit offset within the stream must be reset to zero before
 132      * the read occurs.
 133      *
 134      * @return the value of the next byte in the stream, or <code>-1</code>
 135      * if EOF is reached.
 136      *
 137      * @exception IOException if the stream has been closed.
 138      */
 139     public abstract int read() throws IOException;
 140 
 141     /**
 142      * A convenience method that calls <code>read(b, 0, b.length)</code>.
 143      *
 144      * <p> The bit offset within the stream is reset to zero before
 145      * the read occurs.
 146      *
 147      * @return the number of bytes actually read, or <code>-1</code>
 148      * to indicate EOF.
 149      *
 150      * @exception NullPointerException if <code>b</code> is
 151      * <code>null</code>.
 152      * @exception IOException if an I/O error occurs.
 153      */
 154     public int read(byte[] b) throws IOException {
 155         return read(b, 0, b.length);
 156     }
 157 
 158     /**
 159      * Reads up to <code>len</code> bytes from the stream, and stores
 160      * them into <code>b</code> starting at index <code>off</code>.
 161      * If no bytes can be read because the end of the stream has been
 162      * reached, <code>-1</code> is returned.
 163      *
 164      * <p> The bit offset within the stream must be reset to zero before
 165      * the read occurs.
 166      *
 167      * <p> Subclasses must provide an implementation for this method.
 168      * The subclass implementation should update the stream position
 169      * before exiting.
 170      *
 171      * @param b an array of bytes to be written to.
 172      * @param off the starting position within <code>b</code> to write to.
 173      * @param len the maximum number of bytes to read.
 174      *
 175      * @return the number of bytes actually read, or <code>-1</code>
 176      * to indicate EOF.
 177      *
 178      * @exception IndexOutOfBoundsException if <code>off</code> is
 179      * negative, <code>len</code> is negative, or <code>off +
 180      * len</code> is greater than <code>b.length</code>.
 181      * @exception NullPointerException if <code>b</code> is
 182      * <code>null</code>.
 183      * @exception IOException if an I/O error occurs.
 184      */
 185     public abstract int read(byte[] b, int off, int len) throws IOException;
 186 
 187     public void readBytes(IIOByteBuffer buf, int len) throws IOException {
 188         if (len < 0) {
 189             throw new IndexOutOfBoundsException("len < 0!");
 190         }
 191         if (buf == null) {
 192             throw new NullPointerException("buf == null!");
 193         }
 194 
 195         byte[] data = new byte[len];
 196         len = read(data, 0, len);
 197 
 198         buf.setData(data);
 199         buf.setOffset(0);
 200         buf.setLength(len);
 201     }
 202 


 691             accum |= val;
 692             bitsToRead -= 8;
 693         }
 694 
 695         // Move byte position back if in the middle of a byte
 696         if (newBitOffset != 0) {
 697             seek(getStreamPosition() - 1);
 698         }
 699         this.bitOffset = newBitOffset;
 700 
 701         // Shift away unwanted bits on the right.
 702         accum >>>= (-bitsToRead); // Negative of bitsToRead == extra bits read
 703 
 704         // Mask out unwanted bits on the left
 705         accum &= (-1L >>> (64 - numBits));
 706 
 707         return accum;
 708     }
 709 
 710     /**
 711      * Returns <code>-1L</code> to indicate that the stream has unknown
 712      * length.  Subclasses must override this method to provide actual
 713      * length information.
 714      *
 715      * @return -1L to indicate unknown length.
 716      */
 717     public long length() {
 718         return -1L;
 719     }
 720 
 721     /**
 722      * Advances the current stream position by calling
 723      * <code>seek(getStreamPosition() + n)</code>.
 724      *
 725      * <p> The bit offset is reset to zero.
 726      *
 727      * @param n the number of bytes to seek forward.
 728      *
 729      * @return an <code>int</code> representing the number of bytes
 730      * skipped.
 731      *
 732      * @exception IOException if <code>getStreamPosition</code>
 733      * throws an <code>IOException</code> when computing either
 734      * the starting or ending position.
 735      */
 736     public int skipBytes(int n) throws IOException {
 737         long pos = getStreamPosition();
 738         seek(pos + n);
 739         return (int)(getStreamPosition() - pos);
 740     }
 741 
 742     /**
 743      * Advances the current stream position by calling
 744      * <code>seek(getStreamPosition() + n)</code>.
 745      *
 746      * <p> The bit offset is reset to zero.
 747      *
 748      * @param n the number of bytes to seek forward.
 749      *
 750      * @return a <code>long</code> representing the number of bytes
 751      * skipped.
 752      *
 753      * @exception IOException if <code>getStreamPosition</code>
 754      * throws an <code>IOException</code> when computing either
 755      * the starting or ending position.
 756      */
 757     public long skipBytes(long n) throws IOException {
 758         long pos = getStreamPosition();
 759         seek(pos + n);
 760         return getStreamPosition() - pos;
 761     }
 762 
 763     public void seek(long pos) throws IOException {
 764         checkClosed();
 765 
 766         // This test also covers pos < 0
 767         if (pos < flushedPos) {
 768             throw new IndexOutOfBoundsException("pos < flushedPos!");
 769         }
 770 
 771         this.streamPos = pos;
 772         this.bitOffset = 0;
 773     }
 774 
 775     /**
 776      * Pushes the current stream position onto a stack of marked
 777      * positions.
 778      */
 779     public void mark() {
 780         try {
 781             markByteStack.push(Long.valueOf(getStreamPosition()));
 782             markBitStack.push(Integer.valueOf(getBitOffset()));
 783         } catch (IOException e) {
 784         }
 785     }
 786 
 787     /**
 788      * Resets the current stream byte and bit positions from the stack
 789      * of marked positions.
 790      *
 791      * <p> An <code>IOException</code> will be thrown if the previous
 792      * marked position lies in the discarded portion of the stream.
 793      *
 794      * @exception IOException if an I/O error occurs.
 795      */
 796     public void reset() throws IOException {
 797         if (markByteStack.empty()) {
 798             return;
 799         }
 800 
 801         long pos = markByteStack.pop().longValue();
 802         if (pos < flushedPos) {
 803             throw new IIOException
 804                 ("Previous marked position has been discarded!");
 805         }
 806         seek(pos);
 807 
 808         int offset = markBitStack.pop().intValue();
 809         setBitOffset(offset);
 810     }
 811 


 844     public boolean isCachedMemory() {
 845         return false;
 846     }
 847 
 848     /**
 849      * Default implementation returns false.  Subclasses should
 850      * override this if they cache data in a temporary file.
 851      */
 852     public boolean isCachedFile() {
 853         return false;
 854     }
 855 
 856     public void close() throws IOException {
 857         checkClosed();
 858 
 859         isClosed = true;
 860     }
 861 
 862     /**
 863      * Finalizes this object prior to garbage collection.  The
 864      * <code>close</code> method is called to close any open input
 865      * source.  This method should not be called from application
 866      * code.
 867      *
 868      * @exception Throwable if an error occurs during superclass
 869      * finalization.
 870      */
 871     protected void finalize() throws Throwable {
 872         if (!isClosed) {
 873             try {
 874                 close();
 875             } catch (IOException e) {
 876             }
 877         }
 878         super.finalize();
 879     }
 880 }


  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 javax.imageio.stream;
  27 
  28 import java.io.DataInputStream;
  29 import java.io.EOFException;
  30 import java.io.IOException;
  31 import java.nio.ByteOrder;
  32 import java.util.Stack;
  33 import javax.imageio.IIOException;
  34 
  35 /**
  36  * An abstract class implementing the {@code ImageInputStream} interface.
  37  * This class is designed to reduce the number of methods that must
  38  * be implemented by subclasses.
  39  *
  40  * <p> In particular, this class handles most or all of the details of
  41  * byte order interpretation, buffering, mark/reset, discarding,
  42  * closing, and disposing.
  43  */
  44 public abstract class ImageInputStreamImpl implements ImageInputStream {
  45 
  46     private Stack<Long> markByteStack = new Stack<>();
  47 
  48     private Stack<Integer> markBitStack = new Stack<>();
  49 
  50     private boolean isClosed = false;
  51 
  52     // Length of the buffer used for readFully(type[], int, int)
  53     private static final int BYTE_BUF_LENGTH = 8192;
  54 
  55     /**
  56      * Byte buffer used for readFully(type[], int, int).  Note that this
  57      * array is also used for bulk reads in readShort(), readInt(), etc, so
  58      * it should be large enough to hold a primitive value (i.e. >= 8 bytes).
  59      * Also note that this array is package protected, so that it can be
  60      * used by ImageOutputStreamImpl in a similar manner.
  61      */
  62     byte[] byteBuf = new byte[BYTE_BUF_LENGTH];
  63 
  64     /**
  65      * The byte order of the stream as an instance of the enumeration
  66      * class {@code java.nio.ByteOrder}, where
  67      * {@code ByteOrder.BIG_ENDIAN} indicates network byte order
  68      * and {@code ByteOrder.LITTLE_ENDIAN} indicates the reverse
  69      * order.  By default, the value is
  70      * {@code ByteOrder.BIG_ENDIAN}.
  71      */
  72     protected ByteOrder byteOrder = ByteOrder.BIG_ENDIAN;
  73 
  74     /**
  75      * The current read position within the stream.  Subclasses are
  76      * responsible for keeping this value current from any method they
  77      * override that alters the read position.
  78      */
  79     protected long streamPos;
  80 
  81     /**
  82      * The current bit offset within the stream.  Subclasses are
  83      * responsible for keeping this value current from any method they
  84      * override that alters the bit offset.
  85      */
  86     protected int bitOffset;
  87 
  88     /**
  89      * The position prior to which data may be discarded.  Seeking
  90      * to a smaller position is not allowed.  {@code flushedPos}
  91      * will always be {@literal >= 0}.
  92      */
  93     protected long flushedPos = 0;
  94 
  95     /**
  96      * Constructs an {@code ImageInputStreamImpl}.
  97      */
  98     public ImageInputStreamImpl() {
  99     }
 100 
 101     /**
 102      * Throws an {@code IOException} if the stream has been closed.
 103      * Subclasses may call this method from any of their methods that
 104      * require the stream not to be closed.
 105      *
 106      * @exception IOException if the stream is closed.
 107      */
 108     protected final void checkClosed() throws IOException {
 109         if (isClosed) {
 110             throw new IOException("closed");
 111         }
 112     }
 113 
 114     public void setByteOrder(ByteOrder byteOrder) {
 115         this.byteOrder = byteOrder;
 116     }
 117 
 118     public ByteOrder getByteOrder() {
 119         return byteOrder;
 120     }
 121 
 122     /**
 123      * Reads a single byte from the stream and returns it as an
 124      * {@code int} between 0 and 255.  If EOF is reached,
 125      * {@code -1} is returned.
 126      *
 127      * <p> Subclasses must provide an implementation for this method.
 128      * The subclass implementation should update the stream position
 129      * before exiting.
 130      *
 131      * <p> The bit offset within the stream must be reset to zero before
 132      * the read occurs.
 133      *
 134      * @return the value of the next byte in the stream, or {@code -1}
 135      * if EOF is reached.
 136      *
 137      * @exception IOException if the stream has been closed.
 138      */
 139     public abstract int read() throws IOException;
 140 
 141     /**
 142      * A convenience method that calls {@code read(b, 0, b.length)}.
 143      *
 144      * <p> The bit offset within the stream is reset to zero before
 145      * the read occurs.
 146      *
 147      * @return the number of bytes actually read, or {@code -1}
 148      * to indicate EOF.
 149      *
 150      * @exception NullPointerException if {@code b} is
 151      * {@code null}.
 152      * @exception IOException if an I/O error occurs.
 153      */
 154     public int read(byte[] b) throws IOException {
 155         return read(b, 0, b.length);
 156     }
 157 
 158     /**
 159      * Reads up to {@code len} bytes from the stream, and stores
 160      * them into {@code b} starting at index {@code off}.
 161      * If no bytes can be read because the end of the stream has been
 162      * reached, {@code -1} is returned.
 163      *
 164      * <p> The bit offset within the stream must be reset to zero before
 165      * the read occurs.
 166      *
 167      * <p> Subclasses must provide an implementation for this method.
 168      * The subclass implementation should update the stream position
 169      * before exiting.
 170      *
 171      * @param b an array of bytes to be written to.
 172      * @param off the starting position within {@code b} to write to.
 173      * @param len the maximum number of bytes to read.
 174      *
 175      * @return the number of bytes actually read, or {@code -1}
 176      * to indicate EOF.
 177      *
 178      * @exception IndexOutOfBoundsException if {@code off} is
 179      * negative, {@code len} is negative, or {@code off + len}
 180      * is greater than {@code b.length}.
 181      * @exception NullPointerException if {@code b} is
 182      * {@code null}.
 183      * @exception IOException if an I/O error occurs.
 184      */
 185     public abstract int read(byte[] b, int off, int len) throws IOException;
 186 
 187     public void readBytes(IIOByteBuffer buf, int len) throws IOException {
 188         if (len < 0) {
 189             throw new IndexOutOfBoundsException("len < 0!");
 190         }
 191         if (buf == null) {
 192             throw new NullPointerException("buf == null!");
 193         }
 194 
 195         byte[] data = new byte[len];
 196         len = read(data, 0, len);
 197 
 198         buf.setData(data);
 199         buf.setOffset(0);
 200         buf.setLength(len);
 201     }
 202 


 691             accum |= val;
 692             bitsToRead -= 8;
 693         }
 694 
 695         // Move byte position back if in the middle of a byte
 696         if (newBitOffset != 0) {
 697             seek(getStreamPosition() - 1);
 698         }
 699         this.bitOffset = newBitOffset;
 700 
 701         // Shift away unwanted bits on the right.
 702         accum >>>= (-bitsToRead); // Negative of bitsToRead == extra bits read
 703 
 704         // Mask out unwanted bits on the left
 705         accum &= (-1L >>> (64 - numBits));
 706 
 707         return accum;
 708     }
 709 
 710     /**
 711      * Returns {@code -1L} to indicate that the stream has unknown
 712      * length.  Subclasses must override this method to provide actual
 713      * length information.
 714      *
 715      * @return -1L to indicate unknown length.
 716      */
 717     public long length() {
 718         return -1L;
 719     }
 720 
 721     /**
 722      * Advances the current stream position by calling
 723      * {@code seek(getStreamPosition() + n)}.
 724      *
 725      * <p> The bit offset is reset to zero.
 726      *
 727      * @param n the number of bytes to seek forward.
 728      *
 729      * @return an {@code int} representing the number of bytes
 730      * skipped.
 731      *
 732      * @exception IOException if {@code getStreamPosition}
 733      * throws an {@code IOException} when computing either
 734      * the starting or ending position.
 735      */
 736     public int skipBytes(int n) throws IOException {
 737         long pos = getStreamPosition();
 738         seek(pos + n);
 739         return (int)(getStreamPosition() - pos);
 740     }
 741 
 742     /**
 743      * Advances the current stream position by calling
 744      * {@code seek(getStreamPosition() + n)}.
 745      *
 746      * <p> The bit offset is reset to zero.
 747      *
 748      * @param n the number of bytes to seek forward.
 749      *
 750      * @return a {@code long} representing the number of bytes
 751      * skipped.
 752      *
 753      * @exception IOException if {@code getStreamPosition}
 754      * throws an {@code IOException} when computing either
 755      * the starting or ending position.
 756      */
 757     public long skipBytes(long n) throws IOException {
 758         long pos = getStreamPosition();
 759         seek(pos + n);
 760         return getStreamPosition() - pos;
 761     }
 762 
 763     public void seek(long pos) throws IOException {
 764         checkClosed();
 765 
 766         // This test also covers pos < 0
 767         if (pos < flushedPos) {
 768             throw new IndexOutOfBoundsException("pos < flushedPos!");
 769         }
 770 
 771         this.streamPos = pos;
 772         this.bitOffset = 0;
 773     }
 774 
 775     /**
 776      * Pushes the current stream position onto a stack of marked
 777      * positions.
 778      */
 779     public void mark() {
 780         try {
 781             markByteStack.push(Long.valueOf(getStreamPosition()));
 782             markBitStack.push(Integer.valueOf(getBitOffset()));
 783         } catch (IOException e) {
 784         }
 785     }
 786 
 787     /**
 788      * Resets the current stream byte and bit positions from the stack
 789      * of marked positions.
 790      *
 791      * <p> An {@code IOException} will be thrown if the previous
 792      * marked position lies in the discarded portion of the stream.
 793      *
 794      * @exception IOException if an I/O error occurs.
 795      */
 796     public void reset() throws IOException {
 797         if (markByteStack.empty()) {
 798             return;
 799         }
 800 
 801         long pos = markByteStack.pop().longValue();
 802         if (pos < flushedPos) {
 803             throw new IIOException
 804                 ("Previous marked position has been discarded!");
 805         }
 806         seek(pos);
 807 
 808         int offset = markBitStack.pop().intValue();
 809         setBitOffset(offset);
 810     }
 811 


 844     public boolean isCachedMemory() {
 845         return false;
 846     }
 847 
 848     /**
 849      * Default implementation returns false.  Subclasses should
 850      * override this if they cache data in a temporary file.
 851      */
 852     public boolean isCachedFile() {
 853         return false;
 854     }
 855 
 856     public void close() throws IOException {
 857         checkClosed();
 858 
 859         isClosed = true;
 860     }
 861 
 862     /**
 863      * Finalizes this object prior to garbage collection.  The
 864      * {@code close} method is called to close any open input
 865      * source.  This method should not be called from application
 866      * code.
 867      *
 868      * @exception Throwable if an error occurs during superclass
 869      * finalization.
 870      */
 871     protected void finalize() throws Throwable {
 872         if (!isClosed) {
 873             try {
 874                 close();
 875             } catch (IOException e) {
 876             }
 877         }
 878         super.finalize();
 879     }
 880 }
< prev index next >