package org.infinispan.lucene.impl; import java.io.IOException; import org.apache.lucene.store.IndexInput; /** * Wraps a buffer to expose only a slice of it. * The buffer is not copied to avoid copy operations as the slice is expected to have a lifespan shorter than the buffer itself, * so there would be no benefit in having a smaller copy in heap. * * @author Sanne Grinovero <sanne@hibernate.org> (C) 2014 Red Hat Inc. * @since 7.0 */ final class SlicedBufferIndexInput extends IndexInput { private final byte[] buffer; private final int offset; private final int length; private final int hardLimit; private int bufferPosition; protected SlicedBufferIndexInput(String resourceDescription, byte[] buffer, long offset, long length) { super(resourceDescription); this.buffer = buffer; this.offset = toInt(offset); this.length = toInt(length); this.hardLimit = this.offset + this.length; this.bufferPosition = this.offset; if (hardLimit > buffer.length) { throw new IllegalArgumentException("offset or length too large for the size of this buffer"); } } @Override public void close() throws IOException { //no-op } @Override public long getFilePointer() { return bufferPosition - offset; } @Override public void seek(long pos) throws IOException { //Lucene might use positions larger than length(), in //this case you have to position the pointer to eof. bufferPosition = Math.min(hardLimit, ((int)pos) + offset); } @Override public long length() { return this.length; } public IndexInput slice(String sliceDescription, long offset, long length) throws IOException { return new SlicedBufferIndexInput(sliceDescription, buffer, offset + this.offset, length); } @Override public byte readByte() throws IOException { if (bufferPosition >= hardLimit) { throw new IOException("Read past EOF"); } return buffer[bufferPosition++]; } @Override public void readBytes(byte[] b, int offset, int len) throws IOException { if (hardLimit - bufferPosition < len) { throw new IOException("Read past EOF"); } System.arraycopy(buffer, bufferPosition, b, offset, len); bufferPosition+=len; } private static int toInt(final long n) { if ( n < 0 || n > Integer.MAX_VALUE) { throw new IllegalArgumentException("A SlicedBufferIndexInput can only be defined with offset and length which are positive and fit in an int"); } return (int) n; } }