package org.apache.lucene.index; /** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import java.io.IOException; import org.apache.lucene.store.DataInput; import org.apache.lucene.store.DataOutput; /* IndexInput that knows how to read the byte slices written * by Posting and PostingVector. We read the bytes in * each slice until we hit the end of that slice at which * point we read the forwarding address of the next slice * and then jump to it.*/ final class ByteSliceReader extends DataInput { ByteBlockPool pool; int bufferUpto; byte[] buffer; public int upto; int limit; int level; public int bufferOffset; public int endIndex; public void init(ByteBlockPool pool, int startIndex, int endIndex) { assert endIndex-startIndex >= 0; assert startIndex >= 0; assert endIndex >= 0; this.pool = pool; this.endIndex = endIndex; level = 0; bufferUpto = startIndex / DocumentsWriter.BYTE_BLOCK_SIZE; bufferOffset = bufferUpto * DocumentsWriter.BYTE_BLOCK_SIZE; buffer = pool.buffers[bufferUpto]; upto = startIndex & DocumentsWriter.BYTE_BLOCK_MASK; final int firstSize = ByteBlockPool.levelSizeArray[0]; if (startIndex+firstSize >= endIndex) { // There is only this one slice to read limit = endIndex & DocumentsWriter.BYTE_BLOCK_MASK; } else limit = upto+firstSize-4; } public boolean eof() { assert upto + bufferOffset <= endIndex; return upto + bufferOffset == endIndex; } @Override public byte readByte() { assert !eof(); assert upto <= limit; if (upto == limit) nextSlice(); return buffer[upto++]; } public long writeTo(DataOutput out) throws IOException { long size = 0; while(true) { if (limit + bufferOffset == endIndex) { assert endIndex - bufferOffset >= upto; out.writeBytes(buffer, upto, limit-upto); size += limit-upto; break; } else { out.writeBytes(buffer, upto, limit-upto); size += limit-upto; nextSlice(); } } return size; } public void nextSlice() { // Skip to our next slice final int nextIndex = ((buffer[limit]&0xff)<<24) + ((buffer[1+limit]&0xff)<<16) + ((buffer[2+limit]&0xff)<<8) + (buffer[3+limit]&0xff); level = ByteBlockPool.nextLevelArray[level]; final int newSize = ByteBlockPool.levelSizeArray[level]; bufferUpto = nextIndex / DocumentsWriter.BYTE_BLOCK_SIZE; bufferOffset = bufferUpto * DocumentsWriter.BYTE_BLOCK_SIZE; buffer = pool.buffers[bufferUpto]; upto = nextIndex & DocumentsWriter.BYTE_BLOCK_MASK; if (nextIndex + newSize >= endIndex) { // We are advancing to the final slice assert endIndex - nextIndex > 0; limit = endIndex - bufferOffset; } else { // This is not the final slice (subtract 4 for the // forwarding address at the end of this new slice) limit = upto+newSize-4; } } @Override public void readBytes(byte[] b, int offset, int len) { while(len > 0) { final int numLeft = limit-upto; if (numLeft < len) { // Read entire slice System.arraycopy(buffer, upto, b, offset, numLeft); offset += numLeft; len -= numLeft; nextSlice(); } else { // This slice is the last one System.arraycopy(buffer, upto, b, offset, len); upto += len; break; } } } }