Question

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.

Was it helpful?

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):

#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

OTHER TIPS

Fixed it using @sehe 's answer.

Here's the resulting code: (hope it'll be useful for people with the same errors)

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

    std::vector<char> _data;
    foreach( char ch, data )
        _data.push_back(ch);

    in.push( gzip_decompressor() );
    in.push( boost::iostreams::array_source(_data.data(), _data.size()) );

    QByteArray out;
    while ( in.sgetc() != -1 )
        out += (unsigned char)in.sbumpc();

    std::cout << "out size! :: " << in.in_avail() << std::endl;
    //std::cout << "out size! :: " << _sstream.str().size() << std::endl;
    std::cout << "out size! :: " << out.size() << std::endl;

    return out;
}

I also use a simple character array, and for efficiency's sake did not want to have to create a vector and copy the buffer contents. So,here's my take on a simple in-ram compress/decompress utility class that decompresses or compresses directly from the char array read from the wire into another char array:

/*
 * GzipUtil.h
 *
 *  Created on: Nov 3, 2015
 *      Author: tprice
 */

#ifndef GZIPUTIL_H_
#define GZIPUTIL_H_

#include <unistd.h>
#include <stdint.h>
#include <vector>
#include <stdlib.h>

#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>

namespace BIO = boost::iostreams;

class GzipUtil {
public:
GzipUtil() {}
virtual ~GzipUtil() {}

static ssize_t compress(char *src, char *dest, ssize_t len)
{
    ssize_t retval = 0;

    BIO::filtering_streambuf<BIO::input> in;
    in.push( BIO::gzip_compressor() );
    in.push( BIO::array_source(src, len) );
    for(retval = 0; in.sgetc() != -1; retval++ )
    {
        dest[retval] = (char) in.sbumpc();
    }

    return retval;
}

static ssize_t decompress(char *src, ssize_t srclen, std::vector<char*> & dest, ssize_t destChunkLen)
{
    ssize_t retval = 0;
    char*   chunkPtr = NULL;
    ssize_t chunkUsed = 0;

    BIO::filtering_streambuf<BIO::input> in;
    in.push( BIO::gzip_decompressor() );
    in.push( BIO::array_source(src, srclen) );
    for(retval = 0; in.sgetc() != -1; retval++ )
    {
        if((chunkPtr == NULL) || (chunkUsed >= destChunkLen))
        {
            chunkPtr = (char*) malloc(destChunkLen);
            dest.push_back(chunkPtr);
            chunkUsed = 0;
        }
        chunkPtr[chunkUsed++] = (char) in.sbumpc();
    }

    return retval;
}

};


#endif /* GZIPUTIL_H_ */
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top