Boost logo

Boost Users :

From: aldin seh (aldin_s_at_[hidden])
Date: 2007-03-29 06:05:06


Hello,

This was my test case:

    std::ifstream file_stream;
    std::ofstream dest_stream;

    file_stream.open(“test.txt”, std::ios::in | std::ios::binary);
    dest_stream.open(“output.zip”, std::ios::out | std::ios::binary);

    struct zlib_params params;

    params.level = zlib::default_compression;
    params.method = zlib::deflated;
    params.window_bits = zlib::default_window_bits;
    params.mem_level = zlib::default_mem_level;
    params.strategy = zlib::default_strategy;
    params.noheader = true;
    params.calculate_crc = true;

    filtering_streambuf<input> test;
    test.push(zlib_compressor(params));
    test.push(file_stream);

    uint32 copy_size = static_cast<uint32_t>(boost::iostreams::copy(test,
dest_stream));

PROBLEM: “copy” function returns 0 on first call and right copy size on
second call.

The file size of “test.txt” is 10KB.
It seems that the error is related to “read” function of the symetrical
filter.
While commpressing data this function is called to read from filter ( read
from file_stream and compress) (Symmetrical.hpp)

    template<typename Source>
    std::streamsize read(Source& src, char_type* s, std::streamsize n)

    {

        using namespace std;

        if (!(state() & f_read))
            begin_read();

         buffer_type& buf = pimpl_->buf_;

        int status = (state() & f_eof) != 0 ? f_eof : f_good;

        char_type *next_s = s,
                     *end_s = s + n;

        while (true)
        {
            // Invoke filter if there are unconsumed characters in buffer or
if

            // filter must be flushed.

            bool flush = status == f_eof;

            if (buf.ptr() != buf.eptr() || flush) {

                const char_type* next = buf.ptr();

                bool done =
                    !filter().filter(next, buf.eptr(), next_s, end_s,
flush);

                buf.ptr() = buf.data() + (next - buf.data());

                if (done)
                    return detail::check_eof(static_cast<streamsize>(next_s
- s));
            }

            // If no more characters are available without blocking, or
            // if read request has been satisfied, return.
            if ( status == f_would_block && buf.ptr() == buf.eptr() ||
                 next_s == end_s )
            {
                return static_cast<streamsize>(next_s - s);
            }

            // Fill buffer.
            if (status == f_good)
                status = fill(src);
        }
    }

First the “fill” function is called to fill data from source to the buffer:
(Symmetrical.hpp)

    template<typename Source>
    int fill(Source& src)
    {
        std::streamsize amt = iostreams::read(src, buf().data(),
buf().size());

        if (amt == -1) {
            state() |= f_eof;
            return f_eof;
       }

        buf().set(0, amt);
        return amt == buf().size() ? f_good : f_would_block;
    }

And here is the problem, if we read from source less than buf().size
(indicating eof) “f_would_block” is returned, but if we

use “f_eof” instead , “copy” returns right data on first call. (The zlib
wraper is never called with signal (flush = true) to finish the compression)

Is this a bug or did I something wrong in the above example ?

Thanks!

_________________________________________________________________
Der neue MSN Messenger. Schreiben.Sehen.Hören. Wie im echten Leben. -
http://www.imagine-msn.com/messenger/default2.aspx?locale=de Jetzt
herunterladen!


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