Skip to content

Commit

Permalink
Merge pull request #6017 from wilzbach/fix-18215
Browse files Browse the repository at this point in the history
Fix Issue 18215 - std.array.replace throws a range violation if the from range is longer than the array
merged-on-behalf-of: H. S. Teoh <quickfur@users.noreply.github.com>
  • Loading branch information
dlang-bot committed Jan 9, 2018
2 parents 1f319fe + 7c0dab8 commit aeb7b9b
Showing 1 changed file with 41 additions and 2 deletions.
43 changes: 41 additions & 2 deletions std/array.d
Expand Up @@ -2124,6 +2124,7 @@ if (isDynamicArray!(E[]) && isForwardRange!R1 && isForwardRange!R2
&& (hasLength!R2 || isSomeString!R2))
{
import std.algorithm.searching : find;
import std.range : dropOne;

if (from.empty) return subject;

Expand All @@ -2134,7 +2135,11 @@ if (isDynamicArray!(E[]) && isForwardRange!R1 && isForwardRange!R2
auto app = appender!(E[])();
app.put(subject[0 .. subject.length - balance.length]);
app.put(to.save);
replaceInto(app, balance[from.length .. $], from, to);
// replacing an element in an array is different to a range replacement
static if (is(Unqual!E : Unqual!R1))
replaceInto(app, balance.dropOne, from, to);
else
replaceInto(app, balance[from.length .. $], from, to);

return app.data;
}
Expand All @@ -2146,13 +2151,43 @@ if (isDynamicArray!(E[]) && isForwardRange!R1 && isForwardRange!R2
assert("Hello Wörld".replace("l", "h") == "Hehho Wörhd");
}

@safe unittest
{
assert([1, 2, 3, 4, 2].replace([2], [5]) == [1, 5, 3, 4, 5]);
assert([3, 3, 3].replace([3], [0]) == [0, 0, 0]);
assert([3, 3, 4, 3].replace([3, 3], [1, 1, 1]) == [1, 1, 1, 4, 3]);
}

// https://issues.dlang.org/show_bug.cgi?id=18215
@safe unittest
{
auto arr = ["aaa.dd", "b"];
arr = arr.replace("aaa.dd", ".");
assert(arr == [".", "b"]);

arr = ["_", "_", "aaa.dd", "b", "c", "aaa.dd", "e"];
arr = arr.replace("aaa.dd", ".");
assert(arr == ["_", "_", ".", "b", "c", ".", "e"]);
}

// https://issues.dlang.org/show_bug.cgi?id=18215
@safe unittest
{
assert([[0], [1, 2], [0], [3]].replace([0], [4]) == [[4], [1, 2], [4], [3]]);
assert([[0], [1, 2], [0], [3], [1, 2]]
.replace([1, 2], [0]) == [[0], [0], [0], [3], [0]]);
assert([[0], [1, 2], [0], [3], [1, 2], [0], [1, 2]]
.replace([[0], [1, 2]], [[4]]) == [[4], [0], [3], [1, 2], [4]]);
}

/// ditto
void replaceInto(E, Sink, R1, R2)(Sink sink, E[] subject, R1 from, R2 to)
if (isOutputRange!(Sink, E) && isDynamicArray!(E[])
&& isForwardRange!R1 && isForwardRange!R2
&& (hasLength!R2 || isSomeString!R2))
{
import std.algorithm.searching : find;
import std.range : dropOne;

if (from.empty)
{
Expand All @@ -2169,7 +2204,11 @@ if (isOutputRange!(Sink, E) && isDynamicArray!(E[])
}
sink.put(subject[0 .. subject.length - balance.length]);
sink.put(to.save);
subject = balance[from.length .. $];
// replacing an element in an array is different to a range replacement
static if (is(Unqual!E : Unqual!R1))
subject = balance.dropOne;
else
subject = balance[from.length .. $];
}
}

Expand Down

0 comments on commit aeb7b9b

Please sign in to comment.