mirror of
https://github.com/dlang/phobos.git
synced 2025-05-01 15:40:36 +03:00
Push useCodePoint all the way in
This commit is contained in:
parent
e048dbeb18
commit
620a5a042d
1 changed files with 17 additions and 22 deletions
|
@ -889,20 +889,14 @@ Compares two ranges for equality, as defined by predicate `pred`
|
||||||
*/
|
*/
|
||||||
template equal(alias pred = "a == b")
|
template equal(alias pred = "a == b")
|
||||||
{
|
{
|
||||||
// use code points when comparing two ranges of UTF code units that aren't
|
|
||||||
// the same type. This is for backwards compatibility with autodecode
|
|
||||||
// strings.
|
|
||||||
enum useCodePoint(R1, R2) =
|
|
||||||
isSomeChar!(ElementEncodingType!R1) && isSomeChar!(ElementEncodingType!R2) &&
|
|
||||||
(ElementEncodingType!R1).sizeof != (ElementEncodingType!R2).sizeof;
|
|
||||||
|
|
||||||
/++
|
/++
|
||||||
Compares two ranges for equality. The ranges may have
|
Compares two ranges for equality. The ranges may have
|
||||||
different element types, as long as `pred(r1.front, r2.front)`
|
different element types, as long as `pred(r1.front, r2.front)`
|
||||||
evaluates to `bool`.
|
evaluates to `bool`.
|
||||||
Performs $(BIGOH min(r1.length, r2.length)) evaluations of `pred`.
|
Performs $(BIGOH min(r1.length, r2.length)) evaluations of `pred`.
|
||||||
|
|
||||||
At least one of the ranges must be finite. If one range involved is infinite, the result is `false`.
|
At least one of the ranges must be finite. If one range involved is infinite, the result is
|
||||||
|
(statically known to be) `false`.
|
||||||
|
|
||||||
If the two ranges are different kinds of UTF code unit (`char`, `wchar`, or
|
If the two ranges are different kinds of UTF code unit (`char`, `wchar`, or
|
||||||
`dchar`), then the arrays are compared using UTF decoding to avoid
|
`dchar`), then the arrays are compared using UTF decoding to avoid
|
||||||
|
@ -917,32 +911,37 @@ template equal(alias pred = "a == b")
|
||||||
for element, according to binary predicate `pred`.
|
for element, according to binary predicate `pred`.
|
||||||
+/
|
+/
|
||||||
bool equal(Range1, Range2)(Range1 r1, Range2 r2)
|
bool equal(Range1, Range2)(Range1 r1, Range2 r2)
|
||||||
if (useCodePoint!(Range1, Range2) ||
|
if (isInputRange!Range1 && isInputRange!Range2 &&
|
||||||
isInputRange!Range1 && isInputRange!Range2 &&
|
|
||||||
!(isInfinite!Range1 && isInfinite!Range2) &&
|
!(isInfinite!Range1 && isInfinite!Range2) &&
|
||||||
is(typeof(binaryFun!pred(r1.front, r2.front))))
|
is(typeof(binaryFun!pred(r1.front, r2.front))))
|
||||||
{
|
{
|
||||||
static if (useCodePoint!(Range1, Range2))
|
// Use code points when comparing two ranges of UTF code units that aren't
|
||||||
|
// the same type. This is for backwards compatibility with autodecode
|
||||||
|
// strings.
|
||||||
|
enum useCodePoint =
|
||||||
|
isSomeChar!(ElementEncodingType!Range1) && isSomeChar!(ElementEncodingType!Range2) &&
|
||||||
|
ElementEncodingType!Range1.sizeof != ElementEncodingType!Range2.sizeof;
|
||||||
|
|
||||||
|
static if (useCodePoint)
|
||||||
{
|
{
|
||||||
import std.utf : byDchar;
|
import std.utf : byDchar;
|
||||||
return equal(r1.byDchar, r2.byDchar);
|
return equal(r1.byDchar, r2.byDchar);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// No pred calls necessary.
|
|
||||||
static if (isInfinite!Range1 || isInfinite!Range2)
|
static if (isInfinite!Range1 || isInfinite!Range2)
|
||||||
{
|
{
|
||||||
// No finite range can be ever equal to an infinite range.
|
// No finite range can be ever equal to an infinite range.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//Detect default pred and compatible dynamic array
|
// Detect default pred and compatible dynamic arrays.
|
||||||
else static if (is(typeof(pred) == string) && pred == "a == b" &&
|
else static if (is(typeof(pred) == string) && pred == "a == b" &&
|
||||||
isArray!Range1 && isArray!Range2 && is(typeof(r1 == r2)))
|
isArray!Range1 && isArray!Range2 && is(typeof(r1 == r2)))
|
||||||
{
|
{
|
||||||
return r1 == r2;
|
return r1 == r2;
|
||||||
}
|
}
|
||||||
// if one of the arguments is a string and the other isn't, then auto-decoding
|
// If one of the arguments is a string and the other isn't, then auto-decoding
|
||||||
// can be avoided if they have the same ElementEncodingType
|
// can be avoided if they have the same ElementEncodingType.
|
||||||
else static if (is(typeof(pred) == string) && pred == "a == b" &&
|
else static if (is(typeof(pred) == string) && pred == "a == b" &&
|
||||||
isAutodecodableString!Range1 != isAutodecodableString!Range2 &&
|
isAutodecodableString!Range1 != isAutodecodableString!Range2 &&
|
||||||
is(immutable ElementEncodingType!Range1 == immutable ElementEncodingType!Range2))
|
is(immutable ElementEncodingType!Range1 == immutable ElementEncodingType!Range2))
|
||||||
|
@ -950,23 +949,19 @@ template equal(alias pred = "a == b")
|
||||||
import std.utf : byCodeUnit;
|
import std.utf : byCodeUnit;
|
||||||
|
|
||||||
static if (isAutodecodableString!Range1)
|
static if (isAutodecodableString!Range1)
|
||||||
{
|
|
||||||
return equal(r1.byCodeUnit, r2);
|
return equal(r1.byCodeUnit, r2);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
return equal(r2.byCodeUnit, r1);
|
return equal(r2.byCodeUnit, r1);
|
||||||
}
|
}
|
||||||
}
|
// Try a fast implementation when the ranges have comparable lengths.
|
||||||
//Try a fast implementation when the ranges have comparable lengths
|
|
||||||
else static if (hasLength!Range1 && hasLength!Range2 && is(typeof(r1.length == r2.length)))
|
else static if (hasLength!Range1 && hasLength!Range2 && is(typeof(r1.length == r2.length)))
|
||||||
{
|
{
|
||||||
immutable len1 = r1.length;
|
immutable len1 = r1.length;
|
||||||
immutable len2 = r2.length;
|
immutable len2 = r2.length;
|
||||||
if (len1 != len2) return false; //Short circuit return
|
if (len1 != len2) return false; //Short circuit return
|
||||||
|
|
||||||
//Lengths are the same, so we need to do an actual comparison
|
// Lengths are the same, so we need to do an actual comparison.
|
||||||
//Good news is we can squeeze out a bit of performance by not checking if r2 is empty
|
// Good news is we can squeeze out a bit of performance by not checking if r2 is empty.
|
||||||
for (; !r1.empty; r1.popFront(), r2.popFront())
|
for (; !r1.empty; r1.popFront(), r2.popFront())
|
||||||
{
|
{
|
||||||
if (!binaryFun!(pred)(r1.front, r2.front)) return false;
|
if (!binaryFun!(pred)(r1.front, r2.front)) return false;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue