mirror of
https://github.com/dlang/phobos.git
synced 2025-04-29 14:40:30 +03:00
Struct returned findSplits with bool conversion
This commit is contained in:
parent
75fa251700
commit
100e7a485b
2 changed files with 117 additions and 37 deletions
|
@ -2404,18 +2404,47 @@ Params:
|
|||
needle = What to look for.
|
||||
|
||||
Returns:
|
||||
A tuple of the split portions of `haystack` (see above for details).
|
||||
|
||||
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 $(D true) when the separating $(D needle) was found (!result[1].empty)
|
||||
and $(D false) otherwise. This enables the convenient idiom shown in the
|
||||
following example.
|
||||
|
||||
Example:
|
||||
---
|
||||
if (const split = haystack.findSplit(needle))
|
||||
{
|
||||
doSomethingWithSplit(split);
|
||||
}
|
||||
---
|
||||
*/
|
||||
auto findSplit(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
|
||||
if (isForwardRange!R1 && isForwardRange!R2)
|
||||
{
|
||||
static struct Result(S1, S2) if (isForwardRange!S1 &&
|
||||
isForwardRange!S2)
|
||||
{
|
||||
this(S1 pre, S1 separator, S2 post)
|
||||
{
|
||||
asTuple = typeof(asTuple)(pre, separator, post);
|
||||
}
|
||||
Tuple!(S1, S1, S2) asTuple;
|
||||
bool opCast(T : bool)()
|
||||
{
|
||||
return !asTuple[1].empty;
|
||||
}
|
||||
alias asTuple this;
|
||||
}
|
||||
|
||||
static if (isSomeString!R1 && isSomeString!R2
|
||||
|| isRandomAccessRange!R1 && hasLength!R2)
|
||||
{
|
||||
auto balance = find!pred(haystack, needle);
|
||||
immutable pos1 = haystack.length - balance.length;
|
||||
immutable pos2 = balance.empty ? pos1 : pos1 + needle.length;
|
||||
return tuple(haystack[0 .. pos1],
|
||||
return Result!(typeof(haystack[0 .. pos1]),
|
||||
typeof(haystack[pos2 .. haystack.length]))(haystack[0 .. pos1],
|
||||
haystack[pos1 .. pos2],
|
||||
haystack[pos2 .. haystack.length]);
|
||||
}
|
||||
|
@ -2442,7 +2471,8 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
|||
pos2 = ++pos1;
|
||||
}
|
||||
}
|
||||
return tuple(takeExactly(original, pos1),
|
||||
return Result!(typeof(takeExactly(original, pos1)),
|
||||
typeof(h))(takeExactly(original, pos1),
|
||||
takeExactly(haystack, pos2 - pos1),
|
||||
h);
|
||||
}
|
||||
|
@ -2452,12 +2482,29 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
|||
auto findSplitBefore(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
|
||||
if (isForwardRange!R1 && isForwardRange!R2)
|
||||
{
|
||||
static struct Result(S1, S2) if (isForwardRange!S1 &&
|
||||
isForwardRange!S2)
|
||||
{
|
||||
this(S1 pre, S2 post)
|
||||
{
|
||||
asTuple = typeof(asTuple)(pre, post);
|
||||
}
|
||||
Tuple!(S1, S2) asTuple;
|
||||
bool opCast(T : bool)()
|
||||
{
|
||||
return !asTuple[0].empty;
|
||||
}
|
||||
alias asTuple this;
|
||||
}
|
||||
|
||||
static if (isSomeString!R1 && isSomeString!R2
|
||||
|| isRandomAccessRange!R1 && hasLength!R2)
|
||||
{
|
||||
auto balance = find!pred(haystack, needle);
|
||||
immutable pos = haystack.length - balance.length;
|
||||
return tuple(haystack[0 .. pos], haystack[pos .. haystack.length]);
|
||||
return Result!(typeof(haystack[0 .. pos]),
|
||||
typeof(haystack[pos .. haystack.length]))(haystack[0 .. pos],
|
||||
haystack[pos .. haystack.length]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2481,7 +2528,9 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
|||
++pos;
|
||||
}
|
||||
}
|
||||
return tuple(takeExactly(original, pos), haystack);
|
||||
return Result!(typeof(takeExactly(original, pos)),
|
||||
typeof(haystack))(takeExactly(original, pos),
|
||||
haystack);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2489,12 +2538,29 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
|||
auto findSplitAfter(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
|
||||
if (isForwardRange!R1 && isForwardRange!R2)
|
||||
{
|
||||
static struct Result(S1, S2) if (isForwardRange!S1 &&
|
||||
isForwardRange!S2)
|
||||
{
|
||||
this(S1 pre, S2 post)
|
||||
{
|
||||
asTuple = typeof(asTuple)(pre, post);
|
||||
}
|
||||
Tuple!(S1, S2) asTuple;
|
||||
bool opCast(T : bool)()
|
||||
{
|
||||
return !asTuple[1].empty;
|
||||
}
|
||||
alias asTuple this;
|
||||
}
|
||||
|
||||
static if (isSomeString!R1 && isSomeString!R2
|
||||
|| isRandomAccessRange!R1 && hasLength!R2)
|
||||
{
|
||||
auto balance = find!pred(haystack, needle);
|
||||
immutable pos = balance.empty ? 0 : haystack.length - balance.length + needle.length;
|
||||
return tuple(haystack[0 .. pos], haystack[pos .. haystack.length]);
|
||||
return Result!(typeof(haystack[0 .. pos]),
|
||||
typeof(haystack[pos .. haystack.length]))(haystack[0 .. pos],
|
||||
haystack[pos .. haystack.length]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2508,7 +2574,9 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
|||
if (h.empty)
|
||||
{
|
||||
// Failed search
|
||||
return tuple(takeExactly(original, 0), original);
|
||||
return Result!(typeof(takeExactly(original, 0)),
|
||||
typeof(original))(takeExactly(original, 0),
|
||||
original);
|
||||
}
|
||||
if (binaryFun!pred(h.front, n.front))
|
||||
{
|
||||
|
@ -2524,7 +2592,9 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
|||
pos2 = ++pos1;
|
||||
}
|
||||
}
|
||||
return tuple(takeExactly(original, pos2), h);
|
||||
return Result!(typeof(takeExactly(original, pos2)),
|
||||
typeof(h))(takeExactly(original, pos2),
|
||||
h);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2533,6 +2603,10 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
|||
{
|
||||
auto a = "Carl Sagan Memorial Station";
|
||||
auto r = findSplit(a, "Velikovsky");
|
||||
import std.typecons : isTuple;
|
||||
static assert(isTuple!(typeof(r.asTuple)));
|
||||
static assert(isTuple!(typeof(r)));
|
||||
assert(!r);
|
||||
assert(r[0] == a);
|
||||
assert(r[1].empty);
|
||||
assert(r[2].empty);
|
||||
|
@ -2541,9 +2615,11 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
|||
assert(r[1] == " ");
|
||||
assert(r[2] == "Sagan Memorial Station");
|
||||
auto r1 = findSplitBefore(a, "Sagan");
|
||||
assert(r1);
|
||||
assert(r1[0] == "Carl ", r1[0]);
|
||||
assert(r1[1] == "Sagan Memorial Station");
|
||||
auto r2 = findSplitAfter(a, "Sagan");
|
||||
assert(r2);
|
||||
assert(r2[0] == "Carl Sagan");
|
||||
assert(r2[1] == " Memorial Station");
|
||||
}
|
||||
|
@ -2552,27 +2628,33 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
|||
{
|
||||
auto a = [ 1, 2, 3, 4, 5, 6, 7, 8 ];
|
||||
auto r = findSplit(a, [9, 1]);
|
||||
assert(!r);
|
||||
assert(r[0] == a);
|
||||
assert(r[1].empty);
|
||||
assert(r[2].empty);
|
||||
r = findSplit(a, [3]);
|
||||
assert(r);
|
||||
assert(r[0] == a[0 .. 2]);
|
||||
assert(r[1] == a[2 .. 3]);
|
||||
assert(r[2] == a[3 .. $]);
|
||||
|
||||
auto r1 = findSplitBefore(a, [9, 1]);
|
||||
assert(r1);
|
||||
assert(r1[0] == a);
|
||||
assert(r1[1].empty);
|
||||
r1 = findSplitBefore(a, [3, 4]);
|
||||
assert(r1);
|
||||
assert(r1[0] == a[0 .. 2]);
|
||||
assert(r1[1] == a[2 .. $]);
|
||||
|
||||
r1 = findSplitAfter(a, [9, 1]);
|
||||
assert(r1[0].empty);
|
||||
assert(r1[1] == a);
|
||||
r1 = findSplitAfter(a, [3, 4]);
|
||||
assert(r1[0] == a[0 .. 4]);
|
||||
assert(r1[1] == a[4 .. $]);
|
||||
auto r2 = findSplitAfter(a, [9, 1]);
|
||||
assert(r2);
|
||||
assert(r2[0].empty);
|
||||
assert(r2[1] == a);
|
||||
r2 = findSplitAfter(a, [3, 4]);
|
||||
assert(r2);
|
||||
assert(r2[0] == a[0 .. 4]);
|
||||
assert(r2[1] == a[4 .. $]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
|
@ -2583,27 +2665,33 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
|||
auto a = [ 1, 2, 3, 4, 5, 6, 7, 8 ];
|
||||
auto fwd = filter!"a > 0"(a);
|
||||
auto r = findSplit(fwd, [9, 1]);
|
||||
assert(!r);
|
||||
assert(equal(r[0], a));
|
||||
assert(r[1].empty);
|
||||
assert(r[2].empty);
|
||||
r = findSplit(fwd, [3]);
|
||||
assert(r);
|
||||
assert(equal(r[0], a[0 .. 2]));
|
||||
assert(equal(r[1], a[2 .. 3]));
|
||||
assert(equal(r[2], a[3 .. $]));
|
||||
|
||||
auto r1 = findSplitBefore(fwd, [9, 1]);
|
||||
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 = findSplitAfter(fwd, [9, 1]);
|
||||
assert(r1[0].empty);
|
||||
assert(equal(r1[1], a));
|
||||
r1 = findSplitAfter(fwd, [3, 4]);
|
||||
assert(equal(r1[0], a[0 .. 4]));
|
||||
assert(equal(r1[1], a[4 .. $]));
|
||||
auto r2 = findSplitAfter(fwd, [9, 1]);
|
||||
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 .. $]));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3528,4 +3616,3 @@ unittest // Issue 13124
|
|||
auto s = "hello how\nare you";
|
||||
s.until!(c => c.among!('\n', '\r'));
|
||||
}
|
||||
|
||||
|
|
|
@ -1376,17 +1376,11 @@ unittest
|
|||
Returns:
|
||||
true if `T` is a `Tuple` type, false otherwise.
|
||||
*/
|
||||
template isTuple(T)
|
||||
{
|
||||
static if (is(Unqual!T Unused : Tuple!Specs, Specs...))
|
||||
enum isTuple(T) = __traits(compiles,
|
||||
{
|
||||
enum isTuple = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
enum isTuple = false;
|
||||
}
|
||||
}
|
||||
void f(Specs...)(Tuple!Specs tup) {}
|
||||
f(T.init);
|
||||
} );
|
||||
|
||||
///
|
||||
unittest
|
||||
|
@ -6843,4 +6837,3 @@ unittest
|
|||
int, float, RefFun1, RefFun2,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue