package org.simantics.db.common; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; import org.simantics.db.common.utils.Logger; import org.simantics.db.service.Bytes; final public class ByteFileReader { public static int BUFFER = 65536; final private FileInputStream fs; final private ReadableByteChannel channel; final private ByteBuffer byteBuffer; final private byte[] bytes = new byte[BUFFER]; private int size; protected int byteIndex = 0; final protected ReadableByteChannel getChannel() { return channel; } final protected ByteBuffer getByteBuffer() { return byteBuffer; } final protected byte[] getBytes() { return bytes; } final public byte[] readBytes(int amount) throws IOException { byte[] result = new byte[amount]; int has = size-byteIndex; if(amount >= has) { ReadableByteChannel c = channel; System.arraycopy(bytes, byteIndex, result, 0, has); ByteBuffer bb2 = ByteBuffer.wrap(result); bb2.position(has); while(has < amount) has += c.read(bb2); getSome(); } else { System.arraycopy(bytes, byteIndex, result, 0, amount); byteIndex += amount; } return result; } final public void getSome() throws IOException { ReadableByteChannel c = channel; ByteBuffer bb = byteBuffer; bb.position(0); bb.limit(BUFFER); size = c.read(bb); if(size == 0) { long start = System.nanoTime(); while(size == 0) { if(System.nanoTime() - start > 10000000000L) throw new IOException("Timeout"); size = c.read(bb); } } bb.position(0); byteIndex = 0; } final public int readShort() throws IOException { if(byteIndex >= (size-3)) { short result = 0; if(byteIndex == size) { getSome(); } result |= ((short)(bytes[byteIndex++]&0xff)<<0); if(byteIndex == size) { getSome(); } result |= ((short)(bytes[byteIndex++]&0xff)<<8); if(byteIndex == size) { getSome(); } return result; } else { int result = Bytes.readLE2(bytes, byteIndex); byteIndex += 2; return result; } } final public int readInt() throws IOException { if(byteIndex >= (size-5)) { int result = 0; if(byteIndex == size) { getSome(); } result |= ((int)(bytes[byteIndex++]&0xff)<<0); if(byteIndex == size) { getSome(); } result |= ((int)(bytes[byteIndex++]&0xff)<<8); if(byteIndex == size) { getSome(); } result |= ((int)(bytes[byteIndex++]&0xff)<<16); if(byteIndex == size) { getSome(); } result |= ((int)(bytes[byteIndex++]&0xff)<<24); if(byteIndex == size) { getSome(); } return result; } else { int result = Bytes.readLE4(bytes, byteIndex); byteIndex += 4; return result; } } final public long readLong() throws IOException { if(byteIndex >= (size-9)) { long result = 0; if(byteIndex == size) { getSome(); } result |= ((long)(bytes[byteIndex++]&0xff)<<0); if(byteIndex == size) { getSome(); } result |= ((long)(bytes[byteIndex++]&0xff)<<8); if(byteIndex == size) { getSome(); } result |= ((long)(bytes[byteIndex++]&0xff)<<16); if(byteIndex == size) { getSome(); } result |= ((long)(bytes[byteIndex++]&0xff)<<24); if(byteIndex == size) { getSome(); } result |= ((long)(bytes[byteIndex++]&0xff)<<32); if(byteIndex == size) { getSome(); } result |= ((long)(bytes[byteIndex++]&0xff)<<40); if(byteIndex == size) { getSome(); } result |= ((long)(bytes[byteIndex++]&0xff)<<48); if(byteIndex == size) { getSome(); } result |= ((long)(bytes[byteIndex++]&0xff)<<56); if(byteIndex == size) { getSome(); } return result; } else { long result = Bytes.readLE8(bytes, byteIndex); byteIndex += 8; return result; } } public void close() { try { fs.close(); } catch (IOException e) { Logger.defaultLogError(e); } } public ByteFileReader(File file) throws IOException { byteBuffer = ByteBuffer.wrap(bytes); fs = new FileInputStream(file); channel = fs.getChannel(); this.size = channel.read(byteBuffer); byteBuffer.position(0); } }