From e31c22756726c97fb10eb623e5ff5e040704914d Mon Sep 17 00:00:00 2001 From: q66 Date: Wed, 1 Jul 2015 21:46:58 +0100 Subject: [PATCH] add optional range methods get_n/put_n (with accurate default implementations, overridable for performance) --- octa/range.hh | 57 ++++++++++++++++++++++++++++++++++++++++++++++++-- octa/stream.hh | 15 ++++++++++++- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/octa/range.hh b/octa/range.hh index a6358bb..5b88ebe 100644 --- a/octa/range.hh +++ b/octa/range.hh @@ -452,6 +452,28 @@ template half() const { return RangeHalf(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 + 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 @@ -469,14 +491,21 @@ auto citer(const T &r) -> decltype(r.iter()) { return r.iter(); } -template struct OutputRange { using Category = OutputRangeTag; using Size = S; using Difference = D; using Value = V; 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 @@ -858,6 +887,30 @@ struct PointerRange: InputRange, FiniteRandomAccessRangeTag, T> return true; } + octa::Size put_n(const T *p, octa::Size n) { + octa::Size ret = size(); + if (n < ret) ret = n; + if (octa::IsPod()) { + 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 + 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: T *p_beg, *p_end; }; diff --git a/octa/stream.hh b/octa/stream.hh index 5ff90c3..0ef7e94 100644 --- a/octa/stream.hh +++ b/octa/stream.hh @@ -35,7 +35,7 @@ struct StreamRange; namespace detail { template - struct FormatOutRange: octa::OutputRange { + struct FormatOutRange: octa::OutputRange, char> { FormatOutRange(char *buf): buf(buf), idx(0) {} FormatOutRange(const FormatOutRange &r): buf(r.buf), idx(r.idx) {} char *buf; @@ -210,6 +210,19 @@ struct StreamRange: InputRange< return (v == sizeof(T)); } + octa::Size put_n(const T *p, octa::Size n) { + return p_stream->put(p, n); + } + + template + 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: Stream *p_stream; StreamOffset p_size;