[iostreams] filtering streams in a chain are continually writing the same bytes

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[iostreams] filtering streams in a chain are continually writing the same bytes

Boost - Users mailing list
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

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [iostreams] filtering streams in a chain are continually writing the same bytes

Boost - Users mailing list
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 <[hidden email]> 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



--
Andrew Ames

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Loading...