fully generic stream range (works on any type of stream)

This commit is contained in:
q66 2017-02-27 17:52:52 +01:00
parent 5beecdf370
commit e0574308a0

View file

@ -9,6 +9,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <type_traits> #include <type_traits>
#include <locale> #include <locale>
#include <optional>
#include "ostd/platform.hh" #include "ostd/platform.hh"
#include "ostd/types.hh" #include "ostd/types.hh"
@ -157,42 +158,47 @@ struct stream_range<T, true>: input_range<stream_range<T>> {
using difference_type = stream_off_t; using difference_type = stream_off_t;
stream_range() = delete; stream_range() = delete;
stream_range(stream &s): p_stream(&s), p_size(s.size()) {} stream_range(stream &s): p_stream(&s) {}
stream_range(stream_range const &r): p_stream(r.p_stream), p_size(r.p_size) {} stream_range(stream_range const &r): p_stream(r.p_stream) {}
bool empty() const { bool empty() const {
try { if (!p_item.has_value()) {
auto pos = p_stream->tell(); try {
return (p_size - pos) < stream_off_t(sizeof(T)); p_item = p_stream->get<T>();
} catch (...) { } catch (...) {
return true; return true;
}
} }
return false;
} }
void pop_front() { void pop_front() {
T val; if (p_item.has_value()) {
p_stream->read_bytes(&val, sizeof(T)); p_item = std::nullopt;
} else {
p_stream->get<T>();
}
} }
T front() const { T front() const {
T val; if (p_item.has_value()) {
p_stream->read_bytes(&val, sizeof(T)); return p_item.value();
p_stream->seek(-sizeof(T), stream_seek::CUR); } else {
return val; return (p_item = p_stream->get<T>()).value();
}
} }
bool equals_front(stream_range const &s) const { bool equals_front(stream_range const &s) const {
return p_stream->tell() == s.p_stream->tell(); return p_stream == s.p_stream;
} }
void put(T val) { void put(T val) {
p_stream->write_bytes(&val, sizeof(T)); p_stream->put(val);
p_size += sizeof(T);
} }
private: private:
stream *p_stream; stream *p_stream;
stream_off_t p_size; mutable std::optional<T> p_item;
}; };
template<typename T> template<typename T>