diff --git a/octa/algorithm.h b/octa/algorithm.h index 975da23..056b60d 100644 --- a/octa/algorithm.h +++ b/octa/algorithm.h @@ -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 pop_first_n(RangeSize n) { p_range.pop_first_n(n); } RangeSize pop_last_n(RangeSize n) { p_range.pop_last_n(n); } + RangeSize push_first_n(RangeSize n) { return p_range.push_first_n(n); } + RangeSize push_last_n(RangeSize 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 first() const { return p_range.first(); } RangeReference first() { return p_range.first(); } diff --git a/octa/range.h b/octa/range.h index b1915a9..cd57faa 100644 --- a/octa/range.h +++ b/octa/range.h @@ -136,6 +136,20 @@ namespace octa { return n; } + template + RangeSize __octa_push_first_n(R &range, RangeSize n) { + for (RangeSize i = 0; i < n; ++i) + if (!range.push_first()) return i; + return n; + } + + template + RangeSize __octa_push_last_n(R &range, RangeSize n) { + for (RangeSize i = 0; i < n; ++i) + if (!range.push_last()) return i; + return n; + } + template struct InputRange { @@ -159,6 +173,14 @@ namespace octa { return __octa_pop_last_n(*((B *)this), n); } + SizeType push_first_n(SizeType n) { + return __octa_push_first_n(*((B *)this), n); + } + + SizeType push_last_n(SizeType n) { + return __octa_push_last_n(*((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 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 slice(r_size start, r_size end) { return MoveRange(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 @@ -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 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 pop_first_n(RangeSize n) { - p_remaining -= n; - return p_range.pop_first_n((n > p_remaining) ? p_remaining : n); + RangeSize ret = p_range.pop_first_n(n); + p_remaining -= ret; + return ret; + } + RangeSize push_first_n(RangeSize n) { + RangeSize ret = p_range.push_first_n(n); + p_remaining += ret; + return ret; } RangeReference first() { return p_range.first(); } @@ -627,6 +641,14 @@ namespace octa { p_remaining -= n; return (ol < n) ? ol : n; } + RangeSize push_last_n(RangeSize n) { + static_assert(IsRandomAccessRange::value, + "pop_last_n() only available for random access ranges"); + RangeSize rsize = p_range.length(); + RangeSize psize = (rsize < n) ? rsize : n; + p_remaining += psize; + return psize; + } RangeReference last() { static_assert(IsRandomAccessRange::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 an = tmp.push_first_n(p_chunksize); + if (an != p_chunksize) return false; + p_range = tmp; + return true; + } RangeSize pop_first_n(RangeSize n) { - return p_range.pop_first_n(p_chunksize * n); + return p_range.pop_first_n(p_chunksize * n) / p_chunksize; + } + RangeSize push_first_n(RangeSize n) { + T tmp = p_range; + RangeSize an = tmp.push_first_n(p_chunksize * n); + RangeSize 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 first() { return take(p_range, p_chunksize); }