package com.revolsys.io.endian; import java.io.Closeable; import java.io.EOFException; import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; public interface EndianInput extends Closeable { /** * Read a byte. * * @return The long. * @throws IOException If an I/O error occurs. */ int read() throws IOException; default int read(final byte buffer[]) throws IOException { return read(buffer, 0, buffer.length); } default int read(final byte buffer[], final int offset, final int length) throws IOException { int i = 0; for (; i < length; i++) { final int value = read(); if (value == -1) { return i; } else { buffer[offset + i] = (byte)value; } } return i; } /** * See the general contract of the <code>readBoolean</code> * method of <code>DataInput</code>. * <p> * Bytes for this operation are read from the contained * input stream. * * @return the <code>boolean</code> value read. * @exception EOFException if this input stream has reached the end. * @exception IOException the stream has been closed and the contained * input stream does not support reading after close, or * another I/O error occurs. * @see java.io.FilterInputStream#in */ default boolean readBoolean() throws IOException { final int ch = read(); if (ch < 0) { throw new EOFException(); } return ch != 0; } /** * See the general contract of the <code>readByte</code> * method of <code>DataInput</code>. * <p> * Bytes * for this operation are read from the contained * input stream. * * @return the next byte of this input stream as a signed 8-bit * <code>byte</code>. * @exception EOFException if this input stream has reached the end. * @exception IOException the stream has been closed and the contained * input stream does not support reading after close, or * another I/O error occurs. * @see java.io.FilterInputStream#in */ default byte readByte() throws IOException { final int ch = read(); if (ch < 0) { throw new EOFException(); } return (byte)ch; } default byte[] readBytes(final int length) throws IOException { final byte[] buffer = new byte[length]; if (read(buffer, 0, length) == length) { return buffer; } else { throw new EOFException(); } } /** * See the general contract of the <code>readChar</code> * method of <code>DataInput</code>. * <p> * Bytes * for this operation are read from the contained * input stream. * * @return the next two bytes of this input stream, interpreted as a * <code>char</code>. * @exception EOFException if this input stream reaches the end before * reading two bytes. * @exception IOException the stream has been closed and the contained * input stream does not support reading after close, or * another I/O error occurs. * @see java.io.FilterInputStream#in */ default char readChar() throws IOException { final int ch1 = read(); final int ch2 = read(); if ((ch1 | ch2) < 0) { throw new EOFException(); } return (char)((ch1 << 8) + (ch2 << 0)); } /** * Read a big endian double. * * @return The double. * @throws IOException If an I/O error occurs. */ default double readDouble() throws IOException { return Double.longBitsToDouble(readLong()); } /** * See the general contract of the <code>readFloat</code> * method of <code>DataInput</code>. * <p> * Bytes * for this operation are read from the contained * input stream. * * @return the next four bytes of this input stream, interpreted as a * <code>float</code>. * @exception EOFException if this input stream reaches the end before * reading four bytes. * @exception IOException the stream has been closed and the contained * input stream does not support reading after close, or * another I/O error occurs. * @see java.io.DataInputStream#readInt() * @see java.lang.Float#intBitsToFloat(int) */ default float readFloat() throws IOException { return Float.intBitsToFloat(readInt()); } /** * See the general contract of the <code>readFully</code> * method of <code>DataInput</code>. * <p> * Bytes * for this operation are read from the contained * input stream. * * @param b the buffer into which the data is read. * @exception EOFException if this input stream reaches the end before * reading all the bytes. * @exception IOException the stream has been closed and the contained * input stream does not support reading after close, or * another I/O error occurs. * @see java.io.FilterInputStream#in */ default void readFully(final byte b[]) throws IOException { readFully(b, 0, b.length); } /** * See the general contract of the <code>readFully</code> * method of <code>DataInput</code>. * <p> * Bytes * for this operation are read from the contained * input stream. * * @param b the buffer into which the data is read. * @param off the start offset of the data. * @param len the number of bytes to read. * @exception EOFException if this input stream reaches the end before * reading all the bytes. * @exception IOException the stream has been closed and the contained * input stream does not support reading after close, or * another I/O error occurs. * @see java.io.FilterInputStream#in */ default void readFully(final byte b[], final int off, final int len) throws IOException { if (len < 0) { throw new IndexOutOfBoundsException(); } int n = 0; while (n < len) { final int count = read(b, off + n, len - n); if (count < 0) { throw new EOFException(); } n += count; } } /** * Read a big endian int. * * @return The int. * @throws IOException If an I/O error occurs. */ default int readInt() throws IOException { final int ch1 = read(); final int ch2 = read(); final int ch3 = read(); final int ch4 = read(); if ((ch1 | ch2 | ch3 | ch4) < 0) { throw new EOFException(); } return (ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0); } /** * Read a little endian double. * * @return The double. * @throws IOException If an I/O error occurs. */ default double readLEDouble() throws IOException { final long value = readLELong(); return Double.longBitsToDouble(value); } default float readLEFloat() throws IOException { final int value = readLEInt(); return Float.intBitsToFloat(value); } /** * Read a little endian int. * * @return The int. * @throws IOException If an I/O error occurs. */ default int readLEInt() throws IOException { final int b1 = read(); final int b2 = read(); final int b3 = read(); final int b4 = read(); if ((b1 | b2 | b3 | b4) < 0) { throw new EOFException(); } final int value = (b4 << 24) + (b3 << 16) + (b2 << 8) + b1; return value; } /** * Read a little endian long. * * @return The long. * @throws IOException If an I/O error occurs. */ default long readLELong() throws IOException { long value = 0; for (int shiftBy = 0; shiftBy < 64; shiftBy += 8) { value |= (long)(read() & 0xff) << shiftBy; } return value; } /** * Read a little endian short. * * @return The short. * @throws IOException If an I/O error occurs. */ default short readLEShort() throws IOException { final int b1 = read(); final int b2 = read(); if ((b1 | b2) < 0) { throw new EOFException(); } final int value = (b2 << 8) + b1; return (short)value; } /** * Read a little endian int. * * @return The int. * @throws IOException If an I/O error occurs. */ default long readLEUnsignedInt() throws IOException { final long b1 = read(); final long b2 = read(); final long b3 = read(); final long b4 = read(); if ((b1 | b2 | b3 | b4) < 0) { throw new EOFException(); } final long value = (b4 << 24) + (b3 << 16) + (b2 << 8) + b1; return value; } /** * Read a little endian long. * * @TODO * @return The long. * @throws IOException If an I/O error occurs. */ default long readLEUnsignedLong() throws IOException { long value = 0; for (int shiftBy = 0; shiftBy < 64; shiftBy += 8) { value |= (long)(read() & 0xff) << shiftBy; } return value; } default int readLEUnsignedShort() throws IOException { final int ch1 = read(); final int ch2 = read(); if ((ch1 | ch2) < 0) { throw new EOFException(); } return (ch1 << 0) + (ch2 << 8); } /** * Read a big endian long. * * @return The long. * @throws IOException If an I/O error occurs. */ default long readLong() throws IOException { return ((long)read() << 56) + ((long)(read() & 255) << 48) + ((long)(read() & 255) << 40) + ((long)(read() & 255) << 32) + ((long)(read() & 255) << 24) + ((read() & 255) << 16) + ((read() & 255) << 8) + ((read() & 255) << 0); } /** * Read a big endian short. * * @return The short. * @throws IOException If an I/O error occurs. */ default short readShort() throws IOException { final int ch1 = read(); final int ch2 = read(); if ((ch1 | ch2) < 0) { throw new EOFException(); } return (short)((ch1 << 8) + (ch2 << 0)); } default String readString(final int byteCount, final Charset charset) throws IOException { final byte[] bytes = new byte[byteCount]; final int readCount = read(bytes); int i = 0; for (; i < readCount; i++) { final byte character = bytes[i]; if (character == 0) { return new String(bytes, 0, i, charset); } } return new String(bytes, 0, i, charset); } default int readUnsignedByte() throws IOException { final int ch = read(); if (ch < 0) { throw new EOFException(); } return ch; } default int readUnsignedShort() throws IOException { final int ch1 = read(); final int ch2 = read(); if ((ch1 | ch2) < 0) { throw new EOFException(); } return (ch1 << 8) + (ch2 << 0); } default String readUsAsciiString(final int byteCount) throws IOException { return readString(byteCount, StandardCharsets.US_ASCII); } default int skipBytes(final int byteCount) throws IOException { int i = 0; for (; i < byteCount; i++) { if (read() == -1) { return i; } } return i; } }