forked from OctaForge/libostd
extend IteratorRange to handle pointers as special case
This commit is contained in:
parent
052fa58be4
commit
e1f5cc477f
139
ostd/range.hh
139
ostd/range.hh
|
@ -1274,10 +1274,10 @@ public:
|
||||||
c = n;
|
c = n;
|
||||||
}
|
}
|
||||||
if constexpr(std::is_pod_v<T>) {
|
if constexpr(std::is_pod_v<T>) {
|
||||||
memcpy(p_beg, data(), c * sizeof(T));
|
memcpy(p, p_beg, c * sizeof(T));
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
return copy(PointerRange(p, c), c);
|
return copy(PointerRange(p, p + c), c);
|
||||||
}
|
}
|
||||||
|
|
||||||
T *data() { return p_beg; }
|
T *data() { return p_beg; }
|
||||||
|
@ -1815,19 +1815,31 @@ using IteratorRangeTag = typename detail::IteratorRangeTagBase<T>::Type;
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct IteratorRange: InputRange<
|
struct IteratorRange: InputRange<
|
||||||
IteratorRange<T>,
|
IteratorRange<T>,
|
||||||
IteratorRangeTag<typename std::iterator_traits<T>::iterator_category>,
|
std::conditional_t<
|
||||||
|
std::is_pointer_v<T>,
|
||||||
|
ContiguousRangeTag,
|
||||||
|
IteratorRangeTag<typename std::iterator_traits<T>::iterator_category>
|
||||||
|
>,
|
||||||
typename std::iterator_traits<T>::value_type,
|
typename std::iterator_traits<T>::value_type,
|
||||||
typename std::iterator_traits<T>::reference,
|
typename std::iterator_traits<T>::reference,
|
||||||
std::make_unsigned_t<typename std::iterator_traits<T>::difference_type>,
|
std::make_unsigned_t<typename std::iterator_traits<T>::difference_type>,
|
||||||
typename std::iterator_traits<T>::difference_type
|
typename std::iterator_traits<T>::difference_type
|
||||||
> {
|
> {
|
||||||
private:
|
private:
|
||||||
|
using ValT = typename std::iterator_traits<T>::value_type;
|
||||||
using RefT = typename std::iterator_traits<T>::reference;
|
using RefT = typename std::iterator_traits<T>::reference;
|
||||||
using DiffT = typename std::iterator_traits<T>::difference_type;
|
using DiffT = typename std::iterator_traits<T>::difference_type;
|
||||||
|
using SizeT = std::make_unsigned_t<typename std::iterator_traits<T>::difference_type>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IteratorRange(T beg = T{}, T end = T{}): p_beg(beg), p_end(end) {}
|
IteratorRange(T beg = T{}, T end = T{}): p_beg(beg), p_end(end) {}
|
||||||
|
|
||||||
|
template<typename U, typename = std::enable_if_t<
|
||||||
|
std::is_pointer_v<T> && std::is_pointer_v<U> &&
|
||||||
|
std::is_convertible_v<U, T>
|
||||||
|
>>
|
||||||
|
IteratorRange(IteratorRange<U> 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 const &v): p_beg(v.p_beg), p_end(v.p_end) {}
|
||||||
IteratorRange(IteratorRange &&v):
|
IteratorRange(IteratorRange &&v):
|
||||||
p_beg(std::move(v.p_beg)), p_end(std::move(v.p_end))
|
p_beg(std::move(v.p_beg)), p_end(std::move(v.p_end))
|
||||||
|
@ -1859,6 +1871,31 @@ public:
|
||||||
--p_beg; return true;
|
--p_beg; return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SizeT pop_front_n(SizeT n) {
|
||||||
|
using IC = typename std::iterator_traits<T>::iterator_category;
|
||||||
|
if constexpr(std::is_convertible_v<IC, std::random_access_iterator_tag>) {
|
||||||
|
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<T>::iterator_category;
|
||||||
|
if constexpr(std::is_convertible_v<IC, std::random_access_iterator_tag>) {
|
||||||
|
p_beg -= n;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return detail::push_front_n(*this, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RefT front() const { return *p_beg; }
|
RefT front() const { return *p_beg; }
|
||||||
|
|
||||||
bool equals_front(IteratorRange const &range) const {
|
bool equals_front(IteratorRange const &range) const {
|
||||||
|
@ -1881,6 +1918,31 @@ public:
|
||||||
++p_end; return true;
|
++p_end; return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SizeT pop_back_n(SizeT n) {
|
||||||
|
using IC = typename std::iterator_traits<T>::iterator_category;
|
||||||
|
if constexpr(std::is_convertible_v<IC, std::random_access_iterator_tag>) {
|
||||||
|
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<T>::iterator_category;
|
||||||
|
if constexpr(std::is_convertible_v<IC, std::random_access_iterator_tag>) {
|
||||||
|
p_end += n;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return detail::push_back_n(*this, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RefT back() const { return *(p_end - 1); }
|
RefT back() const { return *(p_end - 1); }
|
||||||
|
|
||||||
bool equals_back(IteratorRange const &range) const {
|
bool equals_back(IteratorRange const &range) const {
|
||||||
|
@ -1892,13 +1954,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* satisfy FiniteRandomAccessRange */
|
/* 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);
|
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 */
|
/* satisfy OutputRange */
|
||||||
bool put(T const &v) {
|
bool put(T const &v) {
|
||||||
|
@ -1916,6 +1978,71 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SizeT put_n(ValT const *p, SizeT n) {
|
||||||
|
using IC = typename std::iterator_traits<T>::iterator_category;
|
||||||
|
if constexpr(std::is_convertible_v<IC, std::random_access_iterator_tag>) {
|
||||||
|
SizeT ret = size();
|
||||||
|
if (n < ret) {
|
||||||
|
ret = n;
|
||||||
|
}
|
||||||
|
if constexpr(std::is_pointer_v<T> && std::is_pod_v<ValT>) {
|
||||||
|
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<typename R>
|
||||||
|
std::enable_if_t<IsOutputRange<R>, SizeT> copy(R &&orange, SizeT n = -1) {
|
||||||
|
if constexpr(std::is_pointer_v<T>) {
|
||||||
|
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<ValT> *p, SizeT n = -1) {
|
||||||
|
using IC = typename std::iterator_traits<T>::iterator_category;
|
||||||
|
if constexpr(std::is_convertible_v<IC, std::random_access_iterator_tag>) {
|
||||||
|
SizeT c = size();
|
||||||
|
if (n < c) {
|
||||||
|
c = n;
|
||||||
|
}
|
||||||
|
if constexpr(std::is_pointer_v<T> && std::is_pod_v<ValT>) {
|
||||||
|
memcpy(p, p_beg, c * sizeof(ValT));
|
||||||
|
return c;
|
||||||
|
} else {
|
||||||
|
return copy(IteratorRange<std::remove_cv_t<ValT> *>(p, p + c), c);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SizeT on = n;
|
||||||
|
for (; n && !empty(); --n) {
|
||||||
|
*p++ = front();
|
||||||
|
pop_front();
|
||||||
|
}
|
||||||
|
return (on - n);
|
||||||
|
}
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
T p_beg, p_end;
|
T p_beg, p_end;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue