From f35de20c723fd63f4c9d84447eb3ae69d516f5b4 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 23 May 2023 23:05:44 -0700 Subject: [PATCH] io: Fix name lookup for read_exact friend specializations --- src/io/streams.hpp | 88 ++++++++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/src/io/streams.hpp b/src/io/streams.hpp index c69637570..ede48f0a9 100644 --- a/src/io/streams.hpp +++ b/src/io/streams.hpp @@ -448,33 +448,35 @@ public: return head_; } - friend void read_exact(SpanStream& stream, tcb::span buffer) - { - const std::size_t remaining = stream.span_.size() - stream.head_; - const std::size_t buffer_size = buffer.size(); - if (buffer_size > remaining) - { - // The span's size will never change, so the generic impl of read_exact will enter an inifinite loop. We can - // throw out early. - throw UnexpectedEof("read buffer size > remaining bytes in span"); - } - if (buffer_size == 0) - { - return; - } - - auto copy_begin = std::next(stream.span_.begin(), stream.head_); - auto copy_end = std::next(stream.span_.begin(), stream.head_ + buffer_size); - stream.head_ += buffer_size; - - std::copy(copy_begin, copy_end, buffer.begin()); - } + friend void read_exact(SpanStream& stream, tcb::span buffer); private: tcb::span span_; std::size_t head_ {0}; }; +inline void read_exact(SpanStream& stream, tcb::span buffer) +{ + const std::size_t remaining = stream.span_.size() - stream.head_; + const std::size_t buffer_size = buffer.size(); + if (buffer_size > remaining) + { + // The span's size will never change, so the generic impl of read_exact will enter an inifinite loop. We can + // throw out early. + throw UnexpectedEof("read buffer size > remaining bytes in span"); + } + if (buffer_size == 0) + { + return; + } + + auto copy_begin = std::next(stream.span_.begin(), stream.head_); + auto copy_end = std::next(stream.span_.begin(), stream.head_ + buffer_size); + stream.head_ += buffer_size; + + std::copy(copy_begin, copy_end, buffer.begin()); +} + class VecStream { std::vector vec_; std::size_t head_ {0}; @@ -543,29 +545,31 @@ public: std::vector& vector() { return vec_; } - friend void read_exact(VecStream& stream, tcb::span buffer) - { - const std::size_t remaining = stream.vec_.size() - stream.head_; - const std::size_t buffer_size = buffer.size(); - if (buffer_size > remaining) - { - // VecStream is not thread safe, so the generic impl of read_exact would enter an infinite loop under - // correct usage. We know when we've reached the end and can throw out early. - throw UnexpectedEof("read buffer size > remaining bytes in vector"); - } - if (buffer_size == 0) - { - return; - } - - auto copy_begin = std::next(stream.vec_.begin(), stream.head_); - auto copy_end = std::next(stream.vec_.begin(), stream.head_ + buffer_size); - stream.head_ += buffer_size; - - std::copy(copy_begin, copy_end, buffer.begin()); - } + friend void read_exact(VecStream& stream, tcb::span buffer); }; +inline void read_exact(VecStream& stream, tcb::span buffer) +{ + const std::size_t remaining = stream.vec_.size() - stream.head_; + const std::size_t buffer_size = buffer.size(); + if (buffer_size > remaining) + { + // VecStream is not thread safe, so the generic impl of read_exact would enter an infinite loop under + // correct usage. We know when we've reached the end and can throw out early. + throw UnexpectedEof("read buffer size > remaining bytes in vector"); + } + if (buffer_size == 0) + { + return; + } + + auto copy_begin = std::next(stream.vec_.begin(), stream.head_); + auto copy_end = std::next(stream.vec_.begin(), stream.head_ + buffer_size); + stream.head_ += buffer_size; + + std::copy(copy_begin, copy_end, buffer.begin()); +} + class ZlibException : public std::exception { int err_ {0}; std::string msg_;