diff --git a/include/msgpack/v1/sbuffer.hpp b/include/msgpack/v1/sbuffer.hpp index 7ab303106..21574126b 100644 --- a/include/msgpack/v1/sbuffer.hpp +++ b/include/msgpack/v1/sbuffer.hpp @@ -16,6 +16,7 @@ #include #include +#include namespace msgpack { @@ -81,6 +82,22 @@ class sbuffer { m_size += len; } + size_t read_from(std::istream& is, size_t len) + { + if (len == 0) return 0; + + if(m_alloc - m_size < len) { + expand_buffer(len); + } + + is.read(m_data + m_size, static_cast(len)); + const std::streamsize n = is.gcount(); + if (n <= 0) return 0; + + m_size += static_cast(n); + return static_cast(n); + } + char* data() { return m_data; diff --git a/test/buffer.cpp b/test/buffer.cpp index 3dd4c2f31..527fce713 100644 --- a/test/buffer.cpp +++ b/test/buffer.cpp @@ -5,6 +5,8 @@ #define BOOST_TEST_MODULE buffer #include +#include +#include #include BOOST_AUTO_TEST_CASE(sbuffer) @@ -27,6 +29,41 @@ BOOST_AUTO_TEST_CASE(sbuffer) } +BOOST_AUTO_TEST_CASE(sbuffer_read_from) +{ + const std::string src = "abcdefghij"; + + std::istringstream is(src); + msgpack::sbuffer sbuf; + + // A part of the stream is appended to the buffer. + BOOST_CHECK_EQUAL(4ul, sbuf.read_from(is, 4)); + BOOST_CHECK_EQUAL(4ul, sbuf.size()); + BOOST_CHECK( memcmp(sbuf.data(), "abcd", 4) == 0 ); + + // A request larger than the remaining data reads up to the end of the stream. + BOOST_CHECK_EQUAL(6ul, sbuf.read_from(is, 100)); + BOOST_CHECK_EQUAL(10ul, sbuf.size()); + BOOST_CHECK( memcmp(sbuf.data(), "abcdefghij", 10) == 0 ); + + // len == 0 reads nothing. + BOOST_CHECK_EQUAL(0ul, sbuf.read_from(is, 0)); + BOOST_CHECK_EQUAL(10ul, sbuf.size()); + + // Reading at the end of the stream reads nothing. + is.clear(); + BOOST_CHECK_EQUAL(0ul, sbuf.read_from(is, 1)); + BOOST_CHECK_EQUAL(10ul, sbuf.size()); + + // The buffer grows as needed. + msgpack::sbuffer small(1); + std::istringstream is2(src); + BOOST_CHECK_EQUAL(10ul, small.read_from(is2, 10)); + BOOST_CHECK_EQUAL(10ul, small.size()); + BOOST_CHECK( memcmp(small.data(), "abcdefghij", 10) == 0 ); +} + + BOOST_AUTO_TEST_CASE(vrefbuffer) { msgpack::vrefbuffer vbuf;