Index: src/java/org/apache/lucene/util/PagedBytes.java =================================================================== --- src/java/org/apache/lucene/util/PagedBytes.java (revision 1417024) +++ src/java/org/apache/lucene/util/PagedBytes.java (working copy) @@ -70,19 +70,16 @@ blockSize = pagedBytes.blockSize; } - /** + /** * Gets a slice out of {@link PagedBytes} starting at start with a - * given length. Iff the slice spans across a block border this method will + * given length. If the slice spans more than one block this method will * allocate sufficient resources and copy the paged data. - *
- * Slices spanning more than one block are not supported. - *
* @lucene.internal **/ public BytesRef fillSlice(BytesRef b, long start, int length) { assert length >= 0: "length=" + length; - assert length <= blockSize+1; - final int index = (int) (start >> blockBits); + assert length <= start+(blocks.length*blockSize)+1; + final int index = (int) (start/blockSize); final int offset = (int) (start & blockMask); b.length = length; if (blockSize - offset >= length) { @@ -90,15 +87,23 @@ b.bytes = blocks[index]; b.offset = offset; } else { - // Split + // Spans variable number of blocks b.bytes = new byte[length]; b.offset = 0; - System.arraycopy(blocks[index], offset, b.bytes, 0, blockSize-offset); - System.arraycopy(blocks[1+index], 0, b.bytes, blockSize-offset, length-(blockSize-offset)); + //Number of blocks that bytes must be sliced from + final int blockSpan = (length+offset-1)/blockSize; + //Length to copy from last block + final int tail = length-(blockSize-offset)-((blockSpan-1)*blockSize); + for (int i=0;i<=blockSpan;i++) { + System.arraycopy(blocks[i+index], (i == 0 ? offset : 0), b.bytes, //Only use offset for first block. + i*blockSize-(i != 0 ? offset : 0), + (i == blockSpan ? tail : blockSize)-(i == 0 ? offset : 0) //Use tail for last block. + ); + } } return b; } - + /** * Reads length as 1 or 2 byte vInt prefix, starting at start. *
Index: src/test/org/apache/lucene/util/TestPagedBytes.java
===================================================================
--- src/test/org/apache/lucene/util/TestPagedBytes.java (revision 1417024)
+++ src/test/org/apache/lucene/util/TestPagedBytes.java (working copy)
@@ -165,4 +165,44 @@
assertEquals(offset+1, in.getPosition());
}
}
+
+ //Parameters for testing fillSlice
+ private final int testBlockBits = 4; //16 bytes per block
+ private final int testBlockCount = 4;
+ private final int testBlockSize = 1 << testBlockBits;
+
+ private void testFillSlice(int start, int length) throws Exception {
+ Random random = random();
+ final PagedBytes p = new PagedBytes(testBlockBits);
+ final DataOutput out = p.getDataOutput();
+ final byte[] bytes = new byte[testBlockSize*testBlockCount];
+ random.nextBytes(bytes);
+ out.writeBytes(bytes, 0, bytes.length);
+
+ final PagedBytes.Reader reader = p.freeze(random.nextBoolean());
+ BytesRef answer = reader.fillSlice(new BytesRef(), start, length);
+ assertEquals(length, answer.length);
+
+ //Loop as long as the values are equal
+ int lastOffset = 0;
+ for(int i=0;i