mirror of
https://github.com/dlang/phobos.git
synced 2025-04-29 22:50:38 +03:00
support for non RA with length in startWith
As suggested by Andrei. Also: More unittests
This commit is contained in:
parent
d00be2ff1a
commit
b39752d5c7
1 changed files with 63 additions and 10 deletions
|
@ -4662,11 +4662,11 @@ if (isInputRange!R1 &&
|
|||
else
|
||||
enum isDefaultPred = false;
|
||||
|
||||
//Note: While narrow strings don't have a "true" length, for a narrow string to start with another
|
||||
//narrow string *of the same type*, it must have *at least* as many code units.
|
||||
static if ((hasLength!R1 && hasLength!R2) ||
|
||||
(isNarrowString!R1 && isNarrowString!R2 && ElementEncodingType!R1.sizeof == ElementEncodingType!R2.sizeof))
|
||||
(isNarrowString!R1 && isNarrowString!R2 && ElementEncodingType!R1.sizeof == ElementEncodingType!R2.sizeof))
|
||||
{
|
||||
//Note: While narrow strings don't have a "true" length, for a narrow string to start with another
|
||||
//narrow string *of the same type*, it must have *at least* as many encoding elements.
|
||||
if (haystack.length < needle.length)
|
||||
return false;
|
||||
}
|
||||
|
@ -4674,10 +4674,12 @@ if (isInputRange!R1 &&
|
|||
static if (isDefaultPred && isArray!R1 && isArray!R2 &&
|
||||
is(Unqual!(ElementEncodingType!R1) == Unqual!(ElementEncodingType!R2)))
|
||||
{
|
||||
//Array slice comparison mode
|
||||
return haystack[0 .. needle.length] == needle;
|
||||
}
|
||||
else static if (isRandomAccessRange!R1 && isRandomAccessRange!R2 && hasLength!R2)
|
||||
{
|
||||
//RA dual indexing mode
|
||||
foreach (j; 0 .. needle.length)
|
||||
{
|
||||
if (!binaryFun!pred(needle[j], haystack[j]))
|
||||
|
@ -4689,14 +4691,27 @@ if (isInputRange!R1 &&
|
|||
}
|
||||
else
|
||||
{
|
||||
if (needle.empty)
|
||||
return true;
|
||||
|
||||
for (; !haystack.empty; haystack.popFront())
|
||||
//Standard input range mode
|
||||
if (needle.empty) return true;
|
||||
static if (hasLength!R1 && hasLength!R2)
|
||||
{
|
||||
if (!binaryFun!pred(haystack.front, needle.front)) break;
|
||||
needle.popFront();
|
||||
if (needle.empty) return true;
|
||||
//We have previously checked that haystack.length > needle.length,
|
||||
//So no need to check haystack.empty during iteration
|
||||
for ( ; ; haystack.popFront() )
|
||||
{
|
||||
if (!binaryFun!pred(haystack.front, needle.front)) break;
|
||||
needle.popFront();
|
||||
if (needle.empty) return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( ; !haystack.empty ; haystack.popFront() )
|
||||
{
|
||||
if (!binaryFun!pred(haystack.front, needle.front)) break;
|
||||
needle.popFront();
|
||||
if (needle.empty) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -4727,6 +4742,7 @@ unittest
|
|||
|
||||
foreach (T; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring))
|
||||
{
|
||||
//Lots of strings
|
||||
assert(startsWith(to!S("abc"), to!T("")));
|
||||
assert(startsWith(to!S("ab"), to!T("a")));
|
||||
assert(startsWith(to!S("abc"), to!T("a")));
|
||||
|
@ -4743,18 +4759,34 @@ unittest
|
|||
assert(startsWith(to!S("abc"), 'a'));
|
||||
assert(!startsWith(to!S("abc"), to!T("sab")));
|
||||
assert(startsWith(to!S("abc"), 'x', to!T("aaa"), 'a', "sab") == 3);
|
||||
|
||||
//Unicode
|
||||
assert(startsWith(to!S("\uFF28el\uFF4co"), to!T("\uFF28el")));
|
||||
assert(startsWith(to!S("\uFF28el\uFF4co"), to!T("Hel"), to!T("\uFF28el")) == 2);
|
||||
assert(startsWith(to!S("日本語"), to!T("日本")));
|
||||
assert(startsWith(to!S("日本語"), to!T("日本語")));
|
||||
assert(!startsWith(to!S("日本"), to!T("日本語")));
|
||||
|
||||
//Empty
|
||||
assert(startsWith(to!S(""), T.init));
|
||||
assert(!startsWith(to!S(""), 'a'));
|
||||
assert(startsWith(to!S("a"), T.init));
|
||||
assert(startsWith(to!S("a"), T.init, "") == 1);
|
||||
assert(startsWith(to!S("a"), T.init, 'a') == 1);
|
||||
assert(startsWith(to!S("a"), 'a', T.init) == 2);
|
||||
}
|
||||
}
|
||||
|
||||
//Length but no RA
|
||||
assert(!startsWith("abc".takeExactly(3), "abcd".takeExactly(4)));
|
||||
assert(startsWith("abc".takeExactly(3), "abcd".takeExactly(3)));
|
||||
assert(startsWith("abc".takeExactly(3), "abcd".takeExactly(1)));
|
||||
|
||||
foreach (T; TypeTuple!(int, short))
|
||||
{
|
||||
immutable arr = cast(T[])[0, 1, 2, 3, 4, 5];
|
||||
|
||||
//RA range
|
||||
assert(startsWith(arr, cast(int[])null));
|
||||
assert(!startsWith(arr, 5));
|
||||
assert(!startsWith(arr, 1));
|
||||
|
@ -4766,6 +4798,7 @@ unittest
|
|||
assert(!startsWith(arr, [0, 1, 7]));
|
||||
assert(startsWith(arr, [0, 1, 7], [0, 1, 2]) == 2);
|
||||
|
||||
//Normal input range
|
||||
assert(!startsWith(filter!"true"(arr), 1));
|
||||
assert(startsWith(filter!"true"(arr), 0));
|
||||
assert(startsWith(filter!"true"(arr), [0]));
|
||||
|
@ -4777,6 +4810,10 @@ unittest
|
|||
assert(startsWith(arr, filter!"true"([0, 1]), 7) == 1);
|
||||
assert(!startsWith(arr, filter!"true"([0, 1, 7])));
|
||||
assert(startsWith(arr, [0, 1, 7], filter!"true"([0, 1, 2])) == 2);
|
||||
|
||||
//Non-default pred
|
||||
assert(startsWith!("a%10 == b%10")(arr, [10, 11]));
|
||||
assert(!startsWith!("a%10 == b%10")(arr, [10, 12]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5004,6 +5041,7 @@ unittest
|
|||
|
||||
foreach (T; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring))
|
||||
{
|
||||
//Lots of strings
|
||||
assert(endsWith(to!S("abc"), to!T("")));
|
||||
assert(!endsWith(to!S("abc"), to!T("a")));
|
||||
assert(!endsWith(to!S("abc"), to!T("b")));
|
||||
|
@ -5017,9 +5055,21 @@ unittest
|
|||
assert(endsWith(to!S("abc"), to!T("x"), "aaa", "c", "sab") == 3);
|
||||
assert(endsWith(to!S("\uFF28el\uFF4co"), to!T("l\uFF4co")));
|
||||
assert(endsWith(to!S("\uFF28el\uFF4co"), to!T("lo"), to!T("l\uFF4co")) == 2);
|
||||
|
||||
//Unicode
|
||||
assert(endsWith(to!S("\uFF28el\uFF4co"), to!T("l\uFF4co")));
|
||||
assert(endsWith(to!S("\uFF28el\uFF4co"), to!T("lo"), to!T("l\uFF4co")) == 2);
|
||||
assert(endsWith(to!S("日本語"), to!T("本語")));
|
||||
assert(endsWith(to!S("日本語"), to!T("日本語")));
|
||||
assert(!endsWith(to!S("本語"), to!T("日本語")));
|
||||
|
||||
//Empty
|
||||
assert(endsWith(to!S(""), T.init));
|
||||
assert(!endsWith(to!S(""), 'a'));
|
||||
assert(endsWith(to!S("a"), T.init));
|
||||
assert(endsWith(to!S("a"), T.init, "") == 1);
|
||||
assert(endsWith(to!S("a"), T.init, 'a') == 1);
|
||||
assert(endsWith(to!S("a"), 'a', T.init) == 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5027,6 +5077,7 @@ unittest
|
|||
{
|
||||
immutable arr = cast(T[])[0, 1, 2, 3, 4, 5];
|
||||
|
||||
//RA range
|
||||
assert(endsWith(arr, cast(int[])null));
|
||||
assert(!endsWith(arr, 0));
|
||||
assert(!endsWith(arr, 4));
|
||||
|
@ -5038,6 +5089,7 @@ unittest
|
|||
assert(!endsWith(arr, [2, 4, 5]));
|
||||
assert(endsWith(arr, [2, 4, 5], [3, 4, 5]) == 2);
|
||||
|
||||
//Normal input range
|
||||
assert(!endsWith(filterBidirectional!"true"(arr), 4));
|
||||
assert(endsWith(filterBidirectional!"true"(arr), 5));
|
||||
assert(endsWith(filterBidirectional!"true"(arr), [5]));
|
||||
|
@ -5050,6 +5102,7 @@ unittest
|
|||
assert(!endsWith(arr, filterBidirectional!"true"([2, 4, 5])));
|
||||
assert(endsWith(arr, [2, 4, 5], filterBidirectional!"true"([3, 4, 5])) == 2);
|
||||
|
||||
//Non-default pred
|
||||
assert(endsWith!("a%10 == b%10")(arr, [14, 15]));
|
||||
assert(!endsWith!("a%10 == b%10")(arr, [15, 14]));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue