blob: 1392ad7efd65e1a53ab56f6207527497b8986953 [file] [log] [blame]
using System;
using System.Diagnostics;
namespace Lucene.Net.Index
{
using ByteBlockPool = Lucene.Net.Util.ByteBlockPool;
/*
* 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 DataInput = Lucene.Net.Store.DataInput;
using DataOutput = Lucene.Net.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.*/
public sealed class ByteSliceReader : DataInput
{
internal ByteBlockPool Pool;
internal int BufferUpto;
byte[] Buffer;
public int Upto;
internal int Limit;
internal int Level;
public int BufferOffset;
public int EndIndex;
public void Init(ByteBlockPool pool, int startIndex, int endIndex)
{
Debug.Assert(endIndex - startIndex >= 0);
Debug.Assert(startIndex >= 0);
Debug.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()
{
Debug.Assert(Upto + BufferOffset <= EndIndex);
return Upto + BufferOffset == EndIndex;
}
public override byte ReadByte()
{
Debug.Assert(!Eof());
Debug.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)
{
Debug.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
Debug.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;
}
}
}
}
}