diff options
author | Shea Levy <shea@shealevy.com> | 2016-11-17T15·10-0500 |
---|---|---|
committer | Shea Levy <shea@shealevy.com> | 2016-11-17T15·10-0500 |
commit | 0d2ebb4373e509521f27a6e8f16bfd39d05b2188 (patch) | |
tree | 4565d5bdfe814fd7b07797b8cc905cefc172490e | |
parent | 3f4d3f8a1a178c4d7a80d20b3bac9889bac49f9c (diff) |
istringstream_nocopy: Implement in a standards-compliant way
Fixes #1135.
-rw-r--r-- | src/libutil/util.hh | 44 |
1 files changed, 40 insertions, 4 deletions
diff --git a/src/libutil/util.hh b/src/libutil/util.hh index a8f6f99b957f..f38c2bb7c154 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} + { + } + +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() { - rdbuf()->pubsetbuf( - (char *) s.data(), s.size()); + return s.size() - off; } }; +struct istringstream_nocopy : public std::istream +{ + istringbuf_nocopy buf; + istringstream_nocopy(const std::string & s) : std::istream(&buf), buf(s) {}; +}; + + } |