Skip to content

Commit

Permalink
Merge pull request dlang#8857 from ntrel/find-split-result
Browse files Browse the repository at this point in the history
[std.algorithm.searching] Refactor `findSplit` result types
  • Loading branch information
dkorpel authored Nov 28, 2023
2 parents 505f81a + 0819fec commit 8c39523
Showing 1 changed file with 43 additions and 110 deletions.
153 changes: 43 additions & 110 deletions std/algorithm/searching.d
Original file line number Diff line number Diff line change
Expand Up @@ -2895,6 +2895,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.
Expand Down Expand Up @@ -2957,45 +2980,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
{
Expand Down Expand Up @@ -3024,54 +3017,26 @@ 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);
}
}

/// Ditto
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
{
Expand Down Expand Up @@ -3101,57 +3066,29 @@ 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);
}
}

/// Ditto
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;
Expand All @@ -3161,9 +3098,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))
{
Expand All @@ -3179,9 +3114,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);
}
}

Expand Down

0 comments on commit 8c39523

Please sign in to comment.