Skip to content

Instantly share code, notes, and snippets.

@John-Colvin
Created May 13, 2017 12:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save John-Colvin/80652ffb400796a93e64c5ac9a346972 to your computer and use it in GitHub Desktop.
Save John-Colvin/80652ffb400796a93e64c5ac9a346972 to your computer and use it in GitHub Desktop.
mutable range wrapper
auto mutableView(R)(R r)
if (isRandomAccessRange!R)
{
return MutableRangeView!R(r);
}
alias MutableRangeView(R) = MutableRangeViewImpl!(R, false);
struct MutableRangeViewImpl(R, bool forceBack)
if (isRandomAccessRange!(Unqual!R))
{
private
{
alias MR = Unqual!R;
enum backSupport = forceBack || hasLength!MR;
enum infinite = !forceBack && isInfinite!MR;
static assert(!(backSupport && infinite));
const R r;
size_t fInd = 0;
static if (backSupport)
size_t bInd = size_t.max;
}
this(R r)
{
this.r = r;
static if (backSupport)
bInd = r.length - 1;
}
invariant()
{
assert(bInd >= fInd);
}
static if (infinite)
enum empty = false;
else
bool empty() @property
{
r.empty || fInd == bInd;
}
auto ref front() @property
in {
assert(!empty);
} body
{
return r[fInd];
}
static if (backSupport)
{
auto ref back() @property
in {
assert(!empty);
} body
{
return r[bInd];
}
void popBack()
in {
assert(!empty);
} body
{
--bInd;
}
}
void popFront()
in {
assert(!empty);
} body
{
++fInd;
}
auto ref opIndex(size_t i)
in {
assert(fInd + i <= bInd);
} body
{
return r[fInd + i];
}
static if (backSupport)
auto ref opSlice(size_t i0, size_t i1)
in {
assert(i0 <= i1);
assert(fInd + i1 <= bInd);
} body
{
auto tmp = this;
tmp.fInd = fInd + i0;
tmp.bInd = fInd + i1 - 1;
}
else static if (infinite)
auto ref opSlice(size_t i0, size_t i1)
{
auto tmp = MutableRangeView!(R, true)(r);
tmp.fInd = fInd + i0;
tmp.bInd = fInd + i1;
}
auto save()
{
return this;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment