initial support for "range extension" - i.e. push_first and push_last methods (+ push_first_n, push_last_n)

master
Daniel Kolesa 2015-05-29 19:52:20 +01:00
parent b5f54b5cca
commit 38fc61481a
2 changed files with 134 additions and 79 deletions

View File

@ -443,9 +443,15 @@ namespace octa {
void pop_first() { p_range.pop_first(); }
void pop_last() { p_range.pop_last(); }
bool push_first() { return p_range.pop_first(); }
bool push_last() { return p_range.push_last(); }
RangeSize<T> pop_first_n(RangeSize<T> n) { p_range.pop_first_n(n); }
RangeSize<T> pop_last_n(RangeSize<T> n) { p_range.pop_last_n(n); }
RangeSize<T> push_first_n(RangeSize<T> n) { return p_range.push_first_n(n); }
RangeSize<T> push_last_n(RangeSize<T> n) { return p_range.push_last_n(n); }
R first() const { return p_func(p_range.first()); }
R last() const { return p_func(p_range.last()); }
@ -528,6 +534,15 @@ namespace octa {
p_range.pop_first();
advance_valid();
}
bool push_first() {
T tmp = p_range;
if (!tmp.push_first()) return false;
while (!pred(tmp.first()))
if (!tmp.push_first())
return false;
p_range = tmp;
return true;
}
RangeReference<T> first() const { return p_range.first(); }
RangeReference<T> first() { return p_range.first(); }

View File

@ -136,6 +136,20 @@ namespace octa {
return n;
}
template<typename R>
RangeSize<R> __octa_push_first_n(R &range, RangeSize<R> n) {
for (RangeSize<R> i = 0; i < n; ++i)
if (!range.push_first()) return i;
return n;
}
template<typename R>
RangeSize<R> __octa_push_last_n(R &range, RangeSize<R> n) {
for (RangeSize<R> i = 0; i < n; ++i)
if (!range.push_last()) return i;
return n;
}
template<typename B, typename C, typename V, typename R = V &,
typename S = size_t
> struct InputRange {
@ -159,6 +173,14 @@ namespace octa {
return __octa_pop_last_n<B>(*((B *)this), n);
}
SizeType push_first_n(SizeType n) {
return __octa_push_first_n<B>(*((B *)this), n);
}
SizeType push_last_n(SizeType n) {
return __octa_push_last_n<B>(*((B *)this), n);
}
B each() {
return B(*((B *)this));
}
@ -212,27 +234,20 @@ namespace octa {
return *this;
}
bool empty() const {
return p_range.empty();
}
bool empty() const { return p_range.empty(); }
r_size size() const { return p_range.size(); }
r_size size() const {
return p_range.size();
}
void pop_first() { p_range.pop_last(); }
void pop_last() { p_range.pop_first(); }
void pop_first() {
p_range.pop_last();
}
void pop_last() {
p_range.pop_first();
}
bool push_first() { return p_range.push_last(); }
bool push_last() { return p_range.push_first(); }
r_size pop_first_n(r_size n) {
return p_range.pop_first_n(n);
}
r_size pop_last_n(r_size n) {
return p_range.pop_last_n(n);
}
r_size pop_first_n(r_size n) { return p_range.pop_first_n(n); }
r_size pop_last_n(r_size n) { return p_range.pop_last_n(n); }
r_size push_first_n(r_size n) { return p_range.push_first_n(n); }
r_size push_last_n(r_size n) { return p_range.push_last_n(n); }
bool operator==(const ReverseRange &v) const {
return p_range == v.p_range;
@ -241,26 +256,14 @@ namespace octa {
return p_range != v.p_range;
}
r_ref first() {
return p_range.last();
}
r_ref first() const {
return p_range.last();
}
r_ref first() { return p_range.last(); }
r_ref first() const { return p_range.last(); }
r_ref last() {
return p_range.first();
}
r_ref last() const {
return p_range.first();
}
r_ref last() { return p_range.first(); }
r_ref last() const { return p_range.first(); }
r_ref operator[](r_size i) {
return p_range[size() - i - 1];
}
r_ref operator[](r_size i) const {
return p_range[size() - i - 1];
}
r_ref operator[](r_size i) { return p_range[size() - i - 1]; }
r_ref operator[](r_size i) const { return p_range[size() - i - 1]; }
ReverseRange<T> slice(r_size start, r_size end) {
r_size len = p_range.size();
@ -310,26 +313,20 @@ namespace octa {
return *this;
}
bool empty() const {
return p_range.empty();
}
r_size size() const {
return p_range.size();
}
bool empty() const { return p_range.empty(); }
r_size size() const { return p_range.size(); }
void pop_first() {
p_range.pop_first();
}
void pop_last() {
p_range.pop_last();
}
void pop_first() { p_range.pop_first(); }
void pop_last() { p_range.pop_last(); }
r_size pop_first_n(r_size n) {
return p_range.pop_first_n(n);
}
r_size pop_last_n(r_size n) {
return p_range.pop_last_n(n);
}
bool push_first() { return p_range.push_first(); }
bool push_last() { return p_range.push_last(); }
r_size pop_first_n(r_size n) { return p_range.pop_first_n(n); }
r_size pop_last_n(r_size n) { return p_range.pop_last_n(n); }
r_size push_first_n(r_size n) { return p_range.push_first_n(n); }
r_size push_last_n(r_size n) { return p_range.push_last_n(n); }
bool operator==(const MoveRange &v) const {
return p_range == v.p_range;
@ -338,27 +335,17 @@ namespace octa {
return p_range != v.p_range;
}
r_ref first() {
return move(p_range.first());
}
r_ref last() {
return move(p_range.last());
}
r_ref first() { return move(p_range.first()); }
r_ref last() { return move(p_range.last()); }
r_ref operator[](r_size i) {
return move(p_range[i]);
}
r_ref operator[](r_size i) { return move(p_range[i]); }
MoveRange<T> slice(r_size start, r_size end) {
return MoveRange<T>(p_range.slice(start, end));
}
void put(const r_val &v) {
p_range.put(v);
}
void put(r_val &&v) {
p_range.put(move(v));
}
void put(const r_val &v) { p_range.put(v); }
void put(r_val &&v) { p_range.put(move(v)); }
};
template<typename T>
@ -384,6 +371,7 @@ namespace octa {
bool empty() const { return p_a * p_step >= p_b * p_step; }
void pop_first() { p_a += p_step; }
bool push_first() { p_a -= p_step; return true; }
T &first() { return p_a; }
private:
@ -428,6 +416,9 @@ namespace octa {
if (p_beg == p_end) return;
++p_beg;
}
bool push_first() {
--p_beg; return true;
}
size_t pop_first_n(size_t n) {
T *obeg = p_beg;
@ -440,6 +431,10 @@ namespace octa {
return n;
}
size_t push_first_n(size_t n) {
p_beg -= n; return true;
}
T &first() { return *p_beg; }
const T &first() const { return *p_beg; }
@ -448,6 +443,9 @@ namespace octa {
if (p_end == p_beg) return;
--p_end;
}
bool push_last() {
++p_end; return true;
}
size_t pop_last_n(size_t n) {
T *oend = p_end;
@ -460,6 +458,10 @@ namespace octa {
return n;
}
size_t push_last_n(size_t n) {
p_end += n; return true;
}
T &last() { return *(p_end - 1); }
const T &last() const { return *(p_end - 1); }
@ -536,16 +538,14 @@ namespace octa {
return *this;
}
bool empty() const {
return p_range.empty();
}
bool empty() const { return p_range.empty(); }
void pop_first() {
++p_index; p_range.pop_first();
}
void pop_first() { ++p_index; p_range.pop_first(); }
r_size pop_first_n(r_size n) {
return p_range.pop_first_n(n);
r_size ret = p_range.pop_first_n(n);
p_index += ret;
return ret;
}
EnumeratedValue<r_ref, r_size> first() {
@ -598,9 +598,23 @@ namespace octa {
bool empty() const { return (p_remaining <= 0) || p_range.empty(); }
void pop_first() { --p_remaining; p_range.pop_first(); }
bool push_first() {
if (p_range.push_first()) {
++p_remaining;
return true;
}
return false;
}
RangeSize<T> pop_first_n(RangeSize<T> n) {
p_remaining -= n;
return p_range.pop_first_n((n > p_remaining) ? p_remaining : n);
RangeSize<T> ret = p_range.pop_first_n(n);
p_remaining -= ret;
return ret;
}
RangeSize<T> push_first_n(RangeSize<T> n) {
RangeSize<T> ret = p_range.push_first_n(n);
p_remaining += ret;
return ret;
}
RangeReference<T> first() { return p_range.first(); }
@ -627,6 +641,14 @@ namespace octa {
p_remaining -= n;
return (ol < n) ? ol : n;
}
RangeSize<T> push_last_n(RangeSize<T> n) {
static_assert(IsRandomAccessRange<T>::value,
"pop_last_n() only available for random access ranges");
RangeSize<T> rsize = p_range.length();
RangeSize<T> psize = (rsize < n) ? rsize : n;
p_remaining += psize;
return psize;
}
RangeReference<T> last() {
static_assert(IsRandomAccessRange<T>::value,
@ -685,8 +707,26 @@ namespace octa {
bool empty() const { return p_range.empty(); }
void pop_first() { p_range.pop_first_n(p_chunksize); }
bool push_first() {
T tmp = p_range;
RangeSize<T> an = tmp.push_first_n(p_chunksize);
if (an != p_chunksize) return false;
p_range = tmp;
return true;
}
RangeSize<T> pop_first_n(RangeSize<T> n) {
return p_range.pop_first_n(p_chunksize * n);
return p_range.pop_first_n(p_chunksize * n) / p_chunksize;
}
RangeSize<T> push_first_n(RangeSize<T> n) {
T tmp = p_range;
RangeSize<T> an = tmp.push_first_n(p_chunksize * n);
RangeSize<T> pn = an / p_chunksize;
if (!pn) return 0;
if (pn == n) {
p_range = tmp;
return pn;
}
return p_range.push_first_n(p_chunksize * an) / p_chunksize;
}
TakeRange<T> first() { return take(p_range, p_chunksize); }