Search code examples
c++boostgzipboost-iostreams

Compressing/decompressing gzip into memory with boost


I'll be brief: I have this piece of code:

QByteArray MyNBT::decompressData(QByteArray data)
{
    filtering_streambuf<input> in;

    std::string _data = data.data();

    in.push( gzip_decompressor() );
    in.push( boost::iostreams::back_inserter(_data) );
    //in.push( std::back_inserter(_data) );

    std::stringstream _sstream;
    boost::iostreams::copy(in, _sstream);

    QByteArray out = _sstream.rdbuf()->str().c_str();

    return out;
}

And it gives an error at this line(s):

in.push( boost::iostreams::back_inserter(_data) );
//in.push( std::back_inserter(_data) );

The error is:

/usr/include/boost/iostreams/chain.hpp:244: error: invalid application of 'sizeof' to incomplete type 'boost::STATIC_ASSERTION_FAILURE<false>'
     BOOST_STATIC_ASSERT((is_convertible<category, Mode>::value));
     ^

The compiler throws this error once in std::back_inserter(_data) and twice with boost's one.

Thanks in advance.


Solution

  • What does a back_inserter do?

    Indeed. It inserts elements at the back of a container.

    What you seem to be after, though, is a "front_reader" or container_source.

    Well, I don't have Qt, but I had luck using array_source to adapt your input (note how it works equally well with std::string, std::vector, std::array or even just const char [] input):

    Live On Coliru

    #include <fstream>
    #include <iostream>
    
    #include <boost/iostreams/filtering_stream.hpp>
    #include <boost/iostreams/filter/gzip.hpp>
    #include <boost/iostreams/copy.hpp>
    #include <sstream>
    
    int main()  {
        using namespace boost::iostreams;
        filtering_streambuf<input> in;
    
    #if 0
        std::string _data { 
    #else
        std::vector<char> _data { 
    #endif
            char(0x1f), char(0x8b), char(0x08), char(0x00), char(0xca), char(0xb5),
            char(0x07), char(0x53), char(0x00), char(0x03), char(0xcb), char(0x48),
            char(0xcd), char(0xc9), char(0xc9), char(0x57), char(0x28), char(0xcf),
            char(0x2f), char(0xca), char(0x49), char(0xe1), char(0x02), char(0x00),
            char(0x2d), char(0x3b), char(0x08), char(0xaf), char(0x0c), char(0x00),
            char(0x00), char(0x00)
        };
    
        in.push( gzip_decompressor() );
        in.push( boost::iostreams::array_source(_data.data(), _data.size()) );
    
        std::stringstream _sstream;
        boost::iostreams::copy(in, _sstream);
    
        std::cout << _sstream.rdbuf();
    }
    

    The output of the program is, of course, hello world