com.io7m.smfj.format.binary.SMFBDataStreamReader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of io7m-smfj-format-binary Show documentation
Show all versions of io7m-smfj-format-binary Show documentation
Sequential mesh format (Binary format)
The newest version!
/*
* Copyright © 2016 http://io7m.com
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package com.io7m.smfj.format.binary;
import com.io7m.ieee754b16.Binary16;
import com.io7m.jnull.NullCheck;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.CountingInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.file.Path;
import java.util.Optional;
/**
* The default implementation of the {@link SMFBDataStreamReaderType} interface.
*/
public final class SMFBDataStreamReader implements SMFBDataStreamReaderType
{
private final Path path;
private final CountingInputStream stream;
private final ByteBuffer buffer8;
private final ByteBuffer buffer4;
private final ByteBuffer buffer2;
private final byte[] byte1;
private final byte[] byte2;
private final byte[] byte4;
private final byte[] byte8;
private SMFBDataStreamReader(
final Path in_path,
final InputStream in_stream)
{
this.path = NullCheck.notNull(in_path, "Path");
this.stream = new CountingInputStream(NullCheck.notNull(
in_stream,
"Stream"));
this.byte1 = new byte[1];
this.byte2 = new byte[2];
this.byte4 = new byte[4];
this.byte8 = new byte[8];
this.buffer8 = ByteBuffer.wrap(this.byte8);
this.buffer8.order(ByteOrder.BIG_ENDIAN);
this.buffer4 = ByteBuffer.wrap(this.byte4);
this.buffer4.order(ByteOrder.BIG_ENDIAN);
this.buffer2 = ByteBuffer.wrap(this.byte2);
this.buffer2.order(ByteOrder.BIG_ENDIAN);
}
/**
* Create a data stream reader.
*
* @param in_path The path
* @param in_stream The stream
*
* @return A new data stream reader
*/
public static SMFBDataStreamReaderType create(
final Path in_path,
final InputStream in_stream)
{
return new SMFBDataStreamReader(in_path, in_stream);
}
@Override
public Path path()
{
return this.path;
}
@Override
public void readBytes(
final Optional name,
final byte[] b)
throws IOException
{
try {
IOUtils.readFully(this.stream, b);
} catch (final IOException e) {
throw this.makeIOException(
name, this.position(), (long) b.length, e.getMessage());
}
}
@Override
public long position()
{
return this.stream.getByteCount();
}
@Override
public long readU8(
final Optional name)
throws IOException
{
try {
IOUtils.readFully(this.stream, this.byte1);
return (long) this.byte1[0] & 0xFFL;
} catch (final IOException e) {
throw this.makeIOException(name, this.position(), 1L, e.getMessage());
}
}
@Override
public long readS8(
final Optional name)
throws IOException
{
try {
IOUtils.readFully(this.stream, this.byte1);
return (long) this.byte1[0];
} catch (final IOException e) {
throw this.makeIOException(name, this.position(), 1L, e.getMessage());
}
}
@Override
public long readU16(
final Optional name)
throws IOException
{
try {
IOUtils.readFully(this.stream, this.byte2);
return (long) this.buffer2.getChar(0) & 0xFFFFL;
} catch (final IOException e) {
throw this.makeIOException(name, this.position(), 2L, e.getMessage());
}
}
@Override
public long readS16(
final Optional name)
throws IOException
{
try {
IOUtils.readFully(this.stream, this.byte2);
return (long) this.buffer2.getShort(0);
} catch (final IOException e) {
throw this.makeIOException(name, this.position(), 2L, e.getMessage());
}
}
@Override
public long readU32(
final Optional name)
throws IOException
{
try {
IOUtils.readFully(this.stream, this.byte4);
return (long) this.buffer4.getInt(0) & 0xFFFFFFFFL;
} catch (final IOException e) {
throw this.makeIOException(name, this.position(), 4L, e.getMessage());
}
}
@Override
public long readS32(
final Optional name)
throws IOException
{
try {
IOUtils.readFully(this.stream, this.byte4);
return (long) this.buffer4.getInt(0);
} catch (final IOException e) {
throw this.makeIOException(name, this.position(), 4L, e.getMessage());
}
}
@Override
public long readU64(
final Optional name)
throws IOException
{
try {
IOUtils.readFully(this.stream, this.byte8);
return this.buffer8.getLong(0);
} catch (final IOException e) {
throw this.makeIOException(name, this.position(), 8L, e.getMessage());
}
}
@Override
public long readS64(
final Optional name)
throws IOException
{
try {
IOUtils.readFully(this.stream, this.byte8);
return this.buffer8.getLong(0);
} catch (final IOException e) {
throw this.makeIOException(name, this.position(), 8L, e.getMessage());
}
}
private IOException makeIOException(
final Optional name,
final long position,
final long expected,
final String cause)
{
final StringBuilder sb = new StringBuilder(128);
sb.append("Failed to read the required number of octets.");
sb.append(System.lineSeparator());
sb.append(" Cause: ");
sb.append(cause);
sb.append(System.lineSeparator());
name.ifPresent(n -> {
sb.append(" Target: ");
sb.append(n);
sb.append(System.lineSeparator());
});
sb.append(" Position: ");
sb.append(position);
sb.append(System.lineSeparator());
sb.append(" Expected: ");
sb.append(expected);
sb.append(" octets");
sb.append(System.lineSeparator());
sb.append(" Received: ");
sb.append(this.buffer4.position());
sb.append(" octets");
sb.append(System.lineSeparator());
return new IOException(sb.toString());
}
@Override
public double readF16(
final Optional name)
throws IOException
{
try {
IOUtils.readFully(this.stream, this.byte2);
return Binary16.unpackDouble(this.buffer2.getChar(0));
} catch (final IOException e) {
throw this.makeIOException(name, this.position(), 2L, e.getMessage());
}
}
@Override
public double readF32(
final Optional name)
throws IOException
{
try {
IOUtils.readFully(this.stream, this.byte4);
return (double) this.buffer4.getFloat(0);
} catch (final IOException e) {
throw this.makeIOException(name, this.position(), 4L, e.getMessage());
}
}
@Override
public double readF64(
final Optional name)
throws IOException
{
try {
IOUtils.readFully(this.stream, this.byte8);
return this.buffer8.getDouble(0);
} catch (final IOException e) {
throw this.makeIOException(name, this.position(), 8L, e.getMessage());
}
}
@Override
public void skip(
final long count)
throws IOException
{
try {
final long skipped = this.stream.skip(count);
if (skipped != count) {
throw new IOException("Could not skip the required number of octets");
}
} catch (final IOException e) {
throw this.makeIOException(
Optional.of("padding"), this.position(), count, e.getMessage());
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy