From 0d2ebb4373e509521f27a6e8f16bfd39d05b2188 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Thu, 17 Nov 2016 10:10:32 -0500 Subject: [PATCH] istringstream_nocopy: Implement in a standards-compliant way Fixes #1135. --- src/libutil/util.hh | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/src/libutil/util.hh b/src/libutil/util.hh index a8f6f99b9..f38c2bb7c 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -435,14 +435,50 @@ void callSuccess( argument. This is useful for large strings. The caller must ensure that the string object is not destroyed while it's referenced by this object. */ -struct istringstream_nocopy : public std::stringstream +class istringbuf_nocopy : public std::streambuf { - istringstream_nocopy(const std::string & s) + const std::string & s; + std::streamsize off; +public: + istringbuf_nocopy(const std::string & s) : s{s}, off{0} { - rdbuf()->pubsetbuf( - (char *) s.data(), s.size()); + } + +private: + int_type underflow() + { + if (off == s.size()) + return traits_type::eof(); + return traits_type::to_int_type(s[off]); + } + + int_type uflow() + { + if (off == s.size()) + return traits_type::eof(); + return traits_type::to_int_type(s[off++]); + } + + int_type pbackfail(int_type ch) + { + if (off == 0 || (ch != traits_type::eof() && ch != s[off - 1])) + return traits_type::eof(); + + return traits_type::to_int_type(s[--off]); + } + + std::streamsize showmanyc() + { + return s.size() - off; } }; +struct istringstream_nocopy : public std::istream +{ + istringbuf_nocopy buf; + istringstream_nocopy(const std::string & s) : std::istream(&buf), buf(s) {}; +}; + + }