|
Boost Users : |
Subject: Re: [Boost-users] [iostreams] filtering streams in a chain are continually writing the same bytes
From: Andrew Ames (aames_at_[hidden])
Date: 2017-02-21 17:29:53
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_at_[hidden]> 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_at_[hidden]
>
-- Andrew Ames aames_at_[hidden]
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net