final int bitOffset = getBitOffset(); long value = readByte() & (0xFF >>> bitOffset); numBits -= (Byte.SIZE - bitOffset); while (numBits > 0) { value = (value << Byte.SIZE) | readUnsignedByte(); numBits -= Byte.SIZE; pushBack(); setBitOffset(numBits); return value;
/** * Reads the next unsigned integer value (32 bits) from the stream. * The implementation is as below: * * {@preformat java * return Integer.toUnsignedLong(readInt()); * } * * @return the value of the next unsigned integer from the stream. * @throws IOException if an error (including EOF) occurred while reading the stream. */ public final long readUnsignedInt() throws IOException { return readInt() & 0xFFFFFFFFL; }
/** * Reads the next unsigned short value (16 bits) from the stream. * The implementation is as below: * * {@preformat java * return Short.toUnsignedInt(readShort()); * } * * @return the value of the next unsigned short from the stream. * @throws IOException if an error (including EOF) occurred while reading the stream. */ public final int readUnsignedShort() throws IOException { return readShort() & 0xFFFF; }
/** * Reads the next offset, which may be encoded on 32 or 64 bits depending on the file format. */ private long readOffset() throws IOException { return is64bits ? input.readLong() : input.readUnsignedInt(); }
/** * Reads a string from the channel in the {@link #NAME_ENCODING}. This is suitable for the dimension, * variable and attribute names in the header. Note that attribute value may have a different encoding. */ private String readName() throws IOException, DataStoreException { final int length = input.readInt(); if (length < 0) { throw malformedHeader(); } final String text = input.readString(length, NAME_ENCODING); align(length); return text; }
case BYTE: {final byte v = input.readByte(); align(1); return v;} case UBYTE: {final short v = (short) input.readUnsignedByte(); align(1); return v;} case SHORT: {final short v = input.readShort(); align(2); return v;} case USHORT: {final int v = input.readUnsignedShort(); align(2); return v;} case INT: return input.readInt(); case INT64: return input.readLong(); case UINT: return input.readUnsignedInt(); case FLOAT: return input.readFloat(); case DOUBLE: return input.readDouble(); final String text = input.readString(length, encoding); align(length); return text.isEmpty() ? null : text; case UBYTE: { final byte[] array = new byte[length]; input.readFully(array); align(length); return array; case USHORT: { final short[] array = new short[length]; input.readFully(array, 0, length); align(length << 1); return array; case UINT: { final int[] array = new int[length]; input.readFully(array, 0, length);
switch (operation) { default: throw new AssertionError(operation); case 0: assertEquals("readByte()", r.readByte(), t.readByte()); break; case 1: assertEquals("readShort()", r.readShort(), t.readShort()); break; case 2: assertEquals("readUnsignedShort()", r.readUnsignedShort(), t.readUnsignedShort()); break; case 3: assertEquals("readChar()", r.readChar(), t.readChar()); break; case 4: assertEquals("readInt()", r.readInt(), t.readInt()); break; case 5: assertEquals("readUnsignedInt()", r.readInt() & 0xFFFFFFFFL, t.readUnsignedInt()); break; case 6: assertEquals("readLong()", r.readLong(), t.readLong()); break; case 7: assertEquals("readFloat()", r.readFloat(), t.readFloat(), 0f); break; case 8: assertEquals("readDouble()", r.readDouble(), t.readDouble(), 0d); break; case 9: { final int n = random.nextInt(ARRAY_MAX_LENGTH); final byte[] tmp = new byte[n]; r.readFully(tmp); assertArrayEquals("readBytes(int)", tmp, t.readBytes(n)); break; final char[] tmp = new char[n]; for (int i=0; i<n; i++) tmp[i] = r.readChar(); assertArrayEquals("readChars(int)", tmp, t.readChars(n)); break; final short[] tmp = new short[n]; for (int i=0; i<n; i++) tmp[i] = r.readShort(); assertArrayEquals("readShorts(int)", tmp, t.readShorts(n)); break; final int[] tmp = new int[n];
for (int j=0; j<nelems; j++) { final String name = readName(); final int n = input.readInt(); final Dimension[] varDims = new Dimension[n]; try { for (int i=0; i<n; i++) { varDims[i] = allDimensions[input.readInt()]; final long tn = input.readLong(); if (tn != 0) { final int tag = (int) (tn >>> Integer.SIZE); DataType.valueOf(input.readInt()), input.readInt(), readOffset());
input.seek(Math.addExact(origin, nextIFD)); nextIFD = 0; // Prevent trying other IFD if we fail to read this one. final short tag = (short) input.readUnsignedShort(); final Type type = Type.valueOf(input.readShort()); // May be null. final long count = readUnsignedInt(); final long size = (type != null) ? Math.multiplyExact(type.size, count) : 0; final long position = input.getStreamPosition(); if (size != 0) { Object error; input.seek(position + offsetSize); // Usually just move the buffer position by a few bytes. } else {
/** * Tests {@link ChannelDataInput#seek(long)} on a channel that do not implement * {@link java.nio.channels.SeekableByteChannel}. * * @throws IOException should never happen since we read and write in memory only. */ @Test public void testSeekOnForwardOnlyChannel() throws IOException { int length = random.nextInt(2048) + 1024; final byte[] array = createRandomArray(length); length -= Long.BYTES; // Safety against buffer underflow. final ByteBuffer buffer = ByteBuffer.wrap(array); final ChannelDataInput input = new ChannelDataInput("testSeekOnForwardOnlyChannel", new DripByteChannel(array, random, 1, 2048), ByteBuffer.allocate(random.nextInt(64) + 16), false); int position = 0; while (position < length) { input.seek(position); assertEquals("getStreamPosition()", position, input.getStreamPosition()); assertEquals(buffer.getLong(position), input.readLong()); position += random.nextInt(128); } }
super(owner); this.input = input; this.origin = input.getStreamPosition(); this.metadata = new MetadataBuilder(); this.doneIFD = new HashSet<>(); final short order = input.readShort(); final boolean isBigEndian = (order == BIG_ENDIAN); if (isBigEndian || order == LITTLE_ENDIAN) { switch (input.readShort()) { case CLASSIC: { // Magic number of classical format. intSizeExpansion = 0; final int numBits = input.readUnsignedShort(); final int powerOf2 = Integer.numberOfTrailingZeros(numBits); // In the [0 … 32] range. if (numBits == (1L << powerOf2) && input.readShort() == 0) { intSizeExpansion = (byte) (powerOf2 - 2); if (intSizeExpansion == 1) {
final byte[] array = createRandomArray(length); final ByteBuffer buffer = ByteBuffer.allocate(random.nextInt(64) + 16); final ChannelDataInput input = new ChannelDataInput("testPrefetch", new DripByteChannel(array, random, 1, 64), buffer, false); int position = 0; while (position != length) { if (random.nextBoolean()) { assertEquals(array[position++], input.readByte()); final int n = input.prefetch(); assertEquals("Position shall be unchanged.", p, buffer.position()); final int limit = buffer.limit();
/** * Fills a buffer with random data and compare the result with a standard image input stream. * We allocate a small buffer for the {@code ChannelDataInput} in order to force frequent * interactions between the buffer and the channel. * * @throws IOException should never happen since we read and write in memory only. */ @Test public void testAllReadMethods() throws IOException { final byte[] array = createRandomArray(STREAM_LENGTH); referenceStream = new DataInputStream(new ByteArrayInputStream(array)); testedStream = new ChannelDataInput("testAllReadMethods", new DripByteChannel(array, random, 1, 1024), ByteBuffer.allocate(random.nextInt(BUFFER_MAX_CAPACITY) + Double.BYTES), false); transferRandomData(testedStream, array.length - ARRAY_MAX_LENGTH, 16); }
/** * Reads the {@code short} or {@code long} value (depending if the file is * standard of big TIFF) at the current {@linkplain #input} position. * * @return the next directory entry value. */ private long readUnsignedShort() throws IOException, DataStoreException { if (intSizeExpansion == 0) { return input.readUnsignedShort(); // Classical format. } final long entry = input.readLong(); // BigTIFF format. if (entry >= 0) { return entry; } throw new DataStoreContentException(owner.getLocale(), "TIFF", input.filename, null); }
/** * Decodes a string from a sequence of bytes in the given encoding. This method tries to avoid the creation * of a temporary {@code byte[]} array when possible. * * <p>This convenience method shall be used only for relatively small amount of {@link String} instances * to decode, for example attribute values in the file header. For large amount of data, consider using * {@link java.nio.charset.CharsetDecoder} instead.</p> * * @param length number of bytes to read. * @param encoding the character encoding. * @return the string decoded from the {@code length} next bytes. * @throws IOException if an error occurred while reading the bytes, or if the given encoding is invalid. */ public final String readString(final int length, final Charset encoding) throws IOException { if (buffer.hasArray() && length <= buffer.capacity()) { ensureBufferContains(length); final int position = buffer.position(); // Must be after 'ensureBufferContains(int)'. buffer.position(position + length); // Before 'new String' for consistency with the 'else' block in case of UnsupportedEncodingException. return new String(buffer.array(), buffer.arrayOffset() + position, length, encoding); } else { return new String(readBytes(length), encoding); } }
/** * Tests the {@link ChannelDataInput#readString(int, Charset)} method. * * @throws IOException should never happen since we read and write in memory only. */ @Test public void testReadString() throws IOException { final String expected = "お元気ですか"; final byte[] array = expected.getBytes("UTF-8"); assertEquals(expected.length()*3, array.length); // Sanity check. final ChannelDataInput input = new ChannelDataInput("testReadString", new DripByteChannel(array, random, 1, 32), ByteBuffer.allocate(array.length + 4), false); assertEquals(expected, input.readString(array.length, StandardCharsets.UTF_8)); assertFalse(input.buffer.hasRemaining()); }
@Override public Object readArray(final ChannelDataInput input, final int count) throws IOException { return input.readBytes(count); } },
@Override public double readDouble(final ChannelDataInput input, final long count) throws IOException { final double value = input.readUnsignedInt() / (double) input.readUnsignedInt(); for (long i=1; i<count; i++) { ensureSingleton(value, input.readUnsignedInt() / (double) input.readUnsignedInt(), count); } return value; } },