add optional range methods get_n/put_n (with accurate default implementations, overridable for performance)
This commit is contained in:
parent
a23525bacf
commit
e31c227567
|
@ -452,6 +452,28 @@ template<typename B, typename C, typename V, typename R = V &,
|
||||||
RangeHalf<B> half() const {
|
RangeHalf<B> half() const {
|
||||||
return RangeHalf<B>(iter());
|
return RangeHalf<B>(iter());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Size put_n(const Value *p, Size n) {
|
||||||
|
B &r = *((B *)this);
|
||||||
|
Size on = n;
|
||||||
|
for (; n && r.put(p++); --n);
|
||||||
|
return (on - n);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OR>
|
||||||
|
Size get_n(OR orange, Size n) {
|
||||||
|
B &r = *((B *)this);
|
||||||
|
Size on = n;
|
||||||
|
for (; n && !r.empty() && orange.put(r.front()); --n);
|
||||||
|
return (on - n);
|
||||||
|
}
|
||||||
|
|
||||||
|
Size get_n(Value *p, Size n) {
|
||||||
|
B &r = *((B *)this);
|
||||||
|
Size on = n;
|
||||||
|
for (; n && !r.empty(); --n) *p++ = r.front();
|
||||||
|
return (on - n);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -469,14 +491,21 @@ auto citer(const T &r) -> decltype(r.iter()) {
|
||||||
return r.iter();
|
return r.iter();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename V, typename R = V &, typename S = octa::Size,
|
template<typename B, typename V, typename R = V &,
|
||||||
typename D = octa::Ptrdiff
|
typename S = octa::Size, typename D = octa::Ptrdiff
|
||||||
> struct OutputRange {
|
> struct OutputRange {
|
||||||
using Category = OutputRangeTag;
|
using Category = OutputRangeTag;
|
||||||
using Size = S;
|
using Size = S;
|
||||||
using Difference = D;
|
using Difference = D;
|
||||||
using Value = V;
|
using Value = V;
|
||||||
using Reference = R;
|
using Reference = R;
|
||||||
|
|
||||||
|
Size put_n(const Value *p, Size n) {
|
||||||
|
B &r = *((B *)this);
|
||||||
|
Size on = n;
|
||||||
|
while (n--) if (!r.put(p++)) break;
|
||||||
|
return (on - n);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -858,6 +887,30 @@ struct PointerRange: InputRange<PointerRange<T>, FiniteRandomAccessRangeTag, T>
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
octa::Size put_n(const T *p, octa::Size n) {
|
||||||
|
octa::Size ret = size();
|
||||||
|
if (n < ret) ret = n;
|
||||||
|
if (octa::IsPod<T>()) {
|
||||||
|
memcpy(p_beg, p, ret * sizeof(T));
|
||||||
|
p_beg += ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
for (octa::Size i = ret; i; --i)
|
||||||
|
*p_beg++ = *p++;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename R>
|
||||||
|
octa::Size get_n(R orange, octa::Size n) {
|
||||||
|
octa::Size c = size();
|
||||||
|
if (n < c) c = n;
|
||||||
|
return orange.put_n(p_beg, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
octa::Size get_n(T *p, octa::Size n) {
|
||||||
|
return get_n(PointerRange(p, n), n);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T *p_beg, *p_end;
|
T *p_beg, *p_end;
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,7 +35,7 @@ struct StreamRange;
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<octa::Size N>
|
template<octa::Size N>
|
||||||
struct FormatOutRange: octa::OutputRange<char> {
|
struct FormatOutRange: octa::OutputRange<FormatOutRange<N>, char> {
|
||||||
FormatOutRange(char *buf): buf(buf), idx(0) {}
|
FormatOutRange(char *buf): buf(buf), idx(0) {}
|
||||||
FormatOutRange(const FormatOutRange &r): buf(r.buf), idx(r.idx) {}
|
FormatOutRange(const FormatOutRange &r): buf(r.buf), idx(r.idx) {}
|
||||||
char *buf;
|
char *buf;
|
||||||
|
@ -210,6 +210,19 @@ struct StreamRange<T, true>: InputRange<
|
||||||
return (v == sizeof(T));
|
return (v == sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
octa::Size put_n(const T *p, octa::Size n) {
|
||||||
|
return p_stream->put(p, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename R>
|
||||||
|
octa::Size get_n(R orange, octa::Size n) {
|
||||||
|
return orange.put_n()
|
||||||
|
}
|
||||||
|
|
||||||
|
octa::Size get_n(T *p, octa::Size n) {
|
||||||
|
return p_stream->get(p, n);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Stream *p_stream;
|
Stream *p_stream;
|
||||||
StreamOffset p_size;
|
StreamOffset p_size;
|
||||||
|
|
Loading…
Reference in a new issue