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(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!