blob: ab7af414ee10a80383d3ff4b9cfba5fe9198ba63 [file] [log] [blame]
using Lucene.Net.Diagnostics;
using Lucene.Net.Index;
using Lucene.Net.Store;
using Lucene.Net.Support;
using System.Diagnostics;
using System.IO;
namespace Lucene.Net.Codecs.Sep
{
/*
* 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.
*/
/// <summary>
/// Implements the skip list reader for the default posting list format
/// that stores positions and payloads.
/// <para/>
/// @lucene.experimental
/// </summary>
// TODO: rewrite this as recursive classes?
internal class SepSkipListReader : MultiLevelSkipListReader
{
private bool currentFieldStoresPayloads;
private Int32IndexInput.Index[] freqIndex;
private Int32IndexInput.Index[] docIndex;
private Int32IndexInput.Index[] posIndex;
private long[] payloadPointer;
private int[] payloadLength;
private readonly Int32IndexInput.Index lastFreqIndex;
private readonly Int32IndexInput.Index lastDocIndex;
// TODO: -- make private again
internal readonly Int32IndexInput.Index lastPosIndex;
private long lastPayloadPointer;
private int lastPayloadLength;
/// <exception cref="IOException"/>
internal SepSkipListReader(IndexInput skipStream,
Int32IndexInput freqIn,
Int32IndexInput docIn,
Int32IndexInput posIn,
int maxSkipLevels,
int skipInterval)
: base(skipStream, maxSkipLevels, skipInterval)
{
if (freqIn != null)
{
freqIndex = new Int32IndexInput.Index[maxSkipLevels];
}
docIndex = new Int32IndexInput.Index[maxSkipLevels];
if (posIn != null)
{
posIndex = new Int32IndexInput.Index[m_maxNumberOfSkipLevels];
}
for (int i = 0; i < maxSkipLevels; i++)
{
if (freqIn != null)
{
freqIndex[i] = freqIn.GetIndex();
}
docIndex[i] = docIn.GetIndex();
if (posIn != null)
{
posIndex[i] = posIn.GetIndex();
}
}
payloadPointer = new long[maxSkipLevels];
payloadLength = new int[maxSkipLevels];
if (freqIn != null)
{
lastFreqIndex = freqIn.GetIndex();
}
else
{
lastFreqIndex = null;
}
lastDocIndex = docIn.GetIndex();
if (posIn != null)
{
lastPosIndex = posIn.GetIndex();
}
else
{
lastPosIndex = null;
}
}
internal IndexOptions indexOptions;
internal void SetIndexOptions(IndexOptions v)
{
indexOptions = v;
}
internal void Init(long skipPointer,
Int32IndexInput.Index docBaseIndex,
Int32IndexInput.Index freqBaseIndex,
Int32IndexInput.Index posBaseIndex,
long payloadBasePointer,
int df,
bool storesPayloads)
{
base.Init(skipPointer, df);
this.currentFieldStoresPayloads = storesPayloads;
lastPayloadPointer = payloadBasePointer;
for (int i = 0; i < m_maxNumberOfSkipLevels; i++)
{
docIndex[i].CopyFrom(docBaseIndex);
if (freqIndex != null)
{
freqIndex[i].CopyFrom(freqBaseIndex);
}
if (posBaseIndex != null)
{
posIndex[i].CopyFrom(posBaseIndex);
}
}
Arrays.Fill(payloadPointer, payloadBasePointer);
Arrays.Fill(payloadLength, 0);
}
internal long PayloadPointer => lastPayloadPointer;
/// <summary>
/// Returns the payload length of the payload stored just before
/// the doc to which the last call of <see cref="MultiLevelSkipListReader.SkipTo(int)"/>
/// has skipped.
/// </summary>
internal int PayloadLength => lastPayloadLength;
/// <exception cref="IOException"/>
protected override void SeekChild(int level)
{
base.SeekChild(level);
payloadPointer[level] = lastPayloadPointer;
payloadLength[level] = lastPayloadLength;
}
protected override void SetLastSkipData(int level)
{
base.SetLastSkipData(level);
lastPayloadPointer = payloadPointer[level];
lastPayloadLength = payloadLength[level];
if (freqIndex != null)
{
lastFreqIndex.CopyFrom(freqIndex[level]);
}
lastDocIndex.CopyFrom(docIndex[level]);
if (lastPosIndex != null)
{
lastPosIndex.CopyFrom(posIndex[level]);
}
if (level > 0)
{
if (freqIndex != null)
{
freqIndex[level - 1].CopyFrom(freqIndex[level]);
}
docIndex[level - 1].CopyFrom(docIndex[level]);
if (posIndex != null)
{
posIndex[level - 1].CopyFrom(posIndex[level]);
}
}
}
internal Int32IndexInput.Index FreqIndex => lastFreqIndex;
internal Int32IndexInput.Index PosIndex => lastPosIndex;
internal Int32IndexInput.Index DocIndex => lastDocIndex;
/// <exception cref="IOException"/>
protected override int ReadSkipData(int level, IndexInput skipStream)
{
int delta;
if (Debugging.AssertsEnabled) Debugging.Assert(indexOptions == IndexOptions.DOCS_AND_FREQS_AND_POSITIONS || !currentFieldStoresPayloads);
if (currentFieldStoresPayloads)
{
// the current field stores payloads.
// if the doc delta is odd then we have
// to read the current payload length
// because it differs from the length of the
// previous payload
delta = skipStream.ReadVInt32();
if ((delta & 1) != 0)
{
payloadLength[level] = skipStream.ReadVInt32();
}
//delta >>>= 1;
delta = (int)((uint)delta >> 1);
}
else
{
delta = skipStream.ReadVInt32();
}
if (indexOptions != IndexOptions.DOCS_ONLY)
{
freqIndex[level].Read(skipStream, false);
}
docIndex[level].Read(skipStream, false);
if (indexOptions == IndexOptions.DOCS_AND_FREQS_AND_POSITIONS)
{
posIndex[level].Read(skipStream, false);
if (currentFieldStoresPayloads)
{
payloadPointer[level] += skipStream.ReadVInt32();
}
}
return delta;
}
}
}