/**
     * Calculates the safe shifts to use if searching backwards. A safe shift is either the length
     * of the sequence, if the byte does not appear in the {@link SequenceMatcher}, or the shortest
     * distance it appears from the beginning of the matcher, with zero being the value of the first
     * position in the sequence.
     */
    @Override
    public SearchInfo create() {
      // Get info about the matcher:
      final SequenceMatcher sequence = getMatcher();
      final int sequenceLength = sequence.length();

      // Create the search info object fields
      final int lastPosition = sequenceLength - 1;
      final ByteMatcher byteMatcher = sequence.getMatcherForPosition(0);
      final SequenceMatcher verifier =
          (lastPosition == 0) ? null : sequence.subsequence(1, sequenceLength);
      // Set the default shift to the length of the sequence
      final int[] shifts = new int[256];
      Arrays.fill(shifts, sequenceLength);

      // Now set specific byte shifts for the bytes actually in
      // the sequence itself.  The shift is the position in the sequence,
      // but we do not create a shift for the first position 0.
      for (int sequencePos = lastPosition; sequencePos > 0; sequencePos--) {
        final ByteMatcher aMatcher = sequence.getMatcherForPosition(sequencePos);
        final byte[] matchingBytes = aMatcher.getMatchingBytes();
        for (final byte b : matchingBytes) {
          shifts[b & 0xFF] = sequencePos;
        }
      }
      return new SearchInfo(shifts, byteMatcher, verifier);
    }
    /**
     * Calculates the safe shifts to use if searching forwards. A safe shift is either the length of
     * the sequence, if the byte does not appear in the {@link SequenceMatcher}, or the shortest
     * distance it appears from the end of the matcher.
     */
    @Override
    public SearchInfo create() {
      // Get info about the matcher:
      final SequenceMatcher sequence = getMatcher();
      final int sequenceLength = sequence.length();

      // Create the search info object fields:
      final int lastPosition = sequenceLength - 1;
      final ByteMatcher byteMatcher = sequence.getMatcherForPosition(lastPosition);
      final SequenceMatcher verifier =
          (lastPosition == 0)
              ? AnyByteMatcher.ANY_BYTE_MATCHER
              : sequence.subsequence(0, lastPosition);

      // Set the default shift to the length of the sequence for all possible byte values:
      final int[] shifts = new int[256];
      Arrays.fill(shifts, sequenceLength);

      // Now set specific shifts for the bytes actually in
      // the sequence itself.  The shift is the distance of a position
      // from the end of the sequence, but we do not create a shift for
      // the very last position.
      for (int sequencePos = 0; sequencePos < lastPosition; sequencePos++) {
        final ByteMatcher aMatcher = sequence.getMatcherForPosition(sequencePos);
        final byte[] matchingBytes = aMatcher.getMatchingBytes();
        final int distanceFromEnd = sequenceLength - sequencePos - 1;
        for (final byte b : matchingBytes) {
          shifts[b & 0xFF] = distanceFromEnd;
        }
      }

      return new SearchInfo(shifts, byteMatcher, verifier);
    }