| using Lucene.Net.Diagnostics; |
| using System; |
| using System.Diagnostics; |
| |
| namespace Lucene.Net.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. |
| */ |
| |
| using ByteBlockPool = Lucene.Net.Util.ByteBlockPool; |
| using DataInput = Lucene.Net.Store.DataInput; |
| using DataOutput = Lucene.Net.Store.DataOutput; |
| |
| /// <summary> |
| /// <see cref="Store.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. |
| /// </summary> |
| public sealed class ByteSliceReader : DataInput // LUCENENET specific - changed from internal to public because returned from public API |
| { |
| private ByteBlockPool pool; |
| private int bufferUpto; |
| private byte[] buffer; |
| private int upto; |
| private int limit; |
| private int level; |
| public int BufferOffset { get; internal set; } // LUCENENET specific - changed setter to internal |
| |
| public int EndIndex { get; internal set; } // LUCENENET specific - changed setter to internal |
| |
| internal ByteSliceReader() { } // LUCENENET specific - made constructor internal since this class was meant to be internal |
| |
| public void Init(ByteBlockPool pool, int startIndex, int endIndex) |
| { |
| if (Debugging.AssertsEnabled) |
| { |
| Debugging.Assert(endIndex - startIndex >= 0); |
| Debugging.Assert(startIndex >= 0); |
| Debugging.Assert(endIndex >= 0); |
| } |
| |
| this.pool = pool; |
| this.EndIndex = endIndex; |
| |
| level = 0; |
| bufferUpto = startIndex / ByteBlockPool.BYTE_BLOCK_SIZE; |
| BufferOffset = bufferUpto * ByteBlockPool.BYTE_BLOCK_SIZE; |
| buffer = pool.Buffers[bufferUpto]; |
| upto = startIndex & ByteBlockPool.BYTE_BLOCK_MASK; |
| |
| int firstSize = ByteBlockPool.LEVEL_SIZE_ARRAY[0]; |
| |
| if (startIndex + firstSize >= endIndex) |
| { |
| // There is only this one slice to read |
| limit = endIndex & ByteBlockPool.BYTE_BLOCK_MASK; |
| } |
| else |
| { |
| limit = upto + firstSize - 4; |
| } |
| } |
| |
| public bool Eof() |
| { |
| if (Debugging.AssertsEnabled) Debugging.Assert(upto + BufferOffset <= EndIndex); |
| return upto + BufferOffset == EndIndex; |
| } |
| |
| public override byte ReadByte() |
| { |
| if (Debugging.AssertsEnabled) |
| { |
| Debugging.Assert(!Eof()); |
| Debugging.Assert(upto <= limit); |
| } |
| if (upto == limit) |
| { |
| NextSlice(); |
| } |
| return (byte)buffer[upto++]; |
| } |
| |
| public long WriteTo(DataOutput @out) |
| { |
| long size = 0; |
| while (true) |
| { |
| if (limit + BufferOffset == EndIndex) |
| { |
| if (Debugging.AssertsEnabled) Debugging.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 |
| int nextIndex = ((buffer[limit] & 0xff) << 24) + ((buffer[1 + limit] & 0xff) << 16) + ((buffer[2 + limit] & 0xff) << 8) + (buffer[3 + limit] & 0xff); |
| |
| level = ByteBlockPool.NEXT_LEVEL_ARRAY[level]; |
| int newSize = ByteBlockPool.LEVEL_SIZE_ARRAY[level]; |
| |
| bufferUpto = nextIndex / ByteBlockPool.BYTE_BLOCK_SIZE; |
| BufferOffset = bufferUpto * ByteBlockPool.BYTE_BLOCK_SIZE; |
| |
| buffer = pool.Buffers[bufferUpto]; |
| upto = nextIndex & ByteBlockPool.BYTE_BLOCK_MASK; |
| |
| if (nextIndex + newSize >= EndIndex) |
| { |
| // We are advancing to the final slice |
| if (Debugging.AssertsEnabled) Debugging.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; |
| } |
| } |
| |
| public override void ReadBytes(byte[] b, int offset, int len) |
| { |
| while (len > 0) |
| { |
| int numLeft = limit - upto; |
| if (numLeft < len) |
| { |
| // Read entire slice |
| Array.Copy(buffer, upto, b, offset, numLeft); |
| offset += numLeft; |
| len -= numLeft; |
| NextSlice(); |
| } |
| else |
| { |
| // this slice is the last one |
| Array.Copy(buffer, upto, b, offset, len); |
| upto += len; |
| break; |
| } |
| } |
| } |
| } |
| } |