diff --git a/ostd/range.hh b/ostd/range.hh index 17a3dda..f5c5c48 100644 --- a/ostd/range.hh +++ b/ostd/range.hh @@ -1274,10 +1274,10 @@ public: c = n; } if constexpr(std::is_pod_v) { - memcpy(p_beg, data(), c * sizeof(T)); + memcpy(p, p_beg, c * sizeof(T)); return c; } - return copy(PointerRange(p, c), c); + return copy(PointerRange(p, p + c), c); } T *data() { return p_beg; } @@ -1815,19 +1815,31 @@ using IteratorRangeTag = typename detail::IteratorRangeTagBase::Type; template struct IteratorRange: InputRange< IteratorRange, - IteratorRangeTag::iterator_category>, + std::conditional_t< + std::is_pointer_v, + ContiguousRangeTag, + IteratorRangeTag::iterator_category> + >, typename std::iterator_traits::value_type, typename std::iterator_traits::reference, std::make_unsigned_t::difference_type>, typename std::iterator_traits::difference_type > { private: + using ValT = typename std::iterator_traits::value_type; using RefT = typename std::iterator_traits::reference; using DiffT = typename std::iterator_traits::difference_type; + using SizeT = std::make_unsigned_t::difference_type>; public: IteratorRange(T beg = T{}, T end = T{}): p_beg(beg), p_end(end) {} + template && std::is_pointer_v && + std::is_convertible_v + >> + IteratorRange(IteratorRange const &v): p_beg(&v[0]), p_end(&v[v.size()]) {} + IteratorRange(IteratorRange const &v): p_beg(v.p_beg), p_end(v.p_end) {} IteratorRange(IteratorRange &&v): p_beg(std::move(v.p_beg)), p_end(std::move(v.p_end)) @@ -1859,6 +1871,31 @@ public: --p_beg; return true; } + SizeT pop_front_n(SizeT n) { + using IC = typename std::iterator_traits::iterator_category; + if constexpr(std::is_convertible_v) { + SizeT olen = SizeT(p_end - p_beg); + p_beg += n; + if (p_beg > p_end) { + p_beg = p_end; + return olen; + } + return n; + } else { + return detail::pop_front_n(*this, n); + } + } + + SizeT push_front_n(SizeT n) { + using IC = typename std::iterator_traits::iterator_category; + if constexpr(std::is_convertible_v) { + p_beg -= n; + return true; + } else { + return detail::push_front_n(*this, n); + } + } + RefT front() const { return *p_beg; } bool equals_front(IteratorRange const &range) const { @@ -1881,6 +1918,31 @@ public: ++p_end; return true; } + SizeT pop_back_n(SizeT n) { + using IC = typename std::iterator_traits::iterator_category; + if constexpr(std::is_convertible_v) { + SizeT olen = SizeT(p_end - p_beg); + p_end -= n; + if (p_end < p_beg) { + p_end = p_beg; + return olen; + } + return n; + } else { + return detail::pop_back_n(*this, n); + } + } + + SizeT push_back_n(SizeT n) { + using IC = typename std::iterator_traits::iterator_category; + if constexpr(std::is_convertible_v) { + p_end += n; + return true; + } else { + return detail::push_back_n(*this, n); + } + } + RefT back() const { return *(p_end - 1); } bool equals_back(IteratorRange const &range) const { @@ -1892,13 +1954,13 @@ public: } /* satisfy FiniteRandomAccessRange */ - size_t size() const { return p_end - p_beg; } + SizeT size() const { return SizeT(p_end - p_beg); } - IteratorRange slice(size_t start, size_t end) const { + IteratorRange slice(SizeT start, SizeT end) const { return IteratorRange(p_beg + start, p_beg + end); } - RefT operator[](size_t i) const { return p_beg[i]; } + RefT operator[](SizeT i) const { return p_beg[i]; } /* satisfy OutputRange */ bool put(T const &v) { @@ -1916,6 +1978,71 @@ public: return true; } + SizeT put_n(ValT const *p, SizeT n) { + using IC = typename std::iterator_traits::iterator_category; + if constexpr(std::is_convertible_v) { + SizeT ret = size(); + if (n < ret) { + ret = n; + } + if constexpr(std::is_pointer_v && std::is_pod_v) { + memcpy(p_beg, p, ret * sizeof(ValT)); + p_beg += ret; + } else { + for (SizeT i = ret; i; --i) { + *p_beg++ = *p++; + } + } + return ret; + } else { + SizeT on = n; + for (; n && put(*p++); --n); + return (on - n); + } + } + + template + std::enable_if_t, SizeT> copy(R &&orange, SizeT n = -1) { + if constexpr(std::is_pointer_v) { + SizeT c = size(); + if (n < c) { + c = n; + } + return orange.put_n(p_beg, c); + } else { + SizeT on = n; + for (; n && !empty(); --n) { + if (!orange.put(front())) { + break; + } + pop_front(); + } + return (on - n); + } + } + + SizeT copy(std::remove_cv_t *p, SizeT n = -1) { + using IC = typename std::iterator_traits::iterator_category; + if constexpr(std::is_convertible_v) { + SizeT c = size(); + if (n < c) { + c = n; + } + if constexpr(std::is_pointer_v && std::is_pod_v) { + memcpy(p, p_beg, c * sizeof(ValT)); + return c; + } else { + return copy(IteratorRange *>(p, p + c), c); + } + } else { + SizeT on = n; + for (; n && !empty(); --n) { + *p++ = front(); + pop_front(); + } + return (on - n); + } + } private: T p_beg, p_end; };