[std.algorithm.searching] Refactor findSplit result types

This commit is contained in:
Nick Treleaven 2023-11-28 17:22:40 +00:00
parent 9cb5f6d7db
commit 0819fec814

View file

@ -2881,6 +2881,29 @@ if (isForwardRange!R1 && ifTestable!(typeof(haystack.front), unaryFun!pred))
assert(findSkip!isWhite(s) == 2);
}
private struct FindSplitResult(ubyte emptyRangeIndex, Types...)
{
this(Types vals)
{
asTuple = typeof(asTuple)(vals);
}
void opAssign(typeof(asTuple) rhs)
{
asTuple = rhs;
}
Tuple!Types asTuple;
alias asTuple this;
static if (hasConstEmptyMember!(typeof(asTuple[emptyRangeIndex])))
{
bool opCast(T : bool)() const => !asTuple[emptyRangeIndex].empty;
}
else
{
bool opCast(T : bool)() => !asTuple[emptyRangeIndex].empty;
}
}
/**
These functions find the first occurrence of `needle` in `haystack` and then
split `haystack` as follows.
@ -2930,45 +2953,15 @@ See_Also: $(LREF find)
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);
}
void opAssign(typeof(asTuple) rhs)
{
asTuple = rhs;
}
Tuple!(S1, S1, S2) asTuple;
static if (hasConstEmptyMember!(typeof(asTuple[1])))
{
bool opCast(T : bool)() const
{
return !asTuple[1].empty;
}
}
else
{
bool opCast(T : bool)()
{
return !asTuple[1].empty;
}
}
alias asTuple this;
}
static if (isSomeString!R1 && isSomeString!R2
|| (isRandomAccessRange!R1 && hasSlicing!R1 && hasLength!R1 && hasLength!R2))
{
auto balance = find!pred(haystack, needle);
immutable pos1 = haystack.length - balance.length;
immutable pos2 = balance.empty ? pos1 : pos1 + needle.length;
return Result!(typeof(haystack[0 .. pos1]),
typeof(haystack[pos2 .. haystack.length]))(haystack[0 .. pos1],
haystack[pos1 .. pos2],
haystack[pos2 .. haystack.length]);
alias Slice = typeof(haystack[0 .. pos1]);
return FindSplitResult!(1, Slice, Slice, Slice)(
haystack[0 .. pos1], haystack[pos1 .. pos2], haystack[pos2 .. haystack.length]);
}
else
{
@ -2997,10 +2990,11 @@ if (isForwardRange!R1 && isForwardRange!R2)
{
pos1 = pos2;
}
return Result!(typeof(takeExactly(original, pos1)),
typeof(h))(takeExactly(original, pos1),
takeExactly(haystack, pos2 - pos1),
h);
return FindSplitResult!(1,
typeof(takeExactly(original, pos1)),
typeof(takeExactly(original, pos1)), typeof(h))(
takeExactly(original, pos1),
takeExactly(haystack, pos2 - pos1), h);
}
}
@ -3008,43 +3002,14 @@ 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);
}
void opAssign(typeof(asTuple) rhs)
{
asTuple = rhs;
}
Tuple!(S1, S2) asTuple;
static if (hasConstEmptyMember!(typeof(asTuple[1])))
{
bool opCast(T : bool)() const
{
return !asTuple[1].empty;
}
}
else
{
bool opCast(T : bool)()
{
return !asTuple[1].empty;
}
}
alias asTuple this;
}
static if (isSomeString!R1 && isSomeString!R2
|| (isRandomAccessRange!R1 && hasLength!R1 && hasSlicing!R1 && hasLength!R2))
{
auto balance = find!pred(haystack, needle);
immutable pos = haystack.length - balance.length;
return Result!(typeof(haystack[0 .. pos]),
typeof(haystack[pos .. haystack.length]))(haystack[0 .. pos],
haystack[pos .. haystack.length]);
return FindSplitResult!(1,
typeof(haystack[0 .. pos]), typeof(haystack[0 .. pos]))(
haystack[0 .. pos], haystack[pos .. haystack.length]);
}
else
{
@ -3074,9 +3039,9 @@ if (isForwardRange!R1 && isForwardRange!R2)
pos1 = pos2;
haystack = h;
}
return Result!(typeof(takeExactly(original, pos1)),
typeof(haystack))(takeExactly(original, pos1),
haystack);
return FindSplitResult!(1,
typeof(takeExactly(original, pos1)), typeof(haystack))(
takeExactly(original, pos1), haystack);
}
}
@ -3084,47 +3049,19 @@ 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);
}
void opAssign(typeof(asTuple) rhs)
{
asTuple = rhs;
}
Tuple!(S1, S2) asTuple;
static if (hasConstEmptyMember!(typeof(asTuple[1])))
{
bool opCast(T : bool)() const
{
return !asTuple[0].empty;
}
}
else
{
bool opCast(T : bool)()
{
return !asTuple[0].empty;
}
}
alias asTuple this;
}
static if (isSomeString!R1 && isSomeString!R2
|| isRandomAccessRange!R1 && hasLength!R1 && hasSlicing!R1 && hasLength!R2)
{
auto balance = find!pred(haystack, needle);
immutable pos = balance.empty ? 0 : haystack.length - balance.length + needle.length;
return Result!(typeof(haystack[0 .. pos]),
typeof(haystack[pos .. haystack.length]))(haystack[0 .. pos],
haystack[pos .. haystack.length]);
return FindSplitResult!(0,
typeof(haystack[0 .. pos]), typeof(haystack[0 .. pos]))(
haystack[0 .. pos], haystack[pos .. haystack.length]);
}
else
{
import std.range : takeExactly;
alias Res = FindSplitResult!(0, typeof(takeExactly(haystack, 0)), typeof(haystack));
auto original = haystack.save;
auto h = haystack.save;
auto n = needle.save;
@ -3134,9 +3071,7 @@ if (isForwardRange!R1 && isForwardRange!R2)
if (h.empty)
{
// Failed search
return Result!(typeof(takeExactly(original, 0)),
typeof(original))(takeExactly(original, 0),
original);
return Res(takeExactly(original, 0), original);
}
if (binaryFun!pred(h.front, n.front))
{
@ -3152,9 +3087,7 @@ if (isForwardRange!R1 && isForwardRange!R2)
pos2 = ++pos1;
}
}
return Result!(typeof(takeExactly(original, pos2)),
typeof(h))(takeExactly(original, pos2),
h);
return Res(takeExactly(original, pos2), h);
}
}