mirror of
https://github.com/dlang/phobos.git
synced 2025-04-27 05:30:33 +03:00
Merge pull request #6611 from MartinNowak/merge_stable
Merge remote-tracking branch 'upstream/stable' into merge_stable
This commit is contained in:
commit
510a14c401
3 changed files with 179 additions and 19 deletions
|
@ -2748,6 +2748,21 @@ if (isForwardRange!R1 && isForwardRange!R2
|
|||
assert(findSkip(s, "def") && s.empty);
|
||||
}
|
||||
|
||||
@safe unittest // issue 19020
|
||||
{
|
||||
static struct WrapperRange
|
||||
{
|
||||
string _r;
|
||||
@property auto empty() { return _r.empty(); }
|
||||
@property auto front() { return _r.front(); }
|
||||
auto popFront() { return _r.popFront(); }
|
||||
@property auto save() { return WrapperRange(_r.save); }
|
||||
}
|
||||
auto tmp = WrapperRange("there is a bug here: *");
|
||||
assert(!tmp.findSkip("*/"));
|
||||
assert(tmp._r == "there is a bug here: *");
|
||||
}
|
||||
|
||||
/// ditto
|
||||
size_t findSkip(alias pred, R1)(ref R1 haystack)
|
||||
if (isForwardRange!R1 && ifTestable!(typeof(haystack.front), unaryFun!pred))
|
||||
|
@ -2821,7 +2836,7 @@ Returns:
|
|||
A sub-type of `Tuple!()` of the split portions of `haystack` (see above for
|
||||
details). This sub-type of `Tuple!()` has `opCast` defined for `bool`. This
|
||||
`opCast` returns `true` when the separating `needle` was found
|
||||
(`!result[1].empty`) and `false` otherwise.
|
||||
and `false` otherwise.
|
||||
|
||||
See_Also: $(LREF find)
|
||||
*/
|
||||
|
@ -2881,6 +2896,10 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
|||
pos2 = ++pos1;
|
||||
}
|
||||
}
|
||||
if (!n.empty) // incomplete match at the end of haystack
|
||||
{
|
||||
pos1 = pos2;
|
||||
}
|
||||
return Result!(typeof(takeExactly(original, pos1)),
|
||||
typeof(h))(takeExactly(original, pos1),
|
||||
takeExactly(haystack, pos2 - pos1),
|
||||
|
@ -2906,7 +2925,7 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
|||
Tuple!(S1, S2) asTuple;
|
||||
bool opCast(T : bool)()
|
||||
{
|
||||
return !asTuple[0].empty;
|
||||
return !asTuple[1].empty;
|
||||
}
|
||||
alias asTuple this;
|
||||
}
|
||||
|
@ -2926,24 +2945,30 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
|||
auto original = haystack.save;
|
||||
auto h = haystack.save;
|
||||
auto n = needle.save;
|
||||
size_t pos;
|
||||
size_t pos1, pos2;
|
||||
while (!n.empty && !h.empty)
|
||||
{
|
||||
if (binaryFun!pred(h.front, n.front))
|
||||
{
|
||||
h.popFront();
|
||||
n.popFront();
|
||||
++pos2;
|
||||
}
|
||||
else
|
||||
{
|
||||
haystack.popFront();
|
||||
n = needle.save;
|
||||
h = haystack.save;
|
||||
++pos;
|
||||
pos2 = ++pos1;
|
||||
}
|
||||
}
|
||||
return Result!(typeof(takeExactly(original, pos)),
|
||||
typeof(haystack))(takeExactly(original, pos),
|
||||
if (!n.empty) // incomplete match at the end of haystack
|
||||
{
|
||||
pos1 = pos2;
|
||||
haystack = h;
|
||||
}
|
||||
return Result!(typeof(takeExactly(original, pos1)),
|
||||
typeof(haystack))(takeExactly(original, pos1),
|
||||
haystack);
|
||||
}
|
||||
}
|
||||
|
@ -2966,7 +2991,7 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
|||
Tuple!(S1, S2) asTuple;
|
||||
bool opCast(T : bool)()
|
||||
{
|
||||
return !asTuple[1].empty;
|
||||
return !asTuple[0].empty;
|
||||
}
|
||||
alias asTuple this;
|
||||
}
|
||||
|
@ -3077,7 +3102,7 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
|||
assert(r[2] == a[3 .. $]);
|
||||
|
||||
auto r1 = findSplitBefore(a, [9, 1]);
|
||||
assert(r1);
|
||||
assert(!r1);
|
||||
assert(r1[0] == a);
|
||||
assert(r1[1].empty);
|
||||
r1 = findSplitBefore(a, [3, 4]);
|
||||
|
@ -3086,7 +3111,7 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
|||
assert(r1[1] == a[2 .. $]);
|
||||
|
||||
auto r2 = findSplitAfter(a, [9, 1]);
|
||||
assert(r2);
|
||||
assert(!r2);
|
||||
assert(r2[0].empty);
|
||||
assert(r2[1] == a);
|
||||
r2 = findSplitAfter(a, [3, 4]);
|
||||
|
@ -3112,24 +3137,37 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
|||
assert(equal(r[0], a[0 .. 2]));
|
||||
assert(equal(r[1], a[2 .. 3]));
|
||||
assert(equal(r[2], a[3 .. $]));
|
||||
r = findSplit(fwd, [8, 9]);
|
||||
assert(!r);
|
||||
assert(equal(r[0], a));
|
||||
assert(r[1].empty);
|
||||
assert(r[2].empty);
|
||||
|
||||
auto r1 = findSplitBefore(fwd, [9, 1]);
|
||||
assert(r1);
|
||||
assert(!r1);
|
||||
assert(equal(r1[0], a));
|
||||
assert(r1[1].empty);
|
||||
r1 = findSplitBefore(fwd, [3, 4]);
|
||||
assert(r1);
|
||||
assert(equal(r1[0], a[0 .. 2]));
|
||||
assert(equal(r1[1], a[2 .. $]));
|
||||
r1 = findSplitBefore(fwd, [8, 9]);
|
||||
assert(!r1);
|
||||
assert(equal(r1[0], a));
|
||||
assert(r1[1].empty);
|
||||
|
||||
auto r2 = findSplitAfter(fwd, [9, 1]);
|
||||
assert(r2);
|
||||
assert(!r2);
|
||||
assert(r2[0].empty);
|
||||
assert(equal(r2[1], a));
|
||||
r2 = findSplitAfter(fwd, [3, 4]);
|
||||
assert(r2);
|
||||
assert(equal(r2[0], a[0 .. 4]));
|
||||
assert(equal(r2[1], a[4 .. $]));
|
||||
r2 = findSplitAfter(fwd, [8, 9]);
|
||||
assert(!r2);
|
||||
assert(r2[0].empty);
|
||||
assert(equal(r2[1], a));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
|
|
|
@ -759,6 +759,63 @@ version(unittest)
|
|||
}
|
||||
}
|
||||
|
||||
/* Basically the `is` operator, but handles static arrays for which `is` is
|
||||
deprecated. For use in CTFE. */
|
||||
private bool bitwiseIdentical(T)(T a, T b)
|
||||
{
|
||||
static if (isStaticArray!T)
|
||||
{
|
||||
foreach (i, e; a)
|
||||
{
|
||||
if (!.bitwiseIdentical(e, b[i])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else return a is b;
|
||||
}
|
||||
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
import std.meta : AliasSeq;
|
||||
|
||||
static struct NeverEq
|
||||
{
|
||||
int x;
|
||||
bool opEquals(NeverEq other) const { return false; }
|
||||
}
|
||||
|
||||
static struct AlwaysEq
|
||||
{
|
||||
int x;
|
||||
bool opEquals(AlwaysEq other) const { return true; }
|
||||
}
|
||||
|
||||
static foreach (x; AliasSeq!(-1, 0, 1, 2, "foo", NeverEq(0)))
|
||||
{
|
||||
assert(bitwiseIdentical(x, x));
|
||||
static assert(bitwiseIdentical(x, x));
|
||||
}
|
||||
|
||||
static foreach (pair; AliasSeq!([0, 1], [-1, 1], [2, 3], ["foo", "bar"],
|
||||
[AlwaysEq(0), AlwaysEq(1)]))
|
||||
{
|
||||
assert(!bitwiseIdentical(pair[0], pair[1]));
|
||||
static assert(!bitwiseIdentical(pair[0], pair[1]));
|
||||
}
|
||||
|
||||
{
|
||||
int[2][2][2] x = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]];
|
||||
int[2][2][2] y = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]];
|
||||
assert(bitwiseIdentical(x, y));
|
||||
}
|
||||
|
||||
{
|
||||
enum int[2][2][2] x = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]];
|
||||
enum int[2][2][2] y = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]];
|
||||
static assert(bitwiseIdentical(x, y));
|
||||
}
|
||||
}
|
||||
|
||||
/+
|
||||
Can the representation be determined at compile time to consist of nothing but
|
||||
zero bits? Padding between a struct's fields is not considered.
|
||||
|
@ -774,15 +831,17 @@ private template isAllZeroBits(T, T value)
|
|||
else static if (isStaticArray!(typeof(value)))
|
||||
enum isAllZeroBits = ()
|
||||
{
|
||||
bool b = true;
|
||||
// Use index so this works when T.length is 0.
|
||||
static foreach (i; 0 .. T.length)
|
||||
{
|
||||
b &= isAllZeroBits!(typeof(value[i]), value[i]);
|
||||
if (b == false) return b;
|
||||
}
|
||||
|
||||
return b;
|
||||
static if (value.length == 0) return true;
|
||||
else static if (.isAllZeroBits!(typeof(value[0]), value[0]))
|
||||
{
|
||||
foreach (e; value[1 .. $])
|
||||
{
|
||||
if (!bitwiseIdentical(e, value[0])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}();
|
||||
else static if (is(typeof(value) == struct) || is(typeof(value) == union))
|
||||
enum isAllZeroBits = ()
|
||||
|
@ -822,6 +881,53 @@ private template isAllZeroBits(T, T value)
|
|||
static assert(isAllZeroBits!(Object, null));
|
||||
}
|
||||
|
||||
@nogc nothrow pure @safe unittest // large static arrays
|
||||
{
|
||||
import std.meta : Repeat;
|
||||
enum n = 16 * 1024;
|
||||
|
||||
static assert(isAllZeroBits!(ubyte[n], (ubyte[n]).init));
|
||||
static assert(!isAllZeroBits!(ubyte[n], [Repeat!(n, 1)]));
|
||||
static assert(!isAllZeroBits!(ubyte[n], [1, Repeat!(n - 1, 0)]));
|
||||
static assert(!isAllZeroBits!(ubyte[n], [Repeat!(n - 1, 0), 1]));
|
||||
|
||||
static assert(!isAllZeroBits!(char[n], (char[n]).init));
|
||||
static assert(isAllZeroBits!(char[n], [Repeat!(n, 0)]));
|
||||
}
|
||||
|
||||
@nogc nothrow pure @safe unittest // nested static arrays
|
||||
{
|
||||
static assert(isAllZeroBits!(int[2][2], [[0, 0], [0, 0]]));
|
||||
static assert(!isAllZeroBits!(int[2][2], [[0, 0], [1, 0]]));
|
||||
}
|
||||
|
||||
@nogc nothrow pure @safe unittest // funky opEquals
|
||||
{
|
||||
static struct AlwaysEq
|
||||
{
|
||||
int x;
|
||||
bool opEquals(AlwaysEq other) const { return true; }
|
||||
}
|
||||
static assert(AlwaysEq(0) == AlwaysEq(0));
|
||||
static assert(AlwaysEq(0) == AlwaysEq(1));
|
||||
static assert(isAllZeroBits!(AlwaysEq, AlwaysEq(0)));
|
||||
static assert(!isAllZeroBits!(AlwaysEq, AlwaysEq(1)));
|
||||
static assert(isAllZeroBits!(AlwaysEq[1], [AlwaysEq(0)]));
|
||||
static assert(!isAllZeroBits!(AlwaysEq[2], [AlwaysEq(0), AlwaysEq(1)]));
|
||||
|
||||
static struct NeverEq
|
||||
{
|
||||
int x;
|
||||
bool opEquals(NeverEq other) const { return false; }
|
||||
}
|
||||
static assert(NeverEq(0) != NeverEq(1));
|
||||
static assert(NeverEq(0) != NeverEq(0));
|
||||
static assert(isAllZeroBits!(NeverEq, NeverEq(0)));
|
||||
static assert(!isAllZeroBits!(NeverEq, NeverEq(1)));
|
||||
static assert(isAllZeroBits!(NeverEq[1], [NeverEq(0)]));
|
||||
static assert(!isAllZeroBits!(NeverEq[2], [NeverEq(0), NeverEq(1)]));
|
||||
}
|
||||
|
||||
/+
|
||||
Is the representation of T.init known at compile time to consist of nothing but
|
||||
zero bits? Padding between a struct's fields is not considered.
|
||||
|
|
|
@ -1410,6 +1410,22 @@ nothrow @safe @nogc unittest
|
|||
"Don't allow zero-ctor-args `make` for structs with `@disable this();`");
|
||||
}
|
||||
|
||||
@safe unittest // issue 18937
|
||||
{
|
||||
static struct S
|
||||
{
|
||||
ubyte[16 * 1024] data;
|
||||
}
|
||||
|
||||
static struct SomeAllocator
|
||||
{
|
||||
ubyte[] allocate(size_t) { return []; }
|
||||
void deallocate(void[]) {}
|
||||
}
|
||||
|
||||
auto x = SomeAllocator().make!S();
|
||||
}
|
||||
|
||||
private void fillWithMemcpy(T)(scope void[] array, auto ref T filler) nothrow
|
||||
if (T.sizeof == 1)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue