
The problem appears to be in the code that calls setp inside the indirect_streambuf. It seems to be using incorrect pointers. Can someone confirm my thinking here? I changed this function from this: template<typename T, typename Tr, typename Alloc, typename Mode> void indirect_streambuf<T, Tr, Alloc, Mode>::sync_impl() { std::streamsize avail, amt; if ((avail = static_cast<std::streamsize>(pptr() - pbase())) > 0) { if ((amt = obj().write(pbase(), avail, next())) == avail) setp(out().begin(), out().end()); else { const char_type* ptr = pptr(); setp(out().begin() + amt, out().end()); pbump(ptr - pptr()); } } } to this: template<typename T, typename Tr, typename Alloc, typename Mode> void indirect_streambuf<T, Tr, Alloc, Mode>::sync_impl() { std::streamsize avail, amt; if ((avail = static_cast<std::streamsize>(pptr() - pbase())) > 0) { if ((amt = obj().write(pbase(), avail, next())) == avail) setp(out().begin(), out().end()); else { const char_type* ptr = pptr(); setp(pbase() + amt, epptr()); pbump(ptr - pptr()); } } } My unit tests now pass. I have several other tests using chained filters and their unit tests now pass, when they did not before. I appreciate any other eyes put on this. On Tue, Feb 21, 2017 at 8:34 AM, Andrew Ames <aames@tanzle.com> wrote:
Perhaps someone can clarify that my use of multichar_output_filter is valid.
When I debug this, even though my write method is returning 4 bytes for every write, the caller of my output filter keeps providing me the same four bytes after the first sequence of 4 bytes.
This is boot version 1.62. Here is compiling code that illustrates:
class fixed_size_output_filter : public boost::iostreams::multichar_ output_filter { public:
fixed_size_output_filter(std::streamsize size = 4) : mSize(size) {}
template<typename Sink> std::streamsize write(Sink &sink, const char *s, std::streamsize n) { std::streamsize bytesAttempted = std::min(mSize, n); std::streamsize bytesActual = boost::iostreams::write(sink, s, bytesAttempted); return bytesActual; }
private:
std::streamsize mSize;
};
BOOST_AUTO_TEST_CASE(FixedSizeOutputFilter) { #define BYTES 500
char sink_buffer[BYTES]; array_sink array_sink(sink_buffer, sizeof(sink_buffer));
std::streampos os_pos; { filtering_ostream os; os.push(fixed_size_output_filter()); os.push(array_sink);
char buffer[BYTES]; for(char i = 0; i < sizeof(buffer); i++) buffer[i] = i;
os.write(buffer, sizeof(buffer)); }
for(char i = 0; i < sizeof(sink_buffer); i++) BOOST_CHECK(i == sink_buffer[i]); }
The actual bytes that end up in the sink_buffer are as follows:
0, 1, 2, 3, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, ....uninitialized bytes follow through the rest of the buffer.
It would appear that the indirect_streambuf in use by the filter chain is incorrectly flushing the bytes.
Is my understanding of the library flawed? Does this appear to be a bug? Any help is greatly appreciated.
-- Andrew Ames aames@tanzle.com
-- Andrew Ames aames@tanzle.com