Merge pull request #720 from jmdavis/8334

Fix for issue# 8334: find cannot handle close match at end of haystack in needle isn't bi-directional
This commit is contained in:
Andrei Alexandrescu 2012-08-19 21:00:27 -07:00
commit 47204076d8
2 changed files with 236 additions and 27 deletions

View file

@ -3201,8 +3201,8 @@ unittest
// Leftover specialization: searching a random-access range for a
// non-bidirectional forward range
R1 find(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
if (isRandomAccessRange!R1 && isForwardRange!R2 && !isBidirectionalRange!R2
&& is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool))
if (isRandomAccessRange!R1 && isForwardRange!R2 && !isBidirectionalRange!R2 &&
is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool))
{
static if (!is(ElementType!R1 == ElementType!R2))
{
@ -3211,11 +3211,25 @@ if (isRandomAccessRange!R1 && isForwardRange!R2 && !isBidirectionalRange!R2
else
{
// Prepare the search with needle's first element
if (needle.empty) return haystack;
if (needle.empty)
return haystack;
haystack = .find!pred(haystack, needle.front);
if (haystack.empty) return haystack;
static if (hasLength!R1 && hasLength!R2 && is(typeof(takeNone(haystack)) == typeof(haystack)))
{
if (needle.length > haystack.length)
return takeNone(haystack);
}
else
{
if (haystack.empty)
return haystack;
}
needle.popFront();
size_t matchLen = 1;
// Loop invariant: haystack[0 .. matchLen] matches everything in
// the initial needle that was popped out of needle.
for (;;)
@ -3223,11 +3237,22 @@ if (isRandomAccessRange!R1 && isForwardRange!R2 && !isBidirectionalRange!R2
// Extend matchLength as much as possible
for (;;)
{
if (needle.empty || haystack.empty) return haystack;
if (!binaryFun!pred(haystack[matchLen], needle.front)) break;
if (needle.empty || haystack.empty)
return haystack;
static if(hasLength!R1 && is(typeof(takeNone(haystack)) == typeof(haystack)))
{
if(matchLen == haystack.length)
return takeNone(haystack);
}
if (!binaryFun!pred(haystack[matchLen], needle.front))
break;
++matchLen;
needle.popFront();
}
auto bestMatch = haystack[0 .. matchLen];
haystack.popFront();
haystack = .find!pred(haystack, bestMatch);
@ -3241,6 +3266,19 @@ unittest
assert(find([ 1, 2, 1, 2, 3, 3 ], SList!int(2, 3)[]) == [ 2, 3, 3 ]);
}
//Bug# 8334
unittest
{
auto haystack = [1, 2, 3, 4, 1, 9, 12, 42];
auto needle = [12, 42, 27];
//different overload of find, but it's the base case.
assert(find(haystack, needle).empty);
assert(find(haystack, takeExactly(filter!"true"(needle), 3)).empty);
assert(find(haystack, filter!"true"(needle)).empty);
}
// Internally used by some find() overloads above. Can't make it
// private due to bugs in the compiler.
/*private*/ R1 simpleMindedFind(alias pred, R1, R2)(R1 haystack, R2 needle)