/** {@inheritDoc} */ @Override protected List<SearchResult<SequenceMatcher>> doSearchBackwards( final WindowReader reader, final long fromPosition, final long toPosition) throws IOException { // Initialise: final SearchInfo info = backwardInfo.get(); final int[] safeShifts = info.shifts; final ByteMatcher startOfSequence = info.matcher; final SequenceMatcher verifier = info.verifier; long searchPosition = fromPosition; // Search backwards across the windows: Window window; while (searchPosition >= toPosition && (window = reader.getWindow(searchPosition)) != null) { // Initialise the window search: final byte[] array = window.getArray(); final int arrayStartPosition = reader.getWindowOffset(searchPosition); final long distanceToEnd = toPosition - window.getWindowPosition(); final int lastSearchPosition = distanceToEnd > 0 ? (int) distanceToEnd : 0; int arraySearchPosition = arrayStartPosition; // Search using the byte array for shifts, using the WindowReader // for verifiying the sequence with the matcher: ARRAY_SEARCH: while (arraySearchPosition >= lastSearchPosition) { // Shift backwards until we match the first position in the sequence, // or we run out of search space. byte currentByte = array[arraySearchPosition]; while (!startOfSequence.matches(currentByte)) { arraySearchPosition -= safeShifts[currentByte & 0xff]; if (arraySearchPosition < lastSearchPosition) { break ARRAY_SEARCH; } currentByte = array[arraySearchPosition]; } // The first byte matched - verify there is a complete match. final int totalShift = arrayStartPosition - arraySearchPosition; final long sequencePosition = searchPosition - totalShift; if (verifier == null || verifier.matches(reader, sequencePosition + 1)) { return SearchUtils.singleResult(sequencePosition, matcher); // match found. } // No match was found - shift backward by the shift for the current byte: arraySearchPosition -= safeShifts[currentByte & 0xff]; } // No match was found in this array - calculate the current search position: searchPosition -= (arrayStartPosition - arraySearchPosition); } return SearchUtils.noResults(); }
/** * Searches forward using the Boyer Moore Horspool algorithm, using byte arrays from Windows to * handle shifting, and the WindowReader interface on the SequenceMatcher to verify whether a * match exists. */ @Override protected List<SearchResult<SequenceMatcher>> doSearchForwards( final WindowReader reader, final long fromPosition, final long toPosition) throws IOException { // Get the objects needed to search: final SearchInfo info = forwardInfo.get(); final int[] safeShifts = info.shifts; final ByteMatcher endOfSequence = info.matcher; final SequenceMatcher verifier = info.verifier; // Initialise window search: final long endSequencePosition = matcher.length() - 1; final long finalPosition = toPosition + endSequencePosition; long searchPosition = fromPosition + endSequencePosition; // While there is a window to search in: Window window; while (searchPosition <= finalPosition && (window = reader.getWindow(searchPosition)) != null) { // Initialise array search: final byte[] array = window.getArray(); final int arrayStartPosition = reader.getWindowOffset(searchPosition); final int arrayEndPosition = window.length() - 1; final int lastMatcherPosition = matcher.length() - 1; final long distanceToEnd = finalPosition - window.getWindowPosition() + lastMatcherPosition; final int lastSearchPosition = distanceToEnd < arrayEndPosition ? (int) distanceToEnd : arrayEndPosition; int arraySearchPosition = arrayStartPosition; // Search forwards in this array: ARRAY_SEARCH: while (arraySearchPosition <= lastSearchPosition) { // Shift forwards until we match the last position in the sequence, // or we run out of search space. byte currentByte = array[arraySearchPosition]; while (!endOfSequence.matches(currentByte)) { arraySearchPosition += safeShifts[currentByte & 0xff]; if (arraySearchPosition > lastSearchPosition) { break ARRAY_SEARCH; // outside the array, move on. } currentByte = array[arraySearchPosition]; } // The last byte matched - verify there is a complete match: final long arrayBytesSearched = arraySearchPosition - arrayStartPosition; final long matchPosition = searchPosition + arrayBytesSearched - endSequencePosition; if (verifier.matches(reader, matchPosition)) { return SearchUtils.singleResult(matchPosition, matcher); // match found. } // No match was found - shift forward by the shift for the current byte: arraySearchPosition += safeShifts[currentByte & 0xff]; } // No match was found in this array - calculate the current search position: searchPosition += arraySearchPosition - arrayStartPosition; } return SearchUtils.noResults(); }