Skip to content

Commit

Permalink
Merge pull request #489 from blackwhale/replace-into
Browse files Browse the repository at this point in the history
replaceInto baseline & unittest
  • Loading branch information
jmdavis committed Jun 4, 2012
2 parents f30dc4d + 92defbb commit 1ea339f
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 11 deletions.
3 changes: 2 additions & 1 deletion changelog.dd
Expand Up @@ -67,8 +67,9 @@ $(VERSION 060, ddd mm, 2012, =================================================,
)

$(VERSION 059, ddd mm, 2012, =================================================,

$(WHATSNEW
$(LI std.array: replaceInto, an alternative for replace that outputs result directly
to an output range, avoiding extra allocation.)
$(LI The deprecated std.date, std.dateparse, and std.gregorian modules
have been removed. Please use std.datetime instead.)
$(LI Several deprecated functions in std.file have been removed.)
Expand Down
61 changes: 51 additions & 10 deletions std/array.d
Expand Up @@ -1427,33 +1427,52 @@ if (isDynamicArray!(E[]) && isForwardRange!R1 && isForwardRange!R2
&& (hasLength!R2 || isSomeString!R2))
{
if (from.empty) return subject;

auto balance = std.algorithm.find(subject, from.save);
if (balance.empty)
return subject;

auto app = appender!(E[])();
app.put(subject[0 .. subject.length - balance.length]);
app.put(to.save);
replaceInto(app, balance[from.length .. $], from, to);

return app.data;
}

/++
Same as above, but outputs the result via OutputRange $(D sink).
If no match is found the original array is transfered to $(D sink) as is.
+/
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))
{
if (from.empty)
{
sink.put(subject);
return;
}
for (;;)
{
auto balance = std.algorithm.find(subject, from.save);
if (balance.empty)
{
if (app.data.empty) return subject;
app.put(subject);
sink.put(subject);
break;
}
app.put(subject[0 .. subject.length - balance.length]);
app.put(to.save);
sink.put(subject[0 .. subject.length - balance.length]);
sink.put(to.save);
subject = balance[from.length .. $];
}

return app.data;
}

unittest
{
debug(std_array) printf("array.replace.unittest\n");

alias TypeTuple!(string, wstring, dstring, char[], wchar[], dchar[])
TestTypes;

foreach (S; TestTypes)
foreach (S; TypeTuple!(string, wstring, dstring, char[], wchar[], dchar[]))
{
auto s = to!S("This is a foo foo list");
auto from = to!S("foo");
Expand All @@ -1476,6 +1495,28 @@ unittest
assert(replace(s, "foo", "silly") == "This is a silly silly list");
}

unittest
{
alias TypeTuple!(string, wstring, dstring, char[], wchar[], dchar[])
TestTypes;

struct CheckOutput(C)
{
C[] desired;
this(C[] arr){ desired = arr; }
void put(C[] part){ assert(skipOver(desired, part)); }
}
foreach (S; TestTypes)
{
alias typeof(S.init[0]) Char;
S s = to!S("yet another dummy text, yet another ...");
S from = to!S("yet another");
S into = to!S("some");
replaceInto(CheckOutput!(Char)(to!S("some dummy text, some ..."))
, s, from, into);
}
}

/+
Commented out until the replace which has been deprecated has been removed.
I'd love to just remove it in favor of replaceInPlace, but then code would then
Expand Down

0 comments on commit 1ea339f

Please sign in to comment.