+++ /dev/null
-/*
- * Copyright 2002-2015 Drew Noakes
- *
- * More information about this project is available at:
- *
- * https://drewnoakes.com/code/exif/
- * https://github.com/drewnoakes/metadata-extractor
- */
-
-package tim.prune.jpeg.drew;
-
-import java.io.IOException;
-
-
-/**
- * Provides methods to read specific values from a byte array,
- * with a consistent, checked exception structure for issues.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-public class ByteArrayReader
-{
- private final byte[] _buffer;
- private boolean _isMotorolaByteOrder = true;
-
- public ByteArrayReader(byte[] buffer)
- {
- if (buffer == null)
- throw new NullPointerException();
-
- _buffer = buffer;
- }
-
- public void setMotorolaByteOrder(boolean motorolaByteOrder)
- {
- _isMotorolaByteOrder = motorolaByteOrder;
- }
-
- public long getLength()
- {
- return _buffer.length;
- }
-
- protected byte getByte(int index)
- {
- return _buffer[index];
- }
-
- protected void validateIndex(int index, int bytesRequested) throws ExifException
- {
- if (!isValidIndex(index, bytesRequested))
- throw new ExifException("Invalid index " + index);
- }
-
- private boolean isValidIndex(int index, int bytesRequested)
- {
- return bytesRequested >= 0
- && index >= 0
- && ((long)index + (long)bytesRequested) <= (long)_buffer.length;
- }
-
- public byte[] getBytes(int index, int count) throws ExifException
- {
- validateIndex(index, count);
-
- byte[] bytes = new byte[count];
- System.arraycopy(_buffer, index, bytes, 0, count);
- return bytes;
- }
-
- /**
- * Returns an unsigned 8-bit int calculated from one byte of data at the specified index.
- *
- * @param index position within the data buffer to read byte
- * @return the 8 bit int value, between 0 and 255
- * @throws IOException the buffer does not contain enough bytes to service the request, or index is negative
- */
- public short getUInt8(int index) throws ExifException
- {
- validateIndex(index, 1);
-
- return (short) (getByte(index) & 0xFF);
- }
-
- /**
- * Returns a signed 8-bit int calculated from one byte of data at the specified index.
- *
- * @param index position within the data buffer to read byte
- * @return the 8 bit int value, between 0x00 and 0xFF
- * @throws IOException the buffer does not contain enough bytes to service the request, or index is negative
- */
- public byte getInt8(int index) throws ExifException
- {
- validateIndex(index, 1);
-
- return getByte(index);
- }
-
- /**
- * Returns an unsigned 16-bit int calculated from two bytes of data at the specified index.
- *
- * @param index position within the data buffer to read first byte
- * @return the 16 bit int value, between 0x0000 and 0xFFFF
- * @throws IOException the buffer does not contain enough bytes to service the request, or index is negative
- */
- public int getUInt16(int index) throws ExifException
- {
- validateIndex(index, 2);
-
- if (_isMotorolaByteOrder) {
- // Motorola - MSB first
- return (getByte(index ) << 8 & 0xFF00) |
- (getByte(index + 1) & 0xFF);
- } else {
- // Intel ordering - LSB first
- return (getByte(index + 1) << 8 & 0xFF00) |
- (getByte(index ) & 0xFF);
- }
- }
-
- /**
- * Returns a signed 16-bit int calculated from two bytes of data at the specified index (MSB, LSB).
- *
- * @param index position within the data buffer to read first byte
- * @return the 16 bit int value, between 0x0000 and 0xFFFF
- * @throws IOException the buffer does not contain enough bytes to service the request, or index is negative
- */
- public short getInt16(int index) throws ExifException
- {
- validateIndex(index, 2);
-
- if (_isMotorolaByteOrder) {
- // Motorola - MSB first
- return (short) (((short)getByte(index ) << 8 & (short)0xFF00) |
- ((short)getByte(index + 1) & (short)0xFF));
- } else {
- // Intel ordering - LSB first
- return (short) (((short)getByte(index + 1) << 8 & (short)0xFF00) |
- ((short)getByte(index ) & (short)0xFF));
- }
- }
-
- /**
- * Get a 32-bit unsigned integer from the buffer, returning it as a long.
- *
- * @param index position within the data buffer to read first byte
- * @return the unsigned 32-bit int value as a long, between 0x00000000 and 0xFFFFFFFF
- * @throws IOException the buffer does not contain enough bytes to service the request, or index is negative
- */
- public long getUInt32(int index) throws ExifException
- {
- validateIndex(index, 4);
-
- if (_isMotorolaByteOrder) {
- // Motorola - MSB first (big endian)
- return (((long)getByte(index )) << 24 & 0xFF000000L) |
- (((long)getByte(index + 1)) << 16 & 0xFF0000L) |
- (((long)getByte(index + 2)) << 8 & 0xFF00L) |
- (((long)getByte(index + 3)) & 0xFFL);
- } else {
- // Intel ordering - LSB first (little endian)
- return (((long)getByte(index + 3)) << 24 & 0xFF000000L) |
- (((long)getByte(index + 2)) << 16 & 0xFF0000L) |
- (((long)getByte(index + 1)) << 8 & 0xFF00L) |
- (((long)getByte(index )) & 0xFFL);
- }
- }
-
- /**
- * Returns a signed 32-bit integer from four bytes of data at the specified index the buffer.
- *
- * @param index position within the data buffer to read first byte
- * @return the signed 32 bit int value, between 0x00000000 and 0xFFFFFFFF
- * @throws IOException the buffer does not contain enough bytes to service the request, or index is negative
- */
- public int getInt32(int index) throws ExifException
- {
- validateIndex(index, 4);
-
- if (_isMotorolaByteOrder) {
- // Motorola - MSB first (big endian)
- return (getByte(index ) << 24 & 0xFF000000) |
- (getByte(index + 1) << 16 & 0xFF0000) |
- (getByte(index + 2) << 8 & 0xFF00) |
- (getByte(index + 3) & 0xFF);
- } else {
- // Intel ordering - LSB first (little endian)
- return (getByte(index + 3) << 24 & 0xFF000000) |
- (getByte(index + 2) << 16 & 0xFF0000) |
- (getByte(index + 1) << 8 & 0xFF00) |
- (getByte(index ) & 0xFF);
- }
- }
-
- /**
- * Creates a String from the _data buffer starting at the specified index,
- * and ending where <code>byte=='\0'</code> or where <code>length==maxLength</code>.
- *
- * @param index The index within the buffer at which to start reading the string.
- * @param maxLengthBytes The maximum number of bytes to read. If a zero-byte is not reached within this limit,
- * reading will stop and the string will be truncated to this length.
- * @return The read string.
- * @throws IOException The buffer does not contain enough bytes to satisfy this request.
- */
- public String getNullTerminatedString(int index, int maxLengthBytes) throws ExifException
- {
- // NOTE currently only really suited to single-byte character strings
-
- byte[] bytes = getBytes(index, maxLengthBytes);
-
- // Count the number of non-null bytes
- int length = 0;
- while (length < bytes.length && bytes[length] != '\0')
- length++;
-
- return new String(bytes, 0, length);
- }
-
- public String getString(int index, int bytesRequested) throws ExifException
- {
- // TODO: validate index
- return new String(getBytes(index, bytesRequested));
- }
-}