first commit

This commit is contained in:
Vhati 2013-08-21 13:23:01 -04:00
parent 352e1653f8
commit 16a197e856
44 changed files with 5942 additions and 3 deletions

View file

@ -0,0 +1,115 @@
package net.vhati.ftldat;
import java.io.InputStream;
import java.io.IOException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.FileChannel;
public class FileChannelRegionInputStream extends InputStream {
private FileChannel channel;
private long regionOffset;
private long regionLength;
// A buffer holds an even narrower region of the file.
// When possible read() calls will reuse this,
// rather than pester the channel.
private ByteBuffer buf = null;
private long bufOffset = 0; // Relative to regionOffset.
private int bufLength = 0;
private long intraPos = 0;
public FileChannelRegionInputStream( FileChannel channel, long offset, long length ) {
this( channel, offset, length, 4096 );
}
public FileChannelRegionInputStream( FileChannel channel, long offset, long length, int bufferSize ) {
this.channel = channel;
this.regionOffset = offset;
this.regionLength = length;
buf = ByteBuffer.allocate( bufferSize );
}
@Override
public int available() throws IOException {
if ( !channel.isOpen() ) throw new ClosedChannelException();
return bufLength;
}
@Override
public int read() throws IOException {
if ( !channel.isOpen() ) throw new ClosedChannelException();
if ( intraPos >= regionLength ) return -1;
if ( intraPos < bufOffset || intraPos >= bufOffset+bufLength ) {
// The requested byte isn't currently buffered.
bufOffset = intraPos;
int len = 0; // Get *something*.
buf.position( 0 );
while ( len == 0 ) {
len = channel.read( buf, regionOffset + bufOffset );
}
if ( len == -1 ) {
bufLength = 0;
return -1;
} else {
bufLength = len;
}
}
// Do an absolute get() from the buffer.
int result = buf.get( (int)(intraPos - bufOffset) );
intraPos++;
return result;
}
@Override
public int read( byte[] b, int bOff, int bLen ) throws IOException {
if ( bLen == 0 ) return 0;
if ( bOff < 0 ) throw new IndexOutOfBoundsException( String.format( "Index: %d, Size: %d", bOff, bLen ) );
if ( bOff + bLen > b.length ) throw new IndexOutOfBoundsException( String.format( "Index: %d, Size: %d", (bOff+bLen), bLen ) );
if ( !channel.isOpen() ) throw new ClosedChannelException();
if ( intraPos >= regionLength ) return -1;
int bytesTotal = Math.min( bLen, (int)(regionLength - intraPos) );
int bytesRemaining = bytesTotal;
if ( intraPos >= bufOffset || intraPos < bufOffset+bufLength ) {
// Read part of the current buffer, possibly until the end.
buf.position( (int)(intraPos - bufOffset) );
int bufTodo = Math.min( bytesRemaining, bufLength - (int)(intraPos - bufOffset) );
buf.get( b, bOff, bufTodo );
bytesRemaining -= bufTodo;
intraPos += bufTodo;
}
if ( bytesRemaining > 0 ) {
// Refill the buffer at the current intraPos.
bufOffset = intraPos;
int len = 0;
buf.position( 0 );
len = channel.read( buf, regionOffset + bufOffset );
if ( len == -1 ) {
bufLength = 0;
throw new BufferUnderflowException();
} else {
bufLength = len;
}
buf.position( 0 );
int bufTodo = Math.min( bytesRemaining, bufLength );
buf.get( b, bOff, bufTodo );
bytesRemaining -= bufTodo;
intraPos += bufTodo;
}
return ( bytesTotal - bytesRemaining ); // Return number of bytes read.
}
}