package org.tomahawk.libtomahawk.resolver;/*
* Diff Match and Patch
*
* Copyright 2006 Google Inc.
* http://code.google.com/p/google-diff-match-patch/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Major modifications in 2015 by Enno Gottschalk <mrmaffen@googlemail.com>
*/
import java.util.HashMap;
import java.util.Map;
public class Bitap {
public static class Result {
public int index = -1;
public int errors = -1;
}
/**
* Locate the best instance of 'pattern' in 'text' near 'loc' using the Bitap algorithm. Returns
* -1 if no match found.
*
* @param text The text to search.
* @param pattern The pattern to search for.
* @return Best match index or -1.
*/
public static Result indexOf(String text, String pattern, int tolerance) {
Result result = new Result();
// Is there an exact match? (speedup)
int exactIndex = text.indexOf(pattern);
if (exactIndex != -1) {
result.index = exactIndex;
result.errors = 0;
return result;
}
// Initialise the alphabet.
Map<Character, Integer> alphabet = initAlphabet(pattern);
// Initialise the bit arrays.
int matchmask = 1 << (pattern.length() - 1);
int[] last_rd = new int[0];
for (int d = 0; d <= tolerance; d++) {
int[] rd = new int[text.length() + pattern.length() + 2];
rd[text.length() + pattern.length() + 1] = (1 << d) - 1;
for (int j = text.length() + pattern.length(); j > 0; j--) {
int charMatch;
if (text.length() <= j - 1 || !alphabet.containsKey(text.charAt(j - 1))) {
// Out of range.
charMatch = 0;
} else {
charMatch = alphabet.get(text.charAt(j - 1));
}
if (d == 0) {
// First pass: exact match.
rd[j] = ((rd[j + 1] << 1) | 1) & charMatch;
} else {
// Subsequent passes: fuzzy match.
rd[j] = (((rd[j + 1] << 1) | 1) & charMatch)
| (((last_rd[j + 1] | last_rd[j]) << 1) | 1) | last_rd[j + 1];
}
if ((rd[j] & matchmask) != 0) {
result.index = j - 1;
result.errors = d;
return result;
}
}
last_rd = rd;
}
return result;
}
/**
* Initialise the alphabet for the Bitap algorithm.
*
* @param pattern The text to encode.
* @return Hash of character locations.
*/
public static Map<Character, Integer> initAlphabet(String pattern) {
Map<Character, Integer> s = new HashMap<>();
char[] char_pattern = pattern.toCharArray();
for (char c : char_pattern) {
s.put(c, 0);
}
int i = 0;
for (char c : char_pattern) {
s.put(c, s.get(c) | (1 << (pattern.length() - i - 1)));
i++;
}
return s;
}
}