1 /*
  2  * Copyright (c) 2000, 2017, 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 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 
203     public boolean readBoolean() throws IOException {
204         int ch = this.read();
205         if (ch < 0) {
206             throw new EOFException();
207         }
208         return (ch != 0);
209     }
210 
211     public byte readByte() throws IOException {
212         int ch = this.read();
213         if (ch < 0) {
214             throw new EOFException();
215         }
216         return (byte)ch;
217     }
218 
219     public int readUnsignedByte() throws IOException {
220         int ch = this.read();
221         if (ch < 0) {
222             throw new EOFException();
223         }
224         return ch;
225     }
226 
227     public short readShort() throws IOException {
228         if (read(byteBuf, 0, 2) != 2) {
229             throw new EOFException();
230         }
231 
232         if (byteOrder == ByteOrder.BIG_ENDIAN) {
233             return (short)
234                 (((byteBuf[0] & 0xff) << 8) | ((byteBuf[1] & 0xff) << 0));
235         } else {
236             return (short)
237                 (((byteBuf[1] & 0xff) << 8) | ((byteBuf[0] & 0xff) << 0));
238         }
239     }
240 
241     public int readUnsignedShort() throws IOException {
242         return ((int)readShort()) & 0xffff;
243     }
244 
245     public char readChar() throws IOException {
246         return (char)readShort();
247     }
248 
249     public int readInt() throws IOException {
250         if (read(byteBuf, 0, 4) !=  4) {
251             throw new EOFException();
252         }
253 
254         if (byteOrder == ByteOrder.BIG_ENDIAN) {
255             return
256                 (((byteBuf[0] & 0xff) << 24) | ((byteBuf[1] & 0xff) << 16) |
257                  ((byteBuf[2] & 0xff) <<  8) | ((byteBuf[3] & 0xff) <<  0));
258         } else {
259             return
260                 (((byteBuf[3] & 0xff) << 24) | ((byteBuf[2] & 0xff) << 16) |
261                  ((byteBuf[1] & 0xff) <<  8) | ((byteBuf[0] & 0xff) <<  0));
262         }
263     }
264 
265     public long readUnsignedInt() throws IOException {
266         return ((long)readInt()) & 0xffffffffL;
267     }
268 
269     public long readLong() throws IOException {
270         // REMIND: Once 6277756 is fixed, we should do a bulk read of all 8
271         // bytes here as we do in readShort() and readInt() for even better
272         // performance (see 6347575 for details).
273         int i1 = readInt();
274         int i2 = readInt();
275 
276         if (byteOrder == ByteOrder.BIG_ENDIAN) {
277             return ((long)i1 << 32) + (i2 & 0xFFFFFFFFL);
278         } else {
279             return ((long)i2 << 32) + (i1 & 0xFFFFFFFFL);
280         }
281     }
282 
283     public float readFloat() throws IOException {
284         return Float.intBitsToFloat(readInt());
285     }
286 
287     public double readDouble() throws IOException {
288         return Double.longBitsToDouble(readLong());
289     }
290 
291     public String readLine() throws IOException {
292         StringBuilder input = new StringBuilder();
293         int c = -1;
294         boolean eol = false;
295 
296         while (!eol) {
297             switch (c = read()) {
298             case -1:
299             case '\n':
300                 eol = true;
301                 break;
302             case '\r':
303                 eol = true;
304                 long cur = getStreamPosition();
305                 if ((read()) != '\n') {
306                     seek(cur);
307                 }
308                 break;
309             default:
310                 input.append((char)c);
311                 break;
312             }
313         }
314 
315         if ((c == -1) && (input.length() == 0)) {
316             return null;
317         }
318         return input.toString();
319     }
320 
321     public String readUTF() throws IOException {
322         this.bitOffset = 0;
323 
324         // Fix 4494369: method ImageInputStreamImpl.readUTF()
325         // does not work as specified (it should always assume
326         // network byte order).
327         ByteOrder oldByteOrder = getByteOrder();
328         setByteOrder(ByteOrder.BIG_ENDIAN);
329 
330         String ret;
331         try {
332             ret = DataInputStream.readUTF(this);
333         } catch (IOException e) {
334             // Restore the old byte order even if an exception occurs
335             setByteOrder(oldByteOrder);
336             throw e;
337         }
338 
339         setByteOrder(oldByteOrder);
340         return ret;
341     }
342 
343     public void readFully(byte[] b, int off, int len) throws IOException {
344         // Fix 4430357 - if off + len < 0, overflow occurred
345         if (off < 0 || len < 0 || off + len > b.length || off + len < 0) {
346             throw new IndexOutOfBoundsException
347                 ("off < 0 || len < 0 || off + len > b.length!");
348         }
349 
350         while (len > 0) {
351             int nbytes = read(b, off, len);
352             if (nbytes == -1) {
353                 throw new EOFException();
354             }
355             off += nbytes;
356             len -= nbytes;
357         }
358     }
359 
360     public void readFully(byte[] b) throws IOException {
361         readFully(b, 0, b.length);
362     }
363 
364     public void readFully(short[] s, int off, int len) throws IOException {
365         // Fix 4430357 - if off + len < 0, overflow occurred
366         if (off < 0 || len < 0 || off + len > s.length || off + len < 0) {
367             throw new IndexOutOfBoundsException
368                 ("off < 0 || len < 0 || off + len > s.length!");
369         }
370 
371         while (len > 0) {
372             int nelts = Math.min(len, byteBuf.length/2);
373             readFully(byteBuf, 0, nelts*2);
374             toShorts(byteBuf, s, off, nelts);
375             off += nelts;
376             len -= nelts;
377         }
378     }
379 
380     public void readFully(char[] c, int off, int len) throws IOException {
381         // Fix 4430357 - if off + len < 0, overflow occurred
382         if (off < 0 || len < 0 || off + len > c.length || off + len < 0) {
383             throw new IndexOutOfBoundsException
384                 ("off < 0 || len < 0 || off + len > c.length!");
385         }
386 
387         while (len > 0) {
388             int nelts = Math.min(len, byteBuf.length/2);
389             readFully(byteBuf, 0, nelts*2);
390             toChars(byteBuf, c, off, nelts);
391             off += nelts;
392             len -= nelts;
393         }
394     }
395 
396     public void readFully(int[] i, int off, int len) throws IOException {
397         // Fix 4430357 - if off + len < 0, overflow occurred
398         if (off < 0 || len < 0 || off + len > i.length || off + len < 0) {
399             throw new IndexOutOfBoundsException
400                 ("off < 0 || len < 0 || off + len > i.length!");
401         }
402 
403         while (len > 0) {
404             int nelts = Math.min(len, byteBuf.length/4);
405             readFully(byteBuf, 0, nelts*4);
406             toInts(byteBuf, i, off, nelts);
407             off += nelts;
408             len -= nelts;
409         }
410     }
411 
412     public void readFully(long[] l, int off, int len) throws IOException {
413         // Fix 4430357 - if off + len < 0, overflow occurred
414         if (off < 0 || len < 0 || off + len > l.length || off + len < 0) {
415             throw new IndexOutOfBoundsException
416                 ("off < 0 || len < 0 || off + len > l.length!");
417         }
418 
419         while (len > 0) {
420             int nelts = Math.min(len, byteBuf.length/8);
421             readFully(byteBuf, 0, nelts*8);
422             toLongs(byteBuf, l, off, nelts);
423             off += nelts;
424             len -= nelts;
425         }
426     }
427 
428     public void readFully(float[] f, int off, int len) throws IOException {
429         // Fix 4430357 - if off + len < 0, overflow occurred
430         if (off < 0 || len < 0 || off + len > f.length || off + len < 0) {
431             throw new IndexOutOfBoundsException
432                 ("off < 0 || len < 0 || off + len > f.length!");
433         }
434 
435         while (len > 0) {
436             int nelts = Math.min(len, byteBuf.length/4);
437             readFully(byteBuf, 0, nelts*4);
438             toFloats(byteBuf, f, off, nelts);
439             off += nelts;
440             len -= nelts;
441         }
442     }
443 
444     public void readFully(double[] d, int off, int len) throws IOException {
445         // Fix 4430357 - if off + len < 0, overflow occurred
446         if (off < 0 || len < 0 || off + len > d.length || off + len < 0) {
447             throw new IndexOutOfBoundsException
448                 ("off < 0 || len < 0 || off + len > d.length!");
449         }
450 
451         while (len > 0) {
452             int nelts = Math.min(len, byteBuf.length/8);
453             readFully(byteBuf, 0, nelts*8);
454             toDoubles(byteBuf, d, off, nelts);
455             off += nelts;
456             len -= nelts;
457         }
458     }
459 
460     private void toShorts(byte[] b, short[] s, int off, int len) {
461         int boff = 0;
462         if (byteOrder == ByteOrder.BIG_ENDIAN) {
463             for (int j = 0; j < len; j++) {
464                 int b0 = b[boff];
465                 int b1 = b[boff + 1] & 0xff;
466                 s[off + j] = (short)((b0 << 8) | b1);
467                 boff += 2;
468             }
469         } else {
470             for (int j = 0; j < len; j++) {
471                 int b0 = b[boff + 1];
472                 int b1 = b[boff] & 0xff;
473                 s[off + j] = (short)((b0 << 8) | b1);
474                 boff += 2;
475             }
476         }
477     }
478 
479     private void toChars(byte[] b, char[] c, int off, int len) {
480         int boff = 0;
481         if (byteOrder == ByteOrder.BIG_ENDIAN) {
482             for (int j = 0; j < len; j++) {
483                 int b0 = b[boff];
484                 int b1 = b[boff + 1] & 0xff;
485                 c[off + j] = (char)((b0 << 8) | b1);
486                 boff += 2;
487             }
488         } else {
489             for (int j = 0; j < len; j++) {
490                 int b0 = b[boff + 1];
491                 int b1 = b[boff] & 0xff;
492                 c[off + j] = (char)((b0 << 8) | b1);
493                 boff += 2;
494             }
495         }
496     }
497 
498     private void toInts(byte[] b, int[] i, int off, int len) {
499         int boff = 0;
500         if (byteOrder == ByteOrder.BIG_ENDIAN) {
501             for (int j = 0; j < len; j++) {
502                 int b0 = b[boff];
503                 int b1 = b[boff + 1] & 0xff;
504                 int b2 = b[boff + 2] & 0xff;
505                 int b3 = b[boff + 3] & 0xff;
506                 i[off + j] = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
507                 boff += 4;
508             }
509         } else {
510             for (int j = 0; j < len; j++) {
511                 int b0 = b[boff + 3];
512                 int b1 = b[boff + 2] & 0xff;
513                 int b2 = b[boff + 1] & 0xff;
514                 int b3 = b[boff] & 0xff;
515                 i[off + j] = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
516                 boff += 4;
517             }
518         }
519     }
520 
521     private void toLongs(byte[] b, long[] l, int off, int len) {
522         int boff = 0;
523         if (byteOrder == ByteOrder.BIG_ENDIAN) {
524             for (int j = 0; j < len; j++) {
525                 int b0 = b[boff];
526                 int b1 = b[boff + 1] & 0xff;
527                 int b2 = b[boff + 2] & 0xff;
528                 int b3 = b[boff + 3] & 0xff;
529                 int b4 = b[boff + 4];
530                 int b5 = b[boff + 5] & 0xff;
531                 int b6 = b[boff + 6] & 0xff;
532                 int b7 = b[boff + 7] & 0xff;
533 
534                 int i0 = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
535                 int i1 = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
536 
537                 l[off + j] = ((long)i0 << 32) | (i1 & 0xffffffffL);
538                 boff += 8;
539             }
540         } else {
541             for (int j = 0; j < len; j++) {
542                 int b0 = b[boff + 7];
543                 int b1 = b[boff + 6] & 0xff;
544                 int b2 = b[boff + 5] & 0xff;
545                 int b3 = b[boff + 4] & 0xff;
546                 int b4 = b[boff + 3];
547                 int b5 = b[boff + 2] & 0xff;
548                 int b6 = b[boff + 1] & 0xff;
549                 int b7 = b[boff]     & 0xff;
550 
551                 int i0 = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
552                 int i1 = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
553 
554                 l[off + j] = ((long)i0 << 32) | (i1 & 0xffffffffL);
555                 boff += 8;
556             }
557         }
558     }
559 
560     private void toFloats(byte[] b, float[] f, int off, int len) {
561         int boff = 0;
562         if (byteOrder == ByteOrder.BIG_ENDIAN) {
563             for (int j = 0; j < len; j++) {
564                 int b0 = b[boff];
565                 int b1 = b[boff + 1] & 0xff;
566                 int b2 = b[boff + 2] & 0xff;
567                 int b3 = b[boff + 3] & 0xff;
568                 int i = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
569                 f[off + j] = Float.intBitsToFloat(i);
570                 boff += 4;
571             }
572         } else {
573             for (int j = 0; j < len; j++) {
574                 int b0 = b[boff + 3];
575                 int b1 = b[boff + 2] & 0xff;
576                 int b2 = b[boff + 1] & 0xff;
577                 int b3 = b[boff + 0] & 0xff;
578                 int i = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
579                 f[off + j] = Float.intBitsToFloat(i);
580                 boff += 4;
581             }
582         }
583     }
584 
585     private void toDoubles(byte[] b, double[] d, int off, int len) {
586         int boff = 0;
587         if (byteOrder == ByteOrder.BIG_ENDIAN) {
588             for (int j = 0; j < len; j++) {
589                 int b0 = b[boff];
590                 int b1 = b[boff + 1] & 0xff;
591                 int b2 = b[boff + 2] & 0xff;
592                 int b3 = b[boff + 3] & 0xff;
593                 int b4 = b[boff + 4];
594                 int b5 = b[boff + 5] & 0xff;
595                 int b6 = b[boff + 6] & 0xff;
596                 int b7 = b[boff + 7] & 0xff;
597 
598                 int i0 = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
599                 int i1 = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
600                 long l = ((long)i0 << 32) | (i1 & 0xffffffffL);
601 
602                 d[off + j] = Double.longBitsToDouble(l);
603                 boff += 8;
604             }
605         } else {
606             for (int j = 0; j < len; j++) {
607                 int b0 = b[boff + 7];
608                 int b1 = b[boff + 6] & 0xff;
609                 int b2 = b[boff + 5] & 0xff;
610                 int b3 = b[boff + 4] & 0xff;
611                 int b4 = b[boff + 3];
612                 int b5 = b[boff + 2] & 0xff;
613                 int b6 = b[boff + 1] & 0xff;
614                 int b7 = b[boff] & 0xff;
615 
616                 int i0 = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
617                 int i1 = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
618                 long l = ((long)i0 << 32) | (i1 & 0xffffffffL);
619 
620                 d[off + j] = Double.longBitsToDouble(l);
621                 boff += 8;
622             }
623         }
624     }
625 
626     public long getStreamPosition() throws IOException {
627         checkClosed();
628         return streamPos;
629     }
630 
631     public int getBitOffset() throws IOException {
632         checkClosed();
633         return bitOffset;
634     }
635 
636     public void setBitOffset(int bitOffset) throws IOException {
637         checkClosed();
638         if (bitOffset < 0 || bitOffset > 7) {
639             throw new IllegalArgumentException("bitOffset must be betwwen 0 and 7!");
640         }
641         this.bitOffset = bitOffset;
642     }
643 
644     public int readBit() throws IOException {
645         checkClosed();
646 
647         // Compute final bit offset before we call read() and seek()
648         int newBitOffset = (this.bitOffset + 1) & 0x7;
649 
650         int val = read();
651         if (val == -1) {
652             throw new EOFException();
653         }
654 
655         if (newBitOffset != 0) {
656             // Move byte position back if in the middle of a byte
657             seek(getStreamPosition() - 1);
658             // Shift the bit to be read to the rightmost position
659             val >>= 8 - newBitOffset;
660         }
661         this.bitOffset = newBitOffset;
662 
663         return val & 0x1;
664     }
665 
666     public long readBits(int numBits) throws IOException {
667         checkClosed();
668 
669         if (numBits < 0 || numBits > 64) {
670             throw new IllegalArgumentException();
671         }
672         if (numBits == 0) {
673             return 0L;
674         }
675 
676         // Have to read additional bits on the left equal to the bit offset
677         int bitsToRead = numBits + bitOffset;
678 
679         // Compute final bit offset before we call read() and seek()
680         int newBitOffset = (this.bitOffset + numBits) & 0x7;
681 
682         // Read a byte at a time, accumulate
683         long accum = 0L;
684         while (bitsToRead > 0) {
685             int val = read();
686             if (val == -1) {
687                 throw new EOFException();
688             }
689 
690             accum <<= 8;
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 
812     public void flushBefore(long pos) throws IOException {
813         checkClosed();
814         if (pos < flushedPos) {
815             throw new IndexOutOfBoundsException("pos < flushedPos!");
816         }
817         if (pos > getStreamPosition()) {
818             throw new IndexOutOfBoundsException("pos > getStreamPosition()!");
819         }
820         // Invariant: flushedPos >= 0
821         flushedPos = pos;
822     }
823 
824     public void flush() throws IOException {
825         flushBefore(getStreamPosition());
826     }
827 
828     public long getFlushedPosition() {
829         return flushedPos;
830     }
831 
832     /**
833      * Default implementation returns false.  Subclasses should
834      * override this if they cache data.
835      */
836     public boolean isCached() {
837         return false;
838     }
839 
840     /**
841      * Default implementation returns false.  Subclasses should
842      * override this if they cache data in main memory.
843      */
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      * @deprecated The {@code finalize} method has been deprecated.
872      *     Subclasses that override {@code finalize} in order to perform cleanup
873      *     should be modified to use alternative cleanup mechanisms and
874      *     to remove the overriding {@code finalize} method.
875      *     When overriding the {@code finalize} method, its implementation must explicitly
876      *     ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}.
877      *     See the specification for {@link Object#finalize()} for further
878      *     information about migration options.
879      */
880     @Deprecated(since="9")
881     protected void finalize() throws Throwable {
882         if (!isClosed) {
883             try {
884                 close();
885             } catch (IOException e) {
886             }
887         }
888         super.finalize();
889     }
890 }