blob: fbfbccff93500baa6d8704857fc9061db8acac66 [file] [log] [blame]
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;
}
}
}
}
}