public SeekStatus ScanToTermLeaf(BytesRef target, bool exactOnly)
{
// if (DEBUG) System.out.println(" scanToTermLeaf: block fp=" + fp + " prefix=" + prefix + " nextEnt=" + nextEnt + " (of " + entCount + ") target=" + brToString(target) + " term=" + brToString(term));
Debug.Assert(NextEnt != -1);
OuterInstance.TermExists = true;
SubCode = 0;
if (NextEnt == EntCount)
{
if (exactOnly)
{
FillTerm();
}
return SeekStatus.END;
}
Debug.Assert(PrefixMatches(target));
// Loop over each entry (term or sub-block) in this block:
//nextTerm: while(nextEnt < entCount) {
while (true)
{
NextEnt++;
Suffix = SuffixesReader.ReadVInt();
// if (DEBUG) {
// BytesRef suffixBytesRef = new BytesRef();
// suffixBytesRef.bytes = suffixBytes;
// suffixBytesRef.offset = suffixesReader.getPosition();
// suffixBytesRef.length = suffix;
// System.out.println(" cycle: term " + (nextEnt-1) + " (of " + entCount + ") suffix=" + brToString(suffixBytesRef));
// }
int termLen = Prefix + Suffix;
StartBytePos = SuffixesReader.Position;
SuffixesReader.SkipBytes(Suffix);
int targetLimit = target.Offset + (target.Length < termLen ? target.Length : termLen);
int targetPos = target.Offset + Prefix;
// Loop over bytes in the suffix, comparing to
// the target
int bytePos = StartBytePos;
while (true)
{
int cmp;
bool stop;
if (targetPos < targetLimit)
{
cmp = (SuffixBytes[bytePos++] & 0xFF) - (target.Bytes[targetPos++] & 0xFF);
stop = false;
}
else
{
Debug.Assert(targetPos == targetLimit);
cmp = termLen - target.Length;
stop = true;
}
if (cmp < 0)
{
// Current entry is still before the target;
// keep scanning
if (NextEnt == EntCount)
{
if (exactOnly)
{
FillTerm();
}
// We are done scanning this block
goto nextTermBreak;
}
else
{
goto nextTermContinue;
}
}
else if (cmp > 0)
{
// Done! Current entry is after target --
// return NOT_FOUND:
FillTerm();
if (!exactOnly && !OuterInstance.TermExists)
{
// We are on a sub-block, and caller wants
// us to position to the next term after
// the target, so we must recurse into the
// sub-frame(s):
OuterInstance.CurrentFrame = OuterInstance.PushFrame(null, OuterInstance.CurrentFrame.LastSubFP, termLen);
OuterInstance.CurrentFrame.LoadBlock();
while (OuterInstance.CurrentFrame.Next())
{
OuterInstance.CurrentFrame = OuterInstance.PushFrame(null, OuterInstance.CurrentFrame.LastSubFP, OuterInstance.Term_Renamed.Length);
OuterInstance.CurrentFrame.LoadBlock();
}
}
//if (DEBUG) System.out.println(" not found");
return SeekStatus.NOT_FOUND;
}
else if (stop)
{
// Exact match!
// this cannot be a sub-block because we
// would have followed the index to this
// sub-block from the start:
Debug.Assert(OuterInstance.TermExists);
FillTerm();
//if (DEBUG) System.out.println(" found!");
return SeekStatus.FOUND;
}
}
nextTermContinue: ;
}
nextTermBreak:
// It is possible (and OK) that terms index pointed us
// at this block, but, we scanned the entire block and
// did not find the term to position to. this happens
// when the target is after the last term in the block
// (but, before the next term in the index). EG
// target could be foozzz, and terms index pointed us
// to the foo* block, but the last term in this block
// was fooz (and, eg, first term in the next block will
// bee fop).
//if (DEBUG) System.out.println(" block end");
if (exactOnly)
{
FillTerm();
}
// TODO: not consistent that in the
// not-exact case we don't next() into the next
// frame here
return SeekStatus.END;
}