blob: 51ceec34e31f2851278f16ff7264ca8fe5626864 [file] [log] [blame]
using Lucene.Net.Diagnostics;
using Lucene.Net.Support;
using System.Diagnostics.CodeAnalysis;
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 BytesRef = Lucene.Net.Util.BytesRef;
/// <summary>
/// Exposes flex API, merged from flex API of sub-segments.
/// <para/>
/// @lucene.experimental
/// </summary>
public sealed class MultiDocsAndPositionsEnum : DocsAndPositionsEnum
{
private readonly MultiTermsEnum parent;
internal readonly DocsAndPositionsEnum[] subDocsAndPositionsEnum;
private EnumWithSlice[] subs;
internal int numSubs;
internal int upto;
internal DocsAndPositionsEnum current;
internal int currentBase;
internal int doc = -1;
/// <summary>
/// Sole constructor. </summary>
public MultiDocsAndPositionsEnum(MultiTermsEnum parent, int subReaderCount)
{
this.parent = parent;
subDocsAndPositionsEnum = new DocsAndPositionsEnum[subReaderCount];
}
/// <summary>
/// Returns <c>true</c> if this instance can be reused by
/// the provided <see cref="MultiTermsEnum"/>.
/// </summary>
public bool CanReuse(MultiTermsEnum parent)
{
return this.parent == parent;
}
/// <summary>
/// Re-use and reset this instance on the provided slices. </summary>
public MultiDocsAndPositionsEnum Reset(EnumWithSlice[] subs, int numSubs)
{
this.numSubs = numSubs;
this.subs = new EnumWithSlice[subs.Length];
for (int i = 0; i < subs.Length; i++)
{
this.subs[i] = new EnumWithSlice();
this.subs[i].DocsAndPositionsEnum = subs[i].DocsAndPositionsEnum;
this.subs[i].Slice = subs[i].Slice;
}
upto = -1;
doc = -1;
current = null;
return this;
}
/// <summary>
/// How many sub-readers we are merging. </summary>
/// <see cref="Subs"/>
public int NumSubs => numSubs;
/// <summary>
/// Returns sub-readers we are merging. </summary>
[WritableArray]
[SuppressMessage("Microsoft.Performance", "CA1819", Justification = "Lucene's design requires some writable array properties")]
public EnumWithSlice[] Subs => subs;
public override int Freq
{
get
{
if (Debugging.AssertsEnabled) Debugging.Assert(current != null);
return current.Freq;
}
}
public override int DocID => doc;
public override int Advance(int target)
{
if (Debugging.AssertsEnabled) Debugging.Assert(target > doc);
while (true)
{
if (current != null)
{
int doc;
if (target < currentBase)
{
// target was in the previous slice but there was no matching doc after it
doc = current.NextDoc();
}
else
{
doc = current.Advance(target - currentBase);
}
if (doc == NO_MORE_DOCS)
{
current = null;
}
else
{
return this.doc = doc + currentBase;
}
}
else if (upto == numSubs - 1)
{
return this.doc = NO_MORE_DOCS;
}
else
{
upto++;
current = subs[upto].DocsAndPositionsEnum;
currentBase = subs[upto].Slice.Start;
}
}
}
public override int NextDoc()
{
while (true)
{
if (current == null)
{
if (upto == numSubs - 1)
{
return this.doc = NO_MORE_DOCS;
}
else
{
upto++;
current = subs[upto].DocsAndPositionsEnum;
currentBase = subs[upto].Slice.Start;
}
}
int doc = current.NextDoc();
if (doc != NO_MORE_DOCS)
{
return this.doc = currentBase + doc;
}
else
{
current = null;
}
}
}
public override int NextPosition()
{
return current.NextPosition();
}
public override int StartOffset => current.StartOffset;
public override int EndOffset => current.EndOffset;
public override BytesRef GetPayload()
{
return current.GetPayload();
}
// TODO: implement bulk read more efficiently than super
/// <summary>
/// Holds a <see cref="Index.DocsAndPositionsEnum"/> along with the
/// corresponding <see cref="ReaderSlice"/>.
/// </summary>
public sealed class EnumWithSlice
{
internal EnumWithSlice()
{
}
/// <summary>
/// <see cref="Index.DocsAndPositionsEnum"/> for this sub-reader. </summary>
public DocsAndPositionsEnum DocsAndPositionsEnum { get; internal set; } // LUCENENET NOTE: Made setter internal because ctor is internal
/// <summary>
/// <see cref="ReaderSlice"/> describing how this sub-reader
/// fits into the composite reader.
/// </summary>
public ReaderSlice Slice { get; internal set; } // LUCENENET NOTE: Made setter internal because ctor is internal
public override string ToString()
{
return Slice.ToString() + ":" + DocsAndPositionsEnum;
}
}
public override long GetCost()
{
long cost = 0;
for (int i = 0; i < numSubs; i++)
{
cost += subs[i].DocsAndPositionsEnum.GetCost();
}
return cost;
}
public override string ToString()
{
return "MultiDocsAndPositionsEnum(" + Arrays.ToString(Subs) + ")";
}
}
}