[Issue 3877] New: std.range.chain do not manage infinite ranges correctly
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Thu Mar 4 06:51:22 PST 2010
http://d.puremagic.com/issues/show_bug.cgi?id=3877
Summary: std.range.chain do not manage infinite ranges
correctly
Product: D
Version: 2.040
Platform: All
OS/Version: All
Status: NEW
Severity: minor
Priority: P2
Component: Phobos
AssignedTo: nobody at puremagic.com
ReportedBy: philippe.sigaud at gmail.com
--- Comment #0 from Philippe Sigaud <philippe.sigaud at gmail.com> 2010-03-04 15:51:21 CET ---
std.range.chain opIndex and opIndexAssign do not work for infinite ranges:
---
import std.range;
void main() {
auto c = chain([0,1,2][], cycle([4,5,6][]), [7,8,9][]); // infinite range
inside
auto c7 = c[7]; // Error, no property .length for cycle([4,5,6][])
}
Here is a fix for this:
(no improvement to opSlice there. It should be possible: verify if all ranges
before the first infinite have a length and slice on them + the infinite
range.)
---
struct ChainImpl(R...)
{
private:
alias CommonType!(staticMap!(.ElementType, R)) RvalueElementType;
template sameET(A)
{
enum sameET = is(.ElementType!(A) == RvalueElementType);
}
enum bool allSameType = allSatisfy!(sameET, R);
public:
Tuple!(R) _input;
// This doesn't work yet
static if (allSameType)
alias ref RvalueElementType ElementType;
else
alias RvalueElementType ElementType;
this(R input)
{
foreach (i, v; input)
{
_input.field[i] = v;
}
}
bool empty()
{
foreach (i, Unused; R)
{
if (!_input.field[i].empty) return false;
}
return true;
}
void popFront()
{
foreach (i, Unused; R)
{
if (_input.field[i].empty) continue;
_input.field[i].popFront;
return;
}
}
//@@@BUG 2597@@@
//auto front()
//@@@AWKWARD!!!@@@
mixin(
(allSameType ? "ref " : "")~
q{ElementType front()
{
foreach (i, Unused; R)
{
if (_input.field[i].empty) continue;
return _input.field[i].front;
}
assert(false);
}
});
static if (allSatisfy!(isBidirectionalRange, R))
{
mixin(
(allSameType ? "ref " : "")~
q{ElementType back()
{
foreach_reverse (i, Unused; R)
{
if (_input.field[i].empty) continue;
return _input.field[i].back;
}
assert(false);
}
});
void popBack()
{
foreach_reverse (i, Unused; R)
{
if (_input.field[i].empty) continue;
_input.field[i].popBack;
return;
}
}
}
static if (allSatisfy!(hasLength, R))
size_t length()
{
size_t result;
foreach (i, Unused; R)
{
result += _input.field[i].length;
}
return result;
}
static if (allSatisfy!(isRandomAccessRange, R))
{
mixin(
(allSameType ? "ref " : "")~
q{ElementType opIndex(uint index)
{
foreach (i, Type; R)
{
static if (hasLength!Type) {
immutable length = _input.field[i].length;
if (index < length) return _input.field[i][index];
index -= length;
}
else {
static if (isInfinite!Type) {
return _input.field[i][index];
}
}
}
assert(false);
}
});
static if (allSameType && allSatisfy!(hasAssignableElements, R)) void
opIndexAssign(ElementType v, uint index)
{
foreach (i, Type; R)
{
static if (hasLength!Type) {
immutable length = _input.field[i].length;
if (index < length)
{
_input.field[i][index] = v;
return;
}
index -= length;
}
else {
static if (isInfinite!Type) {
_input.field[i][index] = v;
return;
}
}
}
assert(false);
}
}
static if (allSatisfy!(hasLength, R) && allSatisfy!(hasSlicing, R))
ChainImpl opSlice(size_t begin, size_t end)
{
auto result = this;
foreach (i, Unused; R)
{
immutable len = result._input.field[i].length;
if (len < begin)
{
result._input.field[i] = result._input.field[i]
[len .. len];
begin -= len;
}
else
{
result._input.field[i] = result._input.field[i]
[begin .. len];
break;
}
}
auto cut = length;
cut = cut <= end ? 0 : cut - end;
foreach_reverse (i, Unused; R)
{
immutable len = result._input.field[i].length;
if (cut > len)
{
result._input.field[i] = result._input.field[i]
[0 .. 0];
cut -= len;
}
else
{
result._input.field[i] = result._input.field[i]
[0 .. len - cut];
break;
}
}
return result;
}
}
--
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
More information about the Digitalmars-d-bugs
mailing list