patternLength *= bytesPerComparison;
targetLength *= bytesPerComparison;
if (start < 1) {
Object[] params = new Object[] {new Long(start)};
throw new SQLException(CorePlugin.Util.getString("MMClob_MMBlob.2", params)); //$NON-NLS-1$
}
start = (start - 1)*bytesPerComparison;
if (start + patternLength > targetLength) {
return -1;
}
/*
* Use karp-rabin matching to reduce the cost of back tracing for failed matches
*
* TODO: optimize for patterns that are small enough to fit in a reasonable buffer
*/
try {
InputStream patternStream = pattern.getBinaryStream();
InputStream targetStream = target.getBinaryStream();
InputStream laggingTargetStream = target.getBinaryStream();
try {
int patternHash = computeStreamHash(patternStream, patternLength);
int lastMod = 1;
for (int i = 0; i < patternLength; i++) {
lastMod *= MOD;
}
targetStream.skip(start);
laggingTargetStream.skip(start);
long position = start + 1;
int streamHash = computeStreamHash(targetStream, patternLength);
do {
if ((position -1)%bytesPerComparison == 0 && patternHash == streamHash && validateMatch(pattern, target, position)) {
return (position - 1)/bytesPerComparison + 1;
}
streamHash = MOD * streamHash + targetStream.read() - lastMod * laggingTargetStream.read();
position++;
} while (position + patternLength - 1 <= targetLength);
return -1;
} finally {
if (patternStream != null) {
patternStream.close();
}
if (targetStream != null) {
targetStream.close();
}
if (laggingTargetStream != null) {
laggingTargetStream.close();
}
}
} catch (IOException e) {
throw new SQLException(e);
}
}