mirror of
https://github.com/dlang/phobos.git
synced 2025-04-29 22:50:38 +03:00
Fix for popBack/popFront
popBack/popFront works for RoRs starting and/or ending with empty items
This commit is contained in:
parent
e32b635f05
commit
7a715fe687
1 changed files with 72 additions and 17 deletions
|
@ -2918,11 +2918,11 @@ if (isInputRange!RoR && isInputRange!(ElementType!RoR)
|
||||||
{
|
{
|
||||||
private RoR _items;
|
private RoR _items;
|
||||||
private ElementType!RoR _current;
|
private ElementType!RoR _current;
|
||||||
bool startsWithEmpty = false;
|
bool inputStartsWithEmpty = false;
|
||||||
static if (isBidirectional)
|
static if (isBidirectional)
|
||||||
{
|
{
|
||||||
private ElementType!RoR _currentBack;
|
private ElementType!RoR _currentBack;
|
||||||
bool endsWithEmpty = false;
|
bool inputEndsWithEmpty = false;
|
||||||
}
|
}
|
||||||
enum isBidirectional = isBidirectionalRange!RoR &&
|
enum isBidirectional = isBidirectionalRange!RoR &&
|
||||||
isBidirectionalRange!(ElementType!RoR);
|
isBidirectionalRange!(ElementType!RoR);
|
||||||
|
@ -3064,14 +3064,14 @@ if (isInputRange!RoR && isInputRange!(ElementType!RoR)
|
||||||
{
|
{
|
||||||
if (_currentBack.empty)
|
if (_currentBack.empty)
|
||||||
{
|
{
|
||||||
endsWithEmpty = true;
|
inputEndsWithEmpty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_current.empty)
|
if (_current.empty)
|
||||||
{
|
{
|
||||||
// No data in the current item - toggle to use the separator
|
// No data in the current item - toggle to use the separator
|
||||||
startsWithEmpty = true;
|
inputStartsWithEmpty = true;
|
||||||
|
|
||||||
//A range with a single element which is empty will always
|
//A range with a single element which is empty will always
|
||||||
// return an empty Result
|
// return an empty Result
|
||||||
|
@ -3102,13 +3102,18 @@ if (isInputRange!RoR && isInputRange!(ElementType!RoR)
|
||||||
return _items.empty;
|
return _items.empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property ElementType!(ElementType!RoR) front()
|
//no data in the first item of the initial range - use the separator
|
||||||
{
|
private enum useSepIfFrontIsEmpty = q{
|
||||||
if (startsWithEmpty)
|
if (inputStartsWithEmpty)
|
||||||
{
|
{
|
||||||
useSeparator();
|
useSeparator();
|
||||||
startsWithEmpty = false;
|
inputStartsWithEmpty = false;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@property ElementType!(ElementType!RoR) front()
|
||||||
|
{
|
||||||
|
mixin(useSepIfFrontIsEmpty);
|
||||||
if (!_currentSep.empty) return _currentSep.front;
|
if (!_currentSep.empty) return _currentSep.front;
|
||||||
assert(!_current.empty, "Attempting to fetch the front of an empty joiner.");
|
assert(!_current.empty, "Attempting to fetch the front of an empty joiner.");
|
||||||
return _current.front;
|
return _current.front;
|
||||||
|
@ -3118,6 +3123,8 @@ if (isInputRange!RoR && isInputRange!(ElementType!RoR)
|
||||||
{
|
{
|
||||||
assert(!_items.empty, "Attempting to popFront an empty joiner.");
|
assert(!_items.empty, "Attempting to popFront an empty joiner.");
|
||||||
// Using separator?
|
// Using separator?
|
||||||
|
mixin(useSepIfFrontIsEmpty);
|
||||||
|
|
||||||
if (!_currentSep.empty)
|
if (!_currentSep.empty)
|
||||||
{
|
{
|
||||||
_currentSep.popFront();
|
_currentSep.popFront();
|
||||||
|
@ -3159,15 +3166,20 @@ if (isInputRange!RoR && isInputRange!(ElementType!RoR)
|
||||||
|
|
||||||
static if (isBidirectional)
|
static if (isBidirectional)
|
||||||
{
|
{
|
||||||
|
//no data in the last item of the initial range - use the separator
|
||||||
|
private enum useSepIfBackIsEmpty = q{
|
||||||
|
if (inputEndsWithEmpty)
|
||||||
|
{
|
||||||
|
useBackSeparator;
|
||||||
|
inputEndsWithEmpty = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private void setBackItem()
|
private void setBackItem()
|
||||||
{
|
{
|
||||||
if (!_items.empty)
|
if (!_items.empty)
|
||||||
{
|
{
|
||||||
// If we're exporting .save, we must not consume any of the
|
_currentBack = _items.back.save;
|
||||||
// subranges, since RoR.save does not guarantee that the states
|
|
||||||
// of the subranges are also saved.
|
|
||||||
_currentBack = _items.back.save;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3202,11 +3214,8 @@ if (isInputRange!RoR && isInputRange!(ElementType!RoR)
|
||||||
|
|
||||||
@property ElementType!(ElementType!RoR) back()
|
@property ElementType!(ElementType!RoR) back()
|
||||||
{
|
{
|
||||||
if (endsWithEmpty)
|
mixin(useSepIfBackIsEmpty);
|
||||||
{
|
|
||||||
useBackSeparator;
|
|
||||||
endsWithEmpty = false;
|
|
||||||
}
|
|
||||||
if (!_currentBackSep.empty) return _currentBackSep.front;
|
if (!_currentBackSep.empty) return _currentBackSep.front;
|
||||||
assert(!_currentBack.empty, "Attempting to fetch the back of an empty joiner.");
|
assert(!_currentBack.empty, "Attempting to fetch the back of an empty joiner.");
|
||||||
return _currentBack.back;
|
return _currentBack.back;
|
||||||
|
@ -3215,6 +3224,9 @@ if (isInputRange!RoR && isInputRange!(ElementType!RoR)
|
||||||
void popBack()
|
void popBack()
|
||||||
{
|
{
|
||||||
assert(!_items.empty, "Attempting to popBack an empty joiner.");
|
assert(!_items.empty, "Attempting to popBack an empty joiner.");
|
||||||
|
|
||||||
|
mixin(useSepIfBackIsEmpty);
|
||||||
|
|
||||||
if (!_currentBackSep.empty)
|
if (!_currentBackSep.empty)
|
||||||
{
|
{
|
||||||
_currentBackSep.popFront();
|
_currentBackSep.popFront();
|
||||||
|
@ -3444,6 +3456,49 @@ if (isInputRange!RoR && isInputRange!(ElementType!RoR)
|
||||||
assert(resFront.equal("../../../abc../"));
|
assert(resFront.equal("../../../abc../"));
|
||||||
assert(resBack.equal("../cba../../../"));
|
assert(resBack.equal("../cba../../../"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto r = ["", "abc", ""].joiner("./");
|
||||||
|
auto rCopy = r.save;
|
||||||
|
r.popBack;
|
||||||
|
rCopy.popFront;
|
||||||
|
|
||||||
|
auto rRev = r.save;
|
||||||
|
auto rCopyRev = rCopy.save;
|
||||||
|
|
||||||
|
char[] r1, r2, r3, r4;
|
||||||
|
|
||||||
|
while (!r.empty)
|
||||||
|
{
|
||||||
|
r1 ~= r.back;
|
||||||
|
r.popBack;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!rCopy.empty)
|
||||||
|
{
|
||||||
|
r2 ~= rCopy.front;
|
||||||
|
rCopy.popFront;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!rRev.empty)
|
||||||
|
{
|
||||||
|
r3 ~= rRev.front;
|
||||||
|
rRev.popFront;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!rCopyRev.empty)
|
||||||
|
{
|
||||||
|
r4 ~= rCopyRev.back;
|
||||||
|
rCopyRev.popBack;
|
||||||
|
}
|
||||||
|
|
||||||
|
import std.algorithm.comparison : equal;
|
||||||
|
|
||||||
|
assert(r1.equal("/cba./"));
|
||||||
|
assert(r2.equal("/abc./"));
|
||||||
|
assert(r3.equal("./abc"));
|
||||||
|
assert(r4.equal("./cba"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@system unittest
|
@system unittest
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue