internal virtual void AdvanceWord(int targetWordNum) { Debug.Assert(targetWordNum > WordNum); int delta = targetWordNum - WordNum; if (delta <= AllOnesLength + DirtyLength + 1) { SkipDirtyBytes(delta - 1); } else { SkipDirtyBytes(); Debug.Assert(DirtyLength == 0); if (delta > IndexThreshold_Renamed) { // use the index int i = ForwardBinarySearch(targetWordNum); int position = (int)Positions.Get(i); if (position > @in.Position) // if the binary search returned a backward offset, don't move { WordNum = (int)WordNums.Get(i) - 1; @in.Position = position; SequenceNum = i * IndexInterval - 1; } } while (true) { if (!ReadSequence()) { return; } delta = targetWordNum - WordNum; if (delta <= AllOnesLength + DirtyLength + 1) { if (delta > 1) { SkipDirtyBytes(delta - 1); } break; } SkipDirtyBytes(); } } NextWord(); }
internal virtual int ForwardBinarySearch(int targetWordNum) { // advance forward and double the window at each step int indexSize = (int)WordNums.Size(); int lo = SequenceNum / IndexInterval, hi = lo + 1; Debug.Assert(SequenceNum == -1 || WordNums.Get(lo) <= WordNum); Debug.Assert(lo + 1 == WordNums.Size() || WordNums.Get(lo + 1) > WordNum); while (true) { if (hi >= indexSize) { hi = indexSize - 1; break; } else if (WordNums.Get(hi) >= targetWordNum) { break; } int newLo = hi; hi += (hi - lo) << 1; lo = newLo; } // we found a window containing our target, let's binary search now while (lo <= hi) { int mid = (int)((uint)(lo + hi) >> 1); int midWordNum = (int)WordNums.Get(mid); if (midWordNum <= targetWordNum) { lo = mid + 1; } else { hi = mid - 1; } } Debug.Assert(WordNums.Get(hi) <= targetWordNum); Debug.Assert(hi + 1 == WordNums.Size() || WordNums.Get(hi + 1) > targetWordNum); return(hi); }