mirror of
https://github.com/dlang/phobos.git
synced 2025-05-01 15:40:36 +03:00
Optimizations for startsWith and endsWith.
This commit is contained in:
parent
6203835e5d
commit
121a69a04b
2 changed files with 80 additions and 66 deletions
138
std/algorithm.d
138
std/algorithm.d
|
@ -4152,12 +4152,15 @@ if (isInputRange!R1 &&
|
||||||
else
|
else
|
||||||
enum isDefaultPred = false;
|
enum isDefaultPred = false;
|
||||||
|
|
||||||
// Special case for two arrays
|
static if (isDefaultPred && isArray!R1 && isArray!R2 &&
|
||||||
static if (isArray!R1 && isArray!R2 &&
|
is(Unqual!(ElementEncodingType!R1) == Unqual!(ElementEncodingType!R2)))
|
||||||
((!isSomeString!R1 && !isSomeString!R2) ||
|
{
|
||||||
(isSomeString!R1 && isSomeString!R2 &&
|
if (haystack.length < needle.length) return false;
|
||||||
is(Unqual!(typeof(haystack[0])) == Unqual!(typeof(needle[0]))) &&
|
|
||||||
isDefaultPred)))
|
return haystack[0 .. needle.length] == needle;
|
||||||
|
}
|
||||||
|
else static if (isArray!R1 && isArray!R2 &&
|
||||||
|
!isNarrowString!R1 && !isNarrowString!R2)
|
||||||
{
|
{
|
||||||
if (haystack.length < needle.length) return false;
|
if (haystack.length < needle.length) return false;
|
||||||
|
|
||||||
|
@ -4205,8 +4208,7 @@ unittest
|
||||||
debug(std_algorithm) scope(success)
|
debug(std_algorithm) scope(success)
|
||||||
writeln("unittest @", __FILE__, ":", __LINE__, " done.");
|
writeln("unittest @", __FILE__, ":", __LINE__, " done.");
|
||||||
|
|
||||||
//foreach (S; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring))
|
foreach (S; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring))
|
||||||
foreach (S; TypeTuple!(char[], wstring))
|
|
||||||
{
|
{
|
||||||
assert(!startsWith(to!S("abc"), 'c'));
|
assert(!startsWith(to!S("abc"), 'c'));
|
||||||
assert(startsWith(to!S("abc"), 'a', 'c') == 1);
|
assert(startsWith(to!S("abc"), 'a', 'c') == 1);
|
||||||
|
@ -4214,8 +4216,7 @@ unittest
|
||||||
assert(startsWith(to!S("abc"), 'x', 'n', 'a') == 3);
|
assert(startsWith(to!S("abc"), 'x', 'n', 'a') == 3);
|
||||||
assert(startsWith(to!S("\uFF28abc"), 'a', '\uFF28', 'c') == 2);
|
assert(startsWith(to!S("\uFF28abc"), 'a', '\uFF28', 'c') == 2);
|
||||||
|
|
||||||
//foreach (T; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring))
|
foreach (T; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring))
|
||||||
foreach (T; TypeTuple!(dchar[], string))
|
|
||||||
{
|
{
|
||||||
assert(startsWith(to!S("abc"), to!T("")));
|
assert(startsWith(to!S("abc"), to!T("")));
|
||||||
assert(startsWith(to!S("ab"), to!T("a")));
|
assert(startsWith(to!S("ab"), to!T("a")));
|
||||||
|
@ -4238,28 +4239,33 @@ unittest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(startsWith([0, 1, 2, 3, 4, 5], cast(int[])null));
|
foreach(T; TypeTuple!(int, short))
|
||||||
assert(!startsWith([0, 1, 2, 3, 4, 5], 5));
|
{
|
||||||
assert(!startsWith([0, 1, 2, 3, 4, 5], 1));
|
immutable arr = cast(T[])[0, 1, 2, 3, 4, 5];
|
||||||
assert(startsWith([0, 1, 2, 3, 4, 5], 0));
|
|
||||||
assert(startsWith([0, 1, 2, 3, 4, 5], 5, 0, 1) == 2);
|
|
||||||
assert(startsWith([0, 1, 2, 3, 4, 5], [0]));
|
|
||||||
assert(startsWith([0, 1, 2, 3, 4, 5], [0, 1]));
|
|
||||||
assert(startsWith([0, 1, 2, 3, 4, 5], [0, 1], 7) == 1);
|
|
||||||
assert(!startsWith([0, 1, 2, 3, 4, 5], [0, 1, 7]));
|
|
||||||
assert(startsWith([0, 1, 2, 3, 4, 5], [0, 1, 7], [0, 1, 2]) == 2);
|
|
||||||
|
|
||||||
assert(!startsWith(filter!"true"([0, 1, 2, 3, 4, 5]), 1));
|
assert(startsWith(arr, cast(int[])null));
|
||||||
assert(startsWith(filter!"true"([0, 1, 2, 3, 4, 5]), 0));
|
assert(!startsWith(arr, 5));
|
||||||
assert(startsWith(filter!"true"([0, 1, 2, 3, 4, 5]), [0]));
|
assert(!startsWith(arr, 1));
|
||||||
assert(startsWith(filter!"true"([0, 1, 2, 3, 4, 5]), [0, 1]));
|
assert(startsWith(arr, 0));
|
||||||
assert(startsWith(filter!"true"([0, 1, 2, 3, 4, 5]), [0, 1], 7) == 1);
|
assert(startsWith(arr, 5, 0, 1) == 2);
|
||||||
assert(!startsWith(filter!"true"([0, 1, 2, 3, 4, 5]), [0, 1, 7]));
|
assert(startsWith(arr, [0]));
|
||||||
assert(startsWith(filter!"true"([0, 1, 2, 3, 4, 5]), [0, 1, 7], [0, 1, 2]) == 2);
|
assert(startsWith(arr, [0, 1]));
|
||||||
assert(startsWith([0, 1, 2, 3, 4, 5], filter!"true"([0, 1])));
|
assert(startsWith(arr, [0, 1], 7) == 1);
|
||||||
assert(startsWith([0, 1, 2, 3, 4, 5], filter!"true"([0, 1]), 7) == 1);
|
assert(!startsWith(arr, [0, 1, 7]));
|
||||||
assert(!startsWith([0, 1, 2, 3, 4, 5], filter!"true"([0, 1, 7])));
|
assert(startsWith(arr, [0, 1, 7], [0, 1, 2]) == 2);
|
||||||
assert(startsWith([0, 1, 2, 3, 4, 5], [0, 1, 7], filter!"true"([0, 1, 2])) == 2);
|
|
||||||
|
assert(!startsWith(filter!"true"(arr), 1));
|
||||||
|
assert(startsWith(filter!"true"(arr), 0));
|
||||||
|
assert(startsWith(filter!"true"(arr), [0]));
|
||||||
|
assert(startsWith(filter!"true"(arr), [0, 1]));
|
||||||
|
assert(startsWith(filter!"true"(arr), [0, 1], 7) == 1);
|
||||||
|
assert(!startsWith(filter!"true"(arr), [0, 1, 7]));
|
||||||
|
assert(startsWith(filter!"true"(arr), [0, 1, 7], [0, 1, 2]) == 2);
|
||||||
|
assert(startsWith(arr, filter!"true"([0, 1])));
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4451,18 +4457,21 @@ if (isInputRange!R1 &&
|
||||||
else
|
else
|
||||||
enum isDefaultPred = false;
|
enum isDefaultPred = false;
|
||||||
|
|
||||||
// Special case for two arrays
|
static if (isDefaultPred && isArray!R1 && isArray!R2 &&
|
||||||
static if (isArray!R1 && isArray!R2 &&
|
is(Unqual!(ElementEncodingType!R1) == Unqual!(ElementEncodingType!R2)))
|
||||||
((!isSomeString!R1 && !isSomeString!R2) ||
|
{
|
||||||
(isSomeString!R1 && isSomeString!R2 &&
|
if (haystack.length < needle.length) return false;
|
||||||
is(Unqual!(typeof(haystack[0])) == Unqual!(typeof(needle[0]))) &&
|
|
||||||
isDefaultPred)))
|
return haystack[$ - needle.length .. $] == needle;
|
||||||
|
}
|
||||||
|
else static if (isArray!R1 && isArray!R2 &&
|
||||||
|
!isNarrowString!R1 && !isNarrowString!R2)
|
||||||
{
|
{
|
||||||
if (haystack.length < needle.length) return false;
|
if (haystack.length < needle.length) return false;
|
||||||
immutable diff = haystack.length - needle.length;
|
immutable diff = haystack.length - needle.length;
|
||||||
foreach (j; 0 .. needle.length)
|
foreach (j; 0 .. needle.length)
|
||||||
{
|
{
|
||||||
if (!binaryFun!(pred)(needle[j], haystack[j + diff]))
|
if (!binaryFun!pred(needle[j], haystack[j + diff]))
|
||||||
// not found
|
// not found
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -4523,8 +4532,7 @@ unittest
|
||||||
return Result(r);
|
return Result(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
//foreach (S; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring))
|
foreach (S; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring))
|
||||||
foreach (S; TypeTuple!(char[], wstring))
|
|
||||||
{
|
{
|
||||||
assert(!endsWith(to!S("abc"), 'a'));
|
assert(!endsWith(to!S("abc"), 'a'));
|
||||||
assert(endsWith(to!S("abc"), 'a', 'c') == 2);
|
assert(endsWith(to!S("abc"), 'a', 'c') == 2);
|
||||||
|
@ -4532,8 +4540,7 @@ unittest
|
||||||
assert(endsWith(to!S("abc"), 'x', 'n', 'c') == 3);
|
assert(endsWith(to!S("abc"), 'x', 'n', 'c') == 3);
|
||||||
assert(endsWith(to!S("abc\uFF28"), 'a', '\uFF28', 'c') == 2);
|
assert(endsWith(to!S("abc\uFF28"), 'a', '\uFF28', 'c') == 2);
|
||||||
|
|
||||||
//foreach (T; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring))
|
foreach (T; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring))
|
||||||
foreach (T; TypeTuple!(dchar[], string))
|
|
||||||
{
|
{
|
||||||
assert(endsWith(to!S("abc"), to!T("")));
|
assert(endsWith(to!S("abc"), to!T("")));
|
||||||
assert(!endsWith(to!S("abc"), to!T("a")));
|
assert(!endsWith(to!S("abc"), to!T("a")));
|
||||||
|
@ -4551,28 +4558,33 @@ unittest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(endsWith([0, 1, 2, 3, 4, 5], cast(int[])null));
|
foreach(T; TypeTuple!(int, short))
|
||||||
assert(!endsWith([0, 1, 2, 3, 4, 5], 0));
|
{
|
||||||
assert(!endsWith([0, 1, 2, 3, 4, 5], 4));
|
immutable arr = cast(T[])[0, 1, 2, 3, 4, 5];
|
||||||
assert(endsWith([0, 1, 2, 3, 4, 5], 5));
|
|
||||||
assert(endsWith([0, 1, 2, 3, 4, 5], 0, 4, 5) == 3);
|
|
||||||
assert(endsWith([0, 1, 2, 3, 4, 5], [5]));
|
|
||||||
assert(endsWith([0, 1, 2, 3, 4, 5], [4, 5]));
|
|
||||||
assert(endsWith([0, 1, 2, 3, 4, 5], [4, 5], 7) == 1);
|
|
||||||
assert(!endsWith([0, 1, 2, 3, 4, 5], [2, 4, 5]));
|
|
||||||
assert(endsWith([0, 1, 2, 3, 4, 5], [2, 4, 5], [3, 4, 5]) == 2);
|
|
||||||
|
|
||||||
assert(!endsWith(wrap([0, 1, 2, 3, 4, 5]), 4));
|
assert(endsWith(arr, cast(int[])null));
|
||||||
assert(endsWith(wrap([0, 1, 2, 3, 4, 5]), 5));
|
assert(!endsWith(arr, 0));
|
||||||
assert(endsWith(wrap([0, 1, 2, 3, 4, 5]), [5]));
|
assert(!endsWith(arr, 4));
|
||||||
assert(endsWith(wrap([0, 1, 2, 3, 4, 5]), [4, 5]));
|
assert(endsWith(arr, 5));
|
||||||
assert(endsWith(wrap([0, 1, 2, 3, 4, 5]), [4, 5], 7) == 1);
|
assert(endsWith(arr, 0, 4, 5) == 3);
|
||||||
assert(!endsWith(wrap([0, 1, 2, 3, 4, 5]), [2, 4, 5]));
|
assert(endsWith(arr, [5]));
|
||||||
assert(endsWith(wrap([0, 1, 2, 3, 4, 5]), [2, 4, 5], [3, 4, 5]) == 2);
|
assert(endsWith(arr, [4, 5]));
|
||||||
assert(endsWith([0, 1, 2, 3, 4, 5], wrap([4, 5])));
|
assert(endsWith(arr, [4, 5], 7) == 1);
|
||||||
assert(endsWith([0, 1, 2, 3, 4, 5], wrap([4, 5]), 7) == 1);
|
assert(!endsWith(arr, [2, 4, 5]));
|
||||||
assert(!endsWith([0, 1, 2, 3, 4, 5], wrap([2, 4, 5])));
|
assert(endsWith(arr, [2, 4, 5], [3, 4, 5]) == 2);
|
||||||
assert(endsWith([0, 1, 2, 3, 4, 5], [2, 4, 5], wrap([3, 4, 5])) == 2);
|
|
||||||
|
assert(!endsWith(wrap(arr), 4));
|
||||||
|
assert(endsWith(wrap(arr), 5));
|
||||||
|
assert(endsWith(wrap(arr), [5]));
|
||||||
|
assert(endsWith(wrap(arr), [4, 5]));
|
||||||
|
assert(endsWith(wrap(arr), [4, 5], 7) == 1);
|
||||||
|
assert(!endsWith(wrap(arr), [2, 4, 5]));
|
||||||
|
assert(endsWith(wrap(arr), [2, 4, 5], [3, 4, 5]) == 2);
|
||||||
|
assert(endsWith(arr, wrap([4, 5])));
|
||||||
|
assert(endsWith(arr, wrap([4, 5]), 7) == 1);
|
||||||
|
assert(!endsWith(arr, wrap([2, 4, 5])));
|
||||||
|
assert(endsWith(arr, [2, 4, 5], wrap([3, 4, 5])) == 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1684,6 +1684,8 @@ C[] chomp(C)(C[] str)
|
||||||
//Pops off the last character if it's lineSep or paraSep.
|
//Pops off the last character if it's lineSep or paraSep.
|
||||||
static if(is(C : const char))
|
static if(is(C : const char))
|
||||||
{
|
{
|
||||||
|
//In UTF-8, lineSep and paraSep are [226, 128, 168], and
|
||||||
|
//[226, 128, 169] respectively, so their first two bytes are the same.
|
||||||
case 168: //Last byte of lineSep
|
case 168: //Last byte of lineSep
|
||||||
case 169: //Last byte of paraSep
|
case 169: //Last byte of paraSep
|
||||||
{
|
{
|
||||||
|
@ -1712,7 +1714,7 @@ C1[] chomp(C1, C2)(C1[] str, const(C2)[] delimiter)
|
||||||
|
|
||||||
static if(is(Unqual!C1 == Unqual!C2))
|
static if(is(Unqual!C1 == Unqual!C2))
|
||||||
{
|
{
|
||||||
if(str.length >= delimiter.length && str[$ - delimiter.length .. $] == delimiter)
|
if(str.endsWith(delimiter))
|
||||||
return str[0 .. $ - delimiter.length];
|
return str[0 .. $ - delimiter.length];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1772,7 +1774,7 @@ unittest
|
||||||
{
|
{
|
||||||
// @@@ BUG IN COMPILER, MUST INSERT CAST
|
// @@@ BUG IN COMPILER, MUST INSERT CAST
|
||||||
assert(chomp(cast(S)null, cast(T)null) is null);
|
assert(chomp(cast(S)null, cast(T)null) is null);
|
||||||
assert(chomp("hello\n", cast(T)null) == "hello");
|
assert(chomp(to!S("hello\n"), cast(T)null) == "hello");
|
||||||
assert(chomp(to!S("hello"), to!T("o")) == "hell");
|
assert(chomp(to!S("hello"), to!T("o")) == "hell");
|
||||||
assert(chomp(to!S("hello"), to!T("p")) == "hello");
|
assert(chomp(to!S("hello"), to!T("p")) == "hello");
|
||||||
// @@@ BUG IN COMPILER, MUST INSERT CAST
|
// @@@ BUG IN COMPILER, MUST INSERT CAST
|
||||||
|
@ -1803,7 +1805,7 @@ C1[] chompPrefix(C1, C2)(C1[] str, C2[] delimiter)
|
||||||
{
|
{
|
||||||
static if(is(Unqual!C1 == Unqual!C2))
|
static if(is(Unqual!C1 == Unqual!C2))
|
||||||
{
|
{
|
||||||
if(str.length >= delimiter.length && str[0 .. delimiter.length] == delimiter)
|
if(str.startsWith(delimiter))
|
||||||
return str[delimiter.length .. $];
|
return str[delimiter.length .. $];
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue