Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStreamImpl.java
41153 views
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
}
891
892