mirror of
https://github.com/dlang/phobos.git
synced 2025-05-07 11:37:24 +03:00
Bug 2903: Splitter should be bi-dir if the input range is bi-dir (Single-character separator version, since range separator version was fixed a long time ago. Excluded terminator version b/c it's not documented/officially part of Phobos yet and there are issues w/ including an empty range if the last character is the terminator that need to be resolved first.)
This commit is contained in:
parent
75705bc9e7
commit
d316980220
1 changed files with 90 additions and 2 deletions
|
@ -1129,6 +1129,16 @@ private:
|
||||||
Separator _separator;
|
Separator _separator;
|
||||||
enum size_t _unComputed = size_t.max - 1, _atEnd = size_t.max;
|
enum size_t _unComputed = size_t.max - 1, _atEnd = size_t.max;
|
||||||
size_t _frontLength = _unComputed;
|
size_t _frontLength = _unComputed;
|
||||||
|
size_t _backLength = _unComputed;
|
||||||
|
|
||||||
|
static if(isBidirectionalRange!Range)
|
||||||
|
{
|
||||||
|
static int lastIndexOf(Range haystack, Separator needle)
|
||||||
|
{
|
||||||
|
immutable index = indexOf(retro(haystack), needle);
|
||||||
|
return (index == -1) ? -1 : haystack.length - 1 - index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
this(Range input, Separator separator)
|
this(Range input, Separator separator)
|
||||||
|
@ -1174,6 +1184,9 @@ public:
|
||||||
{
|
{
|
||||||
// no more input and need to fetch => done
|
// no more input and need to fetch => done
|
||||||
_frontLength = _atEnd;
|
_frontLength = _atEnd;
|
||||||
|
|
||||||
|
// Probably don't need this, but just for consistency:
|
||||||
|
_backLength = _atEnd;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1192,6 +1205,56 @@ public:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static if(isBidirectionalRange!Range)
|
||||||
|
{
|
||||||
|
@property Range back()
|
||||||
|
{
|
||||||
|
assert(!empty);
|
||||||
|
if (_backLength == _unComputed)
|
||||||
|
{
|
||||||
|
immutable lastIndex = lastIndexOf(_input, _separator);
|
||||||
|
if(lastIndex == -1)
|
||||||
|
{
|
||||||
|
_backLength = _input.length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_backLength = _input.length - lastIndex - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _input[_input.length - _backLength .. _input.length];
|
||||||
|
}
|
||||||
|
|
||||||
|
void popBack()
|
||||||
|
{
|
||||||
|
assert(!empty);
|
||||||
|
if (_backLength == _unComputed)
|
||||||
|
{
|
||||||
|
back;
|
||||||
|
}
|
||||||
|
assert(_backLength <= _input.length);
|
||||||
|
if (_backLength == _input.length)
|
||||||
|
{
|
||||||
|
// no more input and need to fetch => done
|
||||||
|
_frontLength = _atEnd;
|
||||||
|
_backLength = _atEnd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_input = _input[0 .. _input.length - _backLength];
|
||||||
|
if(!_input.empty && _input.back == _separator)
|
||||||
|
{
|
||||||
|
_input.popBack();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
_backLength = _unComputed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto
|
/// Ditto
|
||||||
|
@ -1224,14 +1287,39 @@ unittest
|
||||||
a = [ 0, 1 ];
|
a = [ 0, 1 ];
|
||||||
assert(equal(splitter(a, 0), [ [], [1] ][]));
|
assert(equal(splitter(a, 0), [ [], [1] ][]));
|
||||||
|
|
||||||
|
// Thoroughly exercise the bidirectional stuff.
|
||||||
|
auto str = "abc abcd abcde ab abcdefg abcdefghij ab ac ar an at ada";
|
||||||
|
assert(equal(
|
||||||
|
retro(splitter(str, 'a')),
|
||||||
|
retro(array(splitter(str, 'a')))
|
||||||
|
));
|
||||||
|
|
||||||
|
// Test interleaving front and back.
|
||||||
|
auto split = splitter(str, 'a');
|
||||||
|
assert(split.front == "");
|
||||||
|
assert(split.back == "");
|
||||||
|
split.popBack();
|
||||||
|
assert(split.back == "d");
|
||||||
|
split.popFront();
|
||||||
|
assert(split.front == "bc ");
|
||||||
|
assert(split.back == "d");
|
||||||
|
split.popFront();
|
||||||
|
split.popBack();
|
||||||
|
assert(split.back == "t ");
|
||||||
|
split.popBack();
|
||||||
|
split.popBack();
|
||||||
|
split.popFront();
|
||||||
|
split.popFront();
|
||||||
|
assert(split.front == "b ");
|
||||||
|
assert(split.back == "r ");
|
||||||
|
|
||||||
foreach(DummyType; AllDummyRanges) { // Bug 4408
|
foreach(DummyType; AllDummyRanges) { // Bug 4408
|
||||||
static if(isRandomAccessRange!DummyType) {
|
static if(isRandomAccessRange!DummyType) {
|
||||||
static assert(isBidirectionalRange!DummyType);
|
static assert(isBidirectionalRange!DummyType);
|
||||||
DummyType d;
|
DummyType d;
|
||||||
auto s = splitter(d, 5);
|
auto s = splitter(d, 5);
|
||||||
assert(equal(s.front, [1,2,3,4]));
|
assert(equal(s.front, [1,2,3,4]));
|
||||||
s.popFront();
|
assert(equal(s.back, [6,7,8,9,10]));
|
||||||
assert(equal(s.front, [6,7,8,9,10]));
|
|
||||||
|
|
||||||
|
|
||||||
auto s2 = splitter(d, [4, 5]);
|
auto s2 = splitter(d, [4, 5]);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue