SearchUtils { public static int kmp(ByteBuffer buf, byte[] sought) { if (sought == null || sought.length == 0) { return -1; } if (sought.length == 1) { int i = buf.position(); while (buf.hasRemaining()) { if (buf.get(i) == sought[0]) { return i; } i += 1; } return -1; } int i = 0; int[] t = kmpTable(sought); int m = buf.position(); while (m + i < buf.limit()) { if (sought[i] == buf.get(m + i)) { i++; if (i == sought.length) return m; } else { m = m + i - t[i]; if (i > 0) i = t[i]; } } return -1; }  static int kmp(ByteBuffer buf, byte[] sought); static int levenshteinDistance(CharSequence lhs, CharSequence rhs);  }
@Test public void match() { byte[] sought = new byte[]{ 3,3,8,3 }; assertThat(SearchUtils.kmp(buf, sought)).isEqualTo(24); }
@Test public void notMatch() { byte[] sought = new byte[]{ 3,3,9,3 }; assertThat(SearchUtils.kmp(buf, sought)).isEqualTo(-1); }
@Test public void empty() { byte[] sought = new byte[]{}; assertThat(SearchUtils.kmp(buf, sought)).isEqualTo(-1); }
@Test public void oneByte() { byte[] sought = new byte[]{9}; assertThat(SearchUtils.kmp(buf, sought)).isEqualTo(5); }
@Test public void directBuf() { ByteBuffer directBuf = ByteBuffer.allocateDirect(100); directBuf.put(buf.array()); directBuf.flip(); byte[] sought = new byte[]{ 3,3,8,3 }; assertThat(SearchUtils.kmp(directBuf, sought)).isEqualTo(24); }